aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-10-18 14:43:12 +0200
committerMartin Liska <mliska@suse.cz>2021-10-18 14:43:12 +0200
commit39887dd2c2c81cf3e98466827d59cafda279a258 (patch)
tree4cacd91fc1a3199b6dec319bc63cf82ffb65d813 /gcc
parente07d0e579a4e532ac4bd2d223105d73d6418868f (diff)
parent247c407c83f0015f4b92d5f71e45b63192f6757e (diff)
downloadgcc-39887dd2c2c81cf3e98466827d59cafda279a258.zip
gcc-39887dd2c2c81cf3e98466827d59cafda279a258.tar.gz
gcc-39887dd2c2c81cf3e98466827d59cafda279a258.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5959
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in10
-rw-r--r--gcc/ada/ChangeLog2436
-rw-r--r--gcc/ada/Makefile.rtl152
-rw-r--r--gcc/ada/adabkend.adb58
-rw-r--r--gcc/ada/adaint.c4
-rw-r--r--gcc/ada/ali-util.adb1
-rw-r--r--gcc/ada/ali.adb37
-rw-r--r--gcc/ada/ali.ads6
-rw-r--r--gcc/ada/aspects.ads16
-rw-r--r--gcc/ada/atree.adb718
-rw-r--r--gcc/ada/atree.ads76
-rw-r--r--gcc/ada/atree.h71
-rw-r--r--gcc/ada/back_end.adb95
-rw-r--r--gcc/ada/backend_utils.adb96
-rw-r--r--gcc/ada/backend_utils.ads36
-rw-r--r--gcc/ada/bcheck.adb134
-rw-r--r--gcc/ada/bindgen.adb31
-rw-r--r--gcc/ada/bindo-graphs.adb14
-rw-r--r--gcc/ada/checks.adb44
-rw-r--r--gcc/ada/checks.ads25
-rw-r--r--gcc/ada/clean.adb2
-rw-r--r--gcc/ada/comperr.adb7
-rw-r--r--gcc/ada/contracts.adb1645
-rw-r--r--gcc/ada/contracts.ads25
-rw-r--r--gcc/ada/cstand.adb77
-rw-r--r--gcc/ada/debug.adb19
-rw-r--r--gcc/ada/doc/gnat_rm.rst1
-rw-r--r--gcc/ada/doc/gnat_rm/about_this_guide.rst3
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst702
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst88
-rw-r--r--gcc/ada/doc/gnat_rm/security_hardening_features.rst89
-rw-r--r--gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst38
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst18
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst14
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst18
-rw-r--r--gcc/ada/doc/gnat_ugn/platform_specific_information.rst5
-rw-r--r--gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst71
-rw-r--r--gcc/ada/einfo-utils.adb380
-rw-r--r--gcc/ada/einfo-utils.ads259
-rw-r--r--gcc/ada/einfo.ads116
-rw-r--r--gcc/ada/err_vars.ads17
-rw-r--r--gcc/ada/errout.adb43
-rw-r--r--gcc/ada/erroutc.adb48
-rw-r--r--gcc/ada/exp_aggr.adb328
-rw-r--r--gcc/ada/exp_attr.adb59
-rw-r--r--gcc/ada/exp_ch3.adb150
-rw-r--r--gcc/ada/exp_ch4.adb265
-rw-r--r--gcc/ada/exp_ch5.adb159
-rw-r--r--gcc/ada/exp_ch6.adb438
-rw-r--r--gcc/ada/exp_ch6.ads3
-rw-r--r--gcc/ada/exp_ch7.adb22
-rw-r--r--gcc/ada/exp_ch9.adb29
-rw-r--r--gcc/ada/exp_dbug.adb6
-rw-r--r--gcc/ada/exp_disp.adb290
-rw-r--r--gcc/ada/exp_dist.adb6
-rw-r--r--gcc/ada/exp_fixd.adb171
-rw-r--r--gcc/ada/exp_intr.adb2
-rw-r--r--gcc/ada/exp_pakd.adb33
-rw-r--r--gcc/ada/exp_prag.adb16
-rw-r--r--gcc/ada/exp_smem.adb2
-rw-r--r--gcc/ada/exp_util.adb350
-rw-r--r--gcc/ada/exp_util.ads69
-rw-r--r--gcc/ada/expander.adb15
-rw-r--r--gcc/ada/fe.h41
-rw-r--r--gcc/ada/freeze.adb665
-rw-r--r--gcc/ada/freeze.ads9
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in3
-rw-r--r--gcc/ada/gcc-interface/cuintp.c1
-rw-r--r--gcc/ada/gcc-interface/decl.c318
-rw-r--r--gcc/ada/gcc-interface/gigi.h13
-rw-r--r--gcc/ada/gcc-interface/lang-specs.h7
-rw-r--r--gcc/ada/gcc-interface/misc.c19
-rw-r--r--gcc/ada/gcc-interface/targtyps.c1
-rw-r--r--gcc/ada/gcc-interface/trans.c27
-rw-r--r--gcc/ada/gcc-interface/utils.c80
-rw-r--r--gcc/ada/gcc-interface/utils2.c2
-rw-r--r--gcc/ada/gen_il-fields.ads26
-rw-r--r--gcc/ada/gen_il-gen-gen_entities.adb35
-rw-r--r--gcc/ada/gen_il-gen-gen_nodes.adb66
-rw-r--r--gcc/ada/gen_il-gen.adb1027
-rw-r--r--gcc/ada/gen_il-internals.adb2
-rw-r--r--gcc/ada/gen_il-internals.ads350
-rw-r--r--gcc/ada/gen_il-types.ads15
-rw-r--r--gcc/ada/ghost.adb9
-rw-r--r--gcc/ada/gnat1drv.adb13
-rw-r--r--gcc/ada/gnat_cuda.adb240
-rw-r--r--gcc/ada/gnat_cuda.ads30
-rw-r--r--gcc/ada/gnat_rm.texi2875
-rw-r--r--gcc/ada/gnat_ugn.texi100
-rw-r--r--gcc/ada/gnatbind.adb2
-rw-r--r--gcc/ada/gnatfind.adb5
-rw-r--r--gcc/ada/gnatlink.adb1
-rw-r--r--gcc/ada/gnatls.adb17
-rw-r--r--gcc/ada/gnatxref.adb5
-rw-r--r--gcc/ada/impunit.adb16
-rw-r--r--gcc/ada/init.c23
-rw-r--r--gcc/ada/inline.adb55
-rw-r--r--gcc/ada/itypes.adb5
-rw-r--r--gcc/ada/layout.adb34
-rw-r--r--gcc/ada/libgnarl/a-intnam__rtems.ads74
-rw-r--r--gcc/ada/libgnarl/a-tasini.adb12
-rw-r--r--gcc/ada/libgnarl/a-tasini.ads9
-rw-r--r--gcc/ada/libgnarl/s-inmaop__hwint.adb (renamed from gcc/ada/libgnarl/s-inmaop__vxworks.adb)7
-rw-r--r--gcc/ada/libgnarl/s-interr__hwint.adb36
-rw-r--r--gcc/ada/libgnarl/s-interr__vxworks.adb37
-rw-r--r--gcc/ada/libgnarl/s-intman__android.adb2
-rw-r--r--gcc/ada/libgnarl/s-intman__lynxos.adb2
-rw-r--r--gcc/ada/libgnarl/s-intman__posix.adb2
-rw-r--r--gcc/ada/libgnarl/s-intman__qnx.adb2
-rw-r--r--gcc/ada/libgnarl/s-intman__rtems.adb93
-rw-r--r--gcc/ada/libgnarl/s-intman__rtems.ads99
-rw-r--r--gcc/ada/libgnarl/s-intman__solaris.adb2
-rw-r--r--gcc/ada/libgnarl/s-intman__susv3.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__rtems.adb150
-rw-r--r--gcc/ada/libgnarl/s-osinte__rtems.ads67
-rw-r--r--gcc/ada/libgnarl/s-osinte__vxworks.adb18
-rw-r--r--gcc/ada/libgnarl/s-osinte__vxworks.ads84
-rw-r--r--gcc/ada/libgnarl/s-taprob.adb2
-rw-r--r--gcc/ada/libgnarl/s-taprop__hpux-dce.adb4
-rw-r--r--gcc/ada/libgnarl/s-taprop__linux.adb6
-rw-r--r--gcc/ada/libgnarl/s-taprop__mingw.adb4
-rw-r--r--gcc/ada/libgnarl/s-taprop__posix.adb6
-rw-r--r--gcc/ada/libgnarl/s-taprop__qnx.adb6
-rw-r--r--gcc/ada/libgnarl/s-taprop__rtems.adb1347
-rw-r--r--gcc/ada/libgnarl/s-taprop__solaris.adb6
-rw-r--r--gcc/ada/libgnarl/s-taprop__vxworks.adb107
-rw-r--r--gcc/ada/libgnarl/s-taskin.adb4
-rw-r--r--gcc/ada/libgnarl/s-taskin.ads8
-rw-r--r--gcc/ada/libgnarl/s-tasque.adb2
-rw-r--r--gcc/ada/libgnarl/s-tassta.adb9
-rw-r--r--gcc/ada/libgnarl/s-tpoben.adb2
-rw-r--r--gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb5
-rw-r--r--gcc/ada/libgnarl/s-tpopsp__vxworks.adb5
-rw-r--r--gcc/ada/libgnarl/s-vxwext.adb6
-rw-r--r--gcc/ada/libgnarl/s-vxwext.ads16
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel-smp.adb20
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel.adb22
-rw-r--r--gcc/ada/libgnarl/s-vxwext__kernel.ads26
-rw-r--r--gcc/ada/libgnarl/s-vxwext__noints.adb126
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp-smp.adb18
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp.adb22
-rw-r--r--gcc/ada/libgnarl/s-vxwext__rtp.ads26
-rw-r--r--gcc/ada/libgnarl/s-vxwext__vthreads.ads109
-rw-r--r--gcc/ada/libgnat/a-calend.adb15
-rw-r--r--gcc/ada/libgnat/a-cbdlli.adb107
-rw-r--r--gcc/ada/libgnat/a-cbdlli.ads8
-rw-r--r--gcc/ada/libgnat/a-cbhama.ads11
-rw-r--r--gcc/ada/libgnat/a-cbhase.ads9
-rw-r--r--gcc/ada/libgnat/a-cbmutr.ads8
-rw-r--r--gcc/ada/libgnat/a-cborma.ads11
-rw-r--r--gcc/ada/libgnat/a-cborse.ads9
-rw-r--r--gcc/ada/libgnat/a-cdlili.adb205
-rw-r--r--gcc/ada/libgnat/a-cfdlli.adb112
-rw-r--r--gcc/ada/libgnat/a-cfdlli.ads4
-rw-r--r--gcc/ada/libgnat/a-cfhama.ads1
-rw-r--r--gcc/ada/libgnat/a-cfhase.ads1
-rw-r--r--gcc/ada/libgnat/a-cfinve.ads1
-rw-r--r--gcc/ada/libgnat/a-cforma.ads1
-rw-r--r--gcc/ada/libgnat/a-cforse.ads1
-rw-r--r--gcc/ada/libgnat/a-chahan.adb122
-rw-r--r--gcc/ada/libgnat/a-chahan.ads359
-rw-r--r--gcc/ada/libgnat/a-cidlli.adb105
-rw-r--r--gcc/ada/libgnat/a-coboho.ads4
-rw-r--r--gcc/ada/libgnat/a-cobove.ads9
-rw-r--r--gcc/ada/libgnat/a-cofove.ads1
-rw-r--r--gcc/ada/libgnat/a-costso.adb191
-rw-r--r--gcc/ada/libgnat/a-costso.ads71
-rw-r--r--gcc/ada/libgnat/a-crdlli.adb108
-rw-r--r--gcc/ada/libgnat/a-elchha__vxworks-ppc-full.adb150
-rw-r--r--gcc/ada/libgnat/a-excach.adb2
-rw-r--r--gcc/ada/libgnat/a-except.adb92
-rw-r--r--gcc/ada/libgnat/a-except.ads9
-rw-r--r--gcc/ada/libgnat/a-stbufi.adb2
-rw-r--r--gcc/ada/libgnat/a-stbufi.ads12
-rw-r--r--gcc/ada/libgnat/a-strbou.adb2
-rw-r--r--gcc/ada/libgnat/a-strbou.ads2152
-rw-r--r--gcc/ada/libgnat/a-strfix.adb270
-rw-r--r--gcc/ada/libgnat/a-strfix.ads463
-rw-r--r--gcc/ada/libgnat/a-strmap.adb337
-rw-r--r--gcc/ada/libgnat/a-strmap.ads127
-rw-r--r--gcc/ada/libgnat/a-strsea.adb319
-rw-r--r--gcc/ada/libgnat/a-strsea.ads540
-rw-r--r--gcc/ada/libgnat/a-strsup.adb1163
-rw-r--r--gcc/ada/libgnat/a-strsup.ads2383
-rw-r--r--gcc/ada/libgnat/a-strunb.ads8
-rw-r--r--gcc/ada/libgnat/a-strunb__shared.ads3
-rw-r--r--gcc/ada/libgnat/a-tags.adb2
-rw-r--r--gcc/ada/libgnat/a-textio.adb3
-rw-r--r--gcc/ada/libgnat/a-textio.ads6
-rw-r--r--gcc/ada/libgnat/a-witeio.adb2
-rw-r--r--gcc/ada/libgnat/a-zchhan.adb34
-rw-r--r--gcc/ada/libgnat/a-zchhan.ads29
-rw-r--r--gcc/ada/libgnat/a-zchuni.adb19
-rw-r--r--gcc/ada/libgnat/a-zchuni.ads12
-rw-r--r--gcc/ada/libgnat/a-ztexio.adb2
-rw-r--r--gcc/ada/libgnat/g-binenv.adb2
-rw-r--r--gcc/ada/libgnat/g-forstr.adb6
-rw-r--r--gcc/ada/libgnat/i-vxwork.ads9
-rw-r--r--gcc/ada/libgnat/i-vxwork__x86.ads9
-rw-r--r--gcc/ada/libgnat/memtrack.adb127
-rw-r--r--gcc/ada/libgnat/s-aoinar.adb2
-rw-r--r--gcc/ada/libgnat/s-aomoar.adb2
-rw-r--r--gcc/ada/libgnat/s-aotase.adb2
-rw-r--r--gcc/ada/libgnat/s-arit128.ads7
-rw-r--r--gcc/ada/libgnat/s-arit64.ads7
-rw-r--r--gcc/ada/libgnat/s-atopex.adb38
-rw-r--r--gcc/ada/libgnat/s-atopri.ads7
-rw-r--r--gcc/ada/libgnat/s-dwalin.adb114
-rw-r--r--gcc/ada/libgnat/s-dwalin.ads26
-rw-r--r--gcc/ada/libgnat/s-ficobl.ads2
-rw-r--r--gcc/ada/libgnat/s-imenne.adb170
-rw-r--r--gcc/ada/libgnat/s-imenne.ads85
-rw-r--r--gcc/ada/libgnat/s-imglli.ads4
-rw-r--r--gcc/ada/libgnat/s-objrea.adb72
-rw-r--r--gcc/ada/libgnat/s-objrea.ads25
-rw-r--r--gcc/ada/libgnat/s-os_lib.ads11
-rw-r--r--gcc/ada/libgnat/s-osprim__vxworks.adb162
-rw-r--r--gcc/ada/libgnat/s-osvers__vxworks-653.ads38
-rw-r--r--gcc/ada/libgnat/s-parame.adb2
-rw-r--r--gcc/ada/libgnat/s-parame__ae653.ads8
-rw-r--r--gcc/ada/libgnat/s-parame__rtems.adb19
-rw-r--r--gcc/ada/libgnat/s-parame__vxworks.adb2
-rw-r--r--gcc/ada/libgnat/s-parame__vxworks.ads4
-rw-r--r--gcc/ada/libgnat/s-regpat.adb63
-rw-r--r--gcc/ada/libgnat/s-regpat.ads11
-rw-r--r--gcc/ada/libgnat/s-secsta.ads5
-rw-r--r--gcc/ada/libgnat/s-stchop__rtems.adb113
-rw-r--r--gcc/ada/libgnat/s-stratt.adb15
-rw-r--r--gcc/ada/libgnat/s-thread.ads14
-rw-r--r--gcc/ada/libgnat/s-thread__ae653.adb78
-rw-r--r--gcc/ada/libgnat/s-trasym__dwarf.adb2
-rw-r--r--gcc/ada/libgnat/system-vxworks-e500-vthread.ads162
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-vthread.ads162
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86-vthread.ads163
-rw-r--r--gcc/ada/live.adb3
-rw-r--r--gcc/ada/make.adb4
-rw-r--r--gcc/ada/opt.ads16
-rw-r--r--gcc/ada/osint-c.adb4
-rw-r--r--gcc/ada/osint.adb6
-rw-r--r--gcc/ada/output.adb26
-rw-r--r--gcc/ada/output.ads1
-rw-r--r--gcc/ada/par-ch10.adb9
-rw-r--r--gcc/ada/par-ch4.adb88
-rw-r--r--gcc/ada/par-prag.adb1
-rw-r--r--gcc/ada/par_sco.adb41
-rw-r--r--gcc/ada/pprint.adb59
-rw-r--r--gcc/ada/prep.adb25
-rw-r--r--gcc/ada/repinfo-input.adb2
-rw-r--r--gcc/ada/repinfo.adb35
-rw-r--r--gcc/ada/restrict.ads2
-rw-r--r--gcc/ada/scn.adb2
-rw-r--r--gcc/ada/scng.adb6
-rw-r--r--gcc/ada/scos.ads2
-rw-r--r--gcc/ada/sem.adb9
-rw-r--r--gcc/ada/sem.ads4
-rw-r--r--gcc/ada/sem_aggr.adb240
-rw-r--r--gcc/ada/sem_attr.adb230
-rw-r--r--gcc/ada/sem_aux.adb30
-rw-r--r--gcc/ada/sem_aux.ads4
-rw-r--r--gcc/ada/sem_case.adb337
-rw-r--r--gcc/ada/sem_ch10.adb21
-rw-r--r--gcc/ada/sem_ch10.ads9
-rw-r--r--gcc/ada/sem_ch12.adb10
-rw-r--r--gcc/ada/sem_ch13.adb895
-rw-r--r--gcc/ada/sem_ch13.ads6
-rw-r--r--gcc/ada/sem_ch3.adb405
-rw-r--r--gcc/ada/sem_ch3.ads12
-rw-r--r--gcc/ada/sem_ch4.adb116
-rw-r--r--gcc/ada/sem_ch5.adb17
-rw-r--r--gcc/ada/sem_ch6.adb53
-rw-r--r--gcc/ada/sem_ch7.adb40
-rw-r--r--gcc/ada/sem_ch8.adb28
-rw-r--r--gcc/ada/sem_ch9.adb6
-rw-r--r--gcc/ada/sem_dim.adb2
-rw-r--r--gcc/ada/sem_disp.adb180
-rw-r--r--gcc/ada/sem_disp.ads4
-rw-r--r--gcc/ada/sem_elab.adb88
-rw-r--r--gcc/ada/sem_eval.adb29
-rw-r--r--gcc/ada/sem_prag.adb105
-rw-r--r--gcc/ada/sem_prag.ads3
-rw-r--r--gcc/ada/sem_res.adb312
-rw-r--r--gcc/ada/sem_type.adb16
-rw-r--r--gcc/ada/sem_util.adb835
-rw-r--r--gcc/ada/sem_util.ads165
-rw-r--r--gcc/ada/sinfo-utils.adb14
-rw-r--r--gcc/ada/sinfo-utils.ads2
-rw-r--r--gcc/ada/sinfo.ads4
-rw-r--r--gcc/ada/snames.adb-tmpl3
-rw-r--r--gcc/ada/snames.ads-tmpl45
-rw-r--r--gcc/ada/socket.c4
-rw-r--r--gcc/ada/sprint.adb12
-rw-r--r--gcc/ada/sysdep.c23
-rw-r--r--gcc/ada/treepr.adb94
-rw-r--r--gcc/ada/ttypes.ads2
-rw-r--r--gcc/ada/types.ads11
-rw-r--r--gcc/ada/uintp.adb344
-rw-r--r--gcc/ada/uintp.ads330
-rw-r--r--gcc/ada/usage.adb6
-rw-r--r--gcc/analyzer/ChangeLog120
-rw-r--r--gcc/analyzer/analyzer.h53
-rw-r--r--gcc/analyzer/call-info.cc162
-rw-r--r--gcc/analyzer/call-info.h83
-rw-r--r--gcc/analyzer/constraint-manager.cc9
-rw-r--r--gcc/analyzer/engine.cc272
-rw-r--r--gcc/analyzer/exploded-graph.h62
-rw-r--r--gcc/analyzer/program-state.cc6
-rw-r--r--gcc/analyzer/region-model-impl-calls.cc190
-rw-r--r--gcc/analyzer/region-model.cc30
-rw-r--r--gcc/analyzer/region-model.h36
-rw-r--r--gcc/analyzer/sm-malloc.cc136
-rw-r--r--gcc/analyzer/sm-signal.cc15
-rw-r--r--gcc/analyzer/sm.h5
-rw-r--r--gcc/analyzer/svalue.cc3
-rw-r--r--gcc/asan.h5
-rw-r--r--gcc/attribs.c34
-rw-r--r--gcc/attribs.h1
-rw-r--r--gcc/bitmap.c12
-rw-r--r--gcc/bitmap.h3
-rw-r--r--gcc/btfout.c10
-rw-r--r--gcc/builtins.c16
-rw-r--r--gcc/builtins.h2
-rw-r--r--gcc/c-family/ChangeLog173
-rw-r--r--gcc/c-family/c-ada-spec.c10
-rw-r--r--gcc/c-family/c-attribs.c96
-rw-r--r--gcc/c-family/c-common.c53
-rw-r--r--gcc/c-family/c-common.h5
-rw-r--r--gcc/c-family/c-cppbuiltin.c49
-rw-r--r--gcc/c-family/c-format.c29
-rw-r--r--gcc/c-family/c-format.h14
-rw-r--r--gcc/c-family/c-omp.c391
-rw-r--r--gcc/c-family/c-opts.c7
-rw-r--r--gcc/c-family/c-ubsan.c49
-rw-r--r--gcc/c-family/c-warn.c32
-rw-r--r--gcc/c-family/c.opt13
-rw-r--r--gcc/c/ChangeLog130
-rw-r--r--gcc/c/c-decl.c52
-rw-r--r--gcc/c/c-parser.c861
-rw-r--r--gcc/c/c-tree.h4
-rw-r--r--gcc/c/c-typeck.c186
-rw-r--r--gcc/c/gimple-parser.c22
-rw-r--r--gcc/cfgcleanup.c8
-rw-r--r--gcc/cfghooks.c13
-rw-r--r--gcc/cgraph.c4
-rw-r--r--gcc/collect-utils.c37
-rw-r--r--gcc/collect-utils.h1
-rw-r--r--gcc/collect2.c43
-rw-r--r--gcc/combine.c35
-rw-r--r--gcc/common.opt62
-rw-r--r--gcc/common/config/arm/arm-common.c10
-rw-r--r--gcc/common/config/avr/avr-common.c3
-rw-r--r--gcc/common/config/i386/cpuinfo.h50
-rw-r--r--gcc/common/config/i386/i386-common.c28
-rw-r--r--gcc/common/config/i386/i386-cpuinfo.h9
-rw-r--r--gcc/common/config/i386/i386-isas.h6
-rw-r--r--gcc/config.gcc143
-rw-r--r--gcc/config.in51
-rw-r--r--gcc/config/aarch64/aarch64-arches.def2
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c57
-rw-r--r--gcc/config/aarch64/aarch64-cores.def9
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def3
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def4
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc1
-rw-r--r--gcc/config/aarch64/aarch64-sve.md154
-rw-r--r--gcc/config/aarch64/aarch64-tune.md2
-rw-r--r--gcc/config/aarch64/aarch64.c317
-rw-r--r--gcc/config/aarch64/aarch64.h23
-rw-r--r--gcc/config/aarch64/arm_neon.h36
-rw-r--r--gcc/config/alpha/alpha.c2
-rw-r--r--gcc/config/alpha/vms.h12
-rw-r--r--gcc/config/arc/arc.c4
-rw-r--r--gcc/config/arc/arc.md8
-rw-r--r--gcc/config/arm/arm-cpus.in10
-rw-r--r--gcc/config/arm/arm-tables.opt3
-rw-r--r--gcc/config/arm/arm-tune.md2
-rw-r--r--gcc/config/arm/arm.c135
-rw-r--r--gcc/config/arm/arm.md16
-rw-r--r--gcc/config/arm/mve.md16
-rw-r--r--gcc/config/arm/vec-common.md4
-rw-r--r--gcc/config/avr/avr-mcus.def1
-rw-r--r--gcc/config/avr/elf.h3
-rw-r--r--gcc/config/bfin/bfin.c5
-rw-r--r--gcc/config/bfin/bfin.md27
-rw-r--r--gcc/config/bpf/bpf-opts.h7
-rw-r--r--gcc/config/bpf/bpf-passes.def20
-rw-r--r--gcc/config/bpf/bpf-protos.h3
-rw-r--r--gcc/config/bpf/bpf.c657
-rw-r--r--gcc/config/bpf/bpf.md58
-rw-r--r--gcc/config/bpf/bpf.opt33
-rw-r--r--gcc/config/bpf/coreout.c356
-rw-r--r--gcc/config/bpf/coreout.h114
-rw-r--r--gcc/config/bpf/t-bpf8
-rw-r--r--gcc/config/c6x/c6x.c3
-rw-r--r--gcc/config/cris/cris.h18
-rw-r--r--gcc/config/csky/csky.c7
-rw-r--r--gcc/config/darwin-driver.c82
-rw-r--r--gcc/config/darwin.c82
-rw-r--r--gcc/config/darwin.h339
-rw-r--r--gcc/config/darwin.opt155
-rw-r--r--gcc/config/dbx.h32
-rw-r--r--gcc/config/dbxcoff.h6
-rw-r--r--gcc/config/frv/frv.c5
-rw-r--r--gcc/config/gcn/gcn-hsa.h60
-rw-r--r--gcc/config/gcn/gcn-protos.h3
-rw-r--r--gcc/config/gcn/gcn-tree.c57
-rw-r--r--gcc/config/gcn/gcn-valu.md16
-rw-r--r--gcc/config/gcn/gcn.c148
-rw-r--r--gcc/config/gcn/gcn.h6
-rw-r--r--gcc/config/gcn/gcn.opt6
-rw-r--r--gcc/config/gcn/mkoffload.c140
-rw-r--r--gcc/config/h8300/bitfield.md11
-rw-r--r--gcc/config/h8300/h8300-protos.h1
-rw-r--r--gcc/config/h8300/h8300.c24
-rw-r--r--gcc/config/h8300/h8300.md9
-rw-r--r--gcc/config/h8300/testcompare.md196
-rw-r--r--gcc/config/i386/amxbf16intrin.h2
-rw-r--r--gcc/config/i386/amxint8intrin.h2
-rw-r--r--gcc/config/i386/amxtileintrin.h2
-rw-r--r--gcc/config/i386/avx512fp16intrin.h7157
-rw-r--r--gcc/config/i386/avx512fp16vlintrin.h3319
-rw-r--r--gcc/config/i386/cpuid.h1
-rw-r--r--gcc/config/i386/cygming.h9
-rw-r--r--gcc/config/i386/darwin.h25
-rw-r--r--gcc/config/i386/djgpp.h2
-rw-r--r--gcc/config/i386/i386-builtin-types.def85
-rw-r--r--gcc/config/i386/i386-builtin.def277
-rw-r--r--gcc/config/i386/i386-builtins.c45
-rw-r--r--gcc/config/i386/i386-c.c2
-rw-r--r--gcc/config/i386/i386-expand.c634
-rw-r--r--gcc/config/i386/i386-features.c63
-rw-r--r--gcc/config/i386/i386-isa.def1
-rw-r--r--gcc/config/i386/i386-modes.def15
-rw-r--r--gcc/config/i386/i386-options.c12
-rw-r--r--gcc/config/i386/i386-protos.h9
-rw-r--r--gcc/config/i386/i386.c428
-rw-r--r--gcc/config/i386/i386.h53
-rw-r--r--gcc/config/i386/i386.md793
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/immintrin.h6
-rw-r--r--gcc/config/i386/lynx.h4
-rw-r--r--gcc/config/i386/mmx.md153
-rw-r--r--gcc/config/i386/sse.md3222
-rw-r--r--gcc/config/i386/subst.md116
-rw-r--r--gcc/config/i386/vxworks.h24
-rw-r--r--gcc/config/i386/x86-tune-costs.h124
-rw-r--r--gcc/config/i386/x86-tune-sched.c2
-rw-r--r--gcc/config/i386/x86-tune.def63
-rw-r--r--gcc/config/ia64/ia64.c6
-rw-r--r--gcc/config/lm32/uclinux-elf.h1
-rw-r--r--gcc/config/lynx.h7
-rw-r--r--gcc/config/m32c/m32c.c3
-rw-r--r--gcc/config/m32r/linux.h91
-rw-r--r--gcc/config/m32r/m32r.c3
-rw-r--r--gcc/config/m32r/m32r.h28
-rw-r--r--gcc/config/m32r/t-linux20
-rw-r--r--gcc/config/m68k/m68k.c9
-rw-r--r--gcc/config/microblaze/microblaze.c3
-rw-r--r--gcc/config/mips/mips-cpus.def228
-rw-r--r--gcc/config/mips/mips.c51
-rw-r--r--gcc/config/mips/mips.h84
-rw-r--r--gcc/config/mips/netbsd.h5
-rw-r--r--gcc/config/mn10300/linux.h2
-rw-r--r--gcc/config/mn10300/mn10300.h3
-rw-r--r--gcc/config/nios2/nios2.c3
-rw-r--r--gcc/config/nvptx/nvptx.c4
-rw-r--r--gcc/config/pa/pa.c10
-rw-r--r--gcc/config/pa/pa.md193
-rw-r--r--gcc/config/pa/som.h4
-rw-r--r--gcc/config/pdp11/pdp11.h3
-rw-r--r--gcc/config/pru/constraints.md5
-rw-r--r--gcc/config/pru/predicates.md19
-rw-r--r--gcc/config/pru/pru-pragma.c2
-rw-r--r--gcc/config/pru/pru-protos.h3
-rw-r--r--gcc/config/pru/pru.c156
-rw-r--r--gcc/config/pru/pru.h5
-rw-r--r--gcc/config/pru/pru.md102
-rw-r--r--gcc/config/riscv/riscv.c11
-rw-r--r--gcc/config/riscv/riscv.md10
-rw-r--r--gcc/config/rs6000/aix71.h6
-rw-r--r--gcc/config/rs6000/aix72.h6
-rw-r--r--gcc/config/rs6000/aix73.h6
-rw-r--r--gcc/config/rs6000/altivec.h2
-rw-r--r--gcc/config/rs6000/darwin.h13
-rw-r--r--gcc/config/rs6000/lynx.h1
-rw-r--r--gcc/config/rs6000/mma.md31
-rw-r--r--gcc/config/rs6000/nmmintrin.h40
-rw-r--r--gcc/config/rs6000/rs6000-builtin-new.def160
-rw-r--r--gcc/config/rs6000/rs6000-c.c1078
-rw-r--r--gcc/config/rs6000/rs6000-call.c1411
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def4
-rw-r--r--gcc/config/rs6000/rs6000-gen-builtins.c44
-rw-r--r--gcc/config/rs6000/rs6000-logue.c15
-rw-r--r--gcc/config/rs6000/rs6000-overload.def4
-rw-r--r--gcc/config/rs6000/rs6000.c581
-rw-r--r--gcc/config/rs6000/rs6000.md36
-rw-r--r--gcc/config/rs6000/rs6000.opt46
-rw-r--r--gcc/config/rs6000/rtems.h4
-rw-r--r--gcc/config/rs6000/smmintrin.h265
-rw-r--r--gcc/config/rs6000/sysv4.h8
-rw-r--r--gcc/config/rs6000/t-rs600017
-rw-r--r--gcc/config/rs6000/vxworks.h6
-rw-r--r--gcc/config/rx/rx.h8
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c86
-rw-r--r--gcc/config/s390/s390.md7
-rw-r--r--gcc/config/s390/tpf.md6
-rw-r--r--gcc/config/s390/vector.md26
-rw-r--r--gcc/config/s390/vx-builtins.md26
-rw-r--r--gcc/config/sh/linux.h4
-rw-r--r--gcc/config/sh/netbsd-elf.h2
-rw-r--r--gcc/config/sh/sh.c12
-rw-r--r--gcc/config/sol2.c3
-rw-r--r--gcc/config/sparc/leon5.md103
-rw-r--r--gcc/config/sparc/sparc-modes.def3
-rw-r--r--gcc/config/sparc/sparc-opts.h1
-rw-r--r--gcc/config/sparc/sparc.c195
-rw-r--r--gcc/config/sparc/sparc.h36
-rw-r--r--gcc/config/sparc/sparc.md12
-rw-r--r--gcc/config/sparc/sparc.opt3
-rw-r--r--gcc/config/tilegx/tilegx.c3
-rw-r--r--gcc/config/visium/visium.c2
-rw-r--r--gcc/config/vxworks.c5
-rw-r--r--gcc/config/xtensa/t-xtensa1
-rw-r--r--gcc/config/xtensa/xtensa.c3
-rwxr-xr-xgcc/configure336
-rw-r--r--gcc/configure.ac149
-rw-r--r--gcc/coretypes.h3
-rw-r--r--gcc/coverage.c50
-rw-r--r--gcc/cp/ChangeLog703
-rw-r--r--gcc/cp/call.c334
-rw-r--r--gcc/cp/class.c38
-rw-r--r--gcc/cp/constexpr.c218
-rw-r--r--gcc/cp/constraint.cc8
-rw-r--r--gcc/cp/coroutines.cc917
-rw-r--r--gcc/cp/cp-gimplify.c4
-rw-r--r--gcc/cp/cp-tree.h40
-rw-r--r--gcc/cp/decl.c188
-rw-r--r--gcc/cp/decl.h3
-rw-r--r--gcc/cp/decl2.c75
-rw-r--r--gcc/cp/init.c11
-rw-r--r--gcc/cp/method.c245
-rw-r--r--gcc/cp/module.cc12
-rw-r--r--gcc/cp/name-lookup.c14
-rw-r--r--gcc/cp/parser.c1065
-rw-r--r--gcc/cp/pt.c312
-rw-r--r--gcc/cp/ptree.c10
-rw-r--r--gcc/cp/rtti.c95
-rw-r--r--gcc/cp/semantics.c90
-rw-r--r--gcc/cp/tree.c13
-rw-r--r--gcc/cp/typeck.c156
-rw-r--r--gcc/cp/typeck2.c31
-rw-r--r--gcc/cppbuiltin.c10
-rw-r--r--gcc/cse.c48
-rw-r--r--gcc/ctfc.c27
-rw-r--r--gcc/ctfc.h10
-rw-r--r--gcc/d/ChangeLog93
-rw-r--r--gcc/d/d-attribs.cc8
-rw-r--r--gcc/d/d-builtins.cc4
-rw-r--r--gcc/d/d-codegen.cc186
-rw-r--r--gcc/d/d-convert.cc4
-rw-r--r--gcc/d/d-lang.cc10
-rw-r--r--gcc/d/d-spec.cc49
-rw-r--r--gcc/d/d-tree.h8
-rw-r--r--gcc/d/expr.cc58
-rw-r--r--gcc/d/runtime.cc5
-rw-r--r--gcc/d/runtime.def24
-rw-r--r--gcc/d/toir.cc2
-rw-r--r--gcc/d/typeinfo.cc9
-rw-r--r--gcc/d/types.cc3
-rw-r--r--gcc/dbgcnt.c10
-rw-r--r--gcc/dbgcnt.h1
-rw-r--r--gcc/defaults.h44
-rw-r--r--gcc/diagnostic-spec.c24
-rw-r--r--gcc/diagnostic-spec.h6
-rw-r--r--gcc/doc/avr-mmcu.texi2
-rw-r--r--gcc/doc/cpp.texi18
-rw-r--r--gcc/doc/extend.texi147
-rw-r--r--gcc/doc/install.texi16
-rw-r--r--gcc/doc/invoke.texi350
-rw-r--r--gcc/doc/md.texi17
-rw-r--r--gcc/doc/rtl.texi12
-rw-r--r--gcc/doc/tm.texi23
-rw-r--r--gcc/doc/tm.texi.in5
-rw-r--r--gcc/doc/trouble.texi7
-rw-r--r--gcc/dumpfile.c1
-rw-r--r--gcc/dumpfile.h52
-rw-r--r--gcc/dwarf2ctf.c58
-rw-r--r--gcc/dwarf2ctf.h4
-rw-r--r--gcc/dwarf2out.c88
-rw-r--r--gcc/dwarf2out.h1
-rw-r--r--gcc/emit-rtl.c23
-rw-r--r--gcc/explow.c9
-rw-r--r--gcc/expmed.c9
-rw-r--r--gcc/expr.c45
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/flag-types.h20
-rw-r--r--gcc/flags.h4
-rw-r--r--gcc/fortran/ChangeLog416
-rw-r--r--gcc/fortran/array.c5
-rw-r--r--gcc/fortran/check.c22
-rw-r--r--gcc/fortran/cpp.c111
-rw-r--r--gcc/fortran/cpp.h4
-rw-r--r--gcc/fortran/decl.c113
-rw-r--r--gcc/fortran/dump-parse-tree.c13
-rw-r--r--gcc/fortran/expr.c51
-rw-r--r--gcc/fortran/f95-lang.c4
-rw-r--r--gcc/fortran/gfortran.h117
-rw-r--r--gcc/fortran/interface.c148
-rw-r--r--gcc/fortran/intrinsic.c7
-rw-r--r--gcc/fortran/intrinsic.texi8
-rw-r--r--gcc/fortran/iso-c-binding.def2
-rw-r--r--gcc/fortran/match.c2
-rw-r--r--gcc/fortran/match.h1
-rw-r--r--gcc/fortran/misc.c10
-rw-r--r--gcc/fortran/module.c66
-rw-r--r--gcc/fortran/openmp.c592
-rw-r--r--gcc/fortran/options.c42
-rw-r--r--gcc/fortran/parse.c29
-rw-r--r--gcc/fortran/primary.c17
-rw-r--r--gcc/fortran/resolve.c59
-rw-r--r--gcc/fortran/scanner.c155
-rw-r--r--gcc/fortran/scanner.h2
-rw-r--r--gcc/fortran/simplify.c44
-rw-r--r--gcc/fortran/symbol.c1
-rw-r--r--gcc/fortran/trans-array.c316
-rw-r--r--gcc/fortran/trans-array.h18
-rw-r--r--gcc/fortran/trans-decl.c1066
-rw-r--r--gcc/fortran/trans-expr.c767
-rw-r--r--gcc/fortran/trans-intrinsic.c252
-rw-r--r--gcc/fortran/trans-openmp.c231
-rw-r--r--gcc/fortran/trans-stmt.c51
-rw-r--r--gcc/fortran/trans-stmt.h1
-rw-r--r--gcc/fortran/trans-types.c110
-rw-r--r--gcc/fortran/trans-types.h5
-rw-r--r--gcc/fortran/trans.c11
-rw-r--r--gcc/fortran/trans.h8
-rw-r--r--gcc/function.h9
-rw-r--r--gcc/gcc-rich-location.h6
-rw-r--r--gcc/gcc.c59
-rw-r--r--gcc/gcov-dump.c9
-rw-r--r--gcc/gcov.c36
-rw-r--r--gcc/gengtype.c4
-rw-r--r--gcc/gimple-fold.c77
-rw-r--r--gcc/gimple-fold.h1
-rw-r--r--gcc/gimple-isel.cc3
-rw-r--r--gcc/gimple-iterator.c4
-rw-r--r--gcc/gimple-iterator.h4
-rw-r--r--gcc/gimple-loop-jam.c3
-rw-r--r--gcc/gimple-match-head.c4
-rw-r--r--gcc/gimple-predicate-analysis.cc2404
-rw-r--r--gcc/gimple-predicate-analysis.h158
-rw-r--r--gcc/gimple-pretty-print.c25
-rw-r--r--gcc/gimple-range-cache.cc23
-rw-r--r--gcc/gimple-range-cache.h2
-rw-r--r--gcc/gimple-range-edge.cc7
-rw-r--r--gcc/gimple-range-edge.h3
-rw-r--r--gcc/gimple-range-fold.cc221
-rw-r--r--gcc/gimple-range-fold.h5
-rw-r--r--gcc/gimple-range-gori.cc32
-rw-r--r--gcc/gimple-range-gori.h7
-rw-r--r--gcc/gimple-range-path.cc443
-rw-r--r--gcc/gimple-range-path.h34
-rw-r--r--gcc/gimple-range-trace.cc31
-rw-r--r--gcc/gimple-range-trace.h17
-rw-r--r--gcc/gimple-range.cc60
-rw-r--r--gcc/gimple-range.h2
-rw-r--r--gcc/gimple-ssa-evrp-analyze.h7
-rw-r--r--gcc/gimple-ssa-evrp.c349
-rw-r--r--gcc/gimple-ssa-store-merging.c27
-rw-r--r--gcc/gimple-ssa-warn-access.cc439
-rw-r--r--gcc/gimple-ssa-warn-access.h1
-rw-r--r--gcc/gimple-ssa-warn-alloca.c7
-rw-r--r--gcc/gimple.c4
-rw-r--r--gcc/gimple.h28
-rw-r--r--gcc/gimplify.c423
-rw-r--r--gcc/go/ChangeLog5
-rw-r--r--gcc/go/go-lang.c1
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc2
-rw-r--r--gcc/go/gofrontend/expressions.h4
-rw-r--r--gcc/go/gofrontend/types.cc80
-rw-r--r--gcc/go/gofrontend/types.h30
-rw-r--r--gcc/graph.c9
-rw-r--r--gcc/hash-map-tests.c10
-rw-r--r--gcc/hash-table.h3
-rw-r--r--gcc/input.c9
-rw-r--r--gcc/internal-fn.c128
-rw-r--r--gcc/internal-fn.def7
-rw-r--r--gcc/ipa-cp.c161
-rw-r--r--gcc/ipa-fnsummary.c1
-rw-r--r--gcc/ipa-inline.c17
-rw-r--r--gcc/ipa-modref-tree.h333
-rw-r--r--gcc/ipa-modref.c42
-rw-r--r--gcc/ipa-modref.h13
-rw-r--r--gcc/ipa-prop.c40
-rw-r--r--gcc/ipa-sra.c40
-rw-r--r--gcc/ira-build.c13
-rw-r--r--gcc/jit/ChangeLog8
-rw-r--r--gcc/jit/jit-playback.c70
-rw-r--r--gcc/jit/jit-playback.h5
-rw-r--r--gcc/lra-constraints.c9
-rw-r--r--gcc/lto-compress.c4
-rw-r--r--gcc/lto-opts.c8
-rw-r--r--gcc/lto-streamer-out.c5
-rw-r--r--gcc/lto-wrapper.c28
-rw-r--r--gcc/lto/ChangeLog16
-rw-r--r--gcc/lto/lto-common.c1
-rw-r--r--gcc/lto/lto-lang.c4
-rw-r--r--gcc/match.pd189
-rw-r--r--gcc/objc/ChangeLog40
-rw-r--r--gcc/objc/objc-act.c81
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c3
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c34
-rw-r--r--gcc/objcp/ChangeLog5
-rw-r--r--gcc/objcp/Make-lang.in1
-rw-r--r--gcc/omp-expand.c354
-rw-r--r--gcc/omp-general.c167
-rw-r--r--gcc/omp-general.h5
-rw-r--r--gcc/omp-low.c229
-rw-r--r--gcc/omp-oacc-neuter-broadcast.cc575
-rw-r--r--gcc/omp-offload.c3
-rw-r--r--gcc/optabs.c11
-rw-r--r--gcc/optabs.def2
-rw-r--r--gcc/opts.c44
-rw-r--r--gcc/opts.h4
-rw-r--r--gcc/output.h85
-rw-r--r--gcc/params.opt36
-rw-r--r--gcc/passes.def6
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/sv.po6
-rw-r--r--gcc/pointer-query.cc207
-rw-r--r--gcc/pointer-query.h3
-rw-r--r--gcc/poly-int.h4
-rw-r--r--gcc/predict.c37
-rw-r--r--gcc/predict.h1
-rw-r--r--gcc/print-tree.c2
-rw-r--r--gcc/range-op.cc72
-rw-r--r--gcc/read-md.c21
-rw-r--r--gcc/real.c6
-rw-r--r--gcc/rtl.def5
-rw-r--r--gcc/simplify-rtx.c144
-rw-r--r--gcc/symbol-summary.h4
-rw-r--r--gcc/target.def23
-rw-r--r--gcc/targhooks.c8
-rw-r--r--gcc/testsuite/ChangeLog3387
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-3.c125
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-4.c106
-rw-r--r--gcc/testsuite/c-c++-common/Warray-compare-1.c44
-rw-r--r--gcc/testsuite/c-c++-common/Warray-compare-2.c44
-rw-r--r--gcc/testsuite/c-c++-common/Wstringop-overflow-2.c20
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-1.c41
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-10.c22
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-11.c14
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-12.c14
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-13.c23
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-14.c23
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-15.c13
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-16.c13
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-2.c41
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-3.c19
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-4.c19
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-5.c21
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-6.c21
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-7.c35
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-8.c35
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-9.c20
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-esra.c35
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-padding-1.c23
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-padding-2.c114
-rw-r--r--gcc/testsuite/c-c++-common/auto-init-padding-3.c114
-rw-r--r--gcc/testsuite/c-c++-common/cpp/va-opt-3.c8
-rw-r--r--gcc/testsuite/c-c++-common/cpp/va-opt-7.c101
-rw-r--r--gcc/testsuite/c-c++-common/goacc-gomp/atomic.c3
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-6.c84
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-7.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-17.c10
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-18.c20
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-21.c3
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-25.c50
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-26.c63
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-27.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-28.c43
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-29.c44
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-30.c142
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clause-dups-1.c32
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-1.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/default-2.c67
-rw-r--r--gcc/testsuite/c-c++-common/gomp/default-3.c14
-rw-r--r--gcc/testsuite/c-c++-common/gomp/flush-1.c9
-rw-r--r--gcc/testsuite/c-c++-common/gomp/flush-2.c7
-rw-r--r--gcc/testsuite/c-c++-common/gomp/order-1.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/order-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/order-5.c101
-rw-r--r--gcc/testsuite/c-c++-common/gomp/order-6.c412
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr102640.c44
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scope-3.c21
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scope-4.c11
-rw-r--r--gcc/testsuite/c-c++-common/gomp/sections1.c22
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-1.c32
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-2.c14
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-ancestor-1.c13
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-ancestor-2.c82
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c37
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c17
-rw-r--r--gcc/testsuite/c-c++-common/pr102285.c10
-rw-r--r--gcc/testsuite/c-c++-common/pr19807-2.c5
-rw-r--r--gcc/testsuite/c-c++-common/pr19807-3.c5
-rw-r--r--gcc/testsuite/c-c++-common/pr57371-4.c8
-rw-r--r--gcc/testsuite/c-c++-common/tsan/atomic_stack.c3
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c18
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c17
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c41
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c41
-rw-r--r--gcc/testsuite/g++.dg/Walloca2.C6
-rw-r--r--gcc/testsuite/g++.dg/abi/anon4.C1
-rw-r--r--gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C3
-rw-r--r--gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C3
-rw-r--r--gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C3
-rw-r--r--gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C3
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr100673.C18
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr101133.C31
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr101765.C45
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr102454.C38
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr99575.C35
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr99710.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-3.C62
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-4.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-5.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-6.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp/elifdef-7.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty17.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-inst1.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype29.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist125.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist126.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr102305.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-label.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction12.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction99.C35
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype4.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype4a.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C68
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp23/lookup2.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize1.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize2.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize3.C80
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize4.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize5.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize6.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp23/normalize7.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ucnid-1-utf8.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ucnid-2-utf8.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias11.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-lambda14.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval3.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-float2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C20
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/constexpr1.C6
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/static_assert4.C30
-rw-r--r--gcc/testsuite/g++.dg/eh/arm-vfp-unwind.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-1.C113
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-2.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-3.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-4.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-5.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-6.C110
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-7.C19
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-8.C17
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-unavailable-9.C17
-rw-r--r--gcc/testsuite/g++.dg/ext/conv2.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/flexary39.C65
-rw-r--r--gcc/testsuite/g++.dg/ext/flexary40.C50
-rw-r--r--gcc/testsuite/g++.dg/ext/is_constructible6.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C17
-rw-r--r--gcc/testsuite/g++.dg/ext/vla22.C2
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov.py5
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-4.C108
-rw-r--r--gcc/testsuite/g++.dg/gomp/atomic-18.C3
-rw-r--r--gcc/testsuite/g++.dg/gomp/atomic-20.C104
-rw-r--r--gcc/testsuite/g++.dg/gomp/atomic-5.C2
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-1.C49
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-14.C4
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-2.C49
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-6.C53
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-7.C20
-rw-r--r--gcc/testsuite/g++.dg/gomp/default-1.C112
-rw-r--r--gcc/testsuite/g++.dg/gomp/sections-2.C4
-rw-r--r--gcc/testsuite/g++.dg/gomp/simd-3.C16
-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/parse/pr101783.C5
-rw-r--r--gcc/testsuite/g++.dg/pr101331.C7
-rw-r--r--gcc/testsuite/g++.dg/pr102359_1.C13
-rw-r--r--gcc/testsuite/g++.dg/pr102359_2.C13
-rw-r--r--gcc/testsuite/g++.dg/pr102360.C54
-rw-r--r--gcc/testsuite/g++.dg/pr88173-1.C9
-rw-r--r--gcc/testsuite/g++.dg/pr88173-2.C9
-rw-r--r--gcc/testsuite/g++.dg/rtti/undeclared1.C5
-rw-r--r--gcc/testsuite/g++.dg/spellcheck-pr77565.C12
-rw-r--r--gcc/testsuite/g++.dg/template/access2.C6
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-15.C7
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-16.C6
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-17.C5
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-18.C6
-rw-r--r--gcc/testsuite/g++.dg/template/conv17.C63
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name15.C18
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name16.C14
-rw-r--r--gcc/testsuite/g++.dg/template/dtor11.C22
-rw-r--r--gcc/testsuite/g++.dg/template/dtor5.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error56.C4
-rw-r--r--gcc/testsuite/g++.dg/template/explicit-args6.C34
-rw-r--r--gcc/testsuite/g++.dg/template/explicit-args7.C33
-rw-r--r--gcc/testsuite/g++.dg/template/fnspec2.C9
-rw-r--r--gcc/testsuite/g++.dg/template/param6.C32
-rw-r--r--gcc/testsuite/g++.dg/template/parm-cv1.C15
-rw-r--r--gcc/testsuite/g++.dg/template/parm-cv2.C23
-rw-r--r--gcc/testsuite/g++.dg/template/parm-cv3.C142
-rw-r--r--gcc/testsuite/g++.dg/tls/pr102496-1.C20
-rw-r--r--gcc/testsuite/g++.dg/tls/pr102496-2.C6
-rw-r--r--gcc/testsuite/g++.dg/torture/pr10148.C52
-rw-r--r--gcc/testsuite/g++.dg/torture/pr102142.C9
-rw-r--r--gcc/testsuite/g++.dg/torture/pr102581.C51
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr81408.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr94403.C2
-rw-r--r--gcc/testsuite/g++.dg/vect/pr102226.cc29
-rw-r--r--gcc/testsuite/g++.dg/vect/pr102421.cc34
-rw-r--r--gcc/testsuite/g++.dg/vect/pr102572.cc14
-rw-r--r--gcc/testsuite/g++.dg/vect/pr102696.cc16
-rw-r--r--gcc/testsuite/g++.dg/vect/pr102788.cc32
-rw-r--r--gcc/testsuite/g++.dg/warn/Waddress-5.C115
-rw-r--r--gcc/testsuite/g++.dg/warn/Waddress-6.C79
-rw-r--r--gcc/testsuite/g++.dg/warn/Winit-list5.C61
-rw-r--r--gcc/testsuite/g++.dg/warn/Winterference-2.C14
-rw-r--r--gcc/testsuite/g++.dg/warn/Winterference.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/Winterference.H7
-rw-r--r--gcc/testsuite/g++.dg/warn/Wlogical-op-3.C12
-rw-r--r--gcc/testsuite/g++.dg/warn/Wplacement-new-size-10.C13
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-13.C5
-rw-r--r--gcc/testsuite/g++.dg/warn/pr101219.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/uninit-pr93100.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/nontype5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/unify6.C4
-rw-r--r--gcc/testsuite/g++.target/aarch64/interference.C9
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/pr102252.C37
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/static-var-in-template.C17
-rw-r--r--gcc/testsuite/g++.target/arm/interference.C9
-rw-r--r--gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C25
-rw-r--r--gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C70
-rw-r--r--gcc/testsuite/g++.target/i386/float16-1.C8
-rw-r--r--gcc/testsuite/g++.target/i386/float16-2.C14
-rw-r--r--gcc/testsuite/g++.target/i386/float16-3.C10
-rw-r--r--gcc/testsuite/g++.target/i386/interference.C8
-rw-r--r--gcc/testsuite/g++.target/i386/mv30.C50
-rw-r--r--gcc/testsuite/g++.target/i386/pr102166.C20
-rw-r--r--gcc/testsuite/g++.target/i386/pr102295.C12
-rw-r--r--gcc/testsuite/g++.target/i386/pr102548.C12
-rw-r--r--gcc/testsuite/g++.target/i386/pr102639.C19
-rw-r--r--gcc/testsuite/g++.target/i386/pr80566-1.C2
-rw-r--r--gcc/testsuite/g++.target/i386/pr80566-2.C2
-rw-r--r--gcc/testsuite/g++.target/powerpc/pr102024.C23
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920826-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920831-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr100316.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr27863.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr70190.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/bitfld-10.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr102134.c23
-rw-r--r--gcc/testsuite/gcc.dg/Waddress-3.c35
-rw-r--r--gcc/testsuite/gcc.dg/Waddress.c2
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-51.c5
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-89.c139
-rw-r--r--gcc/testsuite/gcc.dg/Warray-parameter-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wint-in-bool-context-4.c35
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-11.c8
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-12.c6
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-14.c7
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-21.c8
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-43.c9
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-62.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-68.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-70.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-73.c35
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-74.c22
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-75.c133
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-76.c148
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/capacity-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr99193-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr99193-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/realloc-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/realloc-2.c80
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/strndup-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/pr102225.c6
-rw-r--r--gcc/testsuite/gcc.dg/array-quals-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/associative-math-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/associative-math-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-1.c88
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-3.c10
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-4.c88
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-5.c6
-rw-r--r--gcc/testsuite/gcc.dg/attr-unavailable-6.c11
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-hardreg-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-sra-1.c24
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-sra-2.c24
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-12.c4
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-13.c10
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-14.c4
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-15.c26
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-16.c25
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-17.c15
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-18.c3
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-19.c26
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-20.c4
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-21.c4
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-22.c3
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-23.c27
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-24.c3
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-25.c23
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-26.c23
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-3.c5
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-34.c60
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-36.c238
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-37.c156
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-4.c10
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-5.c6
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-6.c7
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-8.c8
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-9.c8
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-A.c7
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-B.c17
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-C.c5
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-H.c5
-rw-r--r--gcc/testsuite/gcc.dg/auto-init-uninit-I.c3
-rw-r--r--gcc/testsuite/gcc.dg/comp-goto-5.c11
-rw-r--r--gcc/testsuite/gcc.dg/comp-goto-6.c6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c63
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c65
-rw-r--r--gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c65
-rw-r--r--gcc/testsuite/gcc.dg/cpp/ucnid-4-utf8.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/ucnid-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/ucnid-5-utf8.c17
-rw-r--r--gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c26
-rw-r--r--gcc/testsuite/gcc.dg/fold-negate-1.c58
-rw-r--r--gcc/testsuite/gcc.dg/format/c11-dfp-printf-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/format/c11-dfp-scanf-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/format/c11-printf-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/format/c11-scanf-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/format/c2x-dfp-printf-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/format/c2x-dfp-scanf-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/format/c2x-printf-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/format/c2x-scanf-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/format/ext-10.c13
-rw-r--r--gcc/testsuite/gcc.dg/format/ext-9.c29
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-46.c23
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-47.c27
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-error-12.c10
-rw-r--r--gcc/testsuite/gcc.dg/gomp/atomic-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr46032-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr46032-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/sections-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/graphite/fuse-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/guality/example.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/inline-8.c4
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr102714.c117
-rw-r--r--gcc/testsuite/gcc.dg/no-signed-zeros-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/no-signed-zeros-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/no-trapping-math-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/no-trapping-math-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapsi-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapsi-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/out-of-bounds-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr102087.c35
-rw-r--r--gcc/testsuite/gcc.dg/pr102141.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr102152.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr102207.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr102224.c49
-rw-r--r--gcc/testsuite/gcc.dg/pr102269.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr102273.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr102385.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr102463.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr102511.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr102738.c49
-rw-r--r--gcc/testsuite/gcc.dg/pr102798.c41
-rw-r--r--gcc/testsuite/gcc.dg/pr67089-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr78408-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr79412.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr82929-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr82929.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr89984.c20
-rw-r--r--gcc/testsuite/gcc.dg/pr91441.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr94726.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr96260.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr96307.c2
-rw-r--r--gcc/testsuite/gcc.dg/reciprocal-math-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/reciprocal-math-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/rounding-math-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/rounding-math-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_1.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_11.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_13.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_15.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_16.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_19.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_24.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_25.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_28.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_30.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_5.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_7.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_8.c2
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-85.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/20210916.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102124.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102139.c43
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102149.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102518.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102762.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr55107.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr69760.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr89135.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90071.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr93491.c24
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/dump-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/evrp-ignore.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-1.c72
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-2.c83
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-1.c100
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-2.c58
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-3.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-9.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr102546.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr102563.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr102736.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21417.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21559.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr47059.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr59597.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr68198.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr70232.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr71437.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr77445.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr86017.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr88087.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr91482.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr99473-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr99793.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ranger-threader-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h33
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c39
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-19.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-16.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-17.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c39
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp106.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp55.c6
-rw-r--r--gcc/testsuite/gcc.dg/typedef-var-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/uninit-15-O0.c2
-rw-r--r--gcc/testsuite/gcc.dg/uninit-15.c2
-rw-r--r--gcc/testsuite/gcc.dg/uninit-40.c2
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr102403-c2.c34
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr102403.c49
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr93100.c2
-rw-r--r--gcc/testsuite/gcc.dg/unroll-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-16.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr101145.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr101145_1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr101145_2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr101145_3.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr102318.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr65206.c22
-rw-r--r--gcc/testsuite/gcc.misc-tests/help.exp2
-rw-r--r--gcc/testsuite/gcc.misc-tests/linkage.exp12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-1.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-2.c35
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-3.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-4.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-5.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-6.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-7.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-8.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cpymem-size.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/lane-bound-1.c14
-rw-r--r--gcc/testsuite/gcc.target/aarch64/lane-bound-2.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_unary_4.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr93183.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-cond-reduc.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-1.c23
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-2.c23
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-3.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-4.c14
-rw-r--r--gcc/testsuite/gcc.target/arm/mve/mve.exp3
-rw-r--r--gcc/testsuite/gcc.target/arm/mve/mve_load_memory_modes.c357
-rw-r--r--gcc/testsuite/gcc.target/arm/mve/mve_store_memory_modes.c370
-rw-r--r--gcc/testsuite/gcc.target/arm/pr51534.c5
-rw-r--r--gcc/testsuite/gcc.target/bfin/ones.c11
-rw-r--r--gcc/testsuite/gcc.target/bfin/parity.c9
-rw-r--r--gcc/testsuite/gcc.target/bfin/popcount.c9
-rw-r--r--gcc/testsuite/gcc.target/bfin/ssabs.c11
-rw-r--r--gcc/testsuite/gcc.target/bfin/ssneg.c11
-rw-r--r--gcc/testsuite/gcc.target/bpf/alu-1.c56
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-attr-1.c23
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-attr-2.c21
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-attr-3.c41
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-attr-4.c35
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-1.c64
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-2.c26
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-3.c26
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-lto-1.c9
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-section-1.c38
-rw-r--r--gcc/testsuite/gcc.target/bpf/jmp-1.c57
-rw-r--r--gcc/testsuite/gcc.target/i386/387-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-3.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/attr-optimize.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-1.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-2.c37
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-21.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-22.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-23.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-24.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-4.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-5.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-6.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-7.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-8.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-10.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-11.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-12.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-3.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-4.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-5.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-6.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-7.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-8.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/auto-init-padding-9.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-1.c137
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-covert-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-fp-covert-1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-int-covert-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-pr102224.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-pr89984.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512-check.h3
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqb-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqw-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtb-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtw-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-abs-copysign-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqd-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqq-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtd-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtq-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-10a.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-10b.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-11a.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-11b.c75
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-12a.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-12b.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-13.c140
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-14.c85
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1b.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1c.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1d.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-1e.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-2a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-2b.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-2c.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-3a.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-3b.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-3c.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-4.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-5.c133
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-6.c57
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c75
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-7.c86
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-8.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-9a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-9b.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-2.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-builtin_shuffle-1.c86
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c34
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c69
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-helper.h284
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-neg-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-neg-1b.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c56
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-pr94680.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c132
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c96
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c91
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1a.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1b.c82
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-typecast-1.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-typecast-2.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-v4hf-concat.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1b.c92
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1b.c104
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vararg-1.c122
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vararg-2.c107
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vararg-3.c114
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vararg-4.c115
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1a.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1b.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1a.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1b.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1a.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1b.c66
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1c.c66
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c143
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1b.c82
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1b.c81
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1b.c84
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1b.c83
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1b.c84
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1b.c84
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1b.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1b.c57
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1b.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1b.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1b.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1b.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1b.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1b.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1b.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1b.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1b.c84
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1b.c83
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1b.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1b.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1b.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1b.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1b.c83
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1b.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1b.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1b.c93
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1b.c92
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1b.c97
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1b.c76
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vec_set_var.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1a.c121
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1b.c119
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c133
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1c.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c111
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c71
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1b.c160
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1b.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c131
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1c.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1b.c171
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1a.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1b.c155
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1b.c89
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1b.c175
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c115
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c71
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1b.c159
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1a.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1b.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1a.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1b.c157
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1b.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1b.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1b.c76
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1b.c99
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1b.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1b.c102
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1b.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1b.c94
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1b.c72
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1b.c93
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1b.c72
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1b.c115
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1a.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1b.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2a.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2b.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3a.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3b.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4b.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1b.c92
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1b.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1b.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1b.c57
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1b.c116
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1b.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1b.c101
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1b.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1b.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1b.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1a.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1b.c94
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1a.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1b.c58
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1b.c92
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1a.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1b.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1b.c93
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1b.c76
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-xorsign-1.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1b.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c244
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-1.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-2.c37
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1a.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1a.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1a.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1b.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1a.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1a.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1a.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1a.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1a.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1a.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1b.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-abs-copysign-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqd-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqq-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtd-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtq-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vlfp16-11a.c68
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vlfp16-11b.c96
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/bitwise_mask_op-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/bitwise_mask_op-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/builtin_target.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/eh_return-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-3a.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-3b.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-4a.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-4b.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-5.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-6.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/float16-7.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/funcspec-56.inc2
-rw-r--r--gcc/testsuite/gcc.target/i386/m512-check.h38
-rw-r--r--gcc/testsuite/gcc.target/i386/mmx-reduce-op-1.c58
-rw-r--r--gcc/testsuite/gcc.target/i386/mmx-reduce-op-2.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/mvc16.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memcpy-15.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-11.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-14.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-20.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-23.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-29.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-30.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-33.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-34.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-37.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-44.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pieces-memset-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-10a.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-4a.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101282.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101900-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101900-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101900-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102080.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102230.c38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102327-1.c65
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102327-2.c95
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102464.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102483-2.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102483.c58
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102498.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102627.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/pr34012.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49781-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-11.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-12.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-13.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85730.c95
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-1a.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-1b.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-2a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-2b.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-2c.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85819-3.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr89954.c45
-rw-r--r--gcc/testsuite/gcc.target/i386/pr89984-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr89984-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-20.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-21.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-22.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-23.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-26.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91103-1.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91103-2.c85
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx512f.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95798-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95798-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97950.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr99591.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c137
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c282
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c281
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c137
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-covert-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-int-covert-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-float16-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-float16-2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-float16-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c90
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-10.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-11.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-12.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-3.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-5.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-7.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-8.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-float16-9.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-pr82426.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-pr97352.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-rebuild.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xorsign-avx.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp1
-rw-r--r--gcc/testsuite/gcc.target/mips/msa-insert-split.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dform-1.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dform-2.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-call.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion-p10-stst.c31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion-p10-stst2.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr101985-1.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr101985-2.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr78102.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80510-2.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr97142.c35
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-packusdw.c73
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pcmpeqq.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-phminposuw.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsb.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsd.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxud.c47
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxuw.c47
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pminsb.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pminsd.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pminud.c47
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pminuw.c47
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbd.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbq.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbw.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxdq.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwd.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwq.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbd.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbq.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbw.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxdq.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwd.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwq.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmuldq.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_1-pmulld.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_2-check.h18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/unwind-backchain.c24
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c11
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-as-pointer.c11
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-2.c13
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-3.c19
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl-4.c17
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-decl.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-di.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-hi.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio-qi.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/regio.c58
-rw-r--r--gcc/testsuite/gcc.target/pru/regio.h7
-rw-r--r--gcc/testsuite/gcc.target/s390/pr102222.c16
-rw-r--r--gcc/testsuite/gcc.target/s390/pr80725.c2
-rw-r--r--gcc/testsuite/gcc.target/s390/rawmemchr-1.c99
-rw-r--r--gcc/testsuite/gcc.target/sparc/20210917-1.c19
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp48
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h190
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S81
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h74
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h3
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h166
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp45
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h182
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S81
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h3
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c54
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c370
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c113
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c337
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c160
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp48
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h186
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S97
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h4
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c62
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c380
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c123
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c415
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c164
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h53
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c794
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c45
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c43
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c87
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c43
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c42
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c40
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c104
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c73
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c1066
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c510
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c332
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c335
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c274
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c164
-rw-r--r--gcc/testsuite/gdc.dg/lto/pr102094_0.d18
-rw-r--r--gcc/testsuite/gdc.dg/pr102185.d7
-rw-r--r--gcc/testsuite/gdc.dg/pr102476.d3
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/PR100911.c82
-rw-r--r--gcc/testsuite/gfortran.dg/PR100911.f90282
-rw-r--r--gcc/testsuite/gfortran.dg/PR100914.c225
-rw-r--r--gcc/testsuite/gfortran.dg/PR100914.f90652
-rw-r--r--gcc/testsuite/gfortran.dg/PR100915.c80
-rw-r--r--gcc/testsuite/gfortran.dg/PR100915.f90273
-rw-r--r--gcc/testsuite/gfortran.dg/PR93963.f9080
-rw-r--r--gcc/testsuite/gfortran.dg/PR94110.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/associated_assumed_rank.f90126
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_18.f905
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_22.f90169
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c68
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_23.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_24.f90137
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_10.f905
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_11.f905
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_12.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_13.c26
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_13.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/attr_deprecated-2.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-char-descr.f90104
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c345
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f901574
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f9082
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c180
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90656
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c370
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f901720
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c345
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f901574
-rw-r--r--gcc/testsuite/gfortran.dg/bind-c-intent-out.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_array_params_2.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_char_10.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_char_6.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_char_7.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_char_8.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_char_9.f90161
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_contiguous.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/bounds_check_23.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy-c.c54
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy.f9098
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocatable-optional-pointer.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocate-c.c168
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocate-errors-c.c109
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocate-errors.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/allocate.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-1.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-2.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-3.f9051
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-4.f9050
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-5.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-6.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-7.f9051
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-8.f9050
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f9084
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c-interop.exp57
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c1255-1.f9083
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90106
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c1255a.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407a-1.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407a-2.f9088
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407b-1.f90107
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90150
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c407c-1.f9063
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c516.f90109
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c524a.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535a-1.f9065
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535a-2.f9078
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90331
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90386
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535b-3.f9079
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535c-1.f90164
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535c-2.f9074
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535c-3.f9072
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/c535c-4.f9072
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1-c.c91
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2-c.c91
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2.f9082
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3-c.c92
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3.f9058
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4-c.c112
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4.f9073
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c37
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6-c.c81
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6.f9072
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7-c.c81
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7.f9074
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8-c.c73
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8.f9078
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1-c.c87
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1.f90174
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2-c.c87
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2.f90157
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3-c.c108
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3.f90134
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4-c.c175
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4.f90207
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5-c.c31
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6-c.c42
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90115
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-1-c.c56
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-1.f9067
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-2-c.c113
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-2.f90152
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-3-c.c80
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/contiguous-3.f90171
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/deferred-character-1.f9076
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.c195
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.h12
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/establish-c.c134
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/establish-errors-c.c120
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/establish-errors.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/establish.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/explicit-interface.f9060
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1-c.c46
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2-c.c68
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3-c.c42
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4-c.c57
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5-c.c28
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6-c.c51
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6.f9050
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7-c.c53
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7.f90147
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8-c.c20
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9-c.c42
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1-c.c52
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2-c.c52
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3-c.c71
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3.f9059
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4-c.c96
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4.f9075
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5-c.c30
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6-c.c50
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6.f9049
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7-c.c136
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-1.f90123
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-2.f9097
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-3.f90148
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-4.f90198
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-5.f9061
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-6.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-7.f9089
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/note-5-3.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/note-5-4-c.c10
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/note-5-4.f9063
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/optional-c.c82
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/optional.f90114
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/rank-class.f9088
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/rank.f9099
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-1.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-2.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-3.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-4.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-1-c.c135
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-1.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-1p.f9075
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-2-c.c175
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-2.f90102
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-2p.f90104
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-3-c.c235
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-3.f90103
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-3p.f90127
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-4-c.c101
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-4.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-errors-c.c149
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/section-errors.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/select-c.c138
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/select-errors-c.c125
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/select-errors.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/select.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/setpointer-c.c78
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/setpointer-errors-c.c127
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/setpointer-errors.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/setpointer.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/shape.f9077
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/size.f90106
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/tkr.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic-c.c169
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic.f90151
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char-c.c41
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char.f9047
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c38
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128-c.c40
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble-c.c37
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c178
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic-c.c168
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic.f90160
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c38
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128-c.c41
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble-c.c37
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/ubound.f90129
-rw-r--r--gcc/testsuite/gfortran.dg/class_72.f9083
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/derived_constructor_char_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/entry_24.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/entry_25.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/privatization-1-compute.f906
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f24
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/unexpected-end.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f9093
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f9097
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-11.f90134
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-12.f90159
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-13.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-14.f9049
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-18.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-19.f9049
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90197
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-2a.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90237
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-4.f9062
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f9075
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-6.f90188
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f9093
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-8.f90218
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-9.f9058
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/flush-1.f908
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/flush-2.f909
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-5.f90129
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-6.f90436
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-7.f9059
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-8.f9061
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/order-9.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr43711.f908
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-1.f9067
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-2.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-1.f909
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-2.f9092
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-3.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/unexpected-end.f90123
-rw-r--r--gcc/testsuite/gfortran.dg/goto_9.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/include_14.f906
-rw-r--r--gcc/testsuite/gfortran.dg/include_15.f909
-rw-r--r--gcc/testsuite/gfortran.dg/include_16.f902
-rw-r--r--gcc/testsuite/gfortran.dg/include_17.f906
-rw-r--r--gcc/testsuite/gfortran.dg/include_18.f905
-rw-r--r--gcc/testsuite/gfortran.dg/include_19.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_20.f905
-rw-r--r--gcc/testsuite/gfortran.dg/include_21.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/include_23.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_24.f904
-rw-r--r--gcc/testsuite/gfortran.dg/include_6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/include_9.f901
-rw-r--r--gcc/testsuite/gfortran.dg/intent_out_14.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/interface_operator_3.f90141
-rw-r--r--gcc/testsuite/gfortran.dg/intrinsic_size_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/parameter_array_init_8.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/pr100950.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr101327.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/pr102366.f909
-rw-r--r--gcc/testsuite/gfortran.dg/pr102458.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/pr102458b.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/pr102520.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr102685.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/pr32599.f032
-rw-r--r--gcc/testsuite/gfortran.dg/pr70931.f903
-rw-r--r--gcc/testsuite/gfortran.dg/pr77498.f2
-rw-r--r--gcc/testsuite/gfortran.dg/pr82314.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/pr93792.f902
-rw-r--r--gcc/testsuite/gfortran.dg/predict-2.f904
-rw-r--r--gcc/testsuite/gfortran.dg/reshape_shape_2.f907
-rw-r--r--gcc/testsuite/gfortran.dg/shape_10.f906
-rw-r--r--gcc/testsuite/gfortran.dg/size_optional_dim_1.f904
-rw-r--r--gcc/testsuite/gfortran.dg/substr_6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/transfer_simplify_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/transpose_optimization_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f0317
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90254
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_33.f9018
-rw-r--r--gcc/testsuite/gnat.dg/asan1.adb2
-rw-r--r--gcc/testsuite/gnat.dg/enum_rep2.adb117
-rw-r--r--gcc/testsuite/gnat.dg/unroll1.adb2
-rw-r--r--gcc/testsuite/gnat.dg/zcur_attr.adb8
-rw-r--r--gcc/testsuite/gnat.dg/zcur_attr.ads4
-rw-r--r--gcc/testsuite/jit.dg/jit.exp154
-rw-r--r--gcc/testsuite/jit.dg/test-debuginfo.c72
-rw-r--r--gcc/testsuite/jit.dg/test-error-array-bounds.c2
-rw-r--r--gcc/testsuite/lib/prune.exp6
-rw-r--r--gcc/testsuite/lib/target-supports.exp45
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-unavailable-1.mm34
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-unavailable-2.mm24
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-unavailable-3.mm22
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-unavailable-1.mm38
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-unavailable-2.mm26
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dotsyntax-unavailable-1.mm42
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-unavailable-1.m34
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-unavailable-2.m24
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-unavailable-3.m22
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-unavailable-1.m39
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-unavailable-2.m26
-rw-r--r--gcc/testsuite/objc.dg/property/dotsyntax-unavailable-1.m42
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.c130
-rw-r--r--gcc/toplev.h1
-rw-r--r--gcc/tree-cfg.c61
-rw-r--r--gcc/tree-core.h23
-rw-r--r--gcc/tree-data-ref.c175
-rw-r--r--gcc/tree-data-ref.h9
-rw-r--r--gcc/tree-if-conv.c49
-rw-r--r--gcc/tree-inline.c18
-rw-r--r--gcc/tree-loop-distribution.c519
-rw-r--r--gcc/tree-object-size.c42
-rw-r--r--gcc/tree-object-size.h3
-rw-r--r--gcc/tree-pass.h4
-rw-r--r--gcc/tree-predcom.c6
-rw-r--r--gcc/tree-pretty-print.c74
-rw-r--r--gcc/tree-sra.c130
-rw-r--r--gcc/tree-ssa-ccp.c3
-rw-r--r--gcc/tree-ssa-dce.c14
-rw-r--r--gcc/tree-ssa-dom.c216
-rw-r--r--gcc/tree-ssa-dse.c5
-rw-r--r--gcc/tree-ssa-loop-ch.c1
-rw-r--r--gcc/tree-ssa-loop-im.c80
-rw-r--r--gcc/tree-ssa-loop-manip.c111
-rw-r--r--gcc/tree-ssa-loop-manip.h5
-rw-r--r--gcc/tree-ssa-loop-niter.c16
-rw-r--r--gcc/tree-ssa-loop-prefetch.c3
-rw-r--r--gcc/tree-ssa-loop.c2
-rw-r--r--gcc/tree-ssa-pre.c157
-rw-r--r--gcc/tree-ssa-reassoc.c125
-rw-r--r--gcc/tree-ssa-sccvn.c150
-rw-r--r--gcc/tree-ssa-sccvn.h3
-rw-r--r--gcc/tree-ssa-strlen.c558
-rw-r--r--gcc/tree-ssa-structalias.c523
-rw-r--r--gcc/tree-ssa-ter.c10
-rw-r--r--gcc/tree-ssa-threadbackward.c428
-rw-r--r--gcc/tree-ssa-threadedge.c473
-rw-r--r--gcc/tree-ssa-threadedge.h76
-rw-r--r--gcc/tree-ssa-threadupdate.c422
-rw-r--r--gcc/tree-ssa-threadupdate.h69
-rw-r--r--gcc/tree-ssa-uninit.c2294
-rw-r--r--gcc/tree-ssa.c44
-rw-r--r--gcc/tree-ssanames.c19
-rw-r--r--gcc/tree-streamer-in.c6
-rw-r--r--gcc/tree-streamer-out.c5
-rw-r--r--gcc/tree-vect-data-refs.c383
-rw-r--r--gcc/tree-vect-loop.c32
-rw-r--r--gcc/tree-vect-patterns.c34
-rw-r--r--gcc/tree-vect-slp.c241
-rw-r--r--gcc/tree-vect-stmts.c94
-rw-r--r--gcc/tree-vectorizer.c6
-rw-r--r--gcc/tree-vectorizer.h80
-rw-r--r--gcc/tree-vrp.c400
-rw-r--r--gcc/tree.c272
-rw-r--r--gcc/tree.h63
-rw-r--r--gcc/tsystem.h2
-rw-r--r--gcc/value-pointer-equiv.cc302
-rw-r--r--gcc/value-pointer-equiv.h62
-rw-r--r--gcc/value-query.cc5
-rw-r--r--gcc/value-range.cc76
-rw-r--r--gcc/value-range.h17
-rw-r--r--gcc/value-relation.cc563
-rw-r--r--gcc/value-relation.h115
-rw-r--r--gcc/var-tracking.c3
-rw-r--r--gcc/varasm.c17
-rw-r--r--gcc/vr-values.c73
-rw-r--r--gcc/vr-values.h9
-rw-r--r--gcc/warning-control.cc81
-rw-r--r--gcc/wide-int.cc7
2345 files changed, 152653 insertions, 23704 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4e7991e..8175862 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,5962 @@
+2021-10-17 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-pass.h (make_pass_thread_jumps_full): New.
+ * tree-ssa-threadbackward.c (pass_thread_jumps::gate): Inline.
+ (try_thread_blocks): Add resolve and speed arguments.
+ (pass_thread_jumps::execute): Inline.
+ (do_early_thread_jumps): New.
+ (do_thread_jumps): New.
+ (make_pass_thread_jumps): Move.
+ (pass_early_thread_jumps::gate): Inline.
+ (pass_early_thread_jumps::execute): Inline.
+ (class pass_thread_jumps_full): New.
+
+2021-10-16 Piotr Kubaj <pkubaj@FreeBSD.org>
+
+ * configure.ac: Treat powerpc64*-*-freebsd* the same as
+ powerpc64-*-freebsd*.
+ * configure: Regenerate.
+
+2021-10-16 H.J. Lu <hjl.tools@gmail.com>
+
+ * value-query.cc (get_ssa_name_ptr_info_nonnull): Change
+ set_ptr_nonull to set_ptr_nonnull in comments.
+
+2021-10-16 Jan Hubicka <hubicka@ucw.cz>
+
+ PR tree-optimization/102720
+ * tree-ssa-structalias.c (compute_points_to_sets): Fix producing
+ of call used and clobbered sets.
+
+2021-10-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (LINK_COMMAND_SPEC_A): Update 'r' handling to
+ skip gomp and itm when r or nodefaultlibs is given.
+ (DSYMUTIL_SPEC): Do not call dsymutil for '-r' link lines.
+ Update ordering of exclusions, remove duplicate 'v' addition
+ (collect2 will add this from the main command line).
+
+2021-10-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (darwin_driver_init): Revise comments, handle
+ filelist and framework options in specs instead of code.
+ * config/darwin.h (SUBTARGET_DRIVER_SELF_SPECS): Update to handle link
+ specs that are really driver ones.
+ (DARWIN_CC1_SPEC): Likewise.
+ (CPP_SPEC): Likewise.
+ (SYSROOT_SPEC): Append space.
+ (LINK_SYSROOT_SPEC): Remove most driver link specs.
+ (STANDARD_STARTFILE_PREFIX_2): Update link-related specs.
+ (STARTFILE_SPEC): Likewise.
+ (ASM_MMACOSX_VERSION_MIN_SPEC): Fix line wrap.
+ (ASM_SPEC): Update driver-related specs.
+ (ASM_FINAL_SPEC): Likewise.
+ * config/darwin.opt: Remove now unused option aliases.
+ * config/i386/darwin.h (EXTRA_ASM_OPTS): Ensure space after opt.
+ (ASM_SPEC): Update driver-related specs.
+
+2021-10-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/i386/i386.c (ix86_hardreg_mov_ok): For vector modes,
+ allow standard_sse_constant_p immediate constants.
+
+2021-10-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config.gcc: Add tm-dwarf2.h to tm_d-file.
+
+2021-10-15 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-fold.h (gimple_range_ssa_p): Don't process names
+ that occur in abnormal phis.
+ * gimple-range.cc (gimple_ranger::range_on_edge): Return false for
+ abnormal and EH edges.
+ * gimple-ssa-evrp.c (rvrp_folder::value_of_expr): Ditto.
+ (rvrp_folder::value_on_edge): Ditto.
+ (rvrp_folder::value_of_stmt): Ditto.
+ (hybrid_folder::value_of_expr): Ditto for ranger queries.
+ (hybrid_folder::value_on_edge): Ditto.
+ (hybrid_folder::value_of_stmt): Ditto.
+ * value-query.cc (gimple_range_global): Always return a range if
+ the type is supported.
+
+2021-10-15 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md: Consistently use "rG" constraint for copy
+ instruction in move patterns.
+
+2021-10-15 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn-hsa.h (S_FIJI): Set unconditionally.
+ (S_900): Likewise.
+ (S_906): Likewise.
+ * config/gcn/gcn.c: Hard code SRAM ECC settings for old architectures.
+ * config/gcn/mkoffload.c (ELFABIVERSION_AMDGPU_HSA): Rename to ...
+ (ELFABIVERSION_AMDGPU_HSA_V3): ... this.
+ (ELFABIVERSION_AMDGPU_HSA_V4): New.
+ (SET_SRAM_ECC_UNSUPPORTED): New.
+ (copy_early_debug_info): Create elf flags to match the other objects.
+ (main): Just let the attribute flags pass through.
+
+2021-10-15 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * tree-loop-distribution.c (reduction_var_overflows_first):
+ Pass the type of reduction_var as first argument as it is also
+ done for the load type.
+ (loop_distribution::transform_reduction_loop): Add missing
+ TREE_TYPE while determining precission of reduction_var.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ * defaults.h (PREFERRED_DEBUGGING_TYPE): Choose DWARF2_DEBUG
+ when not set.
+ * toplev.c (process_options): Warn when STABS debugging is
+ enabled but not the preferred format.
+ * config/pa/som.h (PREFERRED_DEBUGGING_TYPE): Define to
+ DBX_DEBUG.
+ * config/pdp11/pdp11.h (PREFERRED_DEBUGGING_TYPE): Likewise.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ PR ipa/102762
+ * tree-inline.c (copy_bb): Avoid underflowing nargs.
+
+2021-10-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386-expand.c (ix86_expand_vec_perm): Convert
+ HFmode input operand to HImode.
+ (ix86_vectorize_vec_perm_const): Likewise.
+ * config/i386/sse.md (*avx512bw_permvar_truncv16siv16hi_1_hf):
+ New define_insn.
+ (*avx512f_permvar_truncv8siv8hi_1_hf):
+ Likewise.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102682
+ * expmed.c (store_bit_field_1): Ensure a LHS subreg would
+ not create a paradoxical subreg.
+
+2021-10-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386-expand.c (ix86_expand_vector_init):
+ For half_vector concat for HFmode, handle them like HImode.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (class back_threader): Add m_resolve.
+ (back_threader::back_threader): Same.
+ (back_threader::resolve_phi): Try to solve without looking back if
+ possible.
+ (back_threader::find_paths_to_names): Same.
+ (try_thread_blocks): Pass resolve argument to back threader.
+ (pass_early_thread_jumps::execute): Same.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/invoke.texi: Remove max-fsm-thread-length,
+ max-fsm-thread-paths, and fsm-maximum-phi-arguments.
+ * params.opt: Same.
+ * tree-ssa-threadbackward.c (back_threader::back_threader): Remove
+ argument.
+ (back_threader_registry::back_threader_registry): Same.
+ (back_threader_profitability::profitable_path_p): Remove
+ param_max_fsm_thread-length.
+ (back_threader_registry::register_path): Remove
+ m_max_allowable_paths.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (class back_threader): Make m_imports
+ an auto_bitmap.
+ (back_threader::~back_threader): Do not release m_path.
+
+2021-10-14 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/102738
+ * vr-values.c (simplify_using_ranges::simplify): Handle RSHIFT_EXPR.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * omp-general.c (omp_check_context_selector): Move from c-omp.c.
+ (omp_mark_declare_variant): Move from c-omp.c.
+ (omp_context_name_list_prop): Update for Fortran strings.
+ * omp-general.h (omp_check_context_selector): New prototype.
+ (omp_mark_declare_variant): New prototype.
+
+2021-10-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/rs6000/rs6000.c (rs6000_density_test): Move early
+ exit test further up the function.
+
+2021-10-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/arm/arm.c (arm_add_stmt_cost): Delete.
+ (TARGET_VECTORIZE_ADD_STMT_COST): Delete.
+
+2021-10-14 Martin Jambor <mjambor@suse.cz>
+
+ * doc/invoke.texi (Optimize Options): Add entry for
+ ipa-cp-recursive-freq-factor.
+
+2021-10-14 Tamar Christina <tamar.christina@arm.com>
+
+ * match.pd: New rule.
+
+2021-10-14 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/102557
+ * ipa-modref-tree.h (modref_access_node::update2):
+ Also check that parm_offset is unchanged.
+ (modref_ref_node::insert_access): Fix updating of
+ parameter.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (back_threader::resolve_phi): Add
+ FIXME note.
+
+2021-10-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102659
+ * tree-if-conv.c (if_convertible_gimple_assign_stmt_p): Also
+ rewrite pointer typed undefined overflow operations.
+ (predicate_statements): Likewise. Make sure to emit invariant
+ conversions in the preheader.
+ * tree-vectorizer.c (vect_loop_vectorized_call): Look through
+ non-empty preheaders.
+ * tree-data-ref.c (dr_analyze_indices): Strip useless
+ conversions to the MEM_REF base type.
+
+2021-10-14 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Stop using AUTODETECT_VALUE
+ and use EnabledBy where possible.
+ * opts.c: Enable OPT_fvar_tracking with optimize >= 1.
+ * toplev.c (AUTODETECT_VALUE): Remove macro.
+ (process_options): Simplify by using EnabledBy and
+ OPT_fvar_tracking. Use OPTION_SET_P macro instead of
+ AUTODETECT_VALUE.
+
+2021-10-14 Jonathan Wright <jonathan.wright@arm.com>
+
+ * config/aarch64/arm_neon.h (vld1_s8_x3): Use signed type for
+ pointer parameter.
+ (vld1_s32_x3): Likewise.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102736
+ PR tree-optimization/102736
+ * gimple-range-path.cc (path_range_query::range_on_path_entry):
+ Assert that the requested range is defined outside the path.
+ (path_range_query::ssa_range_in_phi): Do not call
+ range_on_path_entry for SSA names that are defined within the
+ path.
+
+2021-10-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (darwin_find_version_from_kernel):
+ Quote internal identifiers and avoid contractions in
+ warnings.
+ (darwin_default_min_version): Likewise.
+ (darwin_driver_init): Likewise.
+
+2021-10-14 Martin Jambor <mjambor@suse.cz>
+
+ * params.opt (ipa-cp-recursive-freq-factor): New.
+ * ipa-cp.c (ipcp_value): Switch to inline initialization. New members
+ scc_no, self_recursion_generated_level, same_scc and
+ self_recursion_generated_p.
+ (ipcp_lattice::add_value): Replaced parameter unlimited with
+ same_lat_gen_level, usit it determine limit of values and store it to
+ the value.
+ (ipcp_lattice<valtype>::print): Dump the new fileds.
+ (allocate_and_init_ipcp_value): Take same_lat_gen_level as a new
+ parameter and store it to the new value.
+ (self_recursively_generated_p): Removed.
+ (propagate_vals_across_arith_jfunc): Use self_recursion_generated_p
+ instead of self_recursively_generated_p, store self generation level
+ to such values.
+ (value_topo_info<valtype>::add_val): Set scc_no.
+ (value_topo_info<valtype>::propagate_effects): Multiply frequencies of
+ recursively feeding values and self generated values by appropriate
+ new factors.
+
+2021-10-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_add_stmt_cost): Remove
+ redundant test for flag_vect_cost_model.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * bitmap.c (debug): New overloaded function for auto_bitmaps.
+ * bitmap.h (debug): Same.
+
+2021-10-14 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_mask_fcmadd_pch):
+ Adjust builtin call.
+ (_mm512_mask3_fcmadd_pch): Likewise.
+ (_mm512_mask_fmadd_pch): Likewise
+ (_mm512_mask3_fmadd_pch): Likewise
+ (_mm512_mask_fcmadd_round_pch): Likewise
+ (_mm512_mask3_fcmadd_round_pch): Likewise
+ (_mm512_mask_fmadd_round_pch): Likewise
+ (_mm512_mask3_fmadd_round_pch): Likewise
+ (_mm_mask_fcmadd_sch): Likewise
+ (_mm_mask3_fcmadd_sch): Likewise
+ (_mm_mask_fmadd_sch): Likewise
+ (_mm_mask3_fmadd_sch): Likewise
+ (_mm_mask_fcmadd_round_sch): Likewise
+ (_mm_mask3_fcmadd_round_sch): Likewise
+ (_mm_mask_fmadd_round_sch): Likewise
+ (_mm_mask3_fmadd_round_sch): Likewise
+ (_mm_fcmadd_round_sch): Likewise
+ * config/i386/avx512fp16vlintrin.h (_mm_mask_fmadd_pch):
+ Adjust builtin call.
+ (_mm_mask3_fmadd_pch): Likewise
+ (_mm256_mask_fmadd_pch): Likewise
+ (_mm256_mask3_fmadd_pch): Likewise
+ (_mm_mask_fcmadd_pch): Likewise
+ (_mm_mask3_fcmadd_pch): Likewise
+ (_mm256_mask_fcmadd_pch): Likewise
+ (_mm256_mask3_fcmadd_pch): Likewise
+ * config/i386/i386-builtin.def: Add mask3 builtin for complex
+ fma, and adjust mask_builtin to corresponding expander.
+ * config/i386/i386-expand.c (ix86_expand_round_builtin):
+ Skip eraseing embedded rounding for expanders that emits
+ multiple insns.
+ * config/i386/sse.md (complexmove): New mode_attr.
+ (<avx512>_fmaddc_<mode>_mask1<round_expand_name>): New expander.
+ (<avx512>_fcmaddc_<mode>_mask1<round_expand_name>): Likewise.
+ (avx512fp16_fmaddcsh_v8hf_mask1<round_expand_name>): Likewise.
+ (avx512fp16_fcmaddcsh_v8hf_mask1<round_expand_name>): Likewise.
+ (avx512fp16_fcmaddcsh_v8hf_mask3<round_expand_name>): Likewise.
+ (avx512fp16_fmaddcsh_v8hf_mask3<round_expand_name>): Likewise.
+ * config/i386/subst.md (round_embedded_complex): New subst.
+
+2021-10-14 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md (cbranchsf4): Disable if TARGET_SOFT_FLOAT.
+ (cbranchdf4): Likewise.
+ Add missing move patterns for TARGET_SOFT_FLOAT.
+
+2021-10-13 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/i386/i386-expand.c (ix86_expand_vector_move): Use a
+ pseudo intermediate when moving a SUBREG into a hard register,
+ by checking ix86_hardreg_mov_ok.
+ (ix86_expand_vector_extract): Store zero-extended SImode
+ intermediate in a pseudo, then set target using a SUBREG_PROMOTED
+ annotated subreg.
+ * config/i386/sse.md (mov<VMOVE>_internal): Prevent CSE creating
+ complex (SUBREG) sets of (vector) hard registers before reload, by
+ checking ix86_hardreg_mov_ok.
+
+2021-10-13 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * ctfc.h (enum ctf_dtu_d_union_enum): Remove redundant comma.
+
+2021-10-13 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * dwarf2ctf.c (gen_ctf_array_type): Fix typo in comment.
+
+2021-10-13 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102630
+ * pointer-query.cc (compute_objsize_r): Handle named address spaces.
+
+2021-10-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * collect2.c (is_lto_object_file): Release simple-object
+ resources, close files.
+
+2021-10-13 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ * config/arm/arm.c (thumb2_legitimate_address_p): Use VALID_MVE_MODE
+ when checking mve addressing modes.
+ (mve_vector_mem_operand): Fix the way we handle pre, post and offset
+ addressing modes.
+ (arm_print_operand): Fix printing of POST_ and PRE_MODIFY.
+ * config/arm/mve.md: Use mve_memory_operand predicate everywhere where
+ there is a single Ux constraint.
+
+2021-10-13 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md (muldi3): Add support for inlining 64-bit
+ multiplication on 32-bit PA 1.1 and 2.0 targets.
+
+2021-10-13 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/90364
+ * coverage.c (build_info): Emit checksum to the global variable.
+ (build_info_type): Add new field for checksum.
+ (coverage_obj_finish): Pass object_checksum.
+ (coverage_init): Use 0 as checksum for .gcno files.
+ * gcov-dump.c (dump_gcov_file): Dump also new checksum field.
+ * gcov.c (read_graph_file): Read also checksum.
+ * doc/invoke.texi: Document the behaviour change.
+
+2021-10-13 Richard Biener <rguenther@suse.de>
+
+ * gimple-iterator.h (gsi_iterator_update): Add GSI_LAST_NEW_STMT,
+ start at integer value 2.
+ * gimple-iterator.c (gsi_insert_seq_nodes_before): Update
+ the iterator for GSI_LAST_NEW_STMT.
+ (gsi_insert_seq_nodes_after): Likewise.
+ * tree-if-conv.c (predicate_statements): Use GSI_LAST_NEW_STMT.
+ * tree-ssa.c (execute_update_addresses_taken): Correct bogus
+ arguments to gsi_replace.
+
+2021-10-13 Martin Liska <mliska@suse.cz>
+
+ PR target/102688
+ * common.opt: Use EnabledBy instead of detection in
+ finish_options and process_options.
+ * opts.c (finish_options): Remove handling of
+ x_flag_unroll_all_loops.
+ * toplev.c (process_options): Likewise for flag_web and
+ flag_rename_registers.
+
+2021-10-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102659
+ * tree-if-conv.c (need_to_rewrite_undefined): New flag.
+ (if_convertible_gimple_assign_stmt_p): Mark the loop for
+ rewrite when stmts with undefined behavior on integer
+ overflow appear.
+ (combine_blocks): Predicate also when we need to rewrite stmts.
+ (predicate_statements): Rewrite affected stmts to something
+ with well-defined behavior on overflow.
+ (tree_if_conversion): Initialize need_to_rewrite_undefined.
+
+2021-10-13 Richard Biener <rguenther@suse.de>
+
+ PR ipa/102714
+ * ipa-sra.c (ptr_parm_has_nonarg_uses): Fix volatileness
+ check.
+
+2021-10-13 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * dwarf2ctf.c: Fix typo in comment.
+
+2021-10-12 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/101985
+ * config/rs6000/altivec.h (vec_cpsgn): Swap operand order.
+ * config/rs6000/rs6000-overload.def (VEC_COPYSIGN): Use SKIP to
+ avoid generating an automatic #define of vec_cpsgn. Use the
+ correct built-in for V4SFmode that doesn't depend on VSX.
+
+2021-10-12 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/85730
+ PR target/82524
+ * config/i386/i386.md (*add<mode>_1_slp): Rewrite as
+ define_insn_and_split pattern. Add alternative 1 and split it
+ post reload to insert operand 1 into the low part of operand 0.
+ (*sub<mode>_1_slp): Ditto.
+ (*and<mode>_1_slp): Ditto.
+ (*<any_or:code><mode>_1_slp): Ditto.
+ (*ashl<mode>3_1_slp): Ditto.
+ (*<any_shiftrt:insn><mode>3_1_slp): Ditto.
+ (*<any_rotate:insn><mode>3_1_slp): Ditto.
+ (*neg<mode>_1_slp): New insn_and_split pattern.
+ (*one_cmpl<mode>_1_slp): Ditto.
+
+2021-10-12 David Edelsohn <dje.gcc@gmail.com>
+
+ * doc/install.texi: Update MinGW and mingw-64 Binaries
+ download links.
+
+2021-10-12 Daniel Le Duc Khoi Nguyen <greenrecyclebin@gmail.com>
+
+ * doc/extend.texi (Common Variable Attributes): Fix typos in
+ alloc_size documentation.
+
+2021-10-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102696
+ * tree-vect-slp.c (vect_build_slp_tree_2): Properly mark
+ the tree fatally failed when we reject a BIT_FIELD_REF.
+
+2021-10-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102572
+ * tree-vect-stmts.c (vect_build_gather_load_calls): When
+ gathering the vectorized defs for the mask pass in the
+ desired mask vector type so invariants will be handled
+ correctly.
+
+2021-10-12 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64-sve.md (*fcm<cmp_op><mode>_bic_combine,
+ *fcm<cmp_op><mode>_nor_combine, *fcmuo<mode>_bic_combine,
+ *fcmuo<mode>_nor_combine): New.
+
+2021-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/102588
+ * config/sparc/sparc-modes.def (OI): New integer mode.
+
+2021-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple-fold.h (clear_padding_type_may_have_padding_p): Declare.
+ * gimple-fold.c (clear_padding_type_may_have_padding_p): No longer
+ static.
+
+2021-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vectorizer.h (loop_cost_model): New function.
+ (unlimited_cost_model): Use it.
+ * tree-vect-loop.c (vect_analyze_loop_costing): Use loop_cost_model
+ call instead of flag_vect_cost_model.
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Likewise.
+ (vect_prune_runtime_alias_test_list): Likewise. Also use it instead
+ of flag_simd_cost_model.
+
+2021-10-12 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102483
+ * config/i386/i386-expand.c (emit_reduc_half): Handle
+ V4QImode.
+ * config/i386/mmx.md (reduc_<code>_scal_v4qi): New expander.
+ (reduc_plus_scal_v4qi): Ditto.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * config/rs6000/smmintrin.h (_mm_cmpeq_epi64, _mm_cmpgt_epi64,
+ _mm_mullo_epi32, _mm_mul_epi32, _mm_packus_epi32): New.
+ * config/rs6000/nmmintrin.h: Copy from i386, tweak to suit.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * config/rs6000/smmintrin.h (_mm_cvtepi8_epi16, _mm_cvtepi8_epi32,
+ _mm_cvtepi8_epi64, _mm_cvtepi16_epi32, _mm_cvtepi16_epi64,
+ _mm_cvtepi32_epi64, _mm_cvtepu8_epi16, _mm_cvtepu8_epi32,
+ _mm_cvtepu8_epi64, _mm_cvtepu16_epi32, _mm_cvtepu16_epi64,
+ _mm_cvtepu32_epi64): New.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * config/rs6000/smmintrin.h (_mm_test_all_zeros,
+ _mm_test_all_ones, _mm_test_mix_ones_zeros): Rewrite as macro.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * config/rs6000/smmintrin.h (_mm_min_epi8, _mm_min_epu16,
+ _mm_min_epi32, _mm_min_epu32, _mm_max_epi8, _mm_max_epu16,
+ _mm_max_epi32, _mm_max_epu32): New.
+
+2021-10-11 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-modref-tree.h (struct modref_access_node): Revert
+ accidental change.
+ (struct modref_ref_node): Likewise.
+
+2021-10-11 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-modref-tree.h (modref_tree::global_access_p): New member
+ function.
+ * ipa-modref.c:
+ (implicint_const_eaf_flags,implicit_pure_eaf_flags,
+ ignore_stores_eaf_flags): Move to ipa-modref.h
+ (remove_useless_eaf_flags): Remove early exit on NOCLOBBER.
+ (modref_summary::global_memory_read_p): New member function.
+ (modref_summary::global_memory_written_p): New member function.
+ * ipa-modref.h (modref_summary::global_memory_read_p,
+ modref_summary::global_memory_written_p): Declare.
+ (implicint_const_eaf_flags,implicit_pure_eaf_flags,
+ ignore_stores_eaf_flags): move here.
+ * tree-ssa-structalias.c: Include ipa-modref-tree.h, ipa-modref.h
+ and attr-fnspec.h.
+ (handle_rhs_call): Rewrite.
+ (handle_call_arg): New function.
+ (determine_global_memory_access): New function.
+ (handle_const_call): Remove
+ (handle_pure_call): Remove
+ (find_func_aliases_for_call): Update use of handle_rhs_call.
+ (compute_points_to_sets): Handle global memory acccesses
+ selectively
+
+2021-10-11 Diane Meirowitz <diane.meirowitz@oracle.com>
+
+ * doc/invoke.texi: Add link to UndefinedBehaviorSanitizer
+ documentation, mention UBSAN_OPTIONS, similar to what is done
+ for AddressSanitizer.
+
+2021-10-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102683
+ * internal-fn.c (expand_DEFERRED_INIT): Check for mode
+ availability before building an integer type for storage
+ purposes.
+
+2021-10-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/101480
+ * gimple.c (gimple_call_fnspec): Do not mark operator new/delete
+ as const.
+
+2021-10-11 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Remove Init(2) for some options.
+ * toplev.c (process_options): Do not use AUTODETECT_VALUE, but
+ use rather OPTION_SET_P.
+
+2021-10-11 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Remove usage of IRA_REGION_AUTODETECT.
+ * flag-types.h (enum ira_region): Likewise.
+ * toplev.c (process_options): Use OPTION_SET_P instead of
+ IRA_REGION_AUTODETECT.
+
+2021-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (omp_runtime_api_call): Handle omp_get_max_teams,
+ omp_[sg]et_teams_thread_limit and omp_set_num_teams.
+
+2021-10-11 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * config/s390/s390-protos.h (s390_rawmemchr): Add prototype.
+ * config/s390/s390.c (s390_rawmemchr): New function.
+ * config/s390/s390.md (rawmemchr<SINT:mode>): New expander.
+ * config/s390/vector.md (@vec_vfees<mode>): Basically a copy of
+ the pattern vfees<mode> from vx-builtins.md.
+ * config/s390/vx-builtins.md (*vfees<mode>): Remove.
+
+2021-10-11 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * builtins.c (get_memory_rtx): Change to external linkage.
+ * builtins.h (get_memory_rtx): Add function prototype.
+ * doc/md.texi (rawmemchr<mode>): Document.
+ * internal-fn.c (expand_RAWMEMCHR): Define.
+ * internal-fn.def (RAWMEMCHR): Add.
+ * optabs.def (rawmemchr_optab): Add.
+ * tree-loop-distribution.c (find_single_drs): Change return code
+ behaviour by also returning true if no single store was found
+ but a single load.
+ (loop_distribution::classify_partition): Respect the new return
+ code behaviour of function find_single_drs.
+ (loop_distribution::execute): Call new function
+ transform_reduction_loop in order to replace rawmemchr or strlen
+ like loops by calls into builtins.
+ (generate_reduction_builtin_1): New function.
+ (generate_rawmemchr_builtin): New function.
+ (generate_strlen_builtin_1): New function.
+ (generate_strlen_builtin): New function.
+ (generate_strlen_builtin_using_rawmemchr): New function.
+ (reduction_var_overflows_first): New function.
+ (determine_reduction_stmt_1): New function.
+ (determine_reduction_stmt): New function.
+ (loop_distribution::transform_reduction_loop): New function.
+
+2021-10-11 Martin Liska <mliska@suse.cz>
+
+ * tree.c (cl_option_hasher::hash): Use cl_optimization_hash
+ and remove legacy hashing code.
+
+2021-10-11 Kito Cheng <kito.cheng@sifive.com>
+
+ PR target/100316
+ * builtins.c (maybe_emit_call_builtin___clear_cache): Allow
+ CONST_INT for BEGIN and END, and use gcc_assert rather than
+ error.
+
+2021-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/102441
+ * var-tracking.c (add_stores): For cselib_sp_derived_value_p values
+ use MO_VAL_SET if loc is not sp.
+
+2021-10-10 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/102622
+ * match.pd: Swap the order of a?pow2cst:0 and a?-1:0 transformations.
+ Swap the order of a?0:pow2cst and a?0:-1 transformations.
+
+2021-10-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102639
+ * config/i386/i386-expand.c (ix86_valid_mask_cmp_mode): Handle
+ HFmode.
+ (ix86_use_mask_cmp_p): Ditto.
+ (ix86_expand_sse_movcc): Ditto.
+ * config/i386/i386.md (setcc_hf_mask): New define_insn.
+ (movhf_mask): Ditto.
+ (UNSPEC_MOVCC_MASK): New unspec.
+ * config/i386/sse.md (UNSPEC_PCMP): Move to i386.md.
+
+2021-10-08 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/102627
+ * lra-constraints.c (split_reg): Use at least natural mode of hard reg.
+
+2021-10-08 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::non_null_deref_p): Grow
+ bitmap if needed.
+
+2021-10-08 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (irange::debug): New.
+ * value-range.h (irange::debug): New.
+
+2021-10-08 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/102385
+ * predict.h (change_edge_frequency): Declare.
+ * predict.c (change_edge_frequency): New function.
+ * tree-ssa-loop-manip.h (tree_transform_and_unroll_loop): Remove
+ edge argument.
+ (tree_unroll_loop): Likewise.
+ * gimple-loop-jam.c (tree_loop_unroll_and_jam): Update accordingly.
+ * tree-predcom.c (pcom_worker::tree_predictive_commoning_loop):
+ Likewise.
+ * tree-ssa-loop-prefetch.c (loop_prefetch_arrays): Likewise.
+ * tree-ssa-loop-manip.c (tree_unroll_loop): Likewise.
+ (tree_transform_and_unroll_loop): Likewise. Use single_dom_exit
+ to retrieve the exit edges. Make all the old profile update code
+ conditional on !single_loop_p -- the case it was written for --
+ and use a different approach for the single-loop case.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * config/alpha/alpha.c (alpha_option_override): Use new macro
+ OPTION_SET_P.
+ * config/arc/arc.c (arc_override_options): Likewise.
+ * config/arm/arm.c (arm_option_override): Likewise.
+ * config/bfin/bfin.c (bfin_load_pic_reg): Likewise.
+ * config/c6x/c6x.c (c6x_option_override): Likewise.
+ * config/csky/csky.c: Likewise.
+ * config/darwin.c (darwin_override_options): Likewise.
+ * config/frv/frv.c (frv_option_override): Likewise.
+ * config/i386/djgpp.h: Likewise.
+ * config/i386/i386.c (ix86_stack_protect_guard): Likewise.
+ (ix86_max_noce_ifcvt_seq_cost): Likewise.
+ * config/ia64/ia64.c (ia64_option_override): Likewise.
+ (ia64_override_options_after_change): Likewise.
+ * config/m32c/m32c.c (m32c_option_override): Likewise.
+ * config/m32r/m32r.c (m32r_init): Likewise.
+ * config/m68k/m68k.c (m68k_option_override): Likewise.
+ * config/microblaze/microblaze.c (microblaze_option_override): Likewise.
+ * config/mips/mips.c (mips_option_override): Likewise.
+ * config/nios2/nios2.c (nios2_option_override): Likewise.
+ * config/nvptx/nvptx.c (nvptx_option_override): Likewise.
+ * config/pa/pa.c (pa_option_override): Likewise.
+ * config/riscv/riscv.c (riscv_option_override): Likewise.
+ * config/rs6000/aix71.h: Likewise.
+ * config/rs6000/aix72.h: Likewise.
+ * config/rs6000/aix73.h: Likewise.
+ * config/rs6000/rs6000.c (darwin_rs6000_override_options): Likewise.
+ (rs6000_override_options_after_change): Likewise.
+ (rs6000_linux64_override_options): Likewise.
+ (glibc_supports_ieee_128bit): Likewise.
+ (rs6000_option_override_internal): Likewise.
+ (rs6000_file_start): Likewise.
+ (rs6000_darwin_file_start): Likewise.
+ * config/rs6000/rtems.h: Likewise.
+ * config/rs6000/sysv4.h: Likewise.
+ * config/rs6000/vxworks.h (SUB3TARGET_OVERRIDE_OPTIONS): Likewise.
+ * config/s390/s390.c (s390_option_override): Likewise.
+ * config/sh/linux.h: Likewise.
+ * config/sh/netbsd-elf.h (while): Likewise.
+ * config/sh/sh.c (sh_option_override): Likewise.
+ * config/sol2.c (solaris_override_options): Likewise.
+ * config/sparc/sparc.c (sparc_option_override): Likewise.
+ * config/tilegx/tilegx.c (tilegx_option_override): Likewise.
+ * config/visium/visium.c (visium_option_override): Likewise.
+ * config/vxworks.c (vxworks_override_options): Likewise.
+ * lto-opts.c (lto_write_options): Likewise.
+ * omp-expand.c (expand_omp_simd): Likewise.
+ * omp-general.c (omp_max_vf): Likewise.
+ * omp-offload.c (oacc_xform_loop): Likewise.
+ * opts.h (OPTION_SET_P): Likewise.
+ * targhooks.c (default_max_noce_ifcvt_seq_cost): Likewise.
+ * toplev.c (process_options): Likewise.
+ * tree-predcom.c: Likewise.
+ * tree-sra.c (analyze_all_variable_accesses): Likewise.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102464
+ * config/i386/i386.c (ix86_optab_supported_p):
+ Return true for HFmode.
+ * match.pd: Simplify (_Float16) ceil ((double) x) to
+ __builtin_ceilf16 (a) when a is _Float16 type and
+ direct_internal_fn_supported_p.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102494
+ * config/i386/i386-expand.c (emit_reduc_half): Hanlde V4HImode.
+ * config/i386/mmx.md (reduc_plus_scal_v4hi): New.
+ (reduc_<code>_scal_v4hi): New.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ * common.opt (ftree-vectorize): Add Var(flag_tree_vectorize).
+ * doc/invoke.texi (Options That Control Optimization): Update
+ documents.
+ * opts.c (default_options_table): Enable auto-vectorization at
+ O2 with very-cheap cost model.
+ (finish_options): Use cheap cost model for
+ explicit -ftree{,-loop}-vectorize.
+
+2021-10-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * ctfc.c (ctfc_delete_container): Free hash table contents.
+
+2021-10-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * toplev.c (process_options): Do not warn for GNU GIMPLE.
+
+2021-10-07 Siddhesh Poyarekar <siddhesh@gotplt.org>
+
+ * tree-object-size.c (addr_object_size,
+ compute_builtin_object_size): Drop PDECL and POFF arguments.
+ (addr_object_size): Adjust calls.
+ * tree-object-size.h (compute_builtin_object_size): Drop PDECL
+ and POFF arguments.
+
+2021-10-07 Roger Sayle <roger@nextmovesoftware.com>
+
+ * rtl.def (SMUL_HIGHPART, UMUL_HIGHPART): New RTX codes for
+ representing signed and unsigned high-part multiplication resp.
+ * simplify-rtx.c (simplify_binary_operation_1) [SMUL_HIGHPART,
+ UMUL_HIGHPART]: Simplify high-part multiplications by zero.
+ [SS_PLUS, US_PLUS, SS_MINUS, US_MINUS, SS_MULT, US_MULT,
+ SS_DIV, US_DIV]: Similar simplifications for saturating
+ arithmetic.
+ (simplify_const_binary_operation) [SS_PLUS, US_PLUS, SS_MINUS,
+ US_MINUS, SS_MULT, US_MULT, SMUL_HIGHPART, UMUL_HIGHPART]:
+ Implement compile-time evaluation for constant operands.
+ * dwarf2out.c (mem_loc_descriptor): Skip SMUL_HIGHPART and
+ UMUL_HIGHPART.
+ * doc/rtl.texi (smul_highpart, umul_highpart): Document RTX codes.
+ * doc/md.texi (smul@var{m}3_highpart, umul@var{m3}_highpart):
+ Mention the new smul_highpart and umul_highpart RTX codes.
+ * doc/invoke.texi: Silence @xref "compilation" warnings.
+
+2021-10-07 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/102388
+ * ipa-prop.c (ipa_edge_args_sum_t::duplicate): Also handle the
+ case when the source reference description corresponds to a
+ referance taken in a function src->caller is inlined to.
+
+2021-10-07 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/102581
+ * ipa-modref-tree.h (modref_access_node::contains_p): Handle offsets
+ better.
+ (modref_access_node::try_merge_with): Add sanity check that there
+ are no redundant entries in the list.
+
+2021-10-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102608
+ * tree-ssa-sccvn.c (visit_stmt): Drop .DEFERRED_INIT to
+ varying.
+
+2021-10-07 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): Make
+ save_opt_decoded_options a pointer type
+ * toplev.h: Likewise.
+
+2021-10-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn-valu.md (gather<mode>_insn_2offsets<exec>): Apply
+ HAVE_GCN_ASM_GLOBAL_LOAD_FIXED.
+ (scatter<mode>_insn_2offsets<exec_scatter>): Likewise.
+
+2021-10-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn-hsa.h (SRAMOPT): Include the whole option string.
+ Adjust for new -msram-ecc=any behaviour.
+ (ASM_SPEC): Adjust -mxnack and -msram-ecc usage.
+ * config/gcn/gcn.c (output_file_start): Implement -msram-ecc=any.
+ * config/gcn/mkoffload.c (EF_AMDGPU_XNACK): Rename to ...
+ (EF_AMDGPU_XNACK_V3): ... this.
+ (EF_AMDGPU_SRAM_ECC): Rename to ...
+ (EF_AMDGPU_SRAM_ECC_V3): ... this.
+ (EF_AMDGPU_FEATURE_XNACK_V4): New.
+ (EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4): New.
+ (EF_AMDGPU_FEATURE_XNACK_ANY_V4): New.
+ (EF_AMDGPU_FEATURE_XNACK_OFF_V4): New.
+ (EF_AMDGPU_FEATURE_XNACK_ON_V4): New.
+ (EF_AMDGPU_FEATURE_SRAMECC_V4): New.
+ (EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4): New.
+ (EF_AMDGPU_FEATURE_SRAMECC_ANY_V4): New.
+ (EF_AMDGPU_FEATURE_SRAMECC_OFF_V4): New.
+ (EF_AMDGPU_FEATURE_SRAMECC_ON_V4): New.
+ (SET_XNACK_ON): New.
+ (SET_XNACK_OFF): New.
+ (TEST_XNACK): New.
+ (SET_SRAM_ECC_ON): New.
+ (SET_SRAM_ECC_ANY): New.
+ (SET_SRAM_ECC_OFF): New.
+ (TEST_SRAM_ECC_ANY): New.
+ (TEST_SRAM_ECC_ON): New.
+ (main): Implement HSACOv4 and -msram-ecc=any.
+
+2021-10-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * config.in: Regenerate.
+ * config/gcn/gcn-hsa.h (X_FIJI): New macro.
+ (X_900): New macro.
+ (X_906): New macro.
+ (X_908): New macro.
+ (A_FIJI): Rename to ...
+ (S_FIJI): ... this.
+ (A_900): Rename to ...
+ (S_900): ... this.
+ (A_906): Rename to ...
+ (S_906): ... this.
+ (A_908): Rename to ...
+ (S_908): ... this.
+ (SRAMOPT): New macro.
+ (ASM_SPEC): Adjust xnack option usage.
+ * config/gcn/gcn.c (output_file_start): Adjust amdgcn_target usage.
+ * configure: Regenerate.
+ * configure.ac: Detect LLVM assembler dialect.
+
+2021-10-07 Richard Biener <rguenther@suse.de>
+
+ * tree-pretty-print.c (dump_generic_node): Do not elide
+ printing '&' when dumping with -gimple.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::adjust_range): Call new
+ intersect routine.
+ * gimple-range-fold.cc (adjust_pointer_diff_expr): Ditto.
+ (adjust_imagpart_expr): Ditto.
+ * value-range.cc (irange::irange_intersect): Call new routine if
+ RHS is a single pair.
+ (irange::intersect): New wide_int version.
+ * value-range.h (class irange): New prototype.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-edge.cc (gimple_outgoing_range::gimple_outgoing_range):
+ Add parameter to limit size when recognizing switches.
+ (gimple_outgoing_range::edge_range_p): Check size limit.
+ * gimple-range-edge.h (gimple_outgoing_range): Add size field.
+ * gimple-range-gori.cc (gori_map::calculate_gori): Ignore switches
+ that exceed the size limit.
+ (gori_compute::gori_compute): Add initializer.
+ * params.opt (evrp-switch-limit): New.
+ * doc/invoke.texi: Update docs.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * value-range.h (irange::set_varying): Use TYPE_MIN_VALUE and
+ TYPE_MAX_VALUE instead of creating new trees when possible.
+
+2021-10-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::adjust_range): Check for
+ zero and non-zero more efficently.
+
+2021-10-06 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * dumpfile.h (TDF_GIMPLE_VAL): New.
+ (dump_flag): Re-order and adjust TDF_* flags. Make
+ the enum uint32_t. Use std::underlying_type in the
+ operator overloads.
+ (optgroup_flag): Likewise for the operator overloads.
+ * tree-pretty-print.c (dump_generic_node): Wrap ADDR_EXPR
+ in _Literal if TDF_GIMPLE_VAL.
+ * gimple-pretty-print.c (dump_gimple_assign): Add
+ TDF_GIMPLE_VAL to flags when dumping operands where only
+ is_gimple_val are allowed.
+ (dump_gimple_cond): Likewise.
+
+2021-10-06 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Remove redundant if
+ condition.
+
+2021-10-05 qing zhao <qing.zhao@oracle.com>
+
+ PR middle-end/102359
+ * gimplify.c (gimplify_decl_expr): Not add initialization for an
+ auto variable when it has been initialized by frontend.
+
+2021-10-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (jt_path_registry::cancel_invalid_paths):
+ Loosen restrictions
+
+2021-10-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * common/config/avr/avr-common.c (avr_handle_option): Mark
+ argument as ATTRIBUTE_UNUSED.
+
+2021-10-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/lm32/uclinux-elf.h (LINK_GCC_C_SEQUENCE_SPEC):
+ Undefine before redefinition.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * toplev.c (no_backend): Remove global var.
+ (process_options): Pass in no_backend, move post_options
+ langhook call to toplev::main.
+ (do_compile): Pass in no_backend, move process_options call
+ to toplev::main.
+ (toplev::run_self_tests): Check no_backend at the caller.
+ (toplev::main): Call post_options and process_options
+ split out from do_compile, do self-tests only if
+ no_backend is initialized.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * tree-cfg.c (dump_function_to_file): Dump the UID of the
+ function as part of the name when requested.
+ * tree-pretty-print.c (dump_function_name): Dump the UID when
+ requested and the langhook produced the actual name.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ PR middle-end/102285
+ * internal-fn.c (expand_DEFERRED_INIT): Fall back to
+ zero-initialization as last resort, use the constant
+ size as given by the DEFERRED_INIT argument to build
+ the initializer.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * doc/invoke.texi: Document -Warray-compare.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * gimplify.c (is_var_need_auto_init): DECL_HARD_REGISTER
+ variables are not to be initialized.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * expr.h (non_mem_decl_p): Declare.
+ (mem_ref_refers_to_non_mem_p): Likewise.
+ * expr.c (non_mem_decl_p): Export.
+ (mem_ref_refers_to_non_mem_p): Likewise.
+ * internal-fn.c (expand_DEFERRED_INIT): Do not expand the LHS
+ but check the base with mem_ref_refers_to_non_mem_p
+ and non_mem_decl_p.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102570
+ * tree-ssa-sccvn.h (vn_reference_op_struct): Document
+ we are using clique for the internal function code.
+ * tree-ssa-sccvn.c (vn_reference_op_eq): Compare the
+ internal function code.
+ (print_vn_reference_ops): Print the internal function code.
+ (vn_reference_op_compute_hash): Hash it.
+ (copy_reference_ops_from_call): Record it.
+ (visit_stmt): Remove the restriction around internal function
+ calls.
+ (fully_constant_vn_reference_p): Use fold_const_call and handle
+ internal functions.
+ (vn_reference_eq): Compare call return types.
+ * tree-ssa-pre.c (create_expression_by_pieces): Handle
+ generating calls to internal functions.
+ (compute_avail): Remove the restriction around internal function
+ calls.
+
+2021-10-04 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102560
+ * gimple-ssa-warn-alloca.c (alloca_call_type): Remove static
+ marker for invalid_range.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ * internal-fn.c (expand_DEFERRED_INIT): Guard register
+ initialization path an avoid initializing VLA registers
+ with it.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/rs6000/vxworks.h (TARGET_INIT_LIBFUNCS): Delete.
+
+2021-10-03 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): Check opt_index if it is a part
+ of cl_options.
+
+2021-10-02 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102563
+ * range-op.cc (operator_lshift::op1_range): Do not clobber
+ range.
+
+2021-10-02 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): save_decoded_options[0] is program
+ name and so it should be skipped.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102546
+ * range-op.cc (operator_lshift::op1_range): Teach range-ops that
+ X << Y is non-zero implies X is also non-zero.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-X2 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-A710 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): New
+ Cortex-A510 core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * doc/invoke.texi (-Waddress): Update.
+ * gengtype.c (write_types): Avoid -Waddress.
+ * poly-int.h (POLY_SET_COEFF): Avoid using null.
+
+2021-10-01 John David Anglin <danglin@gcc.gnu.org>
+
+ PR debug/102373
+ * config/pa/pa.c (pa_option_override): Default to dwarf version 4
+ on hppa64-hpux.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_FL_V9): Update value.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::compute_ranges): Use
+ get_path_oracle.
+ * gimple-range-path.h (class path_range_query): Remove shadowed
+ m_oracle field.
+ (path_range_query::get_path_oracle): New.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * doc/invoke.texi (-fsanitize=integer-divide-by-zero): Remove
+ INT_MIN / -1 division detection from here ...
+ (-fsanitize=signed-integer-overflow): ... and add it here.
+
+2021-10-01 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-arches.def (AARCH64_ARCH): Added
+ armv9-a.
+ * config/aarch64/aarch64.h (AARCH64_FL_V9): New.
+ (AARCH64_FL_FOR_ARCH9): New flags for Armv9-A.
+ (AARCH64_ISA_V9): New ISA flag.
+ * doc/invoke.texi: Update docs.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * toplev.c (toplev::main): Save decoded optimization options.
+ * toplev.h (save_opt_decoded_options): New.
+ * doc/extend.texi: Be more clear about optimize and target
+ attributes.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * explow.c: Include langhooks.h.
+ (set_stack_check_libfunc): Build a proper function type.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c++/64697
+ * config/i386/i386.c (legitimate_pic_address_disp_p): For PE-COFF do
+ not return true for external weak function symbols in medium model.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_ORDER_REPRODUCIBLE): Define.
+ * tree-pretty-print.c (dump_omp_clause) <case OMP_CLAUSE_ORDER>: Print
+ reproducible: for OMP_CLAUSE_ORDER_REPRODUCIBLE.
+ * omp-general.c (omp_extract_for_data): If OMP_CLAUSE_ORDER is seen
+ without OMP_CLAUSE_ORDER_UNCONSTRAINED, overwrite sched_kind to
+ OMP_CLAUSE_SCHEDULE_STATIC.
+
+2021-10-01 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102518
+ * tree-inline.c (setup_one_parameter): Avoid substituting
+ an invariant into contexts where a GIMPLE register is not valid.
+
+2021-09-30 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/arm/arm-cpus.in: Add Cortex-R52+ CPU.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2021-09-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89954
+ * config/i386/i386.md
+ (sign_extend:WIDE (any_logic:NARROW (memory, immediate)) splitters):
+ New splitters.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * omp-low.c (omp_runtime_api_call): Add omp_aligned_{,c}alloc and
+ omp_{c,re}alloc, fix omp_alloc/omp_free.
+
+2021-09-30 Martin Liska <mliska@suse.cz>
+
+ * defaults.h (ASM_OUTPUT_ASCII): Do not hide global variable
+ asm_out_file and stream directly to MYFILE.
+
+2021-09-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel):
+ Restore and fix condition under which we apply npeel to
+ the DRs misalignment value.
+
+2021-09-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel):
+ Fix npeel check for variable amount of peeling.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * lto-wrapper.c (run_gcc): Plug snprintf overflow.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range.cc (gimple_ranger::debug): New.
+ * gimple-range.h (class gimple_ranger): Add debug.
+
+2021-09-30 Aldy Hernandez <aldyh@redhat.com>
+
+ PR middle-end/102519
+ * tree-vrp.c (hybrid_threader::~hybrid_threader): Free m_query.
+
+2021-09-29 Indu Bhagat <indu.bhagat@oracle.com>
+
+ PR debug/102507
+ * btfout.c (GTY): Add GTY (()) albeit for cosmetic only purpose.
+ (btf_finalize): Empty the hash_map btf_var_ids.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (thread_through_all_blocks): Return bool.
+ (execute_vrp_threader): Return TODO_* flags.
+ (pass_data_vrp_threader): Set todo_flags_finish to 0.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * timevar.def (TV_TREE_VRP_THREADER): New.
+ * tree-vrp.c: Use TV_TREE_VRP_THREADER for VRP threader pass.
+
+2021-09-29 David Faust <david.faust@oracle.com>
+
+ * config.gcc (bpf-*-*): Do not overwrite extra_headers.
+
+2021-09-29 Jonathan Wright <jonathan.wright@arm.com>
+
+ * config/aarch64/aarch64-builtins.c (TYPES_BINOP_PPU): Define
+ new type qualifier enum.
+ (TYPES_TERNOP_SSSU): Likewise.
+ (TYPES_TERNOP_PPPU): Likewise.
+ * config/aarch64/aarch64-simd-builtins.def: Define PPU, SSU,
+ PPPU and SSSU builtin generator macros for qtbl1 and qtbx1
+ Neon builtins.
+ * config/aarch64/arm_neon.h (vqtbl1_p8): Use type-qualified
+ builtin and remove casts.
+ (vqtbl1_s8): Likewise.
+ (vqtbl1q_p8): Likewise.
+ (vqtbl1q_s8): Likewise.
+ (vqtbx1_s8): Likewise.
+ (vqtbx1_p8): Likewise.
+ (vqtbx1q_s8): Likewise.
+ (vqtbx1q_p8): Likewise.
+ (vtbl1_p8): Likewise.
+ (vtbl2_p8): Likewise.
+ (vtbx2_p8): Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_dr_misalign_for_aligned_access):
+ New helper.
+ (vect_update_misalignment_for_peel): Use it to update
+ misaligned to the value necessary for an aligned access.
+ (vect_get_peeling_costs_all_drs): Likewise.
+ (vect_enhance_data_refs_alignment): Likewise.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_cpymem): Count number of
+ emitted operations and adjust heuristic for code size.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_setmem): Count number of
+ emitted operations and adjust heuristic for code size.
+
+2021-09-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102504
+ * gimplify.c (gimplify_scan_omp_clauses): Use omp_check_private even
+ in OMP_SCOPE clauses, not just on worksharing construct clauses.
+
+2021-09-28 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/riscv/riscv.md (mulv<mode>4): Call gen_smul<mode>3_highpart.
+ (<u>mulditi3): Call <su>muldi3_highpart.
+ (<u>muldi3_highpart): Rename to <su>muldi3_highpart.
+ (<u>mulsidi3): Call <su>mulsi3_highpart.
+ (<u>mulsi3_highpart): Rename to <su>mulsi3_highpart.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (DSYMUTIL_SPEC): Recognize D sources.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h (FIXED_R13): Add for PPC64.
+ (FIRST_SAVED_GP_REGNO): Save from R13 even when it is one
+ of the fixed regs.
+
+2021-09-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_FL_LS64): Define
+ (AARCH64_FL_V8_7): Likewise.
+ (AARCH64_FL_FOR_ARCH8_7): Likewise.
+ * config/aarch64/aarch64-arches.def (armv8.7-a): Define.
+ * config/aarch64/aarch64-option-extensions.def (ls64): Define.
+ * doc/invoke.texi: Document the above.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * dbgcnt.c (dbg_cnt_counter): New.
+ * dbgcnt.h (dbg_cnt_counter): New.
+ * dumpfile.c (dump_options): Add entry for TDF_THREADING.
+ * dumpfile.h (enum dump_flag): Add TDF_THREADING.
+ * gimple-range-path.cc (DEBUG_SOLVER): Use TDF_THREADING.
+ * tree-ssa-threadupdate.c (dump_jump_thread_path): Dump out
+ debug counter.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * cfgcleanup.c (pass_jump::execute): Check
+ flag_expensive_optimizations.
+ (pass_jump_after_combine::gate): Same.
+ * doc/invoke.texi (-fthread-jumps): Enable for -O1.
+ * opts.c (default_options_table): Enable -fthread-jumps at -O1.
+ * tree-ssa-threadupdate.c
+ (fwd_jt_path_registry::remove_jump_threads_including): Bail unless
+ flag_thread_jumps.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-reassoc.c (biased_names): New global.
+ (propagate_bias_p): New function.
+ (loop_carried_phi): Remove.
+ (propagate_rank): Propagate bias along single uses.
+ (get_rank): Update biased_names when needed.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * passes.def (pass_reassoc): Rename parameter to early_p.
+ * tree-ssa-reassoc.c (reassoc_bias_loop_carried_phi_ranks_p):
+ New variable.
+ (phi_rank): Don't bias loop-carried phi ranks
+ before vectorization pass.
+ (execute_reassoc): Add bias_loop_carried_phi_ranks_p parameter.
+ (pass_reassoc::pass_reassoc): Add bias_loop_carried_phi_ranks_p
+ initializer.
+ (pass_reassoc::set_param): Set bias_loop_carried_phi_ranks_p
+ value.
+ (pass_reassoc::execute): Pass bias_loop_carried_phi_ranks_p to
+ execute_reassoc.
+ (pass_reassoc::bias_loop_carried_phi_ranks_p): New member.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102498
+ * config/i386/i386.c (standard_80387_constant_p): Don't recognize
+ special 80387 instruction XFmode constants if flag_rounding_math.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/100112
+ * tree-ssa-sccvn.c (visit_reference_op_load): Record the
+ referece into the hashtable twice in case last_vuse is
+ different from the original vuse on the stmt.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102492
+ * gimplify.c (gimplify_adjust_omp_clauses_1): Don't call the
+ omp_finish_clause langhook on implicitly added OMP_CLAUSE_PRIVATE
+ clauses on SIMD constructs.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102511
+ * gimple-range-path.cc (path_range_query::range_on_path_entry):
+ Return VARYING when nothing found.
+
+2021-09-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/102230
+ * config/i386/i386.h (VALID_AVX512FP16_REG_MODE): Add
+ V2HF mode check.
+ (VALID_SSE2_REG_VHF_MODE): Add V4HFmode and V2HFmode.
+ (VALID_MMX_REG_MODE): Add V4HFmode.
+ (SSE_REG_MODE_P): Replace VALID_AVX512FP16_REG_MODE with
+ vector mode condition.
+ * config/i386/i386.c (classify_argument): Parse V4HF/V2HF
+ via sse regs.
+ (function_arg_32): Add V4HFmode.
+ (function_arg_advance_32): Likewise.
+ * config/i386/i386.md (mode): Add V4HF/V2HF.
+ (MODE_SIZE): Likewise.
+ * config/i386/mmx.md (MMXMODE): Add V4HF mode.
+ (V_32): Add V2HF mode.
+ (VHF_32_64): New mode iterator.
+ (*mov<mode>_internal): Adjust sse alternatives to support
+ V4HF mode move.
+ (*mov<mode>_internal): Adjust sse alternatives to support
+ V2HF mode move.
+ (<insn><mode>3): New define_insn for add/sub/mul/div.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (pass_thread_jumps::gate): Check
+ flag_thread_jumps.
+ (pass_early_thread_jumps::gate): Same.
+ * tree-ssa-threadedge.c (jump_threader::thread_outgoing_edges):
+ Return if !flag_thread_jumps.
+ * tree-ssa-threadupdate.c
+ (jt_path_registry::register_jump_thread): Assert that
+ flag_thread_jumps is true.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * simplify-rtx.c
+ (simplify_context::simplify_binary_operation_1): Relax
+ condition of simplifying (vec_concat:M (vec_select op0
+ index0)(vec_select op1 index1)) to allow different modes
+ between op0 and M, but have same inner mode.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-expand.c (emit_reduc_half): Handle
+ V8HF/V16HF/V32HFmode.
+ * config/i386/sse.md (REDUC_SSE_PLUS_MODE): Add V8HF.
+ (REDUC_SSE_SMINMAX_MODE): Ditto.
+ (REDUC_PLUS_MODE): Add V16HF and V32HF.
+ (REDUC_SMINMAX_MODE): Ditto.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc
+ (path_range_query::precompute_ranges_in_block): Rename to...
+ (path_range_query::compute_ranges_in_block): ...this.
+ (path_range_query::precompute_ranges): Rename to...
+ (path_range_query::compute_ranges): ...this.
+ (path_range_query::precompute_relations): Rename to...
+ (path_range_query::compute_relations): ...this.
+ (path_range_query::precompute_phi_relations): Rename to...
+ (path_range_query::compute_phi_relations): ...this.
+ * gimple-range-path.h: Rename precompute* to compute*.
+ * tree-ssa-threadbackward.c
+ (back_threader::find_taken_edge_switch): Same.
+ (back_threader::find_taken_edge_cond): Same.
+ * tree-ssa-threadedge.c
+ (hybrid_jt_simplifier::compute_ranges_from_state): Same.
+ (hybrid_jt_state::register_equivs_stmt): Inline...
+ * tree-ssa-threadedge.h: ...here.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (lhs_of_dominating_assert): Remove.
+ (class vrp_jt_state): Remove.
+ (class vrp_jt_simplifier): Remove.
+ (vrp_jt_simplifier::simplify): Remove.
+ (class vrp_jump_threader): Remove.
+ (vrp_jump_threader::vrp_jump_threader): Remove.
+ (vrp_jump_threader::~vrp_jump_threader): Remove.
+ (vrp_jump_threader::before_dom_children): Remove.
+ (vrp_jump_threader::after_dom_children): Remove.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * passes.def (pass_vrp_threader): New.
+ * tree-pass.h (make_pass_vrp_threader): Add make_pass_vrp_threader.
+ * tree-ssa-threadedge.c (hybrid_jt_state::register_equivs_stmt): New.
+ (hybrid_jt_simplifier::hybrid_jt_simplifier): New.
+ (hybrid_jt_simplifier::simplify): New.
+ (hybrid_jt_simplifier::compute_ranges_from_state): New.
+ * tree-ssa-threadedge.h (class hybrid_jt_state): New.
+ (class hybrid_jt_simplifier): New.
+ * tree-vrp.c (execute_vrp): Remove ASSERT_EXPR based jump
+ threader.
+ (class hybrid_threader): New.
+ (hybrid_threader::hybrid_threader): New.
+ (hybrid_threader::~hybrid_threader): New.
+ (hybrid_threader::before_dom_children): New.
+ (hybrid_threader::after_dom_children): New.
+ (execute_vrp_threader): New.
+ (class pass_vrp_threader): New.
+ (make_pass_vrp_threader): New.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * output.h (enum section_flag): New.
+ (SECTION_FORGET): Remove.
+ (SECTION_ENTSIZE): Make it (1UL << 8) - 1.
+ (SECTION_STYLE_MASK): Define it based on other enum
+ values.
+ * varasm.c (switch_to_section): Remove unused handling of
+ SECTION_FORGET.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Add new variable flag_default_complex_method.
+ * opts.c (finish_options): Handle flags related to
+ x_flag_complex_method.
+ * toplev.c (process_options): Remove option handling related
+ to flag_complex_method.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102450
+ * gimple-fold.c (gimple_fold_builtin_memory_op): Avoid using
+ type_for_size, instead use int_mode_for_size.
+
+2021-09-27 Andrew Pinski <apinski@marvell.com>
+
+ PR c/94726
+ * gimplify.c (gimplify_save_expr): Return early
+ if the type of val is error_mark_node.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssanames.c (ssa_name_has_boolean_range): Use
+ get_range_query.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Remove
+ vrp_visit_cond_stmt.
+ * tree-ssa-dom.c (cprop_operand): Convert to range_query API.
+ (cprop_into_stmt): Same.
+ (dom_opt_dom_walker::optimize_stmt): Same.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97351
+ PR tree-optimization/97352
+ PR tree-optimization/82426
+ * tree-vectorizer.h (dr_misalignment): Add vector type
+ argument.
+ (aligned_access_p): Likewise.
+ (known_alignment_for_access_p): Likewise.
+ (vect_supportable_dr_alignment): Likewise.
+ (vect_known_alignment_in_bytes): Likewise. Refactor.
+ (DR_MISALIGNMENT): Remove.
+ (vect_update_shared_vectype): Likewise.
+ * tree-vect-data-refs.c (dr_misalignment): Refactor, handle
+ a vector type with larger alignment requirement and apply
+ the negative step adjustment here.
+ (vect_calculate_target_alignment): Remove.
+ (vect_compute_data_ref_alignment): Get explicit vector type
+ argument, do not apply a negative step alignment adjustment
+ here.
+ (vect_slp_analyze_node_alignment): Re-analyze alignment
+ when we re-visit the DR with a bigger desired alignment but
+ keep more precise results from smaller alignments.
+ * tree-vect-slp.c (vect_update_shared_vectype): Remove.
+ (vect_slp_analyze_node_operations_1): Do not update the
+ shared vector type on stmts.
+ * tree-vect-stmts.c (vect_analyze_stmt): Push/pop the
+ vector type of an SLP node to the representative stmt-info.
+ (vect_transform_stmt): Likewise.
+
+2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * config/i386/sse.md (reduc_plus_scal_<mode>): Split to ..
+ (reduc_plus_scal_v4sf): .. this, New define_expand.
+ (reduc_plus_scal_v2df): .. and this, New define_expand.
+
+2021-09-26 liuhongt <hongtao.liu@intel.com>
+
+ * doc/extend.texi (Half-Precision): Remove storage only
+ description for _Float16 w/o avx512fp16.
+
+2021-09-25 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * config/pru/constraints.md (Rrio): New constraint.
+ * config/pru/predicates.md (regio_operand): New predicate.
+ * config/pru/pru-pragma.c (pru_register_pragmas): Register
+ the __regio_symbol address space.
+ * config/pru/pru-protos.h (pru_symref2ioregno): Declaration.
+ * config/pru/pru.c (pru_symref2ioregno): New helper function.
+ (pru_legitimate_address_p): Remove.
+ (pru_addr_space_legitimate_address_p): Use the address space
+ aware hook variant.
+ (pru_nongeneric_pointer_addrspace): New helper function.
+ (pru_insert_attributes): New function to validate __regio_symbol
+ usage.
+ (TARGET_INSERT_ATTRIBUTES): New macro.
+ (TARGET_LEGITIMATE_ADDRESS_P): Remove.
+ (TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): New macro.
+ * config/pru/pru.h (enum reg_class): Add REGIO_REGS class.
+ * config/pru/pru.md (*regio_readsi): New pattern to read I/O
+ registers.
+ (*regio_nozext_writesi): New pattern to write to I/O registers.
+ (*regio_zext_write_r30<EQS0:mode>): Ditto.
+ * doc/extend.texi: Document the new PRU Named Address Space.
+
+2021-09-24 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98216
+ PR c++/91292
+ * real.c (encode_ieee_double): Avoid unwanted sign extension.
+ (encode_ieee_quad): Likewise.
+
+2021-09-24 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/102147
+ * ira-build.c (ira_conflict_vector_profitable_p): Make
+ profitability calculation independent of host compiler pointer and
+ IRA_INT_BITS sizes.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::path_range_query):
+ Move debugging header...
+ (path_range_query::precompute_ranges): ...here.
+ (path_range_query::internal_range_of_expr): Do not call
+ range_on_path_entry if NAME is defined in the current block.
+
+2021-09-24 Richard Biener <rguenther@suse.de>
+
+ * cfghooks.c (verify_flow_info): Verify unallocated BB and
+ edge flags are not set.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (jt_path_registry::cancel_invalid_paths):
+ New.
+ (jt_path_registry::register_jump_thread): Call
+ cancel_invalid_paths.
+ * tree-ssa-threadupdate.h (class jt_path_registry): Add
+ cancel_invalid_paths.
+
+2021-09-24 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/102400
+ * tree-ssa-sccvn.c (vn_reference_insert_pieces): Initialize
+ result_vdef to zero value.
+
+2021-09-24 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/102451
+ * tree-ssa-dse.c (delete_dead_or_redundant_call): Record bb of stmt
+ before removal.
+
+2021-09-24 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (cond_<insn><mode>): Extend to support
+ vector HFmodes.
+ (cond_mul<mode>): Likewise.
+ (cond_div<mode>): Likewise.
+ (cond_<code><mode>): Likewise.
+ (cond_fma<mode>): Likewise.
+ (cond_fms<mode>): Likewise.
+ (cond_fnma<mode>): Likewise.
+ (cond_fnms<mode>): Likewise.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/102463
+ * gimple-range-fold.cc (fold_using_range::relation_fold_and_or): If
+ there is no range-ops handler, don't look for a relation.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::ranger_cache): Take
+ non-executable_edge flag as parameter.
+ * gimple-range-cache.h (ranger_cache): Adjust prototype.
+ * gimple-range-gori.cc (gori_compute::gori_compute): Take
+ non-executable_edge flag as parameter.
+ (gori_compute::outgoing_edge_range_p): Check new flag.
+ * gimple-range-gori.h (gori_compute): Adjust prototype.
+ * gimple-range.cc (gimple_ranger::gimple_ranger): Create new flag.
+ (gimple_ranger::range_on_edge): Check new flag.
+ * gimple-range.h (gimple_ranger::non_executable_edge_flag): New.
+ * gimple-ssa-evrp.c (rvrp_folder): Pass ranger flag to simplifer.
+ (hybrid_folder::hybrid_folder): Set ranger non-executable flag value.
+ (hybrid_folder::fold_stmt): Set flag value in the simplifer.
+ * vr-values.c (simplify_using_ranges::set_and_propagate_unexecutable):
+ Use not_executable flag if provided inmstead of EDGE_EXECUTABLE.
+ (simplify_using_ranges::simplify_switch_using_ranges): Clear
+ EDGE_EXECUTABLE like it originally did.
+ (simplify_using_ranges::cleanup_edges_and_switches): Clear any
+ NON_EXECUTABLE flags.
+ (simplify_using_ranges::simplify_using_ranges): Adjust.
+ * vr-values.h (class simplify_using_ranges): Adjust.
+ (simplify_using_ranges::set_range_query): Add non-executable flag param.
+
+2021-09-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/102024
+ * config/rs6000/rs6000-call.c (rs6000_aggregate_candidate): Detect
+ zero-width bit fields and return indicator.
+ (rs6000_discover_homogeneous_aggregate): Diagnose when the
+ presence of a zero-width bit field changes parameter passing in
+ GCC 12.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_phi):
+ Remove dominator check.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::precompute_relations):
+ Hoist edge calculations before using EDGE_SUCC.
+
+2021-09-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * configure.ac: Fix --with-multilib-list description.
+ * configure: Regenerate.
+
+2021-09-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102448
+ * tree-vect-data-refs.c (vect_duplicate_ssa_name_ptr_info):
+ Clear alignment info copied from DR_PTR_INFO.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386-expand.c (ix86_use_mask_cmp_p): Enable
+ HFmode mask_cmp.
+ * config/i386/sse.md (sseintvecmodelower): Add HF vector modes.
+ (<avx512>_store<mode>_mask): Extend to support HF vector modes.
+ (vec_cmp<mode><avx512fmaskmodelower>): Likewise.
+ (vcond_mask_<mode><avx512fmaskmodelower>): Likewise.
+ (vcond<mode><mode>): New expander.
+ (vcond<mode><sseintvecmodelower>): Likewise.
+ (vcond<sseintvecmodelower><mode>): Likewise.
+ (vcondu<mode><sseintvecmodelower>): Likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (extend<ssePHmodelower><mode>2):
+ New expander.
+ (extendv4hf<mode>2): Likewise.
+ (extendv2hfv2df2): Likewise.
+ (trunc<mode><ssePHmodelower>2): Likewise.
+ (avx512fp16_vcvt<castmode>2ph_<mode>): Rename to ...
+ (trunc<mode>v4hf2): ... this, and drop constraints.
+ (avx512fp16_vcvtpd2ph_v2df): Rename to ...
+ (truncv2dfv2hf2): ... this, and likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/sse.md (float<floatunssuffix><mode><ssePHmodelower>2):
+ New expander.
+ (avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>):
+ Rename to ...
+ (float<floatunssuffix><mode>v4hf2): ... this, and drop constraints.
+ (avx512fp16_vcvt<floatsuffix>qq2ph_v2di): Rename to ...
+ (float<floatunssuffix>v2div2hf2): ... this, and likewise.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386.md (fix<fixunssuffix>_trunchf<mode>2): New expander.
+ (fixuns_trunchfhi2): Likewise.
+ (*fixuns_trunchfsi2zext): New define_insn.
+ * config/i386/sse.md (ssePHmodelower): New mode_attr.
+ (fix<fixunssuffix>_trunc<ssePHmodelower><mode>2):
+ New expander for same element vector fix_truncate.
+ (fix<fixunssuffix>_trunc<ssePHmodelower><mode>2):
+ Likewise for V4HF to V4SI/V4DI fix_truncate.
+ (fix<fixunssuffix>_truncv2hfv2di2):
+ Likeise for V2HF to V2DI fix_truncate.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386.md (<code>hf3): New expander.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/sse.md (FMAMODEM): extend to handle FP16.
+ (VFH_SF_AVX512VL): Extend to handle HFmode.
+ (VF_SF_AVX512VL): Deleted.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (rinthf2): New expander.
+ (nearbyinthf2): New expander.
+
+2021-09-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-dom.c (class dom_jump_threader_simplifier): Rename...
+ (class dom_jt_state): ...this and provide virtual overrides.
+ (dom_jt_state::register_equiv): New.
+ (class dom_jt_simplifier): Rename from
+ dom_jump_threader_simplifier.
+ (dom_jump_threader_simplifier::simplify): Rename...
+ (dom_jt_simplifier::simplify): ...to this.
+ (pass_dominator::execute): Use dom_jt_simplifier and
+ dom_jt_state.
+ * tree-ssa-threadedge.c (jump_threader::jump_threader):
+ Clean-up.
+ (jt_state::register_equivs_stmt): Abstract out...
+ (jump_threader::record_temporary_equivalences_from_stmts_at_dest):
+ ...from here.
+ (jump_threader::thread_around_empty_blocks): Update state.
+ (jump_threader::thread_through_normal_block): Same.
+ (jt_state::jt_state): Remove.
+ (jt_state::push): Remove pass specific bits. Keep block vector
+ updated.
+ (jt_state::append_path): New.
+ (jt_state::pop): Remove pass specific bits.
+ (jt_state::register_equiv): Same.
+ (jt_state::record_ranges_from_stmt): Same.
+ (jt_state::register_equivs_on_edge): Same. Rename...
+ (jt_state::register_equivs_edge): ...to this.
+ (jt_state::dump): New.
+ (jt_state::debug): New.
+ (jump_threader_simplifier::simplify): Remove.
+ (jt_state::get_path): New.
+ * tree-ssa-threadedge.h (class jt_simplifier): Make into a base
+ class. Expose common functionality as virtual methods.
+ (class jump_threader_simplifier): Same. Rename...
+ (class jt_simplifier): ...to this.
+ * tree-vrp.c (class vrp_jump_threader_simplifier): Rename...
+ (class vrp_jt_simplifier): ...to this. Provide pass specific
+ overrides.
+ (class vrp_jt_state): New.
+ (vrp_jump_threader_simplifier::simplify): Rename...
+ (vrp_jt_simplifier::simplify): ...to this. Inline code from
+ what used to be the base class.
+ (vrp_jump_threader::vrp_jump_threader): Use vrp_jt_state and
+ vrp_jt_simplifier.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * doc/invoke.texi (-Wno-missing-include-dirs.): Document Fortran
+ behavior.
+
+2021-09-22 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * match.pd (negation simplifications): Implement some negation
+ folding transformations from fold-const.c's fold_negate_expr.
+ * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Add a SIMPLIFY
+ argument, to control whether the op should be simplified prior
+ to looking up/assigning a value number.
+ (vn_nary_build_or_lookup): Update call to vn_nary_build_or_lookup_1.
+ (vn_nary_simplify): Likewise.
+ (visit_nary_op): Likewise, but when constructing a NEGATE_EXPR
+ now call vn_nary_build_or_lookup_1 disabling simplification.
+
+2021-09-22 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR tree-optimization/102087
+ * tree-ssa-loop-niter.c (number_of_iterations_until_wrap):
+ Update bound/cmp/control for niter.
+
+2021-09-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_range_op):
+ Move check for non-empty BB here.
+ (fur_source::register_outgoing_edges): ...from here.
+
+2021-09-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::internal_range_of_expr):
+ Remove call to improve_range_with_equivs.
+ (path_range_query::improve_range_with_equivs): Remove
+ * gimple-range-path.h: Remove improve_range_with_equivs.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h:
+ (_mm512_mask_blend_ph): New intrinsic.
+ (_mm512_permutex2var_ph): Ditto.
+ (_mm512_permutexvar_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h:
+ (_mm256_mask_blend_ph): New intrinsic.
+ (_mm256_permutex2var_ph): Ditto.
+ (_mm256_permutexvar_ph): Ditto.
+ (_mm_mask_blend_ph): Ditto.
+ (_mm_permutex2var_ph): Ditto.
+ (_mm_permutexvar_ph): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: Add new intrinsics.
+ (_mm512_conj_pch): New intrinsic.
+ (_mm512_mask_conj_pch): Ditto.
+ (_mm512_maskz_conj_pch): Ditto.
+ * config/i386/avx512fp16vlintrin.h: Add new intrinsics.
+ (_mm256_conj_pch): New intrinsic.
+ (_mm256_mask_conj_pch): Ditto.
+ (_mm256_maskz_conj_pch): Ditto.
+ (_mm_conj_pch): Ditto.
+ (_mm_mask_conj_pch): Ditto.
+ (_mm_maskz_conj_pch): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_MM512_REDUCE_OP): New macro
+ (_mm512_reduce_add_ph): New intrinsic.
+ (_mm512_reduce_mul_ph): Ditto.
+ (_mm512_reduce_min_ph): Ditto.
+ (_mm512_reduce_max_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h
+ (_MM256_REDUCE_OP/_MM_REDUCE_OP): New macro.
+ (_mm256_reduce_add_ph): New intrinsic.
+ (_mm256_reduce_mul_ph): Ditto.
+ (_mm256_reduce_min_ph): Ditto.
+ (_mm256_reduce_max_ph): Ditto.
+ (_mm_reduce_add_ph): Ditto.
+ (_mm_reduce_mul_ph): Ditto.
+ (_mm_reduce_min_ph): Ditto.
+ (_mm_reduce_max_ph): Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (__m512h_u, __m256h_u,
+ __m128h_u): New typedef.
+ (_mm512_load_ph): New intrinsic.
+ (_mm256_load_ph): Ditto.
+ (_mm_load_ph): Ditto.
+ (_mm512_loadu_ph): Ditto.
+ (_mm256_loadu_ph): Ditto.
+ (_mm_loadu_ph): Ditto.
+ (_mm512_store_ph): Ditto.
+ (_mm256_store_ph): Ditto.
+ (_mm_store_ph): Ditto.
+ (_mm512_storeu_ph): Ditto.
+ (_mm256_storeu_ph): Ditto.
+ (_mm_storeu_ph): Ditto.
+ (_mm512_abs_ph): Ditto.
+ * config/i386/avx512fp16vlintrin.h
+ (_mm_abs_ph): Ditto.
+ (_mm256_abs_ph): Ditto.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/tpf.md (prologue_tpf, epilogue_tpf): Add cc clobber.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/102222
+ * config/s390/s390.c (s390_expand_insv): Emit a normal move if it
+ is actually a full copy of the source operand into the target.
+ Don't emit a strict low part move if source and target mode match.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102415
+ * omp-expand.c (expand_omp_single): If region->exit is NULL,
+ assert region->entry is GIMPLE_OMP_SCOPE region and return.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_ALLOCATE_ALIGN): Define.
+ * tree.c (omp_clause_num_ops): Change number of OMP_CLAUSE_ALLOCATE
+ arguments from 2 to 3.
+ * tree-pretty-print.c (dump_omp_clause): Print allocator() around
+ allocate clause allocator and print align if present.
+ * omp-low.c (scan_sharing_clauses): Force allocate_map entry even
+ for omp_default_mem_alloc if align modifier is present. If align
+ modifier is present, use TREE_LIST to encode both allocator and
+ align.
+ (lower_private_allocate, lower_rec_input_clauses, create_task_copyfn):
+ Handle align modifier on allocator clause if present.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (define_attr "isa"): Add
+ fma_or_avx512vl.
+ (define_attr "enabled"): Correspond fma_or_avx512vl to
+ TARGET_FMA || TARGET_AVX512VL.
+ * config/i386/mmx.md (fmav2sf4): Extend to AVX512 fma.
+ (fmsv2sf4): Ditto.
+ (fnmav2sf4): Ditto.
+ (fnmsv2sf4): Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (cstorehf3): New define_expand.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (<rounding_insn>hf2): New expander.
+ (sse4_1_round<mode>2): Extend from MODEF to MODEFH.
+ * config/i386/sse.md (*sse4_1_round<ssescalarmodesuffix>):
+ Extend from VF_128 to VFH_128.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-features.c (i386-features.c): Handle
+ E_HFmode.
+ * config/i386/i386.md (sqrthf2): New expander.
+ (*sqrthf2): New define_insn.
+ * config/i386/sse.md
+ (*<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>):
+ Extend to VFH_128.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_mask_fcmadd_sch):
+ New intrinsic.
+ (_mm_mask3_fcmadd_sch): Likewise.
+ (_mm_maskz_fcmadd_sch): Likewise.
+ (_mm_fcmadd_sch): Likewise.
+ (_mm_mask_fmadd_sch): Likewise.
+ (_mm_mask3_fmadd_sch): Likewise.
+ (_mm_maskz_fmadd_sch): Likewise.
+ (_mm_fmadd_sch): Likewise.
+ (_mm_mask_fcmadd_round_sch): Likewise.
+ (_mm_mask3_fcmadd_round_sch): Likewise.
+ (_mm_maskz_fcmadd_round_sch): Likewise.
+ (_mm_fcmadd_round_sch): Likewise.
+ (_mm_mask_fmadd_round_sch): Likewise.
+ (_mm_mask3_fmadd_round_sch): Likewise.
+ (_mm_maskz_fmadd_round_sch): Likewise.
+ (_mm_fmadd_round_sch): Likewise.
+ (_mm_fcmul_sch): Likewise.
+ (_mm_mask_fcmul_sch): Likewise.
+ (_mm_maskz_fcmul_sch): Likewise.
+ (_mm_fmul_sch): Likewise.
+ (_mm_mask_fmul_sch): Likewise.
+ (_mm_maskz_fmul_sch): Likewise.
+ (_mm_fcmul_round_sch): Likewise.
+ (_mm_mask_fcmul_round_sch): Likewise.
+ (_mm_maskz_fcmul_round_sch): Likewise.
+ (_mm_fmul_round_sch): Likewise.
+ (_mm_mask_fmul_round_sch): Likewise.
+ (_mm_maskz_fmul_round_sch): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/sse.md
+ (avx512fp16_fmaddcsh_v8hf_maskz<round_expand_name>): New expander.
+ (avx512fp16_fcmaddcsh_v8hf_maskz<round_expand_name>): Ditto.
+ (avx512fp16_fma_<complexopname>sh_v8hf<mask_scalarcz_name><round_scalarcz_name>):
+ New define insn.
+ (avx512fp16_<complexopname>sh_v8hf_mask<round_name>): Ditto.
+ (avx512fp16_<complexopname>sh_v8hf<mask_scalarc_name><round_scalarcz_name>):
+ Ditto.
+ * config/i386/subst.md (mask_scalarcz_name): New.
+ (mask_scalarc_name): Ditto.
+ (mask_scalarc_operand3): Ditto.
+ (mask_scalarcz_operand4): Ditto.
+ (round_scalarcz_name): Ditto.
+ (round_scalarc_mask_operand3): Ditto.
+ (round_scalarcz_mask_operand4): Ditto.
+ (round_scalarc_mask_op3): Ditto.
+ (round_scalarcz_mask_op4): Ditto.
+ (round_scalarcz_constraint): Ditto.
+ (round_scalarcz_nimm_predicate): Ditto.
+ (mask_scalarcz): Ditto.
+ (mask_scalarc): Ditto.
+ (round_scalarcz): Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_fcmadd_pch):
+ New intrinsic.
+ (_mm512_mask_fcmadd_pch): Likewise.
+ (_mm512_mask3_fcmadd_pch): Likewise.
+ (_mm512_maskz_fcmadd_pch): Likewise.
+ (_mm512_fmadd_pch): Likewise.
+ (_mm512_mask_fmadd_pch): Likewise.
+ (_mm512_mask3_fmadd_pch): Likewise.
+ (_mm512_maskz_fmadd_pch): Likewise.
+ (_mm512_fcmadd_round_pch): Likewise.
+ (_mm512_mask_fcmadd_round_pch): Likewise.
+ (_mm512_mask3_fcmadd_round_pch): Likewise.
+ (_mm512_maskz_fcmadd_round_pch): Likewise.
+ (_mm512_fmadd_round_pch): Likewise.
+ (_mm512_mask_fmadd_round_pch): Likewise.
+ (_mm512_mask3_fmadd_round_pch): Likewise.
+ (_mm512_maskz_fmadd_round_pch): Likewise.
+ (_mm512_fcmul_pch): Likewise.
+ (_mm512_mask_fcmul_pch): Likewise.
+ (_mm512_maskz_fcmul_pch): Likewise.
+ (_mm512_fmul_pch): Likewise.
+ (_mm512_mask_fmul_pch): Likewise.
+ (_mm512_maskz_fmul_pch): Likewise.
+ (_mm512_fcmul_round_pch): Likewise.
+ (_mm512_mask_fcmul_round_pch): Likewise.
+ (_mm512_maskz_fcmul_round_pch): Likewise.
+ (_mm512_fmul_round_pch): Likewise.
+ (_mm512_mask_fmul_round_pch): Likewise.
+ (_mm512_maskz_fmul_round_pch): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_fmadd_pch):
+ New intrinsic.
+ (_mm_mask_fmadd_pch): Likewise.
+ (_mm_mask3_fmadd_pch): Likewise.
+ (_mm_maskz_fmadd_pch): Likewise.
+ (_mm256_fmadd_pch): Likewise.
+ (_mm256_mask_fmadd_pch): Likewise.
+ (_mm256_mask3_fmadd_pch): Likewise.
+ (_mm256_maskz_fmadd_pch): Likewise.
+ (_mm_fcmadd_pch): Likewise.
+ (_mm_mask_fcmadd_pch): Likewise.
+ (_mm_mask3_fcmadd_pch): Likewise.
+ (_mm_maskz_fcmadd_pch): Likewise.
+ (_mm256_fcmadd_pch): Likewise.
+ (_mm256_mask_fcmadd_pch): Likewise.
+ (_mm256_mask3_fcmadd_pch): Likewise.
+ (_mm256_maskz_fcmadd_pch): Likewise.
+ (_mm_fmul_pch): Likewise.
+ (_mm_mask_fmul_pch): Likewise.
+ (_mm_maskz_fmul_pch): Likewise.
+ (_mm256_fmul_pch): Likewise.
+ (_mm256_mask_fmul_pch): Likewise.
+ (_mm256_maskz_fmul_pch): Likewise.
+ (_mm_fcmul_pch): Likewise.
+ (_mm_mask_fcmul_pch): Likewise.
+ (_mm_maskz_fcmul_pch): Likewise.
+ (_mm256_fcmul_pch): Likewise.
+ (_mm256_mask_fcmul_pch): Likewise.
+ (_mm256_maskz_fcmul_pch): Likewise.
+ * config/i386/i386-builtin-types.def (V8HF_FTYPE_V8HF_V8HF_V8HF,
+ V8HF_FTYPE_V16HF_V16HF_V16HF, V16HF_FTYPE_V16HF_V16HF_V16HF_UQI,
+ V32HF_FTYPE_V32HF_V32HF_V32HF_INT,
+ V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT): Add new builtin types.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/i386-expand.c: Handle new builtin types.
+ * config/i386/subst.md (SUBST_CV): New.
+ (maskc_name): Ditto.
+ (maskc_operand3): Ditto.
+ (maskc): Ditto.
+ (sdc_maskz_name): Ditto.
+ (sdc_mask_op4): Ditto.
+ (sdc_mask_op5): Ditto.
+ (sdc_mask_mode512bit_condition): Ditto.
+ (sdc): Ditto.
+ (round_maskc_operand3): Ditto.
+ (round_sdc_mask_operand4): Ditto.
+ (round_maskc_op3): Ditto.
+ (round_sdc_mask_op4): Ditto.
+ (round_saeonly_sdc_mask_operand5): Ditto.
+ * config/i386/sse.md (unspec): Add complex fma unspecs.
+ (avx512fmaskcmode): New.
+ (UNSPEC_COMPLEX_F_C_MA): Ditto.
+ (UNSPEC_COMPLEX_F_C_MUL): Ditto.
+ (complexopname): Ditto.
+ (<avx512>_fmaddc_<mode>_maskz<round_expand_name>): New expander.
+ (<avx512>_fcmaddc_<mode>_maskz<round_expand_name>): Ditto.
+ (fma_<complexopname>_<mode><sdc_maskz_name><round_name>): New
+ define insn.
+ (<avx512>_<complexopname>_<mode>_mask<round_name>): Ditto.
+ (<avx512>_<complexopname>_<mode><maskc_name><round_name>): Ditto.
+
+2021-09-22 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.opt (rs6000-density-pct-threshold,
+ rs6000-density-size-threshold, rs6000-density-penalty,
+ rs6000-density-load-pct-threshold,
+ rs6000-density-load-num-threshold): New parameter.
+ * config/rs6000/rs6000.c (rs6000_density_test): Adjust with
+ corresponding parameters.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::defined_outside_path):
+ New.
+ (path_range_query::range_on_path_entry): New.
+ (path_range_query::internal_range_of_expr): Resolve unknowns
+ with ranger.
+ (path_range_query::improve_range_with_equivs): New.
+ (path_range_query::ssa_range_in_phi): Resolve unknowns with
+ ranger.
+ * gimple-range-path.h (class path_range_query): Add
+ defined_outside_path, range_on_path_entry, and
+ improve_range_with_equivs.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::add_to_imports): New.
+ (path_range_query::add_copies_to_imports): New.
+ (path_range_query::precompute_ranges): Call
+ add_copies_to_imports.
+ * gimple-range-path.h (class path_range_query): Add prototypes
+ for add_copies_to_imports and add_to_imports.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::range_defined_in_block):
+ Remove useless code.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.h (class fur_source): Make oracle protected.
+ * gimple-range-path.cc (path_range_query::path_range_query): Add
+ resolve argument. Initialize oracle.
+ (path_range_query::~path_range_query): Delete oracle.
+ (path_range_query::range_of_stmt): Adapt to use relations.
+ (path_range_query::precompute_ranges): Pre-compute relations.
+ (class jt_fur_source): New
+ (jt_fur_source::jt_fur_source): New.
+ (jt_fur_source::register_relation): New.
+ (jt_fur_source::query_relation): New.
+ (path_range_query::precompute_relations): New.
+ (path_range_query::precompute_phi_relations): New.
+ * gimple-range-path.h (path_range_query): Add resolve argument.
+ Add oracle, precompute_relations, precompute_phi_relations.
+ * tree-ssa-threadbackward.c (back_threader::back_threader): Pass
+ resolve argument to solver.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_range_op):
+ Rename postfold_gcond_edges to register_outgoing_edges and
+ adapt.
+ (fold_using_range::postfold_gcond_edges): Rename...
+ (fur_source::register_outgoing_edges): ...to this.
+ * gimple-range-fold.h (postfold_gcond_edges): Rename to
+ register_outgoing_edges and move to fur_source.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_phi): Check
+ dom_info_available_p.
+
+2021-09-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-cache.cc (non_null_ref::non_null_ref): Use create
+ and quick_grow_cleared instead of safe_grow_cleared.
+
+2021-09-21 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR other/102408
+ * omp-oacc-neuter-broadcast.cc (oacc_do_neutering): Evaluate
+ 'random ()' to '0'.
+
+2021-09-21 Richard Earnshaw <rearnsha@arm.com>
+
+ * configure.ac: Detect when the assembler supports new-style
+ architecture extensions.
+ * common/config/arm/arm-common.c (arm_rewrite_mcpu): Return
+ the full CPU string if the assembler can grok it.
+ (arm_rewrite_march): Likewise but for the architecture.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+
+2021-09-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102421
+ * tree-vect-loop.c (vect_dissolve_slp_only_groups): Copy and
+ adjust alignment info.
+
+2021-09-21 Kewen Lin <linkw@linux.ibm.com>
+
+ * ipa-fnsummary.c (ipa_fn_summary_write): Remove inconsistent
+ bitfield stream out.
+
+2021-09-20 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::range_of_phi): Ignore
+ undefined edges, apply an equivalence if appropriate.
+ * gimple-range-gori.cc (gori_compute::outgoing_edge_range_p): Return
+ UNDEFINED if EDGE_EXECUTABLE is not set.
+ * gimple-range.cc (gimple_ranger::gimple_ranger): Set all edges
+ as EXECUTABLE upon startup.
+ (gimple_ranger::range_on_edge): Return UNDEFINED for edges without
+ EDGE_EXECUTABLE set.
+ * vr-values.c (set_and_propagate_unexecutable): New.
+ (simplify_using_ranges::fold_cond): Call set_and_propagate.
+ (simplify_using_ranges::simplify_switch_using_ranges): Ditto.
+ * vr-values.h: Add prototype.
+
+2021-09-20 Andrew MacLeod <amacleod@redhat.com>
+
+ * value-relation.cc (equiv_oracle::register_initial_def): New.
+ (equiv_oracle::register_relation): Call register_initial_def.
+ (equiv_oracle::add_equiv_to_block): New. Split register_relation.
+ (relation_oracle::register_stmt): Check def block of PHI arguments.
+ * value-relation.h (equiv_oracle): Add new prototypes.
+
+2021-09-20 Matthias Kretz <m.kretz@gsi.de>
+
+ * cppbuiltin.c (define_builtin_macros_for_compilation_flags):
+ Define __RECIPROCAL_MATH__, __NO_SIGNED_ZEROS__,
+ __NO_TRAPPING_MATH__, __ASSOCIATIVE_MATH__, and
+ __ROUNDING_MATH__ according to their corresponding flags.
+ * doc/cpp.texi: Document __RECIPROCAL_MATH__,
+ __NO_SIGNED_ZEROS__, __NO_TRAPPING_MATH__, __ASSOCIATIVE_MATH__,
+ and __ROUNDING_MATH__.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.c (vectorizable_load): Use the vectype
+ from the SLP node.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_duplicate_ssa_name_ptr_info):
+ Do not compute alignment of the vectorized access here.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment):
+ Store -1 for runtime alias peeling iterations.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ * config.gcc: Obsolete hppa[12]*-*-hpux10* and hppa[12]*-*-hpux11*.
+
+2021-09-20 Thomas Schwinge <thomas@codesourcery.com>
+
+ * input.c (string_concat_db::record_string_concatenation)
+ (string_concat_db::get_string_concatenation): Skip for
+ 'RESERVED_LOCATION_P'.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/65206
+ * tree-data-ref.h (struct data_reference): Add alt_indices,
+ order it last.
+ * tree-data-ref.c (free_data_ref): Release alt_indices.
+ (dr_analyze_indices): Work on struct indices and get DR_REF as tree.
+ (create_data_ref): Adjust.
+ (initialize_data_dependence_relation): Split into head
+ and tail. When the base objects fail to match up try
+ again with pointer-based analysis of indices.
+ * tree-vectorizer.c (vec_info_shared::check_datarefs): Do
+ not compare the lazily computed alternate set of indices.
+
+2021-09-20 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.c: Test for execute OK when we find the
+ programs for assembler linker and dsymutil and those
+ were specified at configure-time.
+
+2021-09-19 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102403
+ * gimple-predicate-analysis.cc (predicate::init_from_control_deps):
+ Correct a function pre/postcondition.
+
+2021-09-19 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102243
+ * tree-ssa-strlen.c (get_range): Handle null cfun.
+
+2021-09-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (LINK_COMMAND_SPEC_A): Use Darwin10
+ unwinder shim as a convenience library.
+
+2021-09-19 Andrew Pinski <apinski@marvell.com>
+
+ * doc/install.texi: Add note about
+ binutils 2.35 is required for LTO usage.
+
+2021-09-19 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c
+ (back_threader_registry::register_path): Use push_edge.
+ * tree-ssa-threadedge.c
+ (jump_threader::thread_around_empty_blocks): Same.
+ (jump_threader::thread_through_normal_block): Same.
+ (jump_threader::thread_across_edge): Same. Also, use auto_bitmap.
+ Tidy up code.
+ * tree-ssa-threadupdate.c
+ (jt_path_registry::allocate_thread_edge): Remove.
+ (jt_path_registry::push_edge): New.
+ (dump_jump_thread_path): Make static.
+ * tree-ssa-threadupdate.h (allocate_thread_edge): Remove.
+ (push_edge): New.
+
+2021-09-19 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::path_range_query): Add
+ header.
+ (path_range_query::dump): Remove extern declaration of dump_ranger.
+ * gimple-range-trace.cc (dump_ranger): Add DEBUG_FUNCTION marker.
+ * gimple-range-trace.h (dump_ranger): Add prototype.
+
+2021-09-19 John Ericson <git@JohnEricson.me>
+
+ * gcc.c (find_a_program): New function, factored out of...
+ (find_a_file): Here.
+ (execute): Use find_a_program when looking for programs rather
+ than find_a_file.
+
+2021-09-19 Matwey V. Kornilov <matwey.kornilov@gmail.com>
+
+ * config/avr/avr-mcus.def: Add atmega324pb.
+ * doc/avr-mmcu.texi: Corresponding changes.
+
+2021-09-19 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR middle-end/88173
+ * match.pd (cmp @0 REAL_CST@1): When @0 is also REAL_CST, apply
+ the same transformations as to @1. For comparisons against NaN,
+ don't check HONOR_SNANS but confirm that neither operand is a
+ signaling NaN.
+
+2021-09-19 Benjamin Peterson <benjamin@locrian.net>
+
+ * attribs.c (make_unique_name): Delete.
+ * attribs.h (make_unique_name): Delete.
+
+2021-09-19 Andrew Pinski <apinski@marvell.com>
+
+ * lra-constraints.c (check_and_process_move): Assert
+ that dclass and sclass are greater than or equal to NO_REGS.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_ORDER_UNCONSTRAINED): Define.
+ * tree-pretty-print.c (dump_omp_clause): Print unconstrained:
+ for OMP_CLAUSE_ORDER_UNCONSTRAINED.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-features.c (remove_partial_avx_dependency):
+ Restrict TARGET_USE_VECTOR_FP_CONVERTS and
+ TARGET_USE_VECTOR_CONVERTS to conversion instructions only.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (omp_default_clause): For C/C++ default({,first}private),
+ if file/namespace scope variable doesn't have predetermined sharing,
+ treat it as if there was default(none).
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_fmadd_sh):
+ New intrinsic.
+ (_mm_mask_fmadd_sh): Likewise.
+ (_mm_mask3_fmadd_sh): Likewise.
+ (_mm_maskz_fmadd_sh): Likewise.
+ (_mm_fmadd_round_sh): Likewise.
+ (_mm_mask_fmadd_round_sh): Likewise.
+ (_mm_mask3_fmadd_round_sh): Likewise.
+ (_mm_maskz_fmadd_round_sh): Likewise.
+ (_mm_fnmadd_sh): Likewise.
+ (_mm_mask_fnmadd_sh): Likewise.
+ (_mm_mask3_fnmadd_sh): Likewise.
+ (_mm_maskz_fnmadd_sh): Likewise.
+ (_mm_fnmadd_round_sh): Likewise.
+ (_mm_mask_fnmadd_round_sh): Likewise.
+ (_mm_mask3_fnmadd_round_sh): Likewise.
+ (_mm_maskz_fnmadd_round_sh): Likewise.
+ (_mm_fmsub_sh): Likewise.
+ (_mm_mask_fmsub_sh): Likewise.
+ (_mm_mask3_fmsub_sh): Likewise.
+ (_mm_maskz_fmsub_sh): Likewise.
+ (_mm_fmsub_round_sh): Likewise.
+ (_mm_mask_fmsub_round_sh): Likewise.
+ (_mm_mask3_fmsub_round_sh): Likewise.
+ (_mm_maskz_fmsub_round_sh): Likewise.
+ (_mm_fnmsub_sh): Likewise.
+ (_mm_mask_fnmsub_sh): Likewise.
+ (_mm_mask3_fnmsub_sh): Likewise.
+ (_mm_maskz_fnmsub_sh): Likewise.
+ (_mm_fnmsub_round_sh): Likewise.
+ (_mm_mask_fnmsub_round_sh): Likewise.
+ (_mm_mask3_fnmsub_round_sh): Likewise.
+ (_mm_maskz_fnmsub_round_sh): Likewise.
+ * config/i386/i386-builtin-types.def
+ (V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT): New builtin type.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/i386-expand.c: Handle new builtin type.
+ * config/i386/sse.md (fmai_vmfmadd_<mode><round_name>):
+ Ajdust to support FP16.
+ (fmai_vmfmsub_<mode><round_name>): Ditto.
+ (fmai_vmfnmadd_<mode><round_name>): Ditto.
+ (fmai_vmfnmsub_<mode><round_name>): Ditto.
+ (*fmai_fmadd_<mode>): Ditto.
+ (*fmai_fmsub_<mode>): Ditto.
+ (*fmai_fnmadd_<mode><round_name>): Ditto.
+ (*fmai_fnmsub_<mode><round_name>): Ditto.
+ (avx512f_vmfmadd_<mode>_mask<round_name>): Ditto.
+ (avx512f_vmfmadd_<mode>_mask3<round_name>): Ditto.
+ (avx512f_vmfmadd_<mode>_maskz<round_expand_name>): Ditto.
+ (avx512f_vmfmadd_<mode>_maskz_1<round_name>): Ditto.
+ (*avx512f_vmfmsub_<mode>_mask<round_name>): Ditto.
+ (avx512f_vmfmsub_<mode>_mask3<round_name>): Ditto.
+ (*avx512f_vmfmsub_<mode>_maskz_1<round_name>): Ditto.
+ (*avx512f_vmfnmsub_<mode>_mask<round_name>): Ditto.
+ (*avx512f_vmfnmsub_<mode>_mask3<round_name>): Ditto.
+ (*avx512f_vmfnmsub_<mode>_mask<round_name>): Ditto.
+ (*avx512f_vmfnmadd_<mode>_mask<round_name>): Renamed to ...
+ (avx512f_vmfnmadd_<mode>_mask<round_name>) ... this, and
+ adjust to support FP16.
+ (avx512f_vmfnmadd_<mode>_mask3<round_name>): Ditto.
+ (avx512f_vmfnmadd_<mode>_maskz_1<round_name>): Ditto.
+ (avx512f_vmfnmadd_<mode>_maskz<round_expand_name>): New
+ expander.
+
+2021-09-18 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/sse.md (avx512fmaskmodelower): Extend to support
+ HF modes.
+ (maskload<mode><avx512fmaskmodelower>): Ditto.
+ (maskstore<mode><avx512fmaskmodelower>): Ditto.
+
+2021-09-18 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
+ Handle HFmode.
+ (ix86_expand_copysign): Ditto.
+ (ix86_expand_xorsign): Ditto.
+ * config/i386/i386.c (ix86_build_const_vector): Handle HF vector
+ modes.
+ (ix86_build_signbit_mask): Ditto.
+ (ix86_can_change_mode_class): Ditto.
+ * config/i386/i386.md
+ (SSEMODEF): Add HFmode.
+ (ssevecmodef): Ditto.
+ (<code>hf2): New define_expand.
+ (*<code>hf2_1): New define_insn_and_split.
+ (copysign<mode>): Extend to support HFmode under AVX512FP16.
+ (xorsign<mode>): Ditto.
+ * config/i386/sse.md (VFB): New mode iterator.
+ (VFB_128_256): Ditto.
+ (VFB_512): Ditto.
+ (sseintvecmode2): Support HF vector mode.
+ (<code><mode>2): Use new mode iterator.
+ (*<code><mode>2): Ditto.
+ (copysign<mode>3): Ditto.
+ (xorsign<mode>3): Ditto.
+ (<code><mode>3<mask_name>): Ditto.
+ (<code><mode>3<mask_name>): Ditto.
+ (<sse>_andnot<mode>3<mask_name>): Adjust for HF vector mode.
+ (<sse>_andnot<mode>3<mask_name>): Ditto.
+ (*<code><mode>3<mask_name>): Ditto.
+ (*<code><mode>3<mask_name>): Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_mask_fmadd_ph):
+ New intrinsic.
+ (_mm512_mask3_fmadd_ph): Likewise.
+ (_mm512_maskz_fmadd_ph): Likewise.
+ (_mm512_fmadd_round_ph): Likewise.
+ (_mm512_mask_fmadd_round_ph): Likewise.
+ (_mm512_mask3_fmadd_round_ph): Likewise.
+ (_mm512_maskz_fmadd_round_ph): Likewise.
+ (_mm512_fnmadd_ph): Likewise.
+ (_mm512_mask_fnmadd_ph): Likewise.
+ (_mm512_mask3_fnmadd_ph): Likewise.
+ (_mm512_maskz_fnmadd_ph): Likewise.
+ (_mm512_fnmadd_round_ph): Likewise.
+ (_mm512_mask_fnmadd_round_ph): Likewise.
+ (_mm512_mask3_fnmadd_round_ph): Likewise.
+ (_mm512_maskz_fnmadd_round_ph): Likewise.
+ (_mm512_fmsub_ph): Likewise.
+ (_mm512_mask_fmsub_ph): Likewise.
+ (_mm512_mask3_fmsub_ph): Likewise.
+ (_mm512_maskz_fmsub_ph): Likewise.
+ (_mm512_fmsub_round_ph): Likewise.
+ (_mm512_mask_fmsub_round_ph): Likewise.
+ (_mm512_mask3_fmsub_round_ph): Likewise.
+ (_mm512_maskz_fmsub_round_ph): Likewise.
+ (_mm512_fnmsub_ph): Likewise.
+ (_mm512_mask_fnmsub_ph): Likewise.
+ (_mm512_mask3_fnmsub_ph): Likewise.
+ (_mm512_maskz_fnmsub_ph): Likewise.
+ (_mm512_fnmsub_round_ph): Likewise.
+ (_mm512_mask_fnmsub_round_ph): Likewise.
+ (_mm512_mask3_fnmsub_round_ph): Likewise.
+ (_mm512_maskz_fnmsub_round_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm256_fmadd_ph):
+ New intrinsic.
+ (_mm256_mask_fmadd_ph): Likewise.
+ (_mm256_mask3_fmadd_ph): Likewise.
+ (_mm256_maskz_fmadd_ph): Likewise.
+ (_mm_fmadd_ph): Likewise.
+ (_mm_mask_fmadd_ph): Likewise.
+ (_mm_mask3_fmadd_ph): Likewise.
+ (_mm_maskz_fmadd_ph): Likewise.
+ (_mm256_fnmadd_ph): Likewise.
+ (_mm256_mask_fnmadd_ph): Likewise.
+ (_mm256_mask3_fnmadd_ph): Likewise.
+ (_mm256_maskz_fnmadd_ph): Likewise.
+ (_mm_fnmadd_ph): Likewise.
+ (_mm_mask_fnmadd_ph): Likewise.
+ (_mm_mask3_fnmadd_ph): Likewise.
+ (_mm_maskz_fnmadd_ph): Likewise.
+ (_mm256_fmsub_ph): Likewise.
+ (_mm256_mask_fmsub_ph): Likewise.
+ (_mm256_mask3_fmsub_ph): Likewise.
+ (_mm256_maskz_fmsub_ph): Likewise.
+ (_mm_fmsub_ph): Likewise.
+ (_mm_mask_fmsub_ph): Likewise.
+ (_mm_mask3_fmsub_ph): Likewise.
+ (_mm_maskz_fmsub_ph): Likewise.
+ (_mm256_fnmsub_ph): Likewise.
+ (_mm256_mask_fnmsub_ph): Likewise.
+ (_mm256_mask3_fnmsub_ph): Likewise.
+ (_mm256_maskz_fnmsub_ph): Likewise.
+ (_mm_fnmsub_ph): Likewise.
+ (_mm_mask_fnmsub_ph): Likewise.
+ (_mm_mask3_fnmsub_ph): Likewise.
+ (_mm_maskz_fnmsub_ph): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/sse.md
+ (<avx512>_fmadd_<mode>_maskz<round_expand_name>): Adjust to
+ support HF vector modes.
+ (<sd_mask_codefor>fma_fmadd_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ (*<sd_mask_codefor>fma_fmadd_<mode><sd_maskz_name>_bcst_1): Ditto.
+ (*<sd_mask_codefor>fma_fmadd_<mode><sd_maskz_name>_bcst_2): Ditto.
+ (*<sd_mask_codefor>fma_fmadd_<mode><sd_maskz_name>_bcst_3): Ditto.
+ (<avx512>_fmadd_<mode>_mask<round_name>): Ditto.
+ (<avx512>_fmadd_<mode>_mask3<round_name>): Ditto.
+ (<avx512>_fmsub_<mode>_maskz<round_expand_name>): Ditto.
+ (<sd_mask_codefor>fma_fmsub_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ (*<sd_mask_codefor>fma_fmsub_<mode><sd_maskz_name>_bcst_1): Ditto.
+ (*<sd_mask_codefor>fma_fmsub_<mode><sd_maskz_name>_bcst_2): Ditto.
+ (*<sd_mask_codefor>fma_fmsub_<mode><sd_maskz_name>_bcst_3): Ditto.
+ (<avx512>_fmsub_<mode>_mask<round_name>): Ditto.
+ (<avx512>_fmsub_<mode>_mask3<round_name>): Ditto.
+ (<sd_mask_codefor>fma_fnmadd_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ (*<sd_mask_codefor>fma_fnmadd_<mode><sd_maskz_name>_bcst_1): Ditto.
+ (*<sd_mask_codefor>fma_fnmadd_<mode><sd_maskz_name>_bcst_2): Ditto.
+ (*<sd_mask_codefor>fma_fnmadd_<mode><sd_maskz_name>_bcst_3): Ditto.
+ (<avx512>_fnmadd_<mode>_mask<round_name>): Ditto.
+ (<avx512>_fnmadd_<mode>_mask3<round_name>): Ditto.
+ (<avx512>_fnmsub_<mode>_maskz<round_expand_name>): Ditto.
+ (<sd_mask_codefor>fma_fnmsub_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ (*<sd_mask_codefor>fma_fnmsub_<mode><sd_maskz_name>_bcst_1): Ditto.
+ (*<sd_mask_codefor>fma_fnmsub_<mode><sd_maskz_name>_bcst_2): Ditto.
+ (*<sd_mask_codefor>fma_fnmsub_<mode><sd_maskz_name>_bcst_3): Ditto.
+ (<avx512>_fnmsub_<mode>_mask<round_name>): Ditto.
+ (<avx512>_fnmsub_<mode>_mask3<round_name>): Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_fmaddsub_ph):
+ New intrinsic.
+ (_mm512_mask_fmaddsub_ph): Likewise.
+ (_mm512_mask3_fmaddsub_ph): Likewise.
+ (_mm512_maskz_fmaddsub_ph): Likewise.
+ (_mm512_fmaddsub_round_ph): Likewise.
+ (_mm512_mask_fmaddsub_round_ph): Likewise.
+ (_mm512_mask3_fmaddsub_round_ph): Likewise.
+ (_mm512_maskz_fmaddsub_round_ph): Likewise.
+ (_mm512_mask_fmsubadd_ph): Likewise.
+ (_mm512_mask3_fmsubadd_ph): Likewise.
+ (_mm512_maskz_fmsubadd_ph): Likewise.
+ (_mm512_fmsubadd_round_ph): Likewise.
+ (_mm512_mask_fmsubadd_round_ph): Likewise.
+ (_mm512_mask3_fmsubadd_round_ph): Likewise.
+ (_mm512_maskz_fmsubadd_round_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm256_fmaddsub_ph):
+ New intrinsic.
+ (_mm256_mask_fmaddsub_ph): Likewise.
+ (_mm256_mask3_fmaddsub_ph): Likewise.
+ (_mm256_maskz_fmaddsub_ph): Likewise.
+ (_mm_fmaddsub_ph): Likewise.
+ (_mm_mask_fmaddsub_ph): Likewise.
+ (_mm_mask3_fmaddsub_ph): Likewise.
+ (_mm_maskz_fmaddsub_ph): Likewise.
+ (_mm256_fmsubadd_ph): Likewise.
+ (_mm256_mask_fmsubadd_ph): Likewise.
+ (_mm256_mask3_fmsubadd_ph): Likewise.
+ (_mm256_maskz_fmsubadd_ph): Likewise.
+ (_mm_fmsubadd_ph): Likewise.
+ (_mm_mask_fmsubadd_ph): Likewise.
+ (_mm_mask3_fmsubadd_ph): Likewise.
+ (_mm_maskz_fmsubadd_ph): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/sse.md (VFH_SF_AVX512VL): New mode iterator.
+ * (<avx512>_fmsubadd_<mode>_maskz<round_expand_name>): New expander.
+ * (<avx512>_fmaddsub_<mode>_maskz<round_expand_name>): Use
+ VFH_SF_AVX512VL.
+ * (<sd_mask_codefor>fma_fmaddsub_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ * (<avx512>_fmaddsub_<mode>_mask<round_name>): Ditto.
+ * (<avx512>_fmaddsub_<mode>_mask3<round_name>): Ditto.
+ * (<sd_mask_codefor>fma_fmsubadd_<mode><sd_maskz_name><round_name>):
+ Ditto.
+ * (<avx512>_fmsubadd_<mode>_mask<round_name>): Ditto.
+ * (<avx512>_fmsubadd_<mode>_mask3<round_name>): Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ PR target/87767
+ * config/i386/i386.c (ix86_print_operand): Handle
+ V8HF/V16HF/V32HFmode.
+ * config/i386/i386.h (VALID_BCST_MODE_P): Add HFmode.
+ * config/i386/sse.md (avx512bcst): Remove.
+
+2021-09-17 Martin Sebor <msebor@redhat.com>
+
+ * Makefile.in (OBJS): Add gimple-predicate-analysis.o.
+ * tree-ssa-uninit.c (max_phi_args): Move to gimple-predicate-analysis.
+ (MASK_SET_BIT, MASK_TEST_BIT, MASK_EMPTY): Same.
+ (check_defs): Add comment.
+ (can_skip_redundant_opnd): Update comment.
+ (compute_uninit_opnds_pos): Adjust to namespace change.
+ (find_pdom): Move to gimple-predicate-analysis.cc.
+ (find_dom): Same.
+ (struct uninit_undef_val_t): New.
+ (is_non_loop_exit_postdominating): Move to gimple-predicate-analysis.cc.
+ (find_control_equiv_block): Same.
+ (MAX_NUM_CHAINS, MAX_CHAIN_LEN, MAX_POSTDOM_CHECK): Same.
+ (MAX_SWITCH_CASES): Same.
+ (compute_control_dep_chain): Same.
+ (find_uninit_use): Use predicate analyzer.
+ (struct pred_info): Move to gimple-predicate-analysis.
+ (convert_control_dep_chain_into_preds): Same.
+ (find_predicates): Same.
+ (collect_phi_def_edges): Same.
+ (warn_uninitialized_phi): Use predicate analyzer.
+ (find_def_preds): Move to gimple-predicate-analysis.
+ (dump_pred_info): Same.
+ (dump_pred_chain): Same.
+ (dump_predicates): Same.
+ (destroy_predicate_vecs): Remove.
+ (execute_late_warn_uninitialized): New.
+ (get_cmp_code): Move to gimple-predicate-analysis.
+ (is_value_included_in): Same.
+ (value_sat_pred_p): Same.
+ (find_matching_predicate_in_rest_chains): Same.
+ (is_use_properly_guarded): Same.
+ (prune_uninit_phi_opnds): Same.
+ (find_var_cmp_const): Same.
+ (use_pred_not_overlap_with_undef_path_pred): Same.
+ (pred_equal_p): Same.
+ (is_neq_relop_p): Same.
+ (is_neq_zero_form_p): Same.
+ (pred_expr_equal_p): Same.
+ (is_pred_expr_subset_of): Same.
+ (is_pred_chain_subset_of): Same.
+ (is_included_in): Same.
+ (is_superset_of): Same.
+ (pred_neg_p): Same.
+ (simplify_pred): Same.
+ (simplify_preds_2): Same.
+ (simplify_preds_3): Same.
+ (simplify_preds_4): Same.
+ (simplify_preds): Same.
+ (push_pred): Same.
+ (push_to_worklist): Same.
+ (get_pred_info_from_cmp): Same.
+ (is_degenerated_phi): Same.
+ (normalize_one_pred_1): Same.
+ (normalize_one_pred): Same.
+ (normalize_one_pred_chain): Same.
+ (normalize_preds): Same.
+ (can_one_predicate_be_invalidated_p): Same.
+ (can_chain_union_be_invalidated_p): Same.
+ (uninit_uses_cannot_happen): Same.
+ (pass_late_warn_uninitialized::execute): Define.
+ * gimple-predicate-analysis.cc: New file.
+ * gimple-predicate-analysis.h: New file.
+
+2021-09-17 Julian Brown <julian@codesourcery.com>
+
+ * config/gcn/gcn.c (gimple.h): Include.
+ (gcn_fork_join): Emit barrier for worker-level joins.
+ * omp-oacc-neuter-broadcast.cc (find_local_vars_to_propagate): Add
+ writes_gang_private bitmap parameter. Set bit for blocks
+ containing gang-private variable writes.
+ (worker_single_simple): Don't emit barrier after predicated block.
+ (worker_single_copy): Don't emit barrier if we're not broadcasting
+ anything and the block contains no gang-private writes.
+ (neuter_worker_single): Don't predicate blocks that only contain
+ NOPs or internal marker functions. Pass has_gang_private_write
+ argument to worker_single_copy.
+ (oacc_do_neutering): Add writes_gang_private bitmap handling.
+
+2021-09-17 Julian Brown <julian@codesourcery.com>
+
+ * config/gcn/gcn-protos.h
+ (gcn_goacc_create_worker_broadcast_record): Update prototype.
+ * config/gcn/gcn-tree.c (gcn_goacc_get_worker_red_decl): Use
+ preallocated block of LDS memory. Do not cache/share decls for
+ reduction temporaries between invocations.
+ (gcn_goacc_reduction_teardown): Unshare VAR on second use.
+ (gcn_goacc_create_worker_broadcast_record): Add OFFSET parameter
+ and return temporary LDS space at that offset. Return pointer in
+ "sender" case.
+ * config/gcn/gcn.c (acc_lds_size, gang_private_hwm, lds_allocs):
+ New global vars.
+ (ACC_LDS_SIZE): Define as acc_lds_size.
+ (gcn_init_machine_status): Don't initialise lds_allocated,
+ lds_allocs, reduc_decls fields of machine function struct.
+ (gcn_option_override): Handle default size for gang-private
+ variables and -mgang-private-size option.
+ (gcn_expand_prologue): Use LDS_SIZE instead of LDS_SIZE-1 when
+ initialising M0_REG.
+ (gcn_shared_mem_layout): New function.
+ (gcn_print_lds_decl): Update comment. Use global lds_allocs map and
+ gang_private_hwm variable.
+ (TARGET_GOACC_SHARED_MEM_LAYOUT): Define target hook.
+ * config/gcn/gcn.h (machine_function): Remove lds_allocated,
+ lds_allocs, reduc_decls. Add reduction_base, reduction_limit.
+ * config/gcn/gcn.opt (gang_private_size_opt): New global.
+ (mgang-private-size=): New option.
+ * doc/tm.texi.in (TARGET_GOACC_SHARED_MEM_LAYOUT): Place
+ documentation hook.
+ * doc/tm.texi: Regenerate.
+ * omp-oacc-neuter-broadcast.cc (targhooks.h, diagnostic-core.h):
+ Add includes.
+ (build_sender_ref): Handle sender_decl being pointer.
+ (worker_single_copy): Add PLACEMENT and ISOLATE_BROADCASTS
+ parameters. Pass placement argument to
+ create_worker_broadcast_record hook invocations. Handle
+ sender_decl being pointer and isolate_broadcasts inserting extra
+ barriers.
+ (blk_offset_map_t): Add typedef.
+ (neuter_worker_single): Add BLK_OFFSET_MAP parameter. Pass
+ preallocated range to worker_single_copy call.
+ (dfs_broadcast_reachable_1): New function.
+ (idx_decl_pair_t, used_range_vec_t): New typedefs.
+ (sort_size_descending): New function.
+ (addr_range): New class.
+ (splay_tree_compare_addr_range, splay_tree_free_key)
+ (first_fit_range, merge_ranges_1, merge_ranges): New functions.
+ (execute_omp_oacc_neuter_broadcast): Rename to...
+ (oacc_do_neutering): ... this. Add BOUNDS_LO, BOUNDS_HI
+ parameters. Arrange layout of shared memory for broadcast
+ operations.
+ (execute_omp_oacc_neuter_broadcast): New function.
+ (pass_omp_oacc_neuter_broadcast::gate): Remove num_workers==1
+ handling from here. Enable pass for all OpenACC routines in order
+ to call shared memory-layout hook.
+ * target.def (create_worker_broadcast_record): Add OFFSET
+ parameter.
+ (shared_mem_layout): New hook.
+
+2021-09-17 Julian Brown <julian@codesourcery.com>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-oacc-neuter-broadcast.cc
+ (pass_omp_oacc_neuter_broadcast::gate): Disable if num_workers is
+ 1.
+ (execute_omp_oacc_neuter_broadcast): Adjust.
+
+2021-09-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * value-relation.cc (class equiv_chain): Move to header file.
+ (path_oracle::path_oracle): New.
+ (path_oracle::~path_oracle): New.
+ (path_oracle::register_relation): New.
+ (path_oracle::query_relation): New.
+ (path_oracle::reset_path): New.
+ (path_oracle::dump): New.
+ * value-relation.h (class equiv_chain): Move to here.
+ (class path_oracle): New.
+
+2021-09-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::ranger_cache): Create a DOM
+ based oracle.
+ * gimple-range-fold.cc (fur_depend::register_relation): Use
+ register_stmt/edge routines.
+ * value-relation.cc (equiv_chain::find): Relocate from equiv_oracle.
+ (equiv_oracle::equiv_oracle): Create self equivalence cache.
+ (equiv_oracle::~equiv_oracle): Release same.
+ (equiv_oracle::equiv_set): Return entry from self equiv cache if there
+ are no equivalences.
+ (equiv_oracle::find_equiv_block): Move list find to equiv_chain.
+ (equiv_oracle::register_relation): Rename from register_equiv.
+ (relation_chain_head::find_relation): Relocate from dom_oracle.
+ (relation_oracle::register_stmt): New.
+ (relation_oracle::register_edge): New.
+ (dom_oracle::*): Rename from relation_oracle.
+ (dom_oracle::register_relation): Adjust to call equiv_oracle.
+ (dom_oracle::set_one_relation): Split from register_relation.
+ (dom_oracle::register_transitives): Consolidate 2 methods.
+ (dom_oracle::find_relation_block): Move core to relation_chain.
+ (dom_oracle::query_relation): Rename from find_relation_dom and adjust.
+ * value-relation.h (class relation_oracle): New pure virtual base.
+ (class equiv_oracle): Inherit from relation_oracle and adjust.
+ (class dom_oracle): Rename from old relation_oracle and adjust.
+
+2021-09-17 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102200
+ * pointer-query.cc (access_ref::inform_access): Handle MIN/MAX_EXPR.
+ (handle_min_max_size): Change argument. Store original SSA_NAME for
+ operands to potentially distinct (sub)objects.
+ (compute_objsize_r): Adjust call to the above.
+
+2021-09-17 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000-builtins.h): New include.
+ (rs6000_new_builtin_vectorized_function): New function.
+ (rs6000_new_builtin_md_vectorized_function): Likewise.
+ (rs6000_builtin_vectorized_function): Call
+ rs6000_new_builtin_vectorized_function.
+ (rs6000_builtin_md_vectorized_function): Call
+ rs6000_new_builtin_md_vectorized_function.
+
+2021-09-17 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-builtin-new.def (ASSEMBLE_ACC): Add mmaint flag.
+ (ASSEMBLE_PAIR): Likewise.
+ (BUILD_ACC): Likewise.
+ (DISASSEMBLE_ACC): Likewise.
+ (DISASSEMBLE_PAIR): Likewise.
+ (PMXVBF16GER2): Likewise.
+ (PMXVBF16GER2NN): Likewise.
+ (PMXVBF16GER2NP): Likewise.
+ (PMXVBF16GER2PN): Likewise.
+ (PMXVBF16GER2PP): Likewise.
+ (PMXVF16GER2): Likewise.
+ (PMXVF16GER2NN): Likewise.
+ (PMXVF16GER2NP): Likewise.
+ (PMXVF16GER2PN): Likewise.
+ (PMXVF16GER2PP): Likewise.
+ (PMXVF32GER): Likewise.
+ (PMXVF32GERNN): Likewise.
+ (PMXVF32GERNP): Likewise.
+ (PMXVF32GERPN): Likewise.
+ (PMXVF32GERPP): Likewise.
+ (PMXVF64GER): Likewise.
+ (PMXVF64GERNN): Likewise.
+ (PMXVF64GERNP): Likewise.
+ (PMXVF64GERPN): Likewise.
+ (PMXVF64GERPP): Likewise.
+ (PMXVI16GER2): Likewise.
+ (PMXVI16GER2PP): Likewise.
+ (PMXVI16GER2S): Likewise.
+ (PMXVI16GER2SPP): Likewise.
+ (PMXVI4GER8): Likewise.
+ (PMXVI4GER8PP): Likewise.
+ (PMXVI8GER4): Likewise.
+ (PMXVI8GER4PP): Likewise.
+ (PMXVI8GER4SPP): Likewise.
+ (XVBF16GER2): Likewise.
+ (XVBF16GER2NN): Likewise.
+ (XVBF16GER2NP): Likewise.
+ (XVBF16GER2PN): Likewise.
+ (XVBF16GER2PP): Likewise.
+ (XVF16GER2): Likewise.
+ (XVF16GER2NN): Likewise.
+ (XVF16GER2NP): Likewise.
+ (XVF16GER2PN): Likewise.
+ (XVF16GER2PP): Likewise.
+ (XVF32GER): Likewise.
+ (XVF32GERNN): Likewise.
+ (XVF32GERNP): Likewise.
+ (XVF32GERPN): Likewise.
+ (XVF32GERPP): Likewise.
+ (XVF64GER): Likewise.
+ (XVF64GERNN): Likewise.
+ (XVF64GERNP): Likewise.
+ (XVF64GERPN): Likewise.
+ (XVF64GERPP): Likewise.
+ (XVI16GER2): Likewise.
+ (XVI16GER2PP): Likewise.
+ (XVI16GER2S): Likewise.
+ (XVI16GER2SPP): Likewise.
+ (XVI4GER8): Likewise.
+ (XVI4GER8PP): Likewise.
+ (XVI8GER4): Likewise.
+ (XVI8GER4PP): Likewise.
+ (XVI8GER4SPP): Likewise.
+ (XXMFACC): Likewise.
+ (XXMTACC): Likewise.
+ (XXSETACCZ): Likewise.
+ (ASSEMBLE_PAIR_V): Likewise.
+ (BUILD_PAIR): Likewise.
+ (DISASSEMBLE_PAIR_V): Likewise.
+ (LXVP): New.
+ (STXVP): New.
+ * config/rs6000/rs6000-call.c (rs6000_gimple_fold_new_mma_builtin):
+ Handle RS6000_BIF_LXVP and RS6000_BIF_STXVP.
+ * config/rs6000/rs6000-gen-builtins.c (attrinfo): Add ismmaint.
+ (parse_bif_attrs): Handle ismmaint.
+ (write_decls): Add bif_mmaint_bit and bif_is_mmaint.
+ (write_bif_static_init): Handle ismmaint.
+
+2021-09-17 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (rs6000_gimple_fold_new_builtin): New
+ forward decl.
+ (rs6000_gimple_fold_builtin): Call rs6000_gimple_fold_new_builtin.
+ (rs6000_new_builtin_valid_without_lhs): New function.
+ (rs6000_gimple_fold_new_mma_builtin): Likewise.
+ (rs6000_gimple_fold_new_builtin): Likewise.
+
+2021-09-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ * hash-table.h (hash_table<Descriptor, Lazy, Allocator>::expand):
+ Destruct stale Value objects.
+ * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor_expand):
+ Update.
+
+2021-09-17 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR c/102245
+ * match.pd (shift optimizations): Disable recent sign-changing
+ optimization for shifts by zero, these will be folded later.
+
+2021-09-17 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-builtin-new.def (__builtin_mffsl): Move from
+ [power9] to [always].
+
+2021-09-17 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.c (vectorizable_load): Do not frob
+ stmt_info for SLP.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/i386-features.c (remove_partial_avx_dependency):
+ Also check TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY and
+ and TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY before generating
+ vxorps.
+ * config/i386/i386.h (TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY):
+ New.
+ (TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY): Likewise.
+ * config/i386/i386.md (SSE FP to FP splitters): Replace
+ TARGET_SSE_PARTIAL_REG_DEPENDENCY with
+ TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY.
+ (SSE INT to FP splitter): Replace TARGET_SSE_PARTIAL_REG_DEPENDENCY
+ with TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY.
+ * config/i386/x86-tune.def
+ (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY): New.
+ (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY): Likewise.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101900
+ * config/i386/i386-features.c (remove_partial_avx_dependency):
+ Check TARGET_USE_VECTOR_FP_CONVERTS and TARGET_USE_VECTOR_CONVERTS
+ before generating vxorps.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/i386-options.c (processor_cost_table): Use
+ tremont_cost for Tremont.
+ * config/i386/x86-tune-costs.h (tremont_memcpy): New.
+ (tremont_memset): Likewise.
+ (tremont_cost): Likewise.
+ * config/i386/x86-tune.def (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB):
+ Enable for Tremont.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ * common/config/i386/i386-common.c: Use Haswell scheduling model
+ for Tremont.
+ * config/i386/i386.c (ix86_sched_init_global): Prepare for Tremont
+ scheduling pass.
+ * config/i386/x86-tune-sched.c (ix86_issue_rate): Change Tremont
+ issue rate to 4.
+ (ix86_adjust_cost): Handle Tremont.
+ * config/i386/x86-tune.def (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY):
+ Enable for Tremont.
+ (X86_TUNE_USE_LEAVE): Likewise.
+ (X86_TUNE_PUSH_MEMORY): Likewise.
+ (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Likewise.
+ (X86_TUNE_USE_CLTD): Likewise.
+ (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI): Likewise.
+ (X86_TUNE_AVOID_MFENCE): Likewise.
+ (X86_TUNE_SSE_TYPELESS_STORES): Likewise.
+ (X86_TUNE_SSE_LOAD0_BY_PXOR): Likewise.
+ (X86_TUNE_ACCUMULATE_OUTGOING_ARGS): Disable for Tremont.
+ (X86_TUNE_FOUR_JUMP_LIMIT): Likewise.
+ (X86_TUNE_OPT_AGU): Likewise.
+ (X86_TUNE_AVOID_LEA_FOR_ADDR): Likewise.
+ (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE): Likewise.
+ (X86_TUNE_EXPAND_ABS): Likewise.
+ (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS): Likewise.
+ (X86_TUNE_SLOW_PSHUFB): Likewise.
+
+2021-09-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/102306
+ * combine.c (try_combine): Abort the combination if we are about to
+ duplicate volatile references.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_undefined_ph):
+ New intrinsic.
+ (_mm256_undefined_ph): Likewise.
+ (_mm512_undefined_ph): Likewise.
+ (_mm_cvtsh_h): Likewise.
+ (_mm256_cvtsh_h): Likewise.
+ (_mm512_cvtsh_h): Likewise.
+ (_mm512_castph_ps): Likewise.
+ (_mm512_castph_pd): Likewise.
+ (_mm512_castph_si512): Likewise.
+ (_mm512_castph512_ph128): Likewise.
+ (_mm512_castph512_ph256): Likewise.
+ (_mm512_castph128_ph512): Likewise.
+ (_mm512_castph256_ph512): Likewise.
+ (_mm512_zextph128_ph512): Likewise.
+ (_mm512_zextph256_ph512): Likewise.
+ (_mm512_castps_ph): Likewise.
+ (_mm512_castpd_ph): Likewise.
+ (_mm512_castsi512_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_castph_ps):
+ New intrinsic.
+ (_mm256_castph_ps): Likewise.
+ (_mm_castph_pd): Likewise.
+ (_mm256_castph_pd): Likewise.
+ (_mm_castph_si128): Likewise.
+ (_mm256_castph_si256): Likewise.
+ (_mm_castps_ph): Likewise.
+ (_mm256_castps_ph): Likewise.
+ (_mm_castpd_ph): Likewise.
+ (_mm256_castpd_ph): Likewise.
+ (_mm_castsi128_ph): Likewise.
+ (_mm256_castsi256_ph): Likewise.
+ (_mm256_castph256_ph128): Likewise.
+ (_mm256_castph128_ph256): Likewise.
+ (_mm256_zextph128_ph256): Likewise.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_cvtsh_ss):
+ New intrinsic.
+ (_mm_mask_cvtsh_ss): Likewise.
+ (_mm_maskz_cvtsh_ss): Likewise.
+ (_mm_cvtsh_sd): Likewise.
+ (_mm_mask_cvtsh_sd): Likewise.
+ (_mm_maskz_cvtsh_sd): Likewise.
+ (_mm_cvt_roundsh_ss): Likewise.
+ (_mm_mask_cvt_roundsh_ss): Likewise.
+ (_mm_maskz_cvt_roundsh_ss): Likewise.
+ (_mm_cvt_roundsh_sd): Likewise.
+ (_mm_mask_cvt_roundsh_sd): Likewise.
+ (_mm_maskz_cvt_roundsh_sd): Likewise.
+ (_mm_cvtss_sh): Likewise.
+ (_mm_mask_cvtss_sh): Likewise.
+ (_mm_maskz_cvtss_sh): Likewise.
+ (_mm_cvtsd_sh): Likewise.
+ (_mm_mask_cvtsd_sh): Likewise.
+ (_mm_maskz_cvtsd_sh): Likewise.
+ (_mm_cvt_roundss_sh): Likewise.
+ (_mm_mask_cvt_roundss_sh): Likewise.
+ (_mm_maskz_cvt_roundss_sh): Likewise.
+ (_mm_cvt_roundsd_sh): Likewise.
+ (_mm_mask_cvt_roundsd_sh): Likewise.
+ (_mm_maskz_cvt_roundsd_sh): Likewise.
+ * config/i386/i386-builtin-types.def
+ (V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT,
+ V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT,
+ V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT,
+ V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT): Add new builtin types.
+ * config/i386/i386-builtin.def: Add corrresponding new builtins.
+ * config/i386/i386-expand.c: Handle new builtin types.
+ * config/i386/sse.md (VF48_128): New mode iterator.
+ (avx512fp16_vcvtsh2<ssescalarmodesuffix><mask_scalar_name><round_saeonly_scalar_name>):
+ New.
+ (avx512fp16_vcvt<ssescalarmodesuffix>2sh<mask_scalar_name><round_scalar_name>):
+ Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_cvtph_pd):
+ New intrinsic.
+ (_mm512_mask_cvtph_pd): Likewise.
+ (_mm512_maskz_cvtph_pd): Likewise.
+ (_mm512_cvt_roundph_pd): Likewise.
+ (_mm512_mask_cvt_roundph_pd): Likewise.
+ (_mm512_maskz_cvt_roundph_pd): Likewise.
+ (_mm512_cvtxph_ps): Likewise.
+ (_mm512_mask_cvtxph_ps): Likewise.
+ (_mm512_maskz_cvtxph_ps): Likewise.
+ (_mm512_cvtx_roundph_ps): Likewise.
+ (_mm512_mask_cvtx_roundph_ps): Likewise.
+ (_mm512_maskz_cvtx_roundph_ps): Likewise.
+ (_mm512_cvtxps_ph): Likewise.
+ (_mm512_mask_cvtxps_ph): Likewise.
+ (_mm512_maskz_cvtxps_ph): Likewise.
+ (_mm512_cvtx_roundps_ph): Likewise.
+ (_mm512_mask_cvtx_roundps_ph): Likewise.
+ (_mm512_maskz_cvtx_roundps_ph): Likewise.
+ (_mm512_cvtpd_ph): Likewise.
+ (_mm512_mask_cvtpd_ph): Likewise.
+ (_mm512_maskz_cvtpd_ph): Likewise.
+ (_mm512_cvt_roundpd_ph): Likewise.
+ (_mm512_mask_cvt_roundpd_ph): Likewise.
+ (_mm512_maskz_cvt_roundpd_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_cvtph_pd):
+ New intrinsic.
+ (_mm_mask_cvtph_pd): Likewise.
+ (_mm_maskz_cvtph_pd): Likewise.
+ (_mm256_cvtph_pd): Likewise.
+ (_mm256_mask_cvtph_pd): Likewise.
+ (_mm256_maskz_cvtph_pd): Likewise.
+ (_mm_cvtxph_ps): Likewise.
+ (_mm_mask_cvtxph_ps): Likewise.
+ (_mm_maskz_cvtxph_ps): Likewise.
+ (_mm256_cvtxph_ps): Likewise.
+ (_mm256_mask_cvtxph_ps): Likewise.
+ (_mm256_maskz_cvtxph_ps): Likewise.
+ (_mm_cvtxps_ph): Likewise.
+ (_mm_mask_cvtxps_ph): Likewise.
+ (_mm_maskz_cvtxps_ph): Likewise.
+ (_mm256_cvtxps_ph): Likewise.
+ (_mm256_mask_cvtxps_ph): Likewise.
+ (_mm256_maskz_cvtxps_ph): Likewise.
+ (_mm_cvtpd_ph): Likewise.
+ (_mm_mask_cvtpd_ph): Likewise.
+ (_mm_maskz_cvtpd_ph): Likewise.
+ (_mm256_cvtpd_ph): Likewise.
+ (_mm256_mask_cvtpd_ph): Likewise.
+ (_mm256_maskz_cvtpd_ph): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-expand.c: Handle new builtin types.
+ * config/i386/sse.md
+ (VF4_128_8_256): New.
+ (VF48H_AVX512VL): Ditto.
+ (ssePHmode): Add HF vector modes.
+ (castmode): Add new convertable modes.
+ (qq2phsuff): Ditto.
+ (ph2pssuffix): New.
+ (avx512fp16_vcvt<castmode>2ph_<mode><mask_name><round_name>): Ditto.
+ (avx512fp16_vcvt<castmode>2ph_<mode>): Ditto.
+ (*avx512fp16_vcvt<castmode>2ph_<mode>): Ditto.
+ (avx512fp16_vcvt<castmode>2ph_<mode>_mask): Ditto.
+ (*avx512fp16_vcvt<castmode>2ph_<mode>_mask): Ditto.
+ (*avx512fp16_vcvt<castmode>2ph_<mode>_mask_1): Ditto.
+ (avx512fp16_float_extend_ph<mode>2<mask_name><round_saeonly_name>):
+ Ditto.
+ (avx512fp16_float_extend_ph<mode>2<mask_name>): Ditto.
+ (*avx512fp16_float_extend_ph<mode>2_load<mask_name>): Ditto.
+ (avx512fp16_float_extend_phv2df2<mask_name>): Ditto.
+ (*avx512fp16_float_extend_phv2df2_load<mask_name>): Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_cvttsh_i32):
+ New intrinsic.
+ (_mm_cvttsh_u32): Likewise.
+ (_mm_cvtt_roundsh_i32): Likewise.
+ (_mm_cvtt_roundsh_u32): Likewise.
+ (_mm_cvttsh_i64): Likewise.
+ (_mm_cvttsh_u64): Likewise.
+ (_mm_cvtt_roundsh_i64): Likewise.
+ (_mm_cvtt_roundsh_u64): Likewise.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/sse.md
+ (avx512fp16_fix<fixunssuffix>_trunc<mode>2<round_saeonly_name>):
+ New.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_cvttph_epi32):
+ New intrinsic.
+ (_mm512_mask_cvttph_epi32): Likewise.
+ (_mm512_maskz_cvttph_epi32): Likewise.
+ (_mm512_cvtt_roundph_epi32): Likewise.
+ (_mm512_mask_cvtt_roundph_epi32): Likewise.
+ (_mm512_maskz_cvtt_roundph_epi32): Likewise.
+ (_mm512_cvttph_epu32): Likewise.
+ (_mm512_mask_cvttph_epu32): Likewise.
+ (_mm512_maskz_cvttph_epu32): Likewise.
+ (_mm512_cvtt_roundph_epu32): Likewise.
+ (_mm512_mask_cvtt_roundph_epu32): Likewise.
+ (_mm512_maskz_cvtt_roundph_epu32): Likewise.
+ (_mm512_cvttph_epi64): Likewise.
+ (_mm512_mask_cvttph_epi64): Likewise.
+ (_mm512_maskz_cvttph_epi64): Likewise.
+ (_mm512_cvtt_roundph_epi64): Likewise.
+ (_mm512_mask_cvtt_roundph_epi64): Likewise.
+ (_mm512_maskz_cvtt_roundph_epi64): Likewise.
+ (_mm512_cvttph_epu64): Likewise.
+ (_mm512_mask_cvttph_epu64): Likewise.
+ (_mm512_maskz_cvttph_epu64): Likewise.
+ (_mm512_cvtt_roundph_epu64): Likewise.
+ (_mm512_mask_cvtt_roundph_epu64): Likewise.
+ (_mm512_maskz_cvtt_roundph_epu64): Likewise.
+ (_mm512_cvttph_epi16): Likewise.
+ (_mm512_mask_cvttph_epi16): Likewise.
+ (_mm512_maskz_cvttph_epi16): Likewise.
+ (_mm512_cvtt_roundph_epi16): Likewise.
+ (_mm512_mask_cvtt_roundph_epi16): Likewise.
+ (_mm512_maskz_cvtt_roundph_epi16): Likewise.
+ (_mm512_cvttph_epu16): Likewise.
+ (_mm512_mask_cvttph_epu16): Likewise.
+ (_mm512_maskz_cvttph_epu16): Likewise.
+ (_mm512_cvtt_roundph_epu16): Likewise.
+ (_mm512_mask_cvtt_roundph_epu16): Likewise.
+ (_mm512_maskz_cvtt_roundph_epu16): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_cvttph_epi32):
+ New intirnsic.
+ (_mm_mask_cvttph_epi32): Likewise.
+ (_mm_maskz_cvttph_epi32): Likewise.
+ (_mm256_cvttph_epi32): Likewise.
+ (_mm256_mask_cvttph_epi32): Likewise.
+ (_mm256_maskz_cvttph_epi32): Likewise.
+ (_mm_cvttph_epu32): Likewise.
+ (_mm_mask_cvttph_epu32): Likewise.
+ (_mm_maskz_cvttph_epu32): Likewise.
+ (_mm256_cvttph_epu32): Likewise.
+ (_mm256_mask_cvttph_epu32): Likewise.
+ (_mm256_maskz_cvttph_epu32): Likewise.
+ (_mm_cvttph_epi64): Likewise.
+ (_mm_mask_cvttph_epi64): Likewise.
+ (_mm_maskz_cvttph_epi64): Likewise.
+ (_mm256_cvttph_epi64): Likewise.
+ (_mm256_mask_cvttph_epi64): Likewise.
+ (_mm256_maskz_cvttph_epi64): Likewise.
+ (_mm_cvttph_epu64): Likewise.
+ (_mm_mask_cvttph_epu64): Likewise.
+ (_mm_maskz_cvttph_epu64): Likewise.
+ (_mm256_cvttph_epu64): Likewise.
+ (_mm256_mask_cvttph_epu64): Likewise.
+ (_mm256_maskz_cvttph_epu64): Likewise.
+ (_mm_cvttph_epi16): Likewise.
+ (_mm_mask_cvttph_epi16): Likewise.
+ (_mm_maskz_cvttph_epi16): Likewise.
+ (_mm256_cvttph_epi16): Likewise.
+ (_mm256_mask_cvttph_epi16): Likewise.
+ (_mm256_maskz_cvttph_epi16): Likewise.
+ (_mm_cvttph_epu16): Likewise.
+ (_mm_mask_cvttph_epu16): Likewise.
+ (_mm_maskz_cvttph_epu16): Likewise.
+ (_mm256_cvttph_epu16): Likewise.
+ (_mm256_mask_cvttph_epu16): Likewise.
+ (_mm256_maskz_cvttph_epu16): Likewise.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/sse.md
+ (avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name><round_saeonly_name>):
+ New.
+ (avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name>): Ditto.
+ (*avx512fp16_fix<fixunssuffix>_trunc<mode>2_load<mask_name>): Ditto.
+ (avx512fp16_fix<fixunssuffix>_truncv2di2<mask_name>): Ditto.
+ (avx512fp16_fix<fixunssuffix>_truncv2di2_load<mask_name>): Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_cvtsh_i32): New intrinsic.
+ (_mm_cvtsh_u32): Likewise.
+ (_mm_cvt_roundsh_i32): Likewise.
+ (_mm_cvt_roundsh_u32): Likewise.
+ (_mm_cvtsh_i64): Likewise.
+ (_mm_cvtsh_u64): Likewise.
+ (_mm_cvt_roundsh_i64): Likewise.
+ (_mm_cvt_roundsh_u64): Likewise.
+ (_mm_cvti32_sh): Likewise.
+ (_mm_cvtu32_sh): Likewise.
+ (_mm_cvt_roundi32_sh): Likewise.
+ (_mm_cvt_roundu32_sh): Likewise.
+ (_mm_cvti64_sh): Likewise.
+ (_mm_cvtu64_sh): Likewise.
+ (_mm_cvt_roundi64_sh): Likewise.
+ (_mm_cvt_roundu64_sh): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c (ix86_expand_round_builtin):
+ Handle new builtin types.
+ * config/i386/sse.md
+ (avx512fp16_vcvtsh2<sseintconvertsignprefix>si<rex64namesuffix><round_name>):
+ New define_insn.
+ (avx512fp16_vcvtsh2<sseintconvertsignprefix>si<rex64namesuffix>_2): Likewise.
+ (avx512fp16_vcvt<floatsuffix>si2sh<rex64namesuffix><round_name>): Likewise.
+
+2021-09-16 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-c.c (rs6000-builtins.h): New include.
+ (altivec_resolve_new_overloaded_builtin): New forward decl.
+ (rs6000_new_builtin_type_compatible): New function.
+ (altivec_resolve_overloaded_builtin): Call
+ altivec_resolve_new_overloaded_builtin.
+ (altivec_build_new_resolved_builtin): New function.
+ (altivec_resolve_new_overloaded_builtin): Likewise.
+ * config/rs6000/rs6000-call.c (rs6000_new_builtin_is_supported):
+ Likewise.
+ * config/rs6000/rs6000-gen-builtins.c (write_decls): Remove _p from
+ name of rs6000_new_builtin_is_supported.
+
+2021-09-16 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-protos.h (ix86_decompose_address):
+ Change return type to bool.
+ * config/i386/i386.c (ix86_decompose_address): Ditto.
+
+2021-09-16 Tobias Burnus <tobias@codesourcery.com>
+
+ PR target/102353
+ * config/rs6000/t-rs6000 (build/rs6000-gen-builtins.o, build/rbtree.o):
+ Added 'build/' to target, use build/%.o rule.
+ (build/rs6000-gen-builtins$(build_exeext)): Add 'build/' and
+ '$(build_exeext)' to target and 'build/' for the *.o files.
+ (rs6000-builtins.c): Update for those changes; run rs6000-gen-builtins
+ with $(RUN_GEN).
+
+2021-09-16 Martin Jambor <mjambor@suse.cz>
+
+ * cgraph.c (cgraph_node::dump): Do not check caller count sums if
+ the body has been removed. Remove trailing whitespace.
+
+2021-09-16 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102360
+ * internal-fn.c (expand_DEFERRED_INIT): Make pattern-init
+ of non-memory more robust.
+
+2021-09-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc-opts.h (enum sparc_processor_type): Add LEON5
+ * config/sparc/sparc.c (struct processor_costs): Add LEON5 costs
+ (leon5_adjust_cost): Increase cost of store with data dependency
+ on ALU instruction and FPU anti-dependencies.
+ (sparc_option_override): Add LEON5 costs
+ (sparc_adjust_cost): Add LEON5 cost adjustments
+ * config/sparc/sparc.h: Add LEON5
+ * config/sparc/sparc.md: Include LEON5 scheduling information
+ * config/sparc/sparc.opt: Add LEON5
+ * doc/invoke.texi: Add LEON5
+ * config/sparc/leon5.md: New file.
+
+2021-09-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.md (stack_protect_set32): Add NOP to prevent
+ sensitive sequence for B2BST errata workaround.
+
+2021-09-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.c (sparc_do_work_around_errata): Do not begin
+ functions with atomic instruction in the UT700 errata workaround.
+
+2021-09-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.c (next_active_non_empty_insn): New function
+ that returns next active non empty assembly instruction.
+ (sparc_do_work_around_errata): Use new function.
+
+2021-09-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.c (store_insn_p): Add predicate for store
+ attributes.
+ (load_insn_p): Add predicate for load attributes.
+ (sparc_do_work_around_errata): Use new predicates.
+
+2021-09-16 Andreas Larsson <andreas@gaisler.com>
+
+ * config/sparc/sparc.c (dump_target_flag_bits): Print bit names for
+ LEON and LEON3.
+
+2021-09-16 Martin Liska <mliska@suse.cz>
+
+ * config/mips/netbsd.h: Fix typo in name of a macro.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ PR middle-end/102080
+ * match.pd: Check mask type when doing cond_op related gimple
+ simplification.
+ * tree.c (is_truth_type_for): New function.
+ * tree.h (is_truth_type_for): New declaration.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_cvtepi32_ph): New
+ intrinsic.
+ (_mm512_mask_cvtepi32_ph): Likewise.
+ (_mm512_maskz_cvtepi32_ph): Likewise.
+ (_mm512_cvt_roundepi32_ph): Likewise.
+ (_mm512_mask_cvt_roundepi32_ph): Likewise.
+ (_mm512_maskz_cvt_roundepi32_ph): Likewise.
+ (_mm512_cvtepu32_ph): Likewise.
+ (_mm512_mask_cvtepu32_ph): Likewise.
+ (_mm512_maskz_cvtepu32_ph): Likewise.
+ (_mm512_cvt_roundepu32_ph): Likewise.
+ (_mm512_mask_cvt_roundepu32_ph): Likewise.
+ (_mm512_maskz_cvt_roundepu32_ph): Likewise.
+ (_mm512_cvtepi64_ph): Likewise.
+ (_mm512_mask_cvtepi64_ph): Likewise.
+ (_mm512_maskz_cvtepi64_ph): Likewise.
+ (_mm512_cvt_roundepi64_ph): Likewise.
+ (_mm512_mask_cvt_roundepi64_ph): Likewise.
+ (_mm512_maskz_cvt_roundepi64_ph): Likewise.
+ (_mm512_cvtepu64_ph): Likewise.
+ (_mm512_mask_cvtepu64_ph): Likewise.
+ (_mm512_maskz_cvtepu64_ph): Likewise.
+ (_mm512_cvt_roundepu64_ph): Likewise.
+ (_mm512_mask_cvt_roundepu64_ph): Likewise.
+ (_mm512_maskz_cvt_roundepu64_ph): Likewise.
+ (_mm512_cvtepi16_ph): Likewise.
+ (_mm512_mask_cvtepi16_ph): Likewise.
+ (_mm512_maskz_cvtepi16_ph): Likewise.
+ (_mm512_cvt_roundepi16_ph): Likewise.
+ (_mm512_mask_cvt_roundepi16_ph): Likewise.
+ (_mm512_maskz_cvt_roundepi16_ph): Likewise.
+ (_mm512_cvtepu16_ph): Likewise.
+ (_mm512_mask_cvtepu16_ph): Likewise.
+ (_mm512_maskz_cvtepu16_ph): Likewise.
+ (_mm512_cvt_roundepu16_ph): Likewise.
+ (_mm512_mask_cvt_roundepu16_ph): Likewise.
+ (_mm512_maskz_cvt_roundepu16_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_cvtepi32_ph): New
+ intrinsic.
+ (_mm_mask_cvtepi32_ph): Likewise.
+ (_mm_maskz_cvtepi32_ph): Likewise.
+ (_mm256_cvtepi32_ph): Likewise.
+ (_mm256_mask_cvtepi32_ph): Likewise.
+ (_mm256_maskz_cvtepi32_ph): Likewise.
+ (_mm_cvtepu32_ph): Likewise.
+ (_mm_mask_cvtepu32_ph): Likewise.
+ (_mm_maskz_cvtepu32_ph): Likewise.
+ (_mm256_cvtepu32_ph): Likewise.
+ (_mm256_mask_cvtepu32_ph): Likewise.
+ (_mm256_maskz_cvtepu32_ph): Likewise.
+ (_mm_cvtepi64_ph): Likewise.
+ (_mm_mask_cvtepi64_ph): Likewise.
+ (_mm_maskz_cvtepi64_ph): Likewise.
+ (_mm256_cvtepi64_ph): Likewise.
+ (_mm256_mask_cvtepi64_ph): Likewise.
+ (_mm256_maskz_cvtepi64_ph): Likewise.
+ (_mm_cvtepu64_ph): Likewise.
+ (_mm_mask_cvtepu64_ph): Likewise.
+ (_mm_maskz_cvtepu64_ph): Likewise.
+ (_mm256_cvtepu64_ph): Likewise.
+ (_mm256_mask_cvtepu64_ph): Likewise.
+ (_mm256_maskz_cvtepu64_ph): Likewise.
+ (_mm_cvtepi16_ph): Likewise.
+ (_mm_mask_cvtepi16_ph): Likewise.
+ (_mm_maskz_cvtepi16_ph): Likewise.
+ (_mm256_cvtepi16_ph): Likewise.
+ (_mm256_mask_cvtepi16_ph): Likewise.
+ (_mm256_maskz_cvtepi16_ph): Likewise.
+ (_mm_cvtepu16_ph): Likewise.
+ (_mm_mask_cvtepu16_ph): Likewise.
+ (_mm_maskz_cvtepu16_ph): Likewise.
+ (_mm256_cvtepu16_ph): Likewise.
+ (_mm256_mask_cvtepu16_ph): Likewise.
+ (_mm256_maskz_cvtepu16_ph): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/i386-modes.def: Declare V2HF and V6HF.
+ * config/i386/sse.md (VI2H_AVX512VL): New.
+ (qq2phsuff): Ditto.
+ (sseintvecmode): Add HF vector modes.
+ (avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode><mask_name><round_name>):
+ New.
+ (avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>): Ditto.
+ (*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>): Ditto.
+ (avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask): Ditto.
+ (*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask): Ditto.
+ (*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask_1): Ditto.
+ (avx512fp16_vcvt<floatsuffix>qq2ph_v2di): Ditto.
+ (*avx512fp16_vcvt<floatsuffix>qq2ph_v2di): Ditto.
+ (avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask): Ditto.
+ (*avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask): Ditto.
+ (*avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask_1): Ditto.
+ * config/i386/subst.md (round_qq2phsuff): New subst_attr.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_cvtph_epi32):
+ New intrinsic/
+ (_mm512_mask_cvtph_epi32): Likewise.
+ (_mm512_maskz_cvtph_epi32): Likewise.
+ (_mm512_cvt_roundph_epi32): Likewise.
+ (_mm512_mask_cvt_roundph_epi32): Likewise.
+ (_mm512_maskz_cvt_roundph_epi32): Likewise.
+ (_mm512_cvtph_epu32): Likewise.
+ (_mm512_mask_cvtph_epu32): Likewise.
+ (_mm512_maskz_cvtph_epu32): Likewise.
+ (_mm512_cvt_roundph_epu32): Likewise.
+ (_mm512_mask_cvt_roundph_epu32): Likewise.
+ (_mm512_maskz_cvt_roundph_epu32): Likewise.
+ (_mm512_cvtph_epi64): Likewise.
+ (_mm512_mask_cvtph_epi64): Likewise.
+ (_mm512_maskz_cvtph_epi64): Likewise.
+ (_mm512_cvt_roundph_epi64): Likewise.
+ (_mm512_mask_cvt_roundph_epi64): Likewise.
+ (_mm512_maskz_cvt_roundph_epi64): Likewise.
+ (_mm512_cvtph_epu64): Likewise.
+ (_mm512_mask_cvtph_epu64): Likewise.
+ (_mm512_maskz_cvtph_epu64): Likewise.
+ (_mm512_cvt_roundph_epu64): Likewise.
+ (_mm512_mask_cvt_roundph_epu64): Likewise.
+ (_mm512_maskz_cvt_roundph_epu64): Likewise.
+ (_mm512_cvtph_epi16): Likewise.
+ (_mm512_mask_cvtph_epi16): Likewise.
+ (_mm512_maskz_cvtph_epi16): Likewise.
+ (_mm512_cvt_roundph_epi16): Likewise.
+ (_mm512_mask_cvt_roundph_epi16): Likewise.
+ (_mm512_maskz_cvt_roundph_epi16): Likewise.
+ (_mm512_cvtph_epu16): Likewise.
+ (_mm512_mask_cvtph_epu16): Likewise.
+ (_mm512_maskz_cvtph_epu16): Likewise.
+ (_mm512_cvt_roundph_epu16): Likewise.
+ (_mm512_mask_cvt_roundph_epu16): Likewise.
+ (_mm512_maskz_cvt_roundph_epu16): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_cvtph_epi32):
+ New intrinsic.
+ (_mm_mask_cvtph_epi32): Likewise.
+ (_mm_maskz_cvtph_epi32): Likewise.
+ (_mm256_cvtph_epi32): Likewise.
+ (_mm256_mask_cvtph_epi32): Likewise.
+ (_mm256_maskz_cvtph_epi32): Likewise.
+ (_mm_cvtph_epu32): Likewise.
+ (_mm_mask_cvtph_epu32): Likewise.
+ (_mm_maskz_cvtph_epu32): Likewise.
+ (_mm256_cvtph_epu32): Likewise.
+ (_mm256_mask_cvtph_epu32): Likewise.
+ (_mm256_maskz_cvtph_epu32): Likewise.
+ (_mm_cvtph_epi64): Likewise.
+ (_mm_mask_cvtph_epi64): Likewise.
+ (_mm_maskz_cvtph_epi64): Likewise.
+ (_mm256_cvtph_epi64): Likewise.
+ (_mm256_mask_cvtph_epi64): Likewise.
+ (_mm256_maskz_cvtph_epi64): Likewise.
+ (_mm_cvtph_epu64): Likewise.
+ (_mm_mask_cvtph_epu64): Likewise.
+ (_mm_maskz_cvtph_epu64): Likewise.
+ (_mm256_cvtph_epu64): Likewise.
+ (_mm256_mask_cvtph_epu64): Likewise.
+ (_mm256_maskz_cvtph_epu64): Likewise.
+ (_mm_cvtph_epi16): Likewise.
+ (_mm_mask_cvtph_epi16): Likewise.
+ (_mm_maskz_cvtph_epi16): Likewise.
+ (_mm256_cvtph_epi16): Likewise.
+ (_mm256_mask_cvtph_epi16): Likewise.
+ (_mm256_maskz_cvtph_epi16): Likewise.
+ (_mm_cvtph_epu16): Likewise.
+ (_mm_mask_cvtph_epu16): Likewise.
+ (_mm_maskz_cvtph_epu16): Likewise.
+ (_mm256_cvtph_epu16): Likewise.
+ (_mm256_mask_cvtph_epu16): Likewise.
+ (_mm256_maskz_cvtph_epu16): Likewise.
+ * config/i386/i386-builtin-types.def: Add new builtin types.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/sse.md (sseintconvert): New.
+ (ssePHmode): Ditto.
+ (UNSPEC_US_FIX_NOTRUNC): Ditto.
+ (sseintconvertsignprefix): Ditto.
+ (avx512fp16_vcvtph2<sseintconvertsignprefix><sseintconvert>_<mode><mask_name><round_name>):
+ Ditto.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: (_mm_cvtsi16_si128):
+ New intrinsic.
+ (_mm_cvtsi128_si16): Likewise.
+ (_mm_mask_load_sh): Likewise.
+ (_mm_maskz_load_sh): Likewise.
+ (_mm_mask_store_sh): Likewise.
+ (_mm_move_sh): Likewise.
+ (_mm_mask_move_sh): Likewise.
+ (_mm_maskz_move_sh): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_special_args_builtin): Handle new builtin types.
+ (ix86_expand_vector_init_one_nonzero): Adjust for FP16 target.
+ * config/i386/sse.md (VI2F): New mode iterator.
+ (vec_set<mode>_0): Use new mode iterator.
+ (avx512f_mov<ssescalarmodelower>_mask): Adjust for HF vector mode.
+ (avx512f_store<mode>_mask): Ditto.
+
+2021-09-16 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.opt (-mtoc-fusion): Remove.
+
+2021-09-15 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_xcoff_encode_section_info):
+ Proceed if no symbol summary or the symbol alias flag is false.
+
+2021-09-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/88578
+ PR c++/102295
+ * varasm.c (output_constructor_regular_field): Instead of assertion
+ that array_size_for_constructor result is equal to size of
+ TREE_TYPE (local->val) in bytes, assert that the type size is greater
+ or equal to array_size_for_constructor result and use type size as
+ fieldsize.
+
+2021-09-15 Martin Liska <mliska@suse.cz>
+
+ PR target/102351
+ * config/i386/vxworks.h: Use new macro TARGET_CPU_P.
+
+2021-09-15 Martin Liska <mliska@suse.cz>
+
+ PR target/102349
+ * config/rs6000/rs6000.c (rs6000_xcoff_encode_section_info):
+ Check that we have a symbol summary for a symbol.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ PR target/102348
+ * config/rs6000/lynx.h: Remove undef of PREFERRED_DEBUGGING_TYPE
+ to inherit from elfos.h
+
+2021-09-15 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102327
+ * config/i386/i386-expand.c
+ (ix86_expand_vector_init_interleave): Use puncklwd to pack 2
+ HFmodes.
+ (ix86_expand_vector_set): Use blendw instead of pinsrw.
+ * config/i386/i386.c (ix86_can_change_mode_class): Adjust for
+ AVX512FP16 which supports 16bit vector load.
+ * config/i386/sse.md (avx512bw_interleave_highv32hi<mask_name>):
+ Rename to ..
+ (avx512bw_interleave_high<mode><mask_name>): .. this, and
+ extend to V32HFmode.
+ (avx2_interleave_highv16hi<mask_name>): Rename to ..
+ (avx2_interleave_high<mode><mask_name>): .. this, and extend
+ to V16HFmode.
+ (vec_interleave_highv8hi<mask_name>): Rename to ..
+ (vec_interleave_high<mode><mask_name>): .. this, and extend to V8HFmode.
+ (<mask_codefor>avx512bw_interleave_lowv32hi<mask_name>):
+ Rename to ..
+ (<mask_codefor>avx512bw_interleave_low<mode><mask_name>):
+ this, and extend to V32HFmode.
+ (avx2_interleave_lowv16hi<mask_name>): Rename to ..
+ (avx2_interleave_low<mode><mask_name>): .. this, and extend to V16HFmode.
+ (vec_interleave_lowv8hi<mask_name>): Rename to ..
+ (vec_interleave_low<mode><mask_name>): .. this, and extend to V8HFmode.
+ (sse4_1_pblendw): Rename to ..
+ (sse4_1_pblend<blendsuf>): .. this, and extend to V8HFmode.
+ (avx2_pblendph): New define_expand.
+ (<sse2p4_1>_pinsr<ssemodesuffix>): Refactor, use
+ sseintmodesuffix instead of ssemodesuffix.
+ (blendsuf): New mode attr.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (dr_misalignment): Move out of line.
+ (dr_target_alignment): New.
+ (DR_TARGET_ALIGNMENT): Wrap dr_target_alignment.
+ (set_dr_target_alignment): New.
+ (SET_DR_TARGET_ALIGNMENT): Wrap set_dr_target_alignment.
+ * tree-vect-data-refs.c (dr_misalignment): Compute and
+ return the group members misalignment.
+ (vect_compute_data_ref_alignment): Use SET_DR_TARGET_ALIGNMENT.
+ (vect_analyze_data_refs_alignment): Compute alignment only
+ for the first element of a DR group.
+ (vect_slp_analyze_node_alignment): Likewise.
+
+2021-09-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/avx512fp16intrin.h: Adjust all builtin calls.
+ * config/i386/avx512fp16vlintrin.h: Likewise.
+ * config/i386/i386-builtin.def: Adjust builtin name and
+ enumeration to match AVX512F style.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102318
+ * tree-vect-loop.c (vect_transform_cycle_phi): Revert
+ previous change and do the mode conversion separately from
+ the sign conversion.
+
+2021-09-15 Hongtao Liu <hongtao.liu@intel.com>
+ Peter Cordes <peter@cordes.ca>
+
+ PR target/91103
+ * config/i386/sse.md (extract_suf): Add V8SF/V8SI/V4DF/V4DI.
+ (*vec_extract<mode><ssescalarmodelower>_valign): Output
+ vextract{i,f}{32x4,64x2} instruction when byte_offset % 16 ==
+ 0.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ * config.gcc: Remove vax-*-openbsd* configuration.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ * config.gcc: Remove m68k-openbsd.
+
+2021-09-15 Max Filippov <jcmvbkbc@gmail.com>
+
+ PR target/102336
+ * config/xtensa/t-xtensa (TM_H): Add include/xtensa-config.h.
+
+2021-09-14 Peter Bergner <bergner@linux.ibm.com>
+
+ * config/rs6000/mma.md (unspec): Delete UNSPEC_MMA_XXSETACCZ.
+ (unspecv): Add UNSPECV_MMA_XXSETACCZ.
+ (*mma_xxsetaccz): Delete.
+ (mma_xxsetaccz): Change to define_insn. Remove operand 1.
+ Use UNSPECV_MMA_XXSETACCZ. Update comment.
+ * config/rs6000/rs6000.c (rs6000_rtx_costs): Use UNSPECV_MMA_XXSETACCZ.
+
+2021-09-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * Makefile.in: Remove variables related to applying no-PIE
+ to the exes on $build.
+ * configure: Regenerate.
+ * configure.ac: Remove configuration related to applying
+ no-PIE to the exes on $build.
+
+2021-09-14 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (doloop_end): Add missing mode.
+ (loop_end): Likewise.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (goa_stabilize_expr): Add depth argument, propagate
+ it to recursive calls, for depth above 7 just gimplify or return.
+ Perform a test even for MODIFY_EXPR, ADDR_EXPR, COMPOUND_EXPR with
+ __builtin_clear_padding and TARGET_EXPR.
+ (gimplify_omp_atomic): Adjust goa_stabilize_expr callers.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_fpclass_sh_mask):
+ New intrinsic.
+ (_mm_mask_fpclass_sh_mask): Likewise.
+ (_mm512_mask_fpclass_ph_mask): Likewise.
+ (_mm512_fpclass_ph_mask): Likewise.
+ (_mm_getexp_sh): Likewise.
+ (_mm_mask_getexp_sh): Likewise.
+ (_mm_maskz_getexp_sh): Likewise.
+ (_mm512_getexp_ph): Likewise.
+ (_mm512_mask_getexp_ph): Likewise.
+ (_mm512_maskz_getexp_ph): Likewise.
+ (_mm_getexp_round_sh): Likewise.
+ (_mm_mask_getexp_round_sh): Likewise.
+ (_mm_maskz_getexp_round_sh): Likewise.
+ (_mm512_getexp_round_ph): Likewise.
+ (_mm512_mask_getexp_round_ph): Likewise.
+ (_mm512_maskz_getexp_round_ph): Likewise.
+ (_mm_getmant_sh): Likewise.
+ (_mm_mask_getmant_sh): Likewise.
+ (_mm_maskz_getmant_sh): Likewise.
+ (_mm512_getmant_ph): Likewise.
+ (_mm512_mask_getmant_ph): Likewise.
+ (_mm512_maskz_getmant_ph): Likewise.
+ (_mm_getmant_round_sh): Likewise.
+ (_mm_mask_getmant_round_sh): Likewise.
+ (_mm_maskz_getmant_round_sh): Likewise.
+ (_mm512_getmant_round_ph): Likewise.
+ (_mm512_mask_getmant_round_ph): Likewise.
+ (_mm512_maskz_getmant_round_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_mask_fpclass_ph_mask):
+ New intrinsic.
+ (_mm_fpclass_ph_mask): Likewise.
+ (_mm256_mask_fpclass_ph_mask): Likewise.
+ (_mm256_fpclass_ph_mask): Likewise.
+ (_mm256_getexp_ph): Likewise.
+ (_mm256_mask_getexp_ph): Likewise.
+ (_mm256_maskz_getexp_ph): Likewise.
+ (_mm_getexp_ph): Likewise.
+ (_mm_mask_getexp_ph): Likewise.
+ (_mm_maskz_getexp_ph): Likewise.
+ (_mm256_getmant_ph): Likewise.
+ (_mm256_mask_getmant_ph): Likewise.
+ (_mm256_maskz_getmant_ph): Likewise.
+ (_mm_getmant_ph): Likewise.
+ (_mm_mask_getmant_ph): Likewise.
+ (_mm_maskz_getmant_ph): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/sse.md (vecmemsuffix): Add HF vector modes.
+ (<avx512>_getexp<mode><mask_name><round_saeonly_name>): Adjust
+ to support HF vector modes.
+ (avx512f_sgetexp<mode><mask_scalar_name><round_saeonly_scalar_name):
+ Ditto.
+ (avx512dq_fpclass<mode><mask_scalar_merge_name>): Ditto.
+ (avx512dq_vmfpclass<mode><mask_scalar_merge_name>): Ditto.
+ (<avx512>_getmant<mode><mask_name><round_saeonly_name>): Ditto.
+ (avx512f_vgetmant<mode><mask_scalar_name><round_saeonly_scalar_name>):
+ Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_reduce_ph):
+ New intrinsic.
+ (_mm512_mask_reduce_ph): Likewise.
+ (_mm512_maskz_reduce_ph): Likewise.
+ (_mm512_reduce_round_ph): Likewise.
+ (_mm512_mask_reduce_round_ph): Likewise.
+ (_mm512_maskz_reduce_round_ph): Likewise.
+ (_mm_reduce_sh): Likewise.
+ (_mm_mask_reduce_sh): Likewise.
+ (_mm_maskz_reduce_sh): Likewise.
+ (_mm_reduce_round_sh): Likewise.
+ (_mm_mask_reduce_round_sh): Likewise.
+ (_mm_maskz_reduce_round_sh): Likewise.
+ (_mm512_roundscale_ph): Likewise.
+ (_mm512_mask_roundscale_ph): Likewise.
+ (_mm512_maskz_roundscale_ph): Likewise.
+ (_mm512_roundscale_round_ph): Likewise.
+ (_mm512_mask_roundscale_round_ph): Likewise.
+ (_mm512_maskz_roundscale_round_ph): Likewise.
+ (_mm_roundscale_sh): Likewise.
+ (_mm_mask_roundscale_sh): Likewise.
+ (_mm_maskz_roundscale_sh): Likewise.
+ (_mm_roundscale_round_sh): Likewise.
+ (_mm_mask_roundscale_round_sh): Likewise.
+ (_mm_maskz_roundscale_round_sh): Likewise.
+ * config/i386/avx512fp16vlintrin.h: (_mm_reduce_ph):
+ New intrinsic.
+ (_mm_mask_reduce_ph): Likewise.
+ (_mm_maskz_reduce_ph): Likewise.
+ (_mm256_reduce_ph): Likewise.
+ (_mm256_mask_reduce_ph): Likewise.
+ (_mm256_maskz_reduce_ph): Likewise.
+ (_mm_roundscale_ph): Likewise.
+ (_mm_mask_roundscale_ph): Likewise.
+ (_mm_maskz_roundscale_ph): Likewise.
+ (_mm256_roundscale_ph): Likewise.
+ (_mm256_mask_roundscale_ph): Likewise.
+ (_mm256_maskz_roundscale_ph): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/sse.md (<mask_codefor>reducep<mode><mask_name>):
+ Renamed to ...
+ (<mask_codefor>reducep<mode><mask_name><round_saeonly_name>):
+ ... this, and adjust for round operands.
+ (reduces<mode><mask_scalar_name>): Likewise, with ...
+ (reduces<mode><mask_scalar_name><round_saeonly_scalar_name):
+ ... this.
+ (<avx512>_rndscale<mode><mask_name><round_saeonly_name>):
+ Adjust for HF vector modes.
+ (avx512f_rndscale<mode><mask_scalar_name><round_saeonly_scalar_name>):
+ Ditto.
+ (*avx512f_rndscale<mode><round_saeonly_name>): Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: (_mm512_rcp_ph):
+ New intrinsic.
+ (_mm512_mask_rcp_ph): Likewise.
+ (_mm512_maskz_rcp_ph): Likewise.
+ (_mm_rcp_sh): Likewise.
+ (_mm_mask_rcp_sh): Likewise.
+ (_mm_maskz_rcp_sh): Likewise.
+ (_mm512_scalef_ph): Likewise.
+ (_mm512_mask_scalef_ph): Likewise.
+ (_mm512_maskz_scalef_ph): Likewise.
+ (_mm512_scalef_round_ph): Likewise.
+ (_mm512_mask_scalef_round_ph): Likewise.
+ (_mm512_maskz_scalef_round_ph): Likewise.
+ (_mm_scalef_sh): Likewise.
+ (_mm_mask_scalef_sh): Likewise.
+ (_mm_maskz_scalef_sh): Likewise.
+ (_mm_scalef_round_sh): Likewise.
+ (_mm_mask_scalef_round_sh): Likewise.
+ (_mm_maskz_scalef_round_sh): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_rcp_ph):
+ New intrinsic.
+ (_mm256_rcp_ph): Likewise.
+ (_mm_mask_rcp_ph): Likewise.
+ (_mm256_mask_rcp_ph): Likewise.
+ (_mm_maskz_rcp_ph): Likewise.
+ (_mm256_maskz_rcp_ph): Likewise.
+ (_mm_scalef_ph): Likewise.
+ (_mm256_scalef_ph): Likewise.
+ (_mm_mask_scalef_ph): Likewise.
+ (_mm256_mask_scalef_ph): Likewise.
+ (_mm_maskz_scalef_ph): Likewise.
+ (_mm256_maskz_scalef_ph): Likewise.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/sse.md (VFH_AVX512VL): New.
+ (avx512fp16_rcp<mode>2<mask_name>): Ditto.
+ (avx512fp16_vmrcpv8hf2<mask_scalar_name>): Ditto.
+ (avx512f_vmscalef<mode><mask_scalar_name><round_scalar_name>):
+ Adjust to support HF vector modes.
+ (<avx512>_scalef<mode><mask_name><round_name>): Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: (_mm512_sqrt_ph):
+ New intrinsic.
+ (_mm512_mask_sqrt_ph): Likewise.
+ (_mm512_maskz_sqrt_ph): Likewise.
+ (_mm512_sqrt_round_ph): Likewise.
+ (_mm512_mask_sqrt_round_ph): Likewise.
+ (_mm512_maskz_sqrt_round_ph): Likewise.
+ (_mm512_rsqrt_ph): Likewise.
+ (_mm512_mask_rsqrt_ph): Likewise.
+ (_mm512_maskz_rsqrt_ph): Likewise.
+ (_mm_rsqrt_sh): Likewise.
+ (_mm_mask_rsqrt_sh): Likewise.
+ (_mm_maskz_rsqrt_sh): Likewise.
+ (_mm_sqrt_sh): Likewise.
+ (_mm_mask_sqrt_sh): Likewise.
+ (_mm_maskz_sqrt_sh): Likewise.
+ (_mm_sqrt_round_sh): Likewise.
+ (_mm_mask_sqrt_round_sh): Likewise.
+ (_mm_maskz_sqrt_round_sh): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_sqrt_ph): New intrinsic.
+ (_mm256_sqrt_ph): Likewise.
+ (_mm_mask_sqrt_ph): Likewise.
+ (_mm256_mask_sqrt_ph): Likewise.
+ (_mm_maskz_sqrt_ph): Likewise.
+ (_mm256_maskz_sqrt_ph): Likewise.
+ (_mm_rsqrt_ph): Likewise.
+ (_mm256_rsqrt_ph): Likewise.
+ (_mm_mask_rsqrt_ph): Likewise.
+ (_mm256_mask_rsqrt_ph): Likewise.
+ (_mm_maskz_rsqrt_ph): Likewise.
+ (_mm256_maskz_rsqrt_ph): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtins.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/sse.md (VF_AVX512FP16VL): New.
+ (sqrt<mode>2): Adjust for HF vector modes.
+ (<sse>_sqrt<mode>2<mask_name><round_name>): Likewise.
+ (<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>):
+ Likewise.
+ (<sse>_rsqrt<mode>2<mask_name>): New.
+ (avx512fp16_vmrsqrtv8hf2<mask_scalar_name>): Likewise.
+
+2021-09-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR bootstrap/101574
+ * diagnostic-spec.c (warning_suppressed_at, copy_warning): Handle
+ 'RESERVED_LOCATION_P' locations.
+ * warning-control.cc (get_nowarn_spec, suppress_warning)
+ (copy_warning): Likewise.
+
+2021-09-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ * diagnostic-spec.h (typedef xint_hash_t): Use 'location_t' instead of...
+ (typedef key_type_t): ... this. Remove.
+ (nowarn_map): Document.
+ * diagnostic-spec.c (nowarn_map): Likewise.
+ * warning-control.cc (convert_to_key): Evolve functions into...
+ (get_location): ... these. Adjust all users.
+
+2021-09-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ * warning-control.cc (copy_warning): Remove 'nowarn_map' setup.
+
+2021-09-13 Jason Merrill <jason@redhat.com>
+
+ * params.opt: Add destructive-interference-size and
+ constructive-interference-size.
+ * doc/invoke.texi: Document them.
+ * config/aarch64/aarch64.c (aarch64_override_options_internal):
+ Set them.
+ * config/arm/arm.c (arm_option_override): Set them.
+ * config/i386/i386-options.c (ix86_option_override_internal):
+ Set them.
+
+2021-09-13 Martin Liska <mliska@suse.cz>
+ H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101696
+ * common/config/i386/cpuinfo.h (cpu_indicator_init): Add support
+ for x86-64 micro levels for __builtin_cpu_supports.
+ * common/config/i386/i386-cpuinfo.h (enum feature_priority):
+ Add priorities for the micro-arch levels.
+ (enum processor_features): Add new features.
+ * common/config/i386/i386-isas.h: Add micro-arch features.
+ * config/i386/i386-builtins.c (get_builtin_code_for_version):
+ Support the micro-arch levels by callsing
+ __builtin_cpu_supports.
+ * doc/extend.texi: Document that the levels are support by
+ __builtin_cpu_supports.
+
+2021-09-13 Andrew Pinski <apinski@marvell.com>
+
+ PR target/95969
+ * config/aarch64/aarch64-builtins.c (aarch64_fold_builtin_lane_check):
+ New function.
+ (aarch64_general_fold_builtin): Handle AARCH64_SIMD_BUILTIN_LANE_CHECK.
+ (aarch64_general_gimple_fold_builtin): Likewise.
+
+2021-09-13 Andrew Pinski <apinski@marvell.com>
+
+ * config.gcc: Add m32r-*-linux* and m32rle-*-linux*
+ to the Unsupported targets list.
+ Remove support for m32r-*-linux* and m32rle-*-linux*.
+ * config/m32r/linux.h: Removed.
+ * config/m32r/t-linux: Removed.
+
+2021-09-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/102252
+ * config/aarch64/aarch64.c (aarch64_classify_address): Don't allow
+ register index for SVE predicate modes.
+
+2021-09-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c
+ (back_threader_profitability::profitable_path_p): Remove FSM
+ references.
+ (back_threader_registry::register_path): Same.
+ * tree-ssa-threadedge.c
+ (jump_threader::simplify_control_stmt_condition): Same.
+ * tree-ssa-threadupdate.c (jt_path_registry::jt_path_registry):
+ Add backedge_threads argument.
+ (fwd_jt_path_registry::fwd_jt_path_registry): Pass
+ backedge_threads argument.
+ (back_jt_path_registry::back_jt_path_registry): Same.
+ (dump_jump_thread_path): Adjust for FSM removal.
+ (back_jt_path_registry::rewire_first_differing_edge): Same.
+ (back_jt_path_registry::adjust_paths_after_duplication): Same.
+ (back_jt_path_registry::update_cfg): Same.
+ (jt_path_registry::register_jump_thread): Same.
+ * tree-ssa-threadupdate.h (enum jump_thread_edge_type): Remove
+ EDGE_FSM_THREAD.
+ (class back_jt_path_registry): Add backedge_threads to
+ constructor.
+
+2021-09-13 Martin Liska <mliska@suse.cz>
+
+ PR c++/101331
+ * asan.h (sanitize_coverage_p): Handle when fn == NULL.
+
+2021-09-13 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101935
+ * config/i386/i386.h (TARGET_AVX256_MOVE_BY_PIECES): New.
+ (TARGET_AVX256_STORE_BY_PIECES): Likewise.
+ (MOVE_MAX): Check TARGET_AVX256_MOVE_BY_PIECES and
+ TARGET_AVX256_STORE_BY_PIECES instead of
+ TARGET_AVX256_SPLIT_UNALIGNED_LOAD and
+ TARGET_AVX256_SPLIT_UNALIGNED_STORE.
+ (STORE_MAX_PIECES): Check TARGET_AVX256_STORE_BY_PIECES instead
+ of TARGET_AVX256_SPLIT_UNALIGNED_STORE.
+ * config/i386/x86-tune.def (X86_TUNE_AVX256_MOVE_BY_PIECES): New.
+ (X86_TUNE_AVX256_STORE_BY_PIECES): Likewise.
+
+2021-09-13 liuhongt <hongtao.liu@intel.com>
+
+ PR bootstrap/102302
+ * expmed.c (extract_bit_field_using_extv): Use
+ gen_lowpart_if_possible instead of gen_lowpart to avoid ICE.
+
+2021-09-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * Makefile.in (OBJS): Add value-pointer-equiv.o.
+ * gimple-ssa-evrp.c (class ssa_equiv_stack): Move to
+ value-pointer-equiv.*.
+ (ssa_equiv_stack::ssa_equiv_stack): Same.
+ (ssa_equiv_stack::enter): Same.
+ (ssa_equiv_stack::leave): Same.
+ (ssa_equiv_stack::push_replacement): Same.
+ (ssa_equiv_stack::get_replacement): Same.
+ (is_pointer_ssa): Same.
+ (class pointer_equiv_analyzer): Same.
+ (pointer_equiv_analyzer::pointer_equiv_analyzer): Same.
+ (pointer_equiv_analyzer::~pointer_equiv_analyzer): Same.
+ (pointer_equiv_analyzer::set_global_equiv): Same.
+ (pointer_equiv_analyzer::set_cond_equiv): Same.
+ (pointer_equiv_analyzer::get_equiv): Same.
+ (pointer_equiv_analyzer::enter): Same.
+ (pointer_equiv_analyzer::leave): Same.
+ (pointer_equiv_analyzer::get_equiv_expr): Same.
+ (pta_valueize): Same.
+ (pointer_equiv_analyzer::visit_stmt): Same.
+ (pointer_equiv_analyzer::visit_edge): Same.
+ (hybrid_folder::value_of_expr): Same.
+ (hybrid_folder::value_on_edge): Same.
+ * value-pointer-equiv.cc: New file.
+ * value-pointer-equiv.h: New file.
+
+2021-09-13 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/102125
+ * gimple-fold.c (gimple_fold_builtin_memory_op): Allow folding
+ memcpy if the size is not more than MOVE_MAX * MOVE_RATIO.
+
+2021-09-13 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/102125
+ * config/arm/arm.md (movmisaligndi): New define_expand.
+ * config/arm/vec-common.md (movmisalign<mode>): Iterate over VDQ mode.
+
+2021-09-13 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/102125
+ * emit-rtl.c (gen_highpart): Use adjust_address to handle
+ MEM rather than calling simplify_gen_subreg.
+
+2021-09-13 Jan-Benedict Glaw <jbglaw@ług-owl.de>
+
+ * config/alpha/vms.h (INIT_CUMULATIVE_ARGS): Wrap multi-statment
+ define into a block.
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/darwin.h (DARWIN_PREFER_DWARF): Do not define.
+ * config/i386/darwin.h (PREFERRED_DEBUGGING_TYPE): Do not
+ change based on DARWIN_PREFER_DWARF not being defined.
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/i386/lynx.h: Remove undef of PREFERRED_DEBUGGING_TYPE
+ to inherit from elfos.h
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config.gcc: Add cr16-*-* to the list of obsoleted targets.
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/avr/elf.h (PREFERRED_DEBUGGING_TYPE): Remove
+ override, pick up DWARF2_DEBUG define from elfos.h
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/rx/rx.h (PREFERRED_DEBUGGING_TYPE): Always define to
+ DWARF2_DEBUG.
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/alpha/vms.h (PREFERRED_DEBUGGING_TYPE): Define to
+ DWARF2_DEBUG.
+
+2021-09-13 Richard Biener <rguenther@suse.de>
+
+ * config/i386/cygming.h: Always default to DWARF2 debugging.
+ Do not define DBX_DEBUGGING_INFO, that's done via dbxcoff.h
+ already.
+ * doc/install.texi: Document binutils 2.16 as minimum
+ requirement for mingw.
+
+2021-09-13 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (struct rs6000_cost_data): New members
+ nstmts, nloads and extra_ctor_cost.
+ (rs6000_density_test): Add load density related heuristics. Do
+ extra costing on vector construction statements if need.
+ (rs6000_init_cost): Init new members.
+ (rs6000_update_target_cost_per_stmt): New function.
+ (rs6000_add_stmt_cost): Factor vect_nonmem hunk out to function
+ rs6000_update_target_cost_per_stmt and call it.
+
+2021-09-13 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (struct rs6000_cost_data): Remove typedef.
+ (rs6000_init_cost): Adjust.
+
+2021-09-13 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md: (UNSPEC_COPYSIGN): Remove.
+ (UNSPEC_XORSIGN): Ditto.
+
+2021-09-12 Roger Sayle <roger@nextmovesoftware.com>
+
+ * expr.c (convert_move): Preserve SUBREG_PROMOTED_VAR_P when
+ creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
+ subreg.
+
+2021-09-11 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (class back_threader_registry): Use
+ back_jt_path_registry.
+ * tree-ssa-threadedge.c (jump_threader::jump_threader): Use
+ fwd_jt_path_registry.
+ * tree-ssa-threadedge.h (class jump_threader): Same..
+ * tree-ssa-threadupdate.c
+ (jump_thread_path_registry::jump_thread_path_registry): Rename...
+ (jt_path_registry::jt_path_registry): ...to this.
+ (jump_thread_path_registry::~jump_thread_path_registry): Rename...
+ (jt_path_registry::~jt_path_registry): ...this.
+ (fwd_jt_path_registry::fwd_jt_path_registry): New.
+ (fwd_jt_path_registry::~fwd_jt_path_registry): New.
+ (jump_thread_path_registry::allocate_thread_edge): Rename...
+ (jt_path_registry::allocate_thread_edge): ...to this.
+ (jump_thread_path_registry::allocate_thread_path): Rename...
+ (jt_path_registry::allocate_thread_path): ...to this.
+ (jump_thread_path_registry::lookup_redirection_data): Rename...
+ (fwd_jt_path_registry::lookup_redirection_data): ...to this.
+ (jump_thread_path_registry::thread_block_1): Rename...
+ (fwd_jt_path_registry::thread_block_1): ...to this.
+ (jump_thread_path_registry::thread_block): Rename...
+ (fwd_jt_path_registry::thread_block): ...to this.
+ (jt_path_registry::thread_through_loop_header): Rename...
+ (fwd_jt_path_registry::thread_through_loop_header): ...to this.
+ (jump_thread_path_registry::mark_threaded_blocks): Rename...
+ (fwd_jt_path_registry::mark_threaded_blocks): ...to this.
+ (jump_thread_path_registry::debug_path): Rename...
+ (jt_path_registry::debug_path): ...to this.
+ (jump_thread_path_registry::dump): Rename...
+ (jt_path_registry::debug): ...to this.
+ (jump_thread_path_registry::rewire_first_differing_edge): Rename...
+ (back_jt_path_registry::rewire_first_differing_edge): ...to this.
+ (jump_thread_path_registry::adjust_paths_after_duplication): Rename...
+ (back_jt_path_registry::adjust_paths_after_duplication): ...to this.
+ (jump_thread_path_registry::duplicate_thread_path): Rename...
+ (back_jt_path_registry::duplicate_thread_path): ...to this. Also,
+ drop ill-formed candidates.
+ (jump_thread_path_registry::remove_jump_threads_including): Rename...
+ (fwd_jt_path_registry::remove_jump_threads_including): ...to this.
+ (jt_path_registry::thread_through_all_blocks): New.
+ (back_jt_path_registry::update_cfg): New.
+ (fwd_jt_path_registry::update_cfg): New.
+ (jump_thread_path_registry::register_jump_thread): Rename...
+ (jt_path_registry::register_jump_thread): ...to this.
+ * tree-ssa-threadupdate.h (class jump_thread_path_registry):
+ Abstract to...
+ (class jt_path_registry): ...here.
+ (class fwd_jt_path_registry): New.
+ (class back_jt_path_registry): New.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-09-01 liuhongt <hongtao.liu@intel.com>
+
+ * emit-rtl.c (validate_subreg): Get rid of all float-int
+ special cases.
+
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-core.h (enum omp_memory_order): Add OMP_MEMORY_ORDER_MASK,
+ OMP_FAIL_MEMORY_ORDER_UNSPECIFIED, OMP_FAIL_MEMORY_ORDER_RELAXED,
+ OMP_FAIL_MEMORY_ORDER_ACQUIRE, OMP_FAIL_MEMORY_ORDER_RELEASE,
+ OMP_FAIL_MEMORY_ORDER_ACQ_REL, OMP_FAIL_MEMORY_ORDER_SEQ_CST and
+ OMP_FAIL_MEMORY_ORDER_MASK enumerators.
+ (OMP_FAIL_MEMORY_ORDER_SHIFT): Define.
+ * gimple-pretty-print.c (dump_gimple_omp_atomic_load,
+ dump_gimple_omp_atomic_store): Print [weak] for weak atomic
+ load/store.
+ * gimple.h (enum gf_mask): Change GF_OMP_ATOMIC_MEMORY_ORDER
+ to 6-bit mask, adjust GF_OMP_ATOMIC_NEED_VALUE value and add
+ GF_OMP_ATOMIC_WEAK.
+ (gimple_omp_atomic_weak_p, gimple_omp_atomic_set_weak): New inline
+ functions.
+ * tree.h (OMP_ATOMIC_WEAK): Define.
+ * tree-pretty-print.c (dump_omp_atomic_memory_order): Adjust for
+ fail memory order being encoded in the same enum and also print
+ fail clause if present.
+ (dump_generic_node): Print weak clause if OMP_ATOMIC_WEAK.
+ * gimplify.c (goa_stabilize_expr): Add target_expr and rhs arguments,
+ handle pre_p == NULL case as a test mode that only returns value
+ but doesn't change gimplify nor change anything otherwise, adjust
+ recursive calls, add MODIFY_EXPR, ADDR_EXPR, COND_EXPR, TARGET_EXPR
+ and CALL_EXPR handling, adjust COMPOUND_EXPR handling for
+ __builtin_clear_padding calls, for !rhs gimplify as lvalue rather
+ than rvalue.
+ (gimplify_omp_atomic): Adjust goa_stabilize_expr caller. Handle
+ COND_EXPR rhs. Set weak flag on gimple load/store for
+ OMP_ATOMIC_WEAK.
+ * omp-expand.c (omp_memory_order_to_fail_memmodel): New function.
+ (omp_memory_order_to_memmodel): Adjust for fail clause encoded
+ in the same enum.
+ (expand_omp_atomic_cas): New function.
+ (expand_omp_atomic_pipeline): Use omp_memory_order_to_fail_memmodel
+ function.
+ (expand_omp_atomic): Attempt to optimize atomic compare and exchange
+ using expand_omp_atomic_cas.
+
+2021-09-10 Aldy Hernandez <aldyh@redhat.com>
+ Michael Matz <matz@suse.de>
+
+ * tree-pass.h (PROP_loop_opts_done): New.
+ * gimple-range-path.cc (path_range_query::internal_range_of_expr):
+ Intersect with global range.
+ * tree-ssa-loop.c (tree_ssa_loop_done): Set PROP_loop_opts_done.
+ * tree-ssa-threadbackward.c
+ (back_threader_profitability::profitable_path_p): Disable
+ threading through latches until after loop optimizations have run.
+
+2021-09-10 David Faust <david.faust@oracle.com>
+
+ * doc/invoke.texi: Document BPF -mcpu, -mjmpext, -mjmp32 and -malu32
+ options.
+
+2021-09-10 David Faust <david.faust@oracle.com>
+
+ * config/bpf/bpf-opts.h (bpf_isa_version): New enum.
+ * config/bpf/bpf-protos.h (bpf_expand_cbranch): New.
+ * config/bpf/bpf.c (bpf_option_override): Handle -mcpu option.
+ (bpf_expand_cbranch): New function.
+ * config/bpf/bpf.md (AM mode iterator): Conditionalize support for SI
+ mode.
+ (zero_extendsidi2): Only use mov32 instruction if it is available.
+ (SIM mode iterator): Conditionalize support for SI mode.
+ (JM mode iterator): New.
+ (cbranchdi4): Update name, use new JM iterator. Use bpf_expand_cbranch.
+ (*branch_on_di): Update name, use new JM iterator.
+ * config/bpf/bpf.opt: (mjmpext): New option.
+ (malu32): Likewise.
+ (mjmp32): Likewise.
+ (mcpu): Likewise.
+ (bpf_isa): New enum.
+
+2021-09-10 David Faust <david.faust@oracle.com>
+
+ * config/bpf/bpf.md (zero_extendhidi2): Add new output template
+ for register-to-register extensions.
+ (zero_extendqidi2): Likewise.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102273
+ * internal-fn.c (expand_DEFERRED_INIT): Always expand non-SSA vars.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102269
+ * gimplify.c (is_var_need_auto_init): Empty types do not need
+ initialization.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ * configure.ac (--with-stabs): Remove.
+ * configure: Regenerate.
+ * doc/install.texi: Remove --with-stabs documentation.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: (_mm512_cmp_ph_mask):
+ New intrinsic.
+ (_mm512_mask_cmp_ph_mask): Likewise.
+ (_mm512_cmp_round_ph_mask): Likewise.
+ (_mm512_mask_cmp_round_ph_mask): Likewise.
+ (_mm_cmp_sh_mask): Likewise.
+ (_mm_mask_cmp_sh_mask): Likewise.
+ (_mm_cmp_round_sh_mask): Likewise.
+ (_mm_mask_cmp_round_sh_mask): Likewise.
+ (_mm_comieq_sh): Likewise.
+ (_mm_comilt_sh): Likewise.
+ (_mm_comile_sh): Likewise.
+ (_mm_comigt_sh): Likewise.
+ (_mm_comige_sh): Likewise.
+ (_mm_comineq_sh): Likewise.
+ (_mm_ucomieq_sh): Likewise.
+ (_mm_ucomilt_sh): Likewise.
+ (_mm_ucomile_sh): Likewise.
+ (_mm_ucomigt_sh): Likewise.
+ (_mm_ucomige_sh): Likewise.
+ (_mm_ucomineq_sh): Likewise.
+ (_mm_comi_round_sh): Likewise.
+ (_mm_comi_sh): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_cmp_ph_mask): New intrinsic.
+ (_mm_mask_cmp_ph_mask): Likewise.
+ (_mm256_cmp_ph_mask): Likewise.
+ (_mm256_mask_cmp_ph_mask): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Ditto.
+ * config/i386/i386.md (ssevecmode): Add HF mode.
+ (MODEFH): New mode iterator.
+ * config/i386/sse.md
+ (V48H_AVX512VL): New mode iterator to support HF vector modes.
+ Ajdust corresponding description.
+ (ssecmpintprefix): New.
+ (VI12_AVX512VL): Adjust to support HF vector modes.
+ (cmp_imm_predicate): Likewise.
+ (<avx512>_cmp<mode>3<mask_scalar_merge_name><round_saeonly_name>):
+ Likewise.
+ (avx512f_vmcmp<mode>3<round_saeonly_name>): Likewise.
+ (avx512f_vmcmp<mode>3_mask<round_saeonly_name>): Likewise.
+ (<sse>_<unord>comi<round_saeonly_name>): Likewise.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h: (_mm512_max_ph): New intrinsic.
+ (_mm512_mask_max_ph): Likewise.
+ (_mm512_maskz_max_ph): Likewise.
+ (_mm512_min_ph): Likewise.
+ (_mm512_mask_min_ph): Likewise.
+ (_mm512_maskz_min_ph): Likewise.
+ (_mm512_max_round_ph): Likewise.
+ (_mm512_mask_max_round_ph): Likewise.
+ (_mm512_maskz_max_round_ph): Likewise.
+ (_mm512_min_round_ph): Likewise.
+ (_mm512_mask_min_round_ph): Likewise.
+ (_mm512_maskz_min_round_ph): Likewise.
+ (_mm_max_sh): Likewise.
+ (_mm_mask_max_sh): Likewise.
+ (_mm_maskz_max_sh): Likewise.
+ (_mm_min_sh): Likewise.
+ (_mm_mask_min_sh): Likewise.
+ (_mm_maskz_min_sh): Likewise.
+ (_mm_max_round_sh): Likewise.
+ (_mm_mask_max_round_sh): Likewise.
+ (_mm_maskz_max_round_sh): Likewise.
+ (_mm_min_round_sh): Likewise.
+ (_mm_mask_min_round_sh): Likewise.
+ (_mm_maskz_min_round_sh): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_max_ph): New intrinsic.
+ (_mm256_max_ph): Likewise.
+ (_mm_mask_max_ph): Likewise.
+ (_mm256_mask_max_ph): Likewise.
+ (_mm_maskz_max_ph): Likewise.
+ (_mm256_maskz_max_ph): Likewise.
+ (_mm_min_ph): Likewise.
+ (_mm256_min_ph): Likewise.
+ (_mm_mask_min_ph): Likewise.
+ (_mm256_mask_min_ph): Likewise.
+ (_mm_maskz_min_ph): Likewise.
+ (_mm256_maskz_min_ph): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ * config/i386/sse.md
+ (<code><mode>3<mask_name><round_saeonly_name>): Adjust to
+ support HF vector modes.
+ (*<code><mode>3<mask_name><round_saeonly_name>): Likewise.
+ (ieee_<ieee_maxmin><mode>3<mask_name><round_saeonly_name>):
+ Likewise.
+ (<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>):
+ Likewise.
+ * config/i386/subst.md (round_saeonly_mode512bit_condition):
+ Adjust for HF vector modes.
+
+2021-09-10 Liu, Hongtao <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_add_sh): New intrinsic.
+ (_mm_mask_add_sh): Likewise.
+ (_mm_maskz_add_sh): Likewise.
+ (_mm_sub_sh): Likewise.
+ (_mm_mask_sub_sh): Likewise.
+ (_mm_maskz_sub_sh): Likewise.
+ (_mm_mul_sh): Likewise.
+ (_mm_mask_mul_sh): Likewise.
+ (_mm_maskz_mul_sh): Likewise.
+ (_mm_div_sh): Likewise.
+ (_mm_mask_div_sh): Likewise.
+ (_mm_maskz_div_sh): Likewise.
+ (_mm_add_round_sh): Likewise.
+ (_mm_mask_add_round_sh): Likewise.
+ (_mm_maskz_add_round_sh): Likewise.
+ (_mm_sub_round_sh): Likewise.
+ (_mm_mask_sub_round_sh): Likewise.
+ (_mm_maskz_sub_round_sh): Likewise.
+ (_mm_mul_round_sh): Likewise.
+ (_mm_mask_mul_round_sh): Likewise.
+ (_mm_maskz_mul_round_sh): Likewise.
+ (_mm_div_round_sh): Likewise.
+ (_mm_mask_div_round_sh): Likewise.
+ (_mm_maskz_div_round_sh): Likewise.
+ * config/i386/i386-builtin-types.def: Add corresponding builtin types.
+ * config/i386/i386-builtin.def: Add corresponding new builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_round_builtin): Handle new builtins.
+ * config/i386/sse.md (VF_128): Change description.
+ (<sse>_vm<plusminus_insn><mode>3<mask_scalar_name><round_scalar_name>):
+ Adjust to support HF vector modes.
+ (<sse>_vm<multdiv_mnemonic><mode>3<mask_scalar_name><round_scalar_name>):
+ Likewise.
+
+2021-09-10 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/i386-expand.c
+ (ix86_avx256_split_vector_move_misalign): Handle V16HF mode.
+ * config/i386/i386.c
+ (ix86_preferred_simd_mode): Handle HF mode.
+ * config/i386/sse.md (V_256H): New mode iterator.
+ (avx_vextractf128<mode>): Use it.
+ (VEC_INIT_MODE): Align vector HFmode condition to vector
+ HImodes since there're no real HF instruction used.
+ (VEC_INIT_HALF_MODE): Ditto.
+ (VIHF): Ditto.
+ (VIHF_AVX512BW): Ditto.
+ (*vec_extracthf): Ditto.
+ (VEC_EXTRACT_MODE): Ditto.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ PR target/102255
+ * config/dbx.h: Remove.
+ * config/dbxcoff.h: Do not define PREFERRED_DEBUGGING_TYPE.
+ * config/lynx.h: Likewise.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-expand.c (ix86_expand_copysign): Expand
+ right into ANDNOT + AND + IOR, using paradoxical subregs.
+ (ix86_split_copysign_const): Remove.
+ (ix86_split_copysign_var): Ditto.
+ * config/i386/i386-protos.h (ix86_split_copysign_const): Dotto.
+ (ix86_split_copysign_var): Ditto.
+ * config/i386/i386.md (@copysign<mode>3_const): Ditto.
+ (@copysign<mode>3_var): Ditto.
+
+2021-09-09 qing zhao <qing.zhao@oracle.com>
+
+ * builtins.c (expand_builtin_memset): Make external visible.
+ * builtins.h (expand_builtin_memset): Declare extern.
+ * common.opt (ftrivial-auto-var-init=): New option.
+ * doc/extend.texi: Document the uninitialized attribute.
+ * doc/invoke.texi: Document -ftrivial-auto-var-init.
+ * flag-types.h (enum auto_init_type): New enumerated type
+ auto_init_type.
+ * gimple-fold.c (clear_padding_type): Add one new parameter.
+ (clear_padding_union): Likewise.
+ (clear_padding_emit_loop): Likewise.
+ (clear_type_padding_in_mask): Likewise.
+ (gimple_fold_builtin_clear_padding): Handle this new parameter.
+ * gimplify.c (gimple_add_init_for_auto_var): New function.
+ (gimple_add_padding_init_for_auto_var): New function.
+ (is_var_need_auto_init): New function.
+ (gimplify_decl_expr): Add initialization to automatic variables per
+ users' requests.
+ (gimplify_call_expr): Add one new parameter for call to
+ __builtin_clear_padding.
+ (gimplify_init_constructor): Add padding initialization in the end.
+ * internal-fn.c (INIT_PATTERN_VALUE): New macro.
+ (expand_DEFERRED_INIT): New function.
+ * internal-fn.def (DEFERRED_INIT): New internal function.
+ * tree-cfg.c (verify_gimple_call): Verify calls to .DEFERRED_INIT.
+ * tree-sra.c (generate_subtree_deferred_init): New function.
+ (scan_function): Avoid setting cannot_scalarize_away_bitmap for
+ calls to .DEFERRED_INIT.
+ (sra_modify_deferred_init): New function.
+ (sra_modify_function_body): Handle calls to DEFERRED_INIT specially.
+ * tree-ssa-structalias.c (find_func_aliases_for_call): Likewise.
+ * tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT
+ specially.
+ (check_defs): Likewise.
+ (warn_uninitialized_vars): Likewise.
+ * tree-ssa.c (ssa_undefined_value_p): Likewise.
+ * tree.c (build_common_builtin_nodes): Build tree node for
+ BUILT_IN_CLEAR_PADDING when needed.
+
+2021-09-09 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-loop-im.c (fill_always_executed_in_1): Walk
+ into all subloops.
+
+2021-09-09 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-loop-im.c (fill_always_executed_in_1): Integrate
+ DOM walk from get_loop_body_in_dom_order using a worklist
+ approach.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ * config.gcc: Add avx512fp16vlintrin.h.
+ * config/i386/avx512fp16intrin.h: (_mm512_add_ph): New intrinsic.
+ (_mm512_mask_add_ph): Likewise.
+ (_mm512_maskz_add_ph): Likewise.
+ (_mm512_sub_ph): Likewise.
+ (_mm512_mask_sub_ph): Likewise.
+ (_mm512_maskz_sub_ph): Likewise.
+ (_mm512_mul_ph): Likewise.
+ (_mm512_mask_mul_ph): Likewise.
+ (_mm512_maskz_mul_ph): Likewise.
+ (_mm512_div_ph): Likewise.
+ (_mm512_mask_div_ph): Likewise.
+ (_mm512_maskz_div_ph): Likewise.
+ (_mm512_add_round_ph): Likewise.
+ (_mm512_mask_add_round_ph): Likewise.
+ (_mm512_maskz_add_round_ph): Likewise.
+ (_mm512_sub_round_ph): Likewise.
+ (_mm512_mask_sub_round_ph): Likewise.
+ (_mm512_maskz_sub_round_ph): Likewise.
+ (_mm512_mul_round_ph): Likewise.
+ (_mm512_mask_mul_round_ph): Likewise.
+ (_mm512_maskz_mul_round_ph): Likewise.
+ (_mm512_div_round_ph): Likewise.
+ (_mm512_mask_div_round_ph): Likewise.
+ (_mm512_maskz_div_round_ph): Likewise.
+ * config/i386/avx512fp16vlintrin.h: New header.
+ * config/i386/i386-builtin-types.def (V16HF, V8HF, V32HF):
+ Add new builtin types.
+ * config/i386/i386-builtin.def: Add corresponding builtins.
+ * config/i386/i386-expand.c
+ (ix86_expand_args_builtin): Handle new builtin types.
+ (ix86_expand_round_builtin): Likewise.
+ * config/i386/immintrin.h: Include avx512fp16vlintrin.h
+ * config/i386/sse.md (VFH): New mode_iterator.
+ (VF2H): Likewise.
+ (avx512fmaskmode): Add HF vector modes.
+ (avx512fmaskhalfmode): Likewise.
+ (<plusminus_insn><mode>3<mask_name><round_name>): Adjust to for
+ HF vector modes.
+ (*<plusminus_insn><mode>3<mask_name><round_name>): Likewise.
+ (mul<mode>3<mask_name><round_name>): Likewise.
+ (*mul<mode>3<mask_name><round_name>): Likewise.
+ (div<mode>3): Likewise.
+ (<sse>_div<mode>3<mask_name><round_name>): Likewise.
+ * config/i386/subst.md (SUBST_V): Add HF vector modes.
+ (SUBST_A): Likewise.
+ (round_mode512bit_condition): Adjust for V32HFmode.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * config/i386/sse.md (reduc_plus_scal_<mode>): Split to ..
+ (reduc_plus_scal_v4sf): .. this, New define_expand.
+ (reduc_plus_scal_v2df): .. and this, New define_expand.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/91103
+ * config/i386/sse.md (*vec_extract<mode><ssescalarmodelower>_valign):
+ New define_insn.
+
+2021-09-08 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/60318
+ * doc/trouble.texi (Copy Assignment): Fix description of
+ behaviour and fix code in example.
+
+2021-09-08 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/102107
+ * config/rs6000/rs6000-logue.c (rs6000_emit_epilogue): For ELFv2 use
+ r11 instead of r12 for restoring CR.
+
+2021-09-08 Jakub Jelinek <jakub@redhat.com>
+ liuhongt <hongtao.liu@intel.com>
+
+ PR target/89984
+ * config/i386/i386.md (@xorsign<mode>3_1): Remove.
+ * config/i386/i386-expand.c (ix86_expand_xorsign): Expand right away
+ into AND with mask and XOR, using paradoxical subregs.
+ (ix86_split_xorsign): Remove.
+ * config/i386/i386-protos.h (ix86_split_xorsign): Remove.
+
+2021-09-08 Di Zhao <dizhao@os.amperecomputing.com>
+
+ * tree-ssa-sccvn.c (vn_nary_op_insert_into): fix result compare
+
+2021-09-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102224
+ * config/i386/i386.md (xorsign<mode>3): If operands[1] is equal to
+ operands[2], emit abs<mode>2 instead.
+ (@xorsign<mode>3_1): Add early-clobbers for output operand, enable
+ first alternative even for avx, add another alternative with
+ =&Yv <- 0, Yv, Yvm constraints.
+ * config/i386/i386-expand.c (ix86_split_xorsign): If op0 is equal
+ to op1, emit vpandn instead.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm_set_ph): New intrinsic.
+ (_mm256_set_ph): Likewise.
+ (_mm512_set_ph): Likewise.
+ (_mm_setr_ph): Likewise.
+ (_mm256_setr_ph): Likewise.
+ (_mm512_setr_ph): Likewise.
+ (_mm_set1_ph): Likewise.
+ (_mm256_set1_ph): Likewise.
+ (_mm512_set1_ph): Likewise.
+ (_mm_setzero_ph): Likewise.
+ (_mm256_setzero_ph): Likewise.
+ (_mm512_setzero_ph): Likewise.
+ (_mm_set_sh): Likewise.
+ (_mm_load_sh): Likewise.
+ (_mm_store_sh): Likewise.
+ * config/i386/i386-builtin-types.def (V8HF): New type.
+ (DEF_FUNCTION_TYPE (V8HF, V8HI)): New builtin function type
+ * config/i386/i386-expand.c (ix86_expand_vector_init_duplicate):
+ Support vector HFmodes.
+ (ix86_expand_vector_init_one_nonzero): Likewise.
+ (ix86_expand_vector_init_one_var): Likewise.
+ (ix86_expand_vector_init_interleave): Likewise.
+ (ix86_expand_vector_init_general): Likewise.
+ (ix86_expand_vector_set): Likewise.
+ (ix86_expand_vector_extract): Likewise.
+ (ix86_expand_vector_init_concat): Likewise.
+ (ix86_expand_sse_movcc): Handle vector HFmodes.
+ (ix86_expand_vector_set_var): Ditto.
+ * config/i386/i386-modes.def: Add HF vector modes in comment.
+ * config/i386/i386.c (classify_argument): Add HF vector modes.
+ (ix86_hard_regno_mode_ok): Allow HF vector modes for AVX512FP16.
+ (ix86_vector_mode_supported_p): Likewise.
+ (ix86_set_reg_reg_cost): Handle vector HFmode.
+ (ix86_get_ssemov): Handle vector HFmode.
+ (function_arg_advance_64): Pass unamed V16HFmode and V32HFmode
+ by stack.
+ (function_arg_advance_32): Pass V8HF/V16HF/V32HF by sse reg for 32bit
+ mode.
+ (function_arg_advance_32): Ditto.
+ * config/i386/i386.h (VALID_AVX512FP16_REG_MODE): New.
+ (VALID_AVX256_REG_OR_OI_MODE): Rename to ..
+ (VALID_AVX256_REG_OR_OI_VHF_MODE): .. this, and add V16HF.
+ (VALID_SSE2_REG_VHF_MODE): New.
+ (VALID_AVX512VL_128_REG_MODE): Add V8HF and TImode.
+ (SSE_REG_MODE_P): Add vector HFmode.
+ * config/i386/i386.md (mode): Add HF vector modes.
+ (MODE_SIZE): Likewise.
+ (ssemodesuffix): Add ph suffix for HF vector modes.
+ * config/i386/sse.md (VFH_128): New mode iterator.
+ (VMOVE): Adjust for HF vector modes.
+ (V): Likewise.
+ (V_256_512): Likewise.
+ (avx512): Likewise.
+ (avx512fmaskmode): Likewise.
+ (shuffletype): Likewise.
+ (sseinsnmode): Likewise.
+ (ssedoublevecmode): Likewise.
+ (ssehalfvecmode): Likewise.
+ (ssehalfvecmodelower): Likewise.
+ (ssePScmode): Likewise.
+ (ssescalarmode): Likewise.
+ (ssescalarmodelower): Likewise.
+ (sseintprefix): Likewise.
+ (i128): Likewise.
+ (bcstscalarsuff): Likewise.
+ (xtg_mode): Likewise.
+ (VI12HF_AVX512VL): New mode_iterator.
+ (VF_AVX512FP16): Likewise.
+ (VIHF): Likewise.
+ (VIHF_256): Likewise.
+ (VIHF_AVX512BW): Likewise.
+ (V16_256): Likewise.
+ (V32_512): Likewise.
+ (sseintmodesuffix): New mode_attr.
+ (sse): Add scalar and vector HFmodes.
+ (ssescalarmode): Add vector HFmode mapping.
+ (ssescalarmodesuffix): Add sh suffix for HFmode.
+ (*<sse>_vm<insn><mode>3): Use VFH_128.
+ (*<sse>_vm<multdiv_mnemonic><mode>3): Likewise.
+ (*ieee_<ieee_maxmin><mode>3): Likewise.
+ (<avx512>_blendm<mode>): New define_insn.
+ (vec_setv8hf): New define_expand.
+ (vec_set<mode>_0): New define_insn for HF vector set.
+ (*avx512fp16_movsh): Likewise.
+ (avx512fp16_movsh): Likewise.
+ (vec_extract_lo_v32hi): Rename to ...
+ (vec_extract_lo_<mode>): ... this, and adjust to allow HF
+ vector modes.
+ (vec_extract_hi_v32hi): Likewise.
+ (vec_extract_hi_<mode>): Likewise.
+ (vec_extract_lo_v16hi): Likewise.
+ (vec_extract_lo_<mode>): Likewise.
+ (vec_extract_hi_v16hi): Likewise.
+ (vec_extract_hi_<mode>): Likewise.
+ (vec_set_hi_v16hi): Likewise.
+ (vec_set_hi_<mode>): Likewise.
+ (vec_set_lo_v16hi): Likewise.
+ (vec_set_lo_<mode>): Likewise.
+ (*vec_extract<mode>_0): New define_insn_and_split for HF
+ vector extract.
+ (*vec_extracthf): New define_insn.
+ (VEC_EXTRACT_MODE): Add HF vector modes.
+ (PINSR_MODE): Add V8HF.
+ (sse2p4_1): Likewise.
+ (pinsr_evex_isa): Likewise.
+ (<sse2p4_1>_pinsr<ssemodesuffix>): Adjust to support
+ insert for V8HFmode.
+ (pbroadcast_evex_isa): Add HF vector modes.
+ (AVX2_VEC_DUP_MODE): Likewise.
+ (VEC_INIT_MODE): Likewise.
+ (VEC_INIT_HALF_MODE): Likewise.
+ (avx2_pbroadcast<mode>): Adjust to support HF vector mode
+ broadcast.
+ (avx2_pbroadcast<mode>_1): Likewise.
+ (<avx512>_vec_dup<mode>_1): Likewise.
+ (<avx512>_vec_dup<mode><mask_name>): Likewise.
+ (<mask_codefor><avx512>_vec_dup_gpr<mode><mask_name>):
+ Likewise.
+
+2021-09-08 Guo, Xuepeng <xuepeng.guo@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+ Liu Hongtao <hongtao.liu@intel.com>
+ Wang Hongyu <hongyu.wang@intel.com>
+ Xu Dianhong <dianhong.xu@intel.com>
+
+ * common/config/i386/cpuinfo.h (get_available_features):
+ Detect FEATURE_AVX512FP16.
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA_AVX512FP16_SET,
+ OPTION_MASK_ISA_AVX512FP16_UNSET,
+ OPTION_MASK_ISA2_AVX512FP16_SET,
+ OPTION_MASK_ISA2_AVX512FP16_UNSET): New.
+ (OPTION_MASK_ISA2_AVX512BW_UNSET,
+ OPTION_MASK_ISA2_AVX512BF16_UNSET): Add AVX512FP16.
+ (ix86_handle_option): Handle -mavx512fp16.
+ * common/config/i386/i386-cpuinfo.h (enum processor_features):
+ Add FEATURE_AVX512FP16.
+ * common/config/i386/i386-isas.h: Add entry for AVX512FP16.
+ * config.gcc: Add avx512fp16intrin.h.
+ * config/i386/avx512fp16intrin.h: New intrinsic header.
+ * config/i386/cpuid.h: Add bit_AVX512FP16.
+ * config/i386/i386-builtin-types.def: (FLOAT16): New primitive type.
+ * config/i386/i386-builtins.c: Support _Float16 type for i386
+ backend.
+ (ix86_register_float16_builtin_type): New function.
+ (ix86_float16_type_node): New.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Define
+ __AVX512FP16__.
+ * config/i386/i386-expand.c (ix86_expand_branch): Support
+ HFmode.
+ (ix86_prepare_fp_compare_args): Adjust TARGET_SSE_MATH &&
+ SSE_FLOAT_MODE_P to SSE_FLOAT_MODE_SSEMATH_OR_HF_P.
+ (ix86_expand_fp_movcc): Ditto.
+ * config/i386/i386-isa.def: Add PTA define for AVX512FP16.
+ * config/i386/i386-options.c (isa2_opts): Add -mavx512fp16.
+ (ix86_valid_target_attribute_inner_p): Add avx512fp16 attribute.
+ * config/i386/i386.c (ix86_get_ssemov): Use
+ vmovdqu16/vmovw/vmovsh for HFmode/HImode scalar or vector.
+ (ix86_get_excess_precision): Use
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 when TARGET_AVX512FP16
+ existed.
+ (sse_store_index): Use SFmode cost for HFmode cost.
+ (inline_memory_move_cost): Add HFmode, and perfer SSE cost over
+ GPR cost for HFmode.
+ (ix86_hard_regno_mode_ok): Allow HImode in sse register.
+ (ix86_mangle_type): Add manlging for _Float16 type.
+ (inline_secondary_memory_needed): No memory is needed for
+ 16bit movement between gpr and sse reg under
+ TARGET_AVX512FP16.
+ (ix86_multiplication_cost): Adjust TARGET_SSE_MATH &&
+ SSE_FLOAT_MODE_P to SSE_FLOAT_MODE_SSEMATH_OR_HF_P.
+ (ix86_division_cost): Ditto.
+ (ix86_rtx_costs): Ditto.
+ (ix86_add_stmt_cost): Ditto.
+ (ix86_optab_supported_p): Ditto.
+ * config/i386/i386.h (VALID_AVX512F_SCALAR_MODE): Add HFmode.
+ (SSE_FLOAT_MODE_SSEMATH_OR_HF_P): Add HFmode.
+ (PTA_SAPPHIRERAPIDS): Add PTA_AVX512FP16.
+ * config/i386/i386.md (mode): Add HFmode.
+ (MODE_SIZE): Add HFmode.
+ (isa): Add avx512fp16.
+ (enabled): Handle avx512fp16.
+ (ssemodesuffix): Add sh suffix for HFmode.
+ (comm): Add mult, div.
+ (plusminusmultdiv): New code iterator.
+ (insn): Add mult, div.
+ (*movhf_internal): Adjust for avx512fp16 instruction.
+ (*movhi_internal): Ditto.
+ (*cmpi<unord>hf): New define_insn for HFmode.
+ (*ieee_s<ieee_maxmin>hf3): Likewise.
+ (extendhf<mode>2): Likewise.
+ (trunc<mode>hf2): Likewise.
+ (float<floatunssuffix><mode>hf2): Likewise.
+ (*<insn>hf): Likewise.
+ (cbranchhf4): New expander.
+ (movhfcc): Likewise.
+ (<insn>hf3): Likewise.
+ (mulhf3): Likewise.
+ (divhf3): Likewise.
+ * config/i386/i386.opt: Add mavx512fp16.
+ * config/i386/immintrin.h: Include avx512fp16intrin.h.
+ * doc/invoke.texi: Add mavx512fp16.
+ * doc/extend.texi: Add avx512fp16 Usage Notes.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * common.opt: Support -fexcess-precision=16.
+ * config/aarch64/aarch64.c (aarch64_excess_precision): Return
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 when
+ EXCESS_PRECISION_TYPE_FLOAT16.
+ * config/arm/arm.c (arm_excess_precision): Ditto.
+ * config/i386/i386.c (ix86_get_excess_precision): Ditto.
+ * config/m68k/m68k.c (m68k_excess_precision): Issue an error
+ when EXCESS_PRECISION_TYPE_FLOAT16.
+ * config/s390/s390.c (s390_excess_precision): Ditto.
+ * coretypes.h (enum excess_precision_type): Add
+ EXCESS_PRECISION_TYPE_FLOAT16.
+ * doc/tm.texi (TARGET_C_EXCESS_PRECISION): Update documents.
+ * doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): Ditto.
+ * doc/extend.texi (Half-Precision): Document
+ -fexcess-precision=16.
+ * flag-types.h (enum excess_precision): Add
+ EXCESS_PRECISION_FLOAT16.
+ * target.def (excess_precision): Update document.
+ * tree.c (excess_precision_type): Set excess_precision_type to
+ EXCESS_PRECISION_FLOAT16 when -fexcess-precision=16.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * doc/extend.texi: (@node Floating Types): Adjust the wording.
+ (@node Half-Precision): Ditto.
+
+2021-09-07 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ PR target/102115
+ * config/xtensa/xtensa.c (xtensa_emit_move_sequence): Add
+ 'CONST_INT_P (src)' to the condition of the block that tries to
+ eliminate literal when loading integer contant.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * doc/extend.texi (BPF Type Attributes) New node.
+ Document new preserve_access_index attribute.
+ Document new preserve_access_index builtin.
+ * doc/invoke.texi: Document -mco-re and -mno-co-re options.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * config/bpf/bpf.c: Adjust includes.
+ (bpf_handle_preserve_access_index_attribute): New function.
+ (bpf_attribute_table): Use it here.
+ (bpf_builtins): Add BPF_BUILTIN_PRESERVE_ACCESS_INDEX.
+ (bpf_option_override): Handle "-mco-re" option.
+ (bpf_asm_init_sections): New.
+ (TARGET_ASM_INIT_SECTIONS): Redefine.
+ (bpf_file_end): New.
+ (TARGET_ASM_FILE_END): Redefine.
+ (bpf_init_builtins): Add "__builtin_preserve_access_index".
+ (bpf_core_compute, bpf_core_get_index): New.
+ (is_attr_preserve_access): New.
+ (bpf_expand_builtin): Handle new builtins.
+ (bpf_core_newdecl, bpf_core_is_maybe_aggregate_access): New.
+ (bpf_core_walk): New.
+ (bpf_resolve_overloaded_builtin): New.
+ (TARGET_RESOLVE_OVERLOADED_BUILTIN): Redefine.
+ (handle_attr): New.
+ (pass_bpf_core_attr): New RTL pass.
+ * config/bpf/bpf-passes.def: New file.
+ * config/bpf/bpf-protos.h (make_pass_bpf_core_attr): New.
+ * config/bpf/coreout.c: New file.
+ * config/bpf/coreout.h: Likewise.
+ * config/bpf/t-bpf (TM_H): Add $(srcdir)/config/bpf/coreout.h.
+ (coreout.o): New rule.
+ (PASSES_EXTRA): Add $(srcdir)/config/bpf/bpf-passes.def.
+ * config.gcc (bpf): Add coreout.h to extra_headers.
+ Add coreout.o to extra_objs.
+ Add $(srcdir)/config/bpf/coreout.c to target_gtfiles.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * btfout.c (get_btf_id): Function is no longer static.
+ * ctfc.h: Expose it here.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * ctfc.c (ctf_lookup_tree_type): New function.
+ * ctfc.h: Likewise.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * ctfc.c (ctf_dtd_lookup): Function is no longer static.
+ * ctfc.h: Analogous change.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * dwarf2out.c (lookup_type_die): Function is no longer static.
+ * dwarf2out.h: Expose it here.
+
+2021-09-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * dwarf2ctf.c (ctf_debug_finalize): Make it static.
+ (ctf_debug_early_finish): New definition.
+ (ctf_debug_finish): Likewise.
+ * dwarf2ctf.h (ctf_debug_finalize): Remove declaration.
+ (ctf_debug_early_finish): New declaration.
+ (ctf_debug_finish): Likewise.
+ * dwarf2out.c (dwarf2out_finish): Invoke ctf_debug_finish.
+ (dwarf2out_early_finish): Invoke ctf_debug_early_finish.
+
+2021-09-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * config/bpf/bpf.c (bpf_option_override): For BPF backend, disable LTO
+ support when compiling for CO-RE.
+ * config/bpf/bpf.opt: Add new command line option -mco-re.
+
+2021-09-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * flag-types.h (enum debug_info_type): Add new enum
+ DINFO_TYPE_BTF_WITH_CORE.
+ (BTF_WITH_CORE_DEBUG): New bitmask.
+ * flags.h (btf_with_core_debuginfo_p): New declaration.
+ * opts.c (btf_with_core_debuginfo_p): New definition.
+
+2021-09-07 Jason Merrill <jason@redhat.com>
+
+ * tree.h (error_operand_p): Change to inline function.
+
+2021-09-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadedge.c (forwarder_block_p): Rename to...
+ (empty_block_with_phis_p): ...this.
+ (potentially_threadable_block): Same.
+ (jump_threader::thread_through_normal_block): Same.
+
+2021-09-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR debug/101947
+ * dwarf2out.c (mark_base_types): New overloaded function.
+ (dwarf2out_early_finish): Invoke it on the COMDAT type list as well
+ as the compilation unit, and call move_marked_base_types afterward.
+
+2021-09-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/85819
+ * config/i386/i386-expand.c (ix86_expand_convert_uns_sisf_sse):
+ Enable FMA.
+ (ix86_expand_vector_convert_uns_vsivsf): Likewise.
+
+2021-09-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102226
+ * tree-vect-loop.c (vect_transform_cycle_phi): Record
+ the converted value for the epilogue PHI use.
+
+2021-09-07 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/80223
+ * ipa-inline.c (can_inline_edge_p): Similarly to sanitizer
+ options, do not inline when no_profile_instrument_function
+ attributes are different in early inliner. It's fine to inline
+ it after PGO instrumentation.
+
+2021-09-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/101555
+ * tree-ssa-pre.c (translate_vuse_through_block): Do not
+ perform an alias walk to determine the validity of the
+ mem at the start of the block which is already guaranteed
+ by means of prune_clobbered_mems.
+ (phi_translate_1): Pass edge to translate_vuse_through_block.
+
+2021-09-07 Xionghu Luo <luoxhu@linux.ibm.com>
+
+ PR target/97142
+ * config/rs6000/rs6000.md (fmod<mode>3): New define_expand.
+ (remainder<mode>3): Likewise.
+
+2021-09-07 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * config/mips/mips.c (mips_file_start): add .module for
+ arch and ase.
+
+2021-09-06 Roger Sayle <roger@nextmovesoftware.com>
+
+ * wide-int.cc (wi::clz): Reorder tests to ensure the result
+ is zero for all negative values.
+
+2021-09-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * doc/invoke.texi (-foffload-options): Fix @opindex.
+
+2021-09-06 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/89984
+ * config/i386/i386-expand.c (ix86_split_xorsign): Use operands[2].
+ * config/i386/i386.md (@xorsign<mode>3_1): Add non-destructive
+ source alternative for AVX.
+
+2021-09-06 liuhongt <hongtao.liu@intel.com>
+
+ PR middle-end/102182
+ * optabs.c (expand_fix): Add from1 to avoid from being
+ overwritten.
+
+2021-09-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.c (modified_type_die): Deal with all array types earlier
+ and use local variable consistently throughout the function.
+
+2021-09-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102207
+ * match.pd: Don't demote operands of IFN_{ADD,SUB,MUL}_OVERFLOW if they
+ were promoted from signed to wider unsigned type.
+
+2021-09-06 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/63184
+ * match.pd: Add simplification of pointer_diff of two pointer_plus
+ with addr_expr in the first operand of each pointer_plus.
+ Add simplificatoin of ne/eq of two pointer_plus with addr_expr
+ in the first operand of each pointer_plus.
+
+2021-09-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102176
+ * tree-vect-slp.c (vect_slp_gather_vectorized_scalar_stmts):
+ New function.
+ (vect_bb_slp_scalar_cost): Use the computed set of
+ vectorized scalar stmts instead of relying on the out-of-date
+ and not accurate PURE_SLP_STMT.
+ (vect_bb_vectorization_profitable_p): Compute the set
+ of vectorized scalar stmts.
+
+2021-09-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::range_of_stmt): Remove
+ GIMPLE_COND special casing.
+ (path_range_query::range_defined_in_block): Use range_of_stmt
+ instead of calling fold_range directly.
+
+2021-09-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::range_of_expr): Set
+ m_undefined_path when appropriate.
+ (path_range_query::internal_range_of_expr): Copy from range_of_expr.
+ (path_range_query::unreachable_path_p): New.
+ (path_range_query::precompute_ranges): Set m_undefined_path.
+ * gimple-range-path.h (path_range_query::unreachable_path_p): New.
+ (path_range_query::internal_range_of_expr): New.
+ * tree-ssa-threadbackward.c (back_threader::find_taken_edge_cond):
+ Use unreachable_path_p.
+
+2021-09-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (back_threader::maybe_register_path):
+ Remove argument and call find_taken_edge.
+ (back_threader::resolve_phi): Do not calculate taken edge before
+ calling maybe_register_path.
+ (back_threader::find_paths_to_names): Same.
+
+2021-09-05 Jeff Law <jlaw@localhost.localdomain>
+
+ * config/h8300/h8300.md (QHSI2 mode iterator): New mode iterator.
+ * config/h8300/testcompare.md (store_c): Update name, use new
+ QHSI2 iterator.
+ (store_neg_c, store_shifted_c): New patterns.
+
+2021-09-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/102107
+ * config/rs6000/rs6000-logue.c (rs6000_emit_prologue): On ELFv2 use r11
+ instead of r12 for CR save, in all cases.
+
+2021-09-03 Andrew Pinski <apinski@marvell.com>
+
+ * config/aarch64/aarch64-sve-builtins.cc (register_vector_type):
+ Handle error_mark_node as the type of the type_decl.
+
+2021-09-03 Andrew Pinski <apinski@marvell.com>
+
+ * config/aarch64/aarch64-builtins.c (struct aarch64_simd_type_info):
+ Mark with GTY.
+ (aarch64_simd_types): Likewise.
+ (aarch64_simd_intOI_type_node): Likewise.
+ (aarch64_simd_intCI_type_node): Likewise.
+ (aarch64_simd_intXI_type_node): Likewise.
+ * config/aarch64/aarch64.h (aarch64_fp16_type_node): Likewise.
+ (aarch64_fp16_ptr_type_node): Likewise.
+ (aarch64_bf16_type_node): Likewise.
+ (aarch64_bf16_ptr_type_node): Likewise.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * range-op.cc (operator_minus::op1_op2_relation_effect): Abstract
+ out to...
+ (minus_op1_op2_relation_effect): ...here.
+ (class operator_pointer_diff): New.
+ (operator_pointer_diff::op1_op2_relation_effect): Call
+ minus_op1_op2_relation_effect.
+ (integral_table::integral_table): Add entry for POINTER_DIFF_EXPR.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (back_threader::thread_through_all_blocks):
+ Add may_peel_loop_headers.
+ (back_threader_registry::thread_through_all_blocks): Same.
+ (try_thread_blocks): Pass may_peel_loop_headers argument.
+ (pass_early_thread_jumps::execute): Same.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadedge.c (has_phis_p): New.
+ (forwarder_block_p): New.
+ (potentially_threadable_block): Call forwarder_block_p.
+ (jump_threader::thread_around_empty_blocks): Call has_phis_p.
+ (jump_threader::thread_through_normal_block): Call
+ forwarder_block_p.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadbackward.c (back_threader::dump): New.
+ (back_threader::debug): New.
+ (back_threader_profitability::profitable_path_p): Dump blocks
+ even if we are bailing early.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (cancel_thread): New.
+ (jump_thread_path_registry::thread_block_1): Use cancel_thread.
+ (jump_thread_path_registry::mark_threaded_blocks): Same.
+ (jump_thread_path_registry::register_jump_thread): Same.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadedge.c (jt_state::push): Only call methods for
+ which objects are available.
+ (jt_state::pop): Same.
+ (jt_state::register_equiv): Same.
+ (jt_state::register_equivs_on_edge): Same.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadedge.c (jump_threader::thread_across_edge):
+ Move pop until after a thread is registered.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-threadupdate.c (debug): New.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-trace.cc (push_dump_file::push_dump_file): New.
+ (push_dump_file::~push_dump_file): New.
+ (dump_ranger): Change dump_file temporarily while dumping
+ ranger.
+ * gimple-range-trace.h (class push_dump_file): New.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-trace.cc (debug_seed_ranger): Remove static.
+ (dump_ranger): Dump function name.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::range_defined_in_block):
+ Adjust for non-null.
+ (path_range_query::adjust_for_non_null_uses): New.
+ (path_range_query::precompute_ranges): Call
+ adjust_for_non_null_uses.
+ * gimple-range-path.h: Add m_non_null and
+ adjust_for_non_null_uses.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-path.cc (path_range_query::dump): Dump path
+ length.
+ (path_range_query::precompute_ranges): Dump entire path.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-relation.cc (relation_oracle::debug): New.
+ * value-relation.h (relation_oracle::debug): New.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssa-loop-ch.c: Remove unnecessary include file.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::postfold_gcond_edges):
+ Skip statements with no defining BB.
+ * gimple-range-path.cc (path_range_query::range_defined_in_block):
+ Do not get confused by statements with no defining BB.
+
+2021-09-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-fold.cc (adjust_imagpart_expr): Move from
+ gimple_range_adjustment. Add support for constants.
+ (adjust_realpart_expr): New.
+ (gimple_range_adjustment): Move IMAGPART_EXPR code to
+ adjust_imagpart_expr.
+ * range-op.cc (integral_table::integral_table): Add entry for
+ REALPART_CST.
+
+2021-09-03 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-expand.c (expand_omp_atomic_pipeline): Use
+ IFN_ATOMIC_COMPARE_EXCHANGE instead of
+ BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_? so that memory order
+ can be provided.
+
+2021-09-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102024
+ * tree.h (DECL_FIELD_ABI_IGNORED): Changed into rvalue only macro
+ that is false if DECL_BIT_FIELD.
+ (SET_DECL_FIELD_ABI_IGNORED, DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD,
+ SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD): Define.
+ * tree-streamer-out.c (pack_ts_decl_common_value_fields): For
+ DECL_BIT_FIELD stream DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD instead
+ of DECL_FIELD_ABI_IGNORED.
+ * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use
+ SET_DECL_FIELD_ABI_IGNORED instead of writing to
+ DECL_FIELD_ABI_IGNORED and for DECL_BIT_FIELD use
+ SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD instead.
+ * lto-streamer-out.c (hash_tree): For DECL_BIT_FIELD hash
+ DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD instead of DECL_FIELD_ABI_IGNORED.
+
+2021-09-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102166
+ * config/i386/amxbf16intrin.h : Remove macro check for __AMX_BF16__.
+ * config/i386/amxint8intrin.h : Remove macro check for __AMX_INT8__.
+ * config/i386/amxtileintrin.h : Remove macro check for __AMX_TILE__.
+
+2021-09-02 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/17506
+ PR testsuite/37182
+ * tree-ssa-uninit.c (warn_uninit): Remove conditional guarding note.
+
+2021-09-02 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-loop-im.c (fill_always_executed_in_1): Refine
+ fix for PR78185 and continue processing when leaving
+ finite inner loops.
+
+2021-09-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/99591
+ * match.pd: Demote operands of IFN_{ADD,SUB,MUL}_OVERFLOW if they
+ were promoted.
+
+2021-09-02 Richard Biener <rguenther@suse.de>
+
+ Revert:
+ 2021-09-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102155
+ * tree-ssa-loop-im.c (fill_always_executed_in_1): Iterate
+ over a part of the RPO array and do not recurse here.
+ Dump blocks marked as always executed.
+ (fill_always_executed_in): Walk over the RPO array and
+ process loops whose header we run into.
+ (loop_invariant_motion_in_fun): Compute the first RPO
+ using rev_post_order_and_mark_dfs_back_seme in iteration
+ order and pass that to fill_always_executed_in.
+
+2021-09-02 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-modes.def (FLOAT_MODE): Define ieee HFmode.
+ * config/i386/i386.c (enum x86_64_reg_class): Add
+ X86_64_SSEHF_CLASS.
+ (merge_classes): Handle X86_64_SSEHF_CLASS.
+ (examine_argument): Ditto.
+ (construct_container): Ditto.
+ (classify_argument): Ditto, and set HFmode/HCmode to
+ X86_64_SSEHF_CLASS.
+ (function_value_32): Return _FLoat16/Complex Float16 by
+ %xmm0.
+ (function_value_64): Return _Float16/Complex Float16 by SSE
+ register.
+ (ix86_print_operand): Handle CONST_DOUBLE HFmode.
+ (ix86_secondary_reload): Require gpr as intermediate register
+ to store _Float16 from sse register when sse4 is not
+ available.
+ (ix86_libgcc_floating_mode_supported_p): Enable _FLoat16 under
+ sse2.
+ (ix86_scalar_mode_supported_p): Ditto.
+ (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Defined.
+ * config/i386/i386.h (VALID_SSE2_REG_MODE): Add HFmode.
+ (VALID_INT_MODE_P): Add HFmode and HCmode.
+ * config/i386/i386.md (*pushhf_rex64): New define_insn.
+ (*pushhf): Ditto.
+ (*movhf_internal): Ditto.
+ * doc/extend.texi (Half-Precision Floating Point): Documemt
+ _Float16 for x86.
+
+2021-09-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102155
+ * tree-ssa-loop-im.c (fill_always_executed_in_1): Iterate
+ over a part of the RPO array and do not recurse here.
+ Dump blocks marked as always executed.
+ (fill_always_executed_in): Walk over the RPO array and
+ process loops whose header we run into.
+ (loop_invariant_motion_in_fun): Compute the first RPO
+ using rev_post_order_and_mark_dfs_back_seme in iteration
+ order and pass that to fill_always_executed_in.
+
+2021-09-02 YunQiang Su <syq@debian.org>
+
+ Revert:
+ 2021-08-31 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * config/mips/mips.c (mips_module_isa_name): New.
+ mips_file_start: add .module mipsREV to all asm output
+
+2021-09-01 Jeff Law <jlaw@localhost.localdomain>
+
+ PR tree-optimization/102152
+ * tree-ssa-dom.c (dom_opt_dom_walker::optimize_stmt): Reduce a vector
+ comparison to a scalar comparison before calling
+ update_stmt_if_modified.
+
+2021-09-01 Andrew Pinski <apinski@marvell.com>
+
+ PR target/101934
+ * config/aarch64/aarch64.c (aarch64_expand_setmem):
+ Check STRICT_ALIGNMENT before creating an overlapping
+ store.
+
+2021-09-01 Martin Sebor <msebor@redhat.com>
+
+ * gimple-ssa-warn-access.cc (get_size_range): Add argument.
+ (check_access): Pass additional argument.
+ (check_memop_access): Remove template and make a member function.
+ (maybe_check_dealloc_call): Make a pass_waccess member function.
+ (class pass_waccess): Add, rename, and remove members.
+ (pass_waccess::pass_waccess): Adjust to name change.
+ (pass_waccess::~pass_waccess): Same.
+ (check_alloca): Make a member function.
+ (check_alloc_size_call): Same.
+ (check_strcat): Same.
+ (check_strncat): Same.
+ (check_stxcpy): Same.
+ (check_stxncpy): Same.
+ (check_strncmp): Same.
+ (maybe_warn_rdwr_sizes): Rename...
+ (pass_waccess::maybe_check_access_sizes): ...to this.
+ (pass_waccess::check_call): Adjust to name changes.
+ (pass_waccess::maybe_check_dealloc_call): Make a pass_waccess member
+ function.
+ (pass_waccess::execute): Adjust to name changes.
+ * gimple-ssa-warn-access.h (check_memop_access): Remove.
+ * pointer-query.cc (access_ref::phi): Handle null pointer.
+ (access_ref::inform_access): Same.
+ (pointer_query::put_ref): Modify a cached value, not a copy of it.
+ (pointer_query::dump): New function.
+ (compute_objsize_r): Avoid overwriting access_ref::bndrng. Cache
+ more results.
+ * pointer-query.h (pointer_query::dump): Declare.
+ * tree-ssa-strlen.c (get_range): Simplify. Use function query.
+ (dump_strlen_info): Use function query.
+ (printf_strlen_execute): Factor code out into pointer_query::put_ref.
+
+2021-09-01 Thomas Schwinge <thomas@codesourcery.com>
+
+ * tree.c (walk_tree_1) <OMP_CLAUSE>: Simplify.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * doc/extend.texi: Document unavailable attribute.
+ * print-tree.c (print_node): Handle unavailable attribute.
+ * tree-core.h (struct tree_base): Add a bit to carry unavailability.
+ * tree.c (error_unavailable_use): New.
+ * tree.h (TREE_UNAVAILABLE): New.
+ (error_unavailable_use): New.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102124
+ * tree-vect-patterns.c (vect_recog_widen_op_pattern): For ORIG_CODE
+ MINUS_EXPR, if itype is unsigned with smaller precision than type,
+ add an extra cast to signed variant of itype to ensure sign-extension.
+
+2021-09-01 Martin Liska <mliska@suse.cz>
+
+ * graph.c (draw_cfg_node_succ_edges): Do not color fallthru
+ edges and rather use colors for TRUE and FALSE edges.
+
+2021-09-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/93491
+ * tree-ssa-pre.c (compute_avail): Set BB_MAY_NOTRETURN
+ after processing the stmt itself. Do not consider
+ pure functions possibly not returning. Properly avoid
+ adding possibly trapping calls to EXP_GEN when there's
+ a preceeding possibly not returning call.
+ * tree-ssa-sccvn.c (vn_reference_may_trap): Conservatively
+ not handle calls.
+
+2021-09-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102139
+ * tree-vectorizer.h (vec_base_alignments): Adjust hash-map
+ type to record a std::pair of the stmt-info and the innermost
+ loop behavior.
+ (dr_vec_info::group): New member.
+ * tree-vect-data-refs.c (vect_record_base_alignment): Adjust.
+ (vect_compute_data_ref_alignment): Verify the recorded
+ base alignment can be used.
+ (data_ref_pair): Remove.
+ (dr_group_sort_cmp): Adjust.
+ (vect_analyze_data_ref_accesses): Store the group-ID in the
+ dr_vec_info and operate on a vector of dr_vec_infos.
+
+2021-09-01 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * read-md.c (md_reader::handle_enum): support value assignation.
+ * doc/md.texi: record define_c_enum value assignation support.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102141
+ * gimple-ssa-store-merging.c (bswap_view_convert): Add BEFORE
+ argument. If false, emit stmts after gsi instead of before, and
+ with GSI_NEW_STMT.
+ (bswap_replace): Adjust callers. When converting output of bswap,
+ emit VIEW_CONVERT prepratation stmts after a copy of gsi instead
+ of before it.
+
+2021-09-01 liuhongt <hongtao.liu@intel.com>
+
+ * emit-rtl.c (validate_subreg): Get rid of all float-int
+ special cases.
+
+2021-09-01 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-08-30 liuhongt <hongtao.liu@intel.com>
+
+ * expmed.c (extract_bit_field_1): Make sure we're playing with
+ integral modes before call extract_integral_bit_field.
+ (extract_integral_bit_field): Add a parameter of type
+ scalar_int_mode which corresponds to of tmode.
+ And call extract_and_convert_fixed_bit_field instead of
+ extract_fixed_bit_field and convert_extracted_bit_field.
+ (extract_and_convert_fixed_bit_field): New function, it's a
+ combination of extract_fixed_bit_field and
+ convert_extracted_bit_field.
+
+2021-08-31 Thomas Schwinge <thomas@codesourcery.com>
+
+ * tree.c (walk_tree_1) <OMP_CLAUSE_TILE>: Handle three operands.
+
+2021-08-31 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-general.h (omp_is_reference): Rename to...
+ (omp_privatize_by_reference): ... this. Adjust all users...
+ * omp-general.c: ... here, ...
+ * gimplify.c: ... here, ...
+ * omp-expand.c: ... here, ...
+ * omp-low.c: ... here.
+
+2021-08-31 Martin Sebor <msebor@redhat.com>
+
+ * gimple-ssa-warn-access.cc (maybe_warn_alloc_args_overflow): Test
+ pointer element for equality to zero, not that of the cotaining
+ array.
+
+2021-08-31 Martin Sebor <msebor@redhat.com>
+
+ * gcc-rich-location.h (gcc_rich_location): Make ctor explicit.
+
+2021-08-31 Martin Sebor <msebor@redhat.com>
+
+ * function.h (function): Add comments.
+ (get_range_query): Same. Add attribute returns nonnull.
+
+2021-08-31 Roger Sayle <roger@nextmovesoftware.com>
+
+ * expr.c (convert_modes): Don't use subreg_promoted_mode on a
+ SUBREG if it can't be guaranteed to a SUBREG_PROMOTED_VAR_P set.
+ Instead use the standard (safer) is_a <scalar_int_mode> idiom.
+
+2021-08-31 Jeff Law <jlaw@localhost.localdomain>
+
+ * config.gcc (cris-*-elf, cris-*-none): Remove dbxelf.h from
+ tm_file.
+ (m32r-*-elf, m32rle-*-elf, m32r-*-linux): Likewise.
+ (mn10300-*-*, am33_2.0-*-linux*): Likewise.
+ (xtensa*-*-elf, xtensa*-*-linux, xtensa*-*-uclinux): Likewise.
+ (m32c-*-elf*, m32c-*-rtems*): Likewise.
+ * config/cris/cris.h (DBX_NO_XREFS): Remove.
+ (DBX_CONTIN_LENGTH, DBX_CONTIN_CHAR): Likewise.
+ * config/m32r/m32r.h (DBXOUT_SOURCE_LINE): Likewise.
+ (DBX_DEBUGGING_INFO, DBX_CONTIN_LENGTH): Likewise.
+ * config/mn10300/mn10300.h (DEFAULT_GDB_EXTENSIONS): Likewise.
+ * config/mn10300/linux.h (DBX_REGISTER_NAMES): Likewise.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * gimplify.c (gimplify_scan_omp_clauses): Error handling. 'ancestor' only
+ allowed on target constructs and only with particular other clauses.
+ * omp-expand.c (expand_omp_target): Output of 'sorry, not supported' if
+ 'ancestor' is used.
+ * omp-low.c (check_omp_nesting_restrictions): Error handling. No nested OpenMP
+ structs when 'ancestor' is used.
+ (scan_omp_1_stmt): No usage of OpenMP runtime routines in a target region when
+ 'ancestor' is used.
+ * tree-pretty-print.c (dump_omp_clause): Append 'ancestor'.
+ * tree.h (OMP_CLAUSE_DEVICE_ANCESTOR): Define macro.
+
+2021-08-31 Roger Sayle <roger@nextmovesoftware.com>
+
+ * expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
+ creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
+ subreg.
+ * simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
+ Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
+ partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
+ SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
+ [ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
+ creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
+ subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
+ would be paradoxical.
+
+2021-08-31 Roger Sayle <roger@nextmovesoftware.com>
+
+ * combine.c (combine_simplify_rtx): Avoid converting an explicit
+ TRUNCATE into a lowpart SUBREG on !TRULY_NOOP_TRUNCATION targets.
+ * simplify-rtx.c (simplify_unary_operation_1): Likewise.
+
+2021-08-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102142
+ * tree-vect-slp.c (vect_bb_vectorization_profitable_p): Fix
+ condition under which to unset the visited flag.
+
+2021-08-31 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102129
+ * tree-ssa-ter.c (find_replaceable_in_bb): Do not move
+ possibly trapping expressions across calls.
+
+2021-08-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102134
+ * tree-ssa-ccp.c (bit_value_binop) <case RSHIFT_EXPR>: If sgn is
+ UNSIGNED and r1val | r1mask has MSB set, ensure lzcount doesn't
+ become negative.
+
+2021-08-31 Andrew Pinski <apinski@marvell.com>
+
+ PR driver/79181
+ * collect-utils.c (setup_signals): New declaration.
+ * collect-utils.h (setup_signals): New function.
+ * collect2.c (handler): Delete.
+ (main): Instead of manually setting up the signals,
+ just call setup_signals.
+ * lto-wrapper.c (main): Likewise.
+
+2021-08-31 Andrew Pinski <apinski@marvell.com>
+
+ PR target/56337
+ * config/i386/i386-protos.h (x86_output_aligned_bss):
+ Change align argument to unsigned type.
+ (x86_elf_aligned_decl_common): Likewise.
+ * config/i386/i386.c (x86_elf_aligned_decl_common): Likewise.
+ (x86_output_aligned_bss): Likewise.
+
+2021-08-31 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * config/mips/mips.c (mips_module_isa_name): New.
+ mips_file_start: add .module mipsREV to all asm output
+
+2021-08-31 YunQiang Su <yunqiang.su@cipunited.com>
+
+ * config/mips/mips.h (struct mips_cpu_info): define enum mips_isa;
+ use enum instead of int for 'isa' member.
+ * config.gcc, config/mips/mips.c, config/mips/mips-cpus.def,
+ config/mips/netbsd.h: replace hardcoded numbers with enum.
+
+2021-08-31 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/sse.md (*<avx512>_ucmp<mode>3_1): Change from
+ define_split to define_insn_and_split.
+ (*avx2_eq<mode>3): Removed.
+ (<avx512>_eq<mode>3<mask_scalar_merge_name>): Adjust pattern
+ (<avx512>_eq<mode>3<mask_scalar_merge_name>_1): Rename to ..
+ (*<avx512>_eq<mode>3<mask_scalar_merge_name>_1): .. this, and
+ adjust pattern.
+ (*avx2_gt<mode>3): Removed.
+ (<avx512>_gt<mode>3<mask_scalar_merge_name>): Change from
+ define_insn to define_expand, and adjust pattern.
+ (UNSPEC_MASKED_EQ, UNSPEC_MASKED_GT): Removed.
+
+2021-08-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/99260
+ * Makefile.in (ANALYZER_OBJS): Add analyzer/call-info.o.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ * doc/invoke.texi: Document -Wmissing-requires.
+
+2021-08-30 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (rs6000_init_builtins): Remove
+ TARGET_EXTRA_BUILTINS guard.
+
+2021-08-30 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (rs6000_init_builtins): Change
+ initialization of V2DI_type_node and unsigned_V2DI_type_node.
+
+2021-08-30 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/darwin.h (SUBTARGET_INIT_BUILTINS): Use the new
+ decl when new_builtins_are_live.
+ * config/rs6000/rs6000-builtin-new.def (__builtin_cfstring): New
+ built-in.
+
+2021-08-30 Pat Haugen <pthaugen@linux.ibm.com>
+
+ * config/rs6000/rs6000-cpus.def (ISA_3_1_MASKS_SERVER): Add
+ OPTION_MASK_P10_FUSION_2STORE.
+ (POWERPC_MASKS): Likewise.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable
+ store fusion for Power10.
+ (is_fusable_store): New.
+ (power10_sched_reorder): Likewise.
+ (rs6000_sched_reorder): Do Power10 specific reordering.
+ (rs6000_sched_reorder2): Likewise.
+ * config/rs6000/rs6000.opt: Add new option.
+
+2021-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102128
+ * tree-vect-slp.c (vect_bb_vectorization_profitable_p):
+ Move scanning for if-converted scalar code to the caller
+ and instead delay clearing the visited flag for profitable
+ subgraphs.
+ (vect_slp_region): Cost all subgraphs before scheduling.
+ For if-converted BB vectorization scan for scalar COND_EXPRs
+ and do not vectorize if any found and the cost model is
+ very-cheap.
+
+2021-08-30 Richard Biener <rguenther@suse.de>
+
+ * common.opt (fexceptions): Mark
+ EnabledBy(fnon-call-exceptions).
+ * doc/invoke.texi (fnon-call-exceptions): Document this
+ enables -fexceptions.
+
+2021-08-30 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * tsystem.h (abort): Define abort() if inhibit_libc is defined and it
+ is not already defined.
+
+2021-08-30 liuhongt <hongtao.liu@intel.com>
+
+ * expmed.c (extract_bit_field_1): Make sure we're playing with
+ integral modes before call extract_integral_bit_field.
+ (extract_integral_bit_field): Add a parameter of type
+ scalar_int_mode which corresponds to of tmode.
+ And call extract_and_convert_fixed_bit_field instead of
+ extract_fixed_bit_field and convert_extracted_bit_field.
+ (extract_and_convert_fixed_bit_field): New function, it's a
+ combination of extract_fixed_bit_field and
+ convert_extracted_bit_field.
+
+2021-08-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (darwin_libc_has_function): Do not run
+ the checks for x86 or modern Darwin. Make sure that there
+ is a value set for darwin_macosx_version_min before testing.
+
+2021-08-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/darwin.h (CLEAR_INSN_CACHE): New.
+
+2021-08-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-modref-tree.h (modref_access_node::merge): Break out
+ logic combining offsets and logic merging ranges to ...
+ (modref_access_node::combined_offsets): ... here
+ (modref_access_node::update2): ... here
+ (modref_access_node::closer_pair_p): New member function.
+ (modref_access_node::forced_merge): New member function.
+ (modre_ref_node::insert): Do merging when table is full.
+
+2021-08-28 YunQiang Su <yunqiang.su@cipunited.com>
+
+ PR target/102089
+ * config.gcc: MIPS: use N64 ABI by default if the triple end
+ with -gnuabi64, which is used by Debian since 2013.
+
+2021-08-28 Alexandre Oliva <oliva@adacore.com>
+
+ * ipa-modref.c (analyze_function): Skip debug stmts.
+ * tree-inline.c (estimate_num_insn): Consider builtins even
+ without a cgraph_node.
+
+2021-08-27 Jeff Law <jlaw@localhost.localdomain>
+
+ * config/h8300/bitfield.md (cstore<mode>4): Remove expander.
+ * config/h8300/h8300.c (h8300_expand_branch): Remove function.
+ * config/h8300/h8300-protos.h (h8300_expadn_branch): Remove prototype.
+ * config/h8300/h8300.md (eqne): New code iterator.
+ (geultu, geultu_to_c): Similarly.
+ * config/h8300/testcompare.md (cstore<mode>4): Dummy expander.
+ (store_c_<mode>, store_c_i_<mode>): New define_insn_and_splits
+ (cmp<mode>_c): New pattern
+
+2021-08-27 Jeff Law <jlaw@localhost.localdomain>
+
+ * tree-ssa-dom.c (reduce_vector_comparison_to_scalar_comparison): New
+ function.
+ (dom_opt_dom_walker::optimize_stmt): Use it.
+
+2021-08-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (finalize_ctors): Add a section-start linker-
+ visible symbol.
+ (finalize_dtors): Likewise.
+ * config/darwin.h (MIN_LD64_INIT_TERM_START_LABELS): New.
+
+2021-08-27 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (rs6000-builtins.h): New #include.
+ (rs6000_init_builtins): Call rs6000_init_generated_builtins. Skip the
+ old initialization logic when new builtins are enabled.
+ * config/rs6000/rs6000-gen-builtins.c (write_decls): Rename
+ rs6000_autoinit_builtins to rs6000_init_generated_builtins.
+ (write_init_file): Likewise.
+
+2021-08-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * configure.ac (darwin2[[0-9]]* | darwin19*): Alter use of
+ gcc_GAS_CHECK_FEATURE to remove an extraneous parameter.
+ (amdgcn-* | gcn-*) Likewise.
+
+2021-08-27 Anthony Sharp <anthonysharp15@gmail.com>
+
+ * symbol-summary.h: Added missing template keyword.
+
+2021-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/45178
+ * tree-ssa-dce.c (find_obviously_necessary_stmts): For
+ infinite loops without exit do not mark control dependent
+ edges of the latch necessary.
+
+2021-08-27 konglin1 <lingling.kong@intel.com>
+
+ PR target/101472
+ * config/i386/sse.md: (<avx512>scattersi<mode>): Add mask operand to
+ UNSPEC_VSIBADDR.
+ (<avx512>scattersi<mode>): Likewise.
+ (*avx512f_scattersi<VI48F:mode>): Merge mask operand to set_dest.
+ (*avx512f_scatterdi<VI48F:mode>): Likewise
+
+2021-08-27 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_builtin_md_vectorized_function): Add
+ support for built-in functions MISC_BUILTIN_DIVWE, MISC_BUILTIN_DIVWEU,
+ MISC_BUILTIN_DIVDE, MISC_BUILTIN_DIVDEU, P10_BUILTIN_CFUGED,
+ P10_BUILTIN_CNTLZDM, P10_BUILTIN_CNTTZDM, P10_BUILTIN_PDEPD and
+ P10_BUILTIN_PEXTD on Power10.
+
+2021-08-27 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (builtin_function_type): Add unsigned
+ signedness for some Power10 bifs.
+
+2021-08-27 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/102068
+ * config/rs6000/rs6000.c (rs6000_adjust_field_align): Use
+ computed alignment if the entire struct has attribute packed.
+
+2021-08-27 liuhongt <hongtao.liu@intel.com>
+
+ PR target/98167
+ PR target/43147
+ * config/i386/i386.c (ix86_gimple_fold_builtin): Fold
+ IX86_BUILTIN_SHUFPD512, IX86_BUILTIN_SHUFPS512,
+ IX86_BUILTIN_SHUFPD256, IX86_BUILTIN_SHUFPS,
+ IX86_BUILTIN_SHUFPS256.
+ (ix86_masked_all_ones): New function.
+
2021-08-26 Uroš Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*btr<mode>_1): Call force_reg unconditionally.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index ac2bf5d..1a35f32 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20210827
+20211018
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9714fca..f36ffa4 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -799,13 +799,8 @@ DIR = ../gcc
# Native compiler for the build machine and its switches.
CC_FOR_BUILD = @CC_FOR_BUILD@
CXX_FOR_BUILD = @CXX_FOR_BUILD@
-NO_PIE_CFLAGS_FOR_BUILD = @NO_PIE_CFLAGS_FOR_BUILD@
-NO_PIE_FLAG_FOR_BUILD = @NO_PIE_FLAG_FOR_BUILD@
BUILD_CFLAGS= @BUILD_CFLAGS@ $(GENERATOR_CFLAGS) -DGENERATOR_FILE
BUILD_CXXFLAGS = @BUILD_CXXFLAGS@ $(GENERATOR_CFLAGS) -DGENERATOR_FILE
-BUILD_NO_PIE_CFLAGS = @BUILD_NO_PIE_CFLAGS@
-BUILD_CFLAGS += $(BUILD_NO_PIE_CFLAGS)
-BUILD_CXXFLAGS += $(BUILD_NO_PIE_CFLAGS)
# Native compiler that we use. This may be C++ some day.
COMPILER_FOR_BUILD = $(CXX_FOR_BUILD)
@@ -817,8 +812,6 @@ BUILD_LINKERFLAGS = $(BUILD_CXXFLAGS)
# Native linker and preprocessor flags. For x-fragment overrides.
BUILD_LDFLAGS=@BUILD_LDFLAGS@
-BUILD_NO_PIE_FLAG = @BUILD_NO_PIE_FLAG@
-BUILD_LDFLAGS += $(BUILD_NO_PIE_FLAG)
BUILD_CPPFLAGS= -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
-I$(srcdir)/../include @INCINTL@ $(CPPINC) $(CPPFLAGS)
@@ -1249,6 +1242,7 @@ ANALYZER_OBJS = \
analyzer/analyzer-pass.o \
analyzer/analyzer-selftests.o \
analyzer/bar-chart.o \
+ analyzer/call-info.o \
analyzer/call-string.o \
analyzer/checker-path.o \
analyzer/complexity.o \
@@ -1400,6 +1394,7 @@ OBJS = \
gimple-loop-jam.o \
gimple-loop-versioning.o \
gimple-low.o \
+ gimple-predicate-analysis.o \
gimple-pretty-print.o \
gimple-range.o \
gimple-range-cache.o \
@@ -1697,6 +1692,7 @@ OBJS = \
typed-splay-tree.o \
unique-ptr-tests.o \
valtrack.o \
+ value-pointer-equiv.o \
value-query.o \
value-range.o \
value-range-equiv.o \
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index dddb90f..c6d856a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,2439 @@
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ * gcc-interface/misc.c (gnat_post_options): Do not warn
+ about DBX_DEBUG use here.
+
+2021-10-14 Alexandre Oliva <oliva@adacore.com>
+
+ * par-ch10.adb (P_Compilation_Unit): Reenable ada83 library
+ unit renaming test and error.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h (resolve_atomic_size): Declare.
+ (list_third): New inline function.
+ * gcc-interface/decl.c (type_for_atomic_builtin_p): New function.
+ (resolve_atomic_builtin): Likewise.
+ (gnat_to_gnu_subprog_type): Perform type resolution for most of
+ type-generic GCC atomic builtins and give an error for the rest.
+ * gcc-interface/utils2.c (resolve_atomic_size): Make public.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu) <N_Pop_Constraint_Error_Label>:
+ Given the warning only if No_Exception_Propagation is active.
+ <N_Pop_Storage_Error_Label>: Likewise.
+ <N_Pop_Program_Error_Label>: Likewise.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (promote_object_alignment): Add GNU_SIZE
+ parameter and use it for the size of the object if not null.
+ (gnat_to_gnu_entity) <E_Variable>: Perform the automatic alignment
+ promotion for objects whose nominal subtype is of variable size.
+ (gnat_to_gnu_field): Adjust call to promote_object_alignment.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_param): Strip padding types
+ only if the size does not change in the process. Rename local
+ variable and add bypass for initialization procedures.
+
+2021-10-11 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/s-thread.ads: Fix comments. Remove unused package
+ imports.
+ (Thread_Body_Exception_Exit): Remove Exception_Occurrence
+ parameter.
+ (ATSD): Declare type locally.
+ * libgnat/s-thread__ae653.adb: Fix comments. Remove unused
+ package imports. Remove package references to Stack_Limit
+ checking.
+ (Install_Handler): Remove.
+ (Set_Sec_Stack): Likewise.
+ (Thread_Body_Enter): Remove calls to Install_Handler and
+ Stack_Limit checking.
+ (Thread_Body_Exception_Exit): Remove Exception_Occurrence
+ parameter.
+ (Init_RTS): Call local Get_Sec_Stack. Remove call to
+ Install_Handler. Remove references to accessors for
+ Get_Sec_Stack and Set_Sec_Stack. Remove OS check.
+ (Set_Sec_Stack): Remove.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch3.adb (Make_Predefined_Primitive_Specs,
+ Predefined_Primitive_Bodies): Remove guard with restriction
+ No_Dispatching_Calls.
+
+2021-10-11 Steve Baird <baird@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute_Old_Result): Permit an
+ attribute reference inside a compiler-generated _Postconditions
+ procedure. In this case, Subp_Decl is assigned the declaration
+ of the enclosing subprogram.
+ * exp_util.adb (Insert_Actions): When climbing up the tree
+ looking for an insertion point, do not climb past an
+ N_Iterated_Component/Element_Association, since this could
+ result in inserting a reference to a loop parameter at a
+ location outside of the scope of that loop parameter. On the
+ other hand, be careful to preserve existing behavior in the case
+ of an N_Component_Association node.
+
+2021-10-11 Steve Baird <baird@adacore.com>
+
+ * exp_ch6.adb (Can_Fold_Predicate_Call): Do not attempt folding
+ if there is more than one predicate involved. Recall that
+ predicate aspect specification are additive, not overriding, and
+ that there are three different predicate
+ aspects (Dynamic_Predicate, Static_Predicate, and the
+ GNAT-defined Predicate aspect). These various ways of
+ introducing multiple predicates are all checked for. A new
+ nested function, Augments_Other_Dynamic_Predicate, is
+ introduced.
+ * sem_ch4.adb
+ (Analyze_Indexed_Component_Form.Process_Function_Call): When
+ determining whether a name like "X (Some_Discrete_Type)" might
+ be interpreted as a slice, the answer should be "no" if the
+ type/subtype name denotes the current instance of type/subtype.
+
+2021-10-11 Patrick Bernardi <bernardi@adacore.com>
+
+ * libgnarl/s-osinte__rtems.ads: Change sigset_t to an unsigned
+ long.
+
+2021-10-11 Patrick Bernardi <bernardi@adacore.com>
+
+ * libgnat/s-parame__rtems.adb: use
+ _POSIX_Threads_Minimum_stack_size instead of
+ ada_pthread_minimum_stack_size.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fe.h (No_Exception_Propagation_Active): Declare.
+ * restrict.ads (No_Exception_Propagation_Active): Add WARNING line.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Validate_Unchecked_Conversion): Simplify code
+ for detecting conversions with Ada.Calendar.Time type and extend
+ it to similar types in the Ada.Real_Time package.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch10.adb, sem_prag.adb, sem_util.adb: Use
+ N_Generic_Declaration in membership tests.
+
+2021-10-11 Etienne Servais <servais@adacore.com>
+
+ * ali.adb (Get_Name): Ignore_Spaces is always False.
+ * bindo-graphs.adb (Set_Is_Existing_Source_Target_Relation): Val
+ is always True.
+ * cstand.adb (New_Standard_Entity): New_Node_Kind is always
+ N_Defininig_Identifier.
+ * exp_ch3.adb (Predef_Stream_Attr_Spec): For_Body is always
+ False.
+ * exp_dist.adb (Add_Parameter_To_NVList): RACW_Ctrl is always
+ False.
+ * gnatls.adb (Add_Directories): Prepend is always False.
+ * sem_ch10.adb, sem_ch10.ads (Load_Needed_Body): Do_Analyze is
+ always True.
+ * sem_ch3.adb, sem_ch3.ads (Process_Range_Expr_In_Decl):
+ R_Check_Off is always False.
+ * sem_elab.adb: (Info_Variable_Reference): Info_Msg is always
+ False, In_SPARK is always True.
+ (Set_Is_Traversed_Body, Set_Is_Saved_Construct,
+ Set_Is_Saved_Relation): Val is always True.
+ * treepr.adb (Visit_Descendant): No_Indent is always False.
+ (Print_Node): Fmt does not need such a big scope.
+
+2021-10-11 Etienne Servais <servais@adacore.com>
+
+ * sem_ch4.adb (Analyze_Membership_Op): Finds interpretation for
+ the case of a membership test with a singleton value in case of
+ overloading.
+
+2021-10-11 Patrick Bernardi <bernardi@adacore.com>
+
+ * Makefile.rtl (VxWorks): Rename s-inmaop__vxworks.adb to
+ s-inmaop__hwint.adb.
+ (RTEMS): Use s-inmaop__hwint.adb, s-intman__rtems.adb/s,
+ s-taprop__rtems.adb.
+ * libgnarl/a-intnam__rtems.ads: Remove signals definitions and
+ replace with Hardware_Interrupts.
+ * libgnarl/s-inmaop__vxworks.adb: Rename as...
+ * libgnarl/s-inmaop__hwint.adb: ... this.
+ * libgnarl/s-interr__hwint.adb: Remove unnecessary comments.
+ * libgnarl/s-intman__rtems.ads, libgnarl/s-intman__rtems.adb:
+ New files.
+ * libgnarl/s-osinte__rtems.adb: Add RTEMS API bindings.
+ (Binary_Semaphore_Create, Binary_Semaphore_Delete,
+ Binary_Semaphore_Obtain, Binary_Semaphore_Release,
+ Binary_Semaphore_Flush, Interrupt_Connect,
+ Interrupt_Number_To_Vector): New functions.
+ * libgnarl/s-osinte__rtems.ads (Num_HW_Interrupts, Signal):
+ Removed.
+ (NSIG, Interrupt_Range): New.
+ (Binary_Semaphore_Create, Binary_Semaphore_Delete,
+ Binary_Semaphore_Obtain, Binary_Semaphore_Release,
+ Binary_Semaphore_Flush, Interrupt_Connect,
+ Interrupt_Number_To_Vector): Remove Import pragma.
+ * libgnarl/s-taprop__rtems.adb: New file.
+
+2021-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_fixd.adb (Get_Size_For_Value): New function returning a size
+ suitable for a non-negative integer value.
+ (Get_Type_For_Size): New function returning a standard type suitable
+ for a size.
+ (Build_Divide): Call both functions to compute the result type, but
+ make sure to pass a non-negative value to the first.
+ (Build_Multiply): Likewise.
+ (Do_Multiply_Fixed_Universal): Minor consistency tweak.
+ (Integer_Literal): Call both functions to compute the type.
+
+2021-10-11 Etienne Servais <servais@adacore.com>
+
+ * sem_ch4.adb (Analyze_Membership_Op): Reorder subprogram spec
+ and bodies in alphabetical order.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Build_Class_Wide_Expression): Replace entities
+ of both simple and extended names.
+
+2021-10-11 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * libgnarl/s-intman__android.adb, libgnarl/s-intman__lynxos.adb,
+ libgnarl/s-intman__posix.adb, libgnarl/s-intman__qnx.adb,
+ libgnarl/s-intman__solaris.adb, libgnarl/s-intman__susv3.adb,
+ libgnarl/s-taprob.adb, libgnarl/s-taprop__hpux-dce.adb,
+ libgnarl/s-taprop__linux.adb, libgnarl/s-taprop__mingw.adb,
+ libgnarl/s-taprop__posix.adb, libgnarl/s-taprop__qnx.adb,
+ libgnarl/s-taprop__solaris.adb, libgnarl/s-taprop__vxworks.adb,
+ libgnarl/s-taskin.adb, libgnarl/s-tasque.adb,
+ libgnarl/s-tpoben.adb, libgnat/a-calend.adb,
+ libgnat/a-excach.adb, libgnat/a-except.adb, libgnat/a-tags.adb,
+ libgnat/a-textio.adb, libgnat/a-witeio.adb,
+ libgnat/a-ztexio.adb, libgnat/g-binenv.adb,
+ libgnat/s-parame.adb, libgnat/s-parame__vxworks.adb,
+ libgnat/s-stratt.adb, libgnat/s-trasym__dwarf.adb: Mark imported
+ binder globals as constant.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb (Initialize_Record_Component): Add assertion
+ about one of the parameters, so that illegal attempts to
+ initialize record components with Empty node are detected early
+ on.
+ (Build_Record_Aggr_Code): Handle boxes in aggregate component
+ associations just the components with no initialization in
+ Build_Record_Init_Proc.
+ * sem_aggr.adb (Resolve_Record_Aggregate): For components that
+ require simple initialization carry boxes from resolution to
+ expansion.
+ * sem_util.adb (Needs_Simple_Initialization): Remove redundant
+ paren.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch3.adb (Build_Init_Statements): Simplify detection of
+ concurrent record types.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb (Is_Delayed_Aggregate): Simplify.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb (Has_Default_Init_Comps): Simplify.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb (Component_OK_For_Backend): Remove redundant
+ guard.
+
+2021-10-11 Patrick Bernardi <bernardi@adacore.com>
+
+ * Makefile.rtl (RTEMS): Add s-stchop.o to
+ EXTRA_GNATRTL_NONTASKING_OBJS, remove s-stchop__rtems.adb.
+ * libgnat/s-stchop__rtems.adb: Removed.
+
+2021-10-11 Marc Poulhiès <poulhies@adacore.com>
+
+ * expander.adb (Expand): Skip clearing of Analyzed flag if
+ already set for N_Real_Literal.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_util.adb (Compile_Time_Constraint_Error): Simplify getting
+ the type of the first formal parameter.
+
+2021-10-11 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Inside_Init_Proc): Simplify.
+ * sem_aggr.adb (Resolve_Record_Aggregate): Fix style.
+ * sem_util.adb (Compile_Time_Constraint_Error): Guard against
+ calling Corresponding_Concurrent_Type with an array type entity.
+
+2021-10-11 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/s-parame__ae653.ads (time_t_bits): Change to
+ Long_Long_Integer'Size. Add some comments to explain.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * gcc-interface/misc.c (gnat_post_options): Use new macro
+ OPTION_SET_P.
+ (gnat_init_gcc_eh): Likewise.
+ (gnat_init_gcc_fp): Likewise.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu): Do not wrap boolean values
+ referenced in pragmas.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Subprogram_Body_to_gnu): Do not set the
+ DECL_DISREGARD_INLINE_LIMITS flag if -gnatd.8 is specified.
+
+2021-10-05 Bob Duff <duff@adacore.com>
+
+ * gcc-interface/trans.c (set_end_locus_from_node): Check that
+ Handled_Statement_Sequence is not Empty before calling
+ End_Label, because the Empty node has no End_Label, and
+ depending on the exact node layout chosen by gen_il, calling
+ End_Label might crash, or might work OK by accident.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/cuintp.c: Adjust placement of include directive.
+ * gcc-interface/targtyps.c: Likewise.
+
+2021-10-05 Alexandre Oliva <oliva@adacore.com>
+
+ * doc/gnat_rm.rst: Add...
+ * doc/gnat_rm/security_hardening_features.rst: New.
+ * doc/gnat_rm/about_this_guide.rst: Link to new chapter.
+ * gnat_rm.texi: Regenerate.
+ * gcc-interface/utils.c (handle_strub_attribute): New.
+ (gnat_internal_attribute_table): Add strub.
+ * libgnat/a-except.adb: Make Rcheck_CE_* strub-callable.
+ * libgnat/a-except.ads (Raise_Exception): Likewise.
+ (Raise_Exception_Always): Likewise.
+ * libgnat/s-arit128.ads (Multiply_With_Ovflo_Check128):
+ Likewise.
+ * libgnat/s-arit64.ads (Multiply_With_Ovflo_Check64):
+ Likewise.
+ * libgnat/s-secsta.ads (SS_Allocate, SS_Mark, SS_Release):
+ Likewise.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch9.adb (Install_Private_Data_Declarations): Copy the Sloc of
+ components for the local renamings as well as the Comes_From_Source
+ flag, and also set Warnings_Off on them. Use Nam local variable.
+
+2021-10-05 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/a-tasini.ads (Set_Initialization_Handler): Update
+ comments.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * init.c (QNX): Add #include errno.h.
+
+2021-10-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_attr.adb (Expand_Fpt_Attribute): Likewise.
+ * snames.ads-tmpl (Name_Unaligned_Valid): Delete.
+
+2021-10-05 Etienne Servais <servais@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Forbid use of
+ Compile_Time_(Error|Warning) as configuration pragma.
+ * doc/gnat_ugn/the_gnat_compilation_model.rst:
+ Compile_Time_(Error|Warning) and Compiler_Unit(_Warning) are not
+ configuration pragmas and shall not be listed as such. The
+ following pragmas are either obsolete or undocumented:
+ No_Run_Time, Propagate_Exceptions, Rational, Ravenscar,
+ Restricted_Run_Time, Short_Descriptors, Universal_Data. Fix
+ some typos (notably on Restriction_Warnings).
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Move
+ Rename_Pragma documentation to alphabetical order.
+ * gnat_rm.texi, gnat_ugn.texi: Regenerate.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * adaint.c (QNX): Add #include for sys/time.h.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Next_Format): When there is no more
+ format specifier found issue a proper error message instead of
+ raising a contraint error.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Get_Formatted): Fix computation of the
+ number of zero to use in the formatted string. This was a wrong
+ copy/paste.
+
+2021-10-05 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-forstr.adb (Get_Formatted): Minor code clean-up.
+
+2021-10-05 Etienne Servais <servais@adacore.com>
+
+ * libgnat/a-zchhan.ads, libgnat/a-zchhan.adb
+ (Character_Set_Version, Is_Basic, To_Basic): New.
+ * libgnat/a-zchuni.ads, libgnat/a-zchuni.adb (Is_Basic,
+ To_Basic): New.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Improve error message.
+
+2021-10-05 Gary Dismukes <dismukes@adacore.com>
+
+ * aspects.ads (type Aspect_Id): Add
+ Aspect_Designated_Storage_Model and Aspect_Storage_Model_Type.
+ (Aspect_Argument): Add associations for the above new aspects.
+ (Is_Representation_Aspect): Likewise.
+ (Aspect_Names, Aspect_Delay): Likewise.
+ * exp_ch4.adb (Expand_N_Allocator): Call Find_Storage_Op rather
+ than Find_Prim_Op.
+ * exp_intr.adb (Expand_Unc_Deallocation): Likewise.
+ * exp_util.ads (Find_Storage_Op): New function that locates
+ either a primitive operation of a storage pool or an operation
+ of a storage-model type specified in its Storage_Model_Type
+ aspect.
+ * exp_util.adb (Find_Storage_Op): New function that calls either
+ Find_Prim_Op or Get_Storage_Model_Type_Entity to locate a
+ storage-related operation that is associated with a type.
+ * sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Analyzes,
+ resolves, and validates the arguments of aspect
+ Designated_Storage_Model_Type.
+ (Analyze_Aspect_Specifications): Sets delay-related flags on
+ storage-model aspects when Delay_Required. Checks that aspect
+ Designated_Storage_Model is only specified for an access type
+ and that aspect Storage_Model_Type is only specified on an
+ immutably limited type. Also records such aspects for their
+ associated types.
+ (Check_Aspect_At_Freeze_Point): Resolve each of the argument
+ associations given for a Storage_Model_Type aspect.
+ (Resolve_Storage_Model_Type_Argument): New procedure that
+ resolves an argument given in the association for a given entity
+ name associated with a type with aspect Storage_Model_Type,
+ ensuring that it has the proper kind or profile.
+ (Validate_Storage_Model_Type_Aspect): New procedure that checks
+ the legality and completeness of the entity associations given
+ in a Storage_Model_Type aspect.
+ * sem_util.ads (package Storage_Model_Support): New nested
+ package that encapsulates a set of convenient utility functions
+ for retrieving entities, etc. associated with
+ storage-model-related types and objects.
+ (Get_Storage_Model_Type_Entity): New function to return a
+ specified entity associated with a type that has aspect
+ Storage_Model_Type.
+ (Has_Designated_Storage_Model_Aspect): New function that returns
+ whether a type has aspect Designated_Storage_Model.
+ (Has_Storage_Model_Type_Aspect): New function that returns
+ whether a type has aspect Storage_Model_Type.
+ (Storage_Model_Object): New function that returns the object
+ Entity_Id associated with a type's Designated_Storage_Model
+ aspect.
+ (Storage_Model_Type): New function that returns the type
+ associated with a storage-model object (when the object's type
+ specifies Storage_Model_Type).
+ (Storage_Model_Address_Type): New function that returns the
+ Address_Type associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Null_Address): New function that returns the
+ Null_Address constant associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Allocate): New function that returns the Allocate
+ procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Deallocate): New function that returns the
+ Deallocate procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Copy_From): New function that returns the
+ Copy_From procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Copy_To): New function that returns the Copy_To
+ procedure associated with a type that has aspect
+ Storage_Model_Type.
+ (Storage_Model_Storage_Size): New function that returns the
+ Storage_Size function associated with a type that has aspect
+ Storage_Model_Type.
+ * sem_util.adb (package Storage_Model_Support): Body of new
+ nested package that contains the implementations the utility
+ functions declared in the spec of this package.
+ * snames.ads-tmpl: Add new names Name_Designated_Storage_Pool,
+ Name_Storage_Model, Name_Storage_Model_Type, Name_Address_Type,
+ Name_Copy_From, Name_Copy_To, and Name_Null_Address for the new
+ aspects and associated aspect arguments.
+
+2021-10-05 Richard Kenner <kenner@adacore.com>
+
+ * debug.adb: Add documentation for -gnatd_t.
+
+2021-10-05 Corentin Gay <gay@adacore.com>
+
+ * sysdep.c (__gnat_is_file_not_found_error): Add else if case.
+
+2021-10-05 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Build_Class_Wide_Expression): Replace entities
+ of both identifiers and operator symbols.
+
+2021-10-05 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Derive_Subprogram): Copy ghost status from parent
+ to derived subprogram.
+
+2021-10-05 Joffrey Huguet <huguet@adacore.com>
+
+ * libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Add
+ Default_Initial_Condition to Unbounded_String.
+
+2021-10-05 Claire Dross <dross@adacore.com>
+
+ * libgnat/a-cfdlli.ads: Use pragma Assertion_Policy to disable
+ contract cases at execution.
+ * libgnat/a-cfinve.ads: Idem.
+ * libgnat/a-cofove.ads: Idem.
+ * libgnat/a-cfhase.ads: Idem.
+ * libgnat/a-cfhama.ads: Idem.
+ * libgnat/a-cforse.ads: Idem.
+ * libgnat/a-cforma.ads: Idem.
+
+2021-10-05 Bob Duff <duff@adacore.com>
+
+ * par-ch4.adb (P_Iterated_Component_Association): Parse these
+ features the same way in all language versions. Move the call
+ to Error_Msg_Ada_2022_Feature into semantic analysis.
+ * sem_aggr.adb (Resolve_Iterated_Component_Association,
+ Resolve_Iterated_Association): Move the call to
+ Error_Msg_Ada_2022_Feature here from par-ch4.adb.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * sem_res.adb (Resolve): Recognize specially that case.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strmap.adb: Add ghost code for proof.
+ (To_Range): This is the most involved proof, as it requires
+ creating the result of the call to To_Domain as a ghost
+ variable, and show the unicity of this result in order to prove
+ the postcondition.
+ * libgnat/a-strmap.ads: (SPARK_Proof_Sorted_Character_Sequence):
+ New ghost function.
+ (To_Domain): Add postcondition regarding sorting of result.
+ (To_Range): Fix postcondition that should compare Length instead
+ of Last for the results of To_Domain and To_Range, as the value
+ of Last for an empty result is not specified in the Ada RM.
+
+2021-10-05 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-chahan.adb: Add loop invariants as needed to prove
+ subprograms. Also use extended return statements where
+ appropriate and not done already. Mark data with
+ Relaxed_Initialization where needed for initialization by parts.
+ Convert regular functions to expression functions where needed
+ for proof.
+ * libgnat/a-chahan.ads: Add postconditions.
+ * libgnat/a-strmap.ads (Model): New ghost function to create a
+ publicly visible model of the private data Character_Mapping,
+ needed in order to prove subprograms in Ada.Characters.Handling.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
+ Add new entry for No_Dynamic_Accessibility_Checks documenting
+ behavior.
+ * gnat_rm.texi: Regenerate.
+ * exp_ch4.adb (Expand_N_In): Perform special expansion for
+ membership tests when No_Dynamic_Accessibility_Checks is active.
+ * sem_attr.adb (Resolve_Attribute): Skip static accessibility
+ check on actuals for anonymous access type formal parameters,
+ and add constants for readability.
+ * sem_util.adb (Function_Call_Or_Allocator_Level): Use the
+ innermost master for determining the level for function calls
+ within the alternative accessibility model.
+ (Type_Access_Level): Properly get the level for anonymous access
+ function result types.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (gnateA): This switch no longer looks at the formal parameter
+ type being composite (as originally mandated by SPARK), but in
+ the parameter passing mechanism being not specified (as
+ currently mandated by Ada).
+ * gnat_ugn.texi: Regenerate.
+
+2021-10-04 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Operator_Symbol): Recognize strings as
+ operator names when they are the value of one of the Ada2022
+ aspects for User_Defined_Literals.
+ * sem_ch13.adb (Analyze_One_Aspect): Handle an aspect value
+ given by an Operator_Name.
+ (Validate_Literal_Aspect): Call Analyze_Operator_Symbol when
+ needed.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * gen_il-gen.adb (Put_Make_Spec): Don't emit the LF character in
+ the middle of a string, because the Put routine won't indent it
+ properly.
+
+2021-10-04 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * gnat_cuda.adb (Remove_CUDA_Device_Entities): New function.
+ (Expand_CUDA_Package): Call Remove_CUDA_Device_Entities.
+ * gnat_cuda.ads (Expand_CUDA_Package): Expand documentation.
+ * sem_prag.adb (Analyze_Pragma): Remove warning about
+ CUDA_Device not being implemented.
+
+2021-10-04 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch7.adb (Analyze_Package_Specification): For types marked
+ as Must_Have_Preelab_Init, we now check for the presence of a
+ Preelaborable_Initialization aspect on the type, and pass the
+ aspect's expression (if any) on the call to
+ Has_Preelaborable_Initialization (or pass Empty if the type has
+ no such aspect or the aspect has no associated expression).
+ * sem_util.ads (Has_Preelaborable_Initialization): Change
+ Boolean formal parameter Formal_Types_Have_Preelab_Init to
+ instead be a formal of type Node_Id (named Preelab_Init_Expr),
+ to allow passing an expression that may be a conjunction of
+ Preelaborable_Initialization aspects. Revise spec comment
+ accordingly (and remove ??? comment).
+ * sem_util.adb (Type_Named_In_Preelab_Init_Expression): New
+ nested function with a result indicating whether a given type is
+ named as the prefix of a Preelaborable_Initialization attribute
+ in the expression of a corresponding P_I aspect.
+ (Has_Preelaborable_Initialization): For generic formal derived
+ and private types, test whether the type is named in the
+ expression Preelab_Init_Expr (by calling
+ Type_Named_In_Preelab_Init_Expression), and if so, treat the
+ formal type as having preelaborable initialization (returning
+ True).
+ * libgnat/a-cobove.ads (Vector): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbdlli.ads (List): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbhama.ads (Map): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as (Element_Type'Preelaborable_Initialization and
+ Key_Type'Preelaborable_Initialization).
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cborma.ads (Map): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as (Element_Type'Preelaborable_Initialization and
+ Key_Type'Preelaborable_Initialization).
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbhase.ads (Set): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cborse.ads (Set): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-cbmutr.ads (Tree): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+ * libgnat/a-coboho.ads (Holder): Replace pragma
+ Preelaborable_Initialization with the aspect, specifying its
+ value as Element_Type'Preelaborable_Initialization.
+ (Cursor): Replace pragma P_I with the aspect (defaulting to
+ True).
+
+2021-10-04 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-textio.adb: Mark body out of SPARK.
+ * libgnat/a-textio.ads: Mark spec in SPARK and private part out
+ of SPARK.
+ * sem.adb (Semantics.Do_Analyze): Similar to ghost code
+ attributes, save and restore value of
+ Ignore_SPARK_Mode_Pragmas_In_Instance.
+
+2021-10-04 Bob Duff <duff@adacore.com>
+
+ * libgnat/s-regpat.ads: Change Data_First to Data'First. Change
+ "still" to "always". Similar changes for Data_Last.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sprint.adb (Sprint_Node_Actual): Refactor code for generic
+ package and subprogram declarations.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Indexed_Component, Resolve_Slice): Rename
+ the local constant Name to Pref; remove repeated calls to
+ Prefix.
+
+2021-10-04 Matthieu Eyraud <eyraud@adacore.com>
+
+ * scos.ads: Extend the documentation.
+ * par_sco.adb (Process_Decisions): Emit specific SCOs for
+ quantified expressions.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * checks.adb (Selected_Range_Checks): Fix style.
+ * exp_ch4.adb (Expand_N_Slice): Fix style and comment.
+ * sem_res.adb (Resolve_Indexed_Component): Fix style.
+
+2021-10-04 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strbou.ads: Add comments.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Eval_Attribute): Evaluation of attribute
+ Leading_Part with illegal second parameter is now similar to
+ evaluation of Remainder with its second parameter being zero.
+
+2021-10-04 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Declare_Expression): Use tree traversals
+ to perform name capture of local entities in the expression of
+ the construct.
+ * exp_util.adb (Possible_Side_Effects_In_SPARK): Do not apply to
+ the prefix of an attribute reference Reduce when that prefix is
+ an aggregate, because it will be expanded into a loop, and has
+ no identifiable type.
+
+2021-10-04 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch8.adb (Build_Class_Wide_Wrapper): Fix handling of
+ class-wide subtypes; required to handle chains of
+ instantiations. Adding also code to identify these wrappers and
+ properly resolve instantiations where the wrapper and a tagged
+ type primitive are visible.
+ * einfo.ads (Is_Class_Wide_Wrapper): Adding documentation.
+ * gen_il-fields.ads (Opt_Field_Enum): Adding
+ Is_Class_Wide_Wrapper.
+ * gen_il-gen-gen_entities.adb (Root_Entity_Type): Adding
+ semantic flag Is_Class_Wide_Wrapper.
+
+2021-10-04 Bob Duff <duff@adacore.com>
+
+ * einfo.ads (Declaration_Node): Document that Declaration_Node
+ for Itypes.
+ * einfo-utils.adb (Declaration_Node): Make it return Empty for
+ Itypes, or a proper type or subtype declaration.
+ * gen_il-gen.adb: Minor comment improvement.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Fix application of range checks
+ to slice range given as a subtype name.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Handle range given as a subtype
+ indication.
+
+2021-10-04 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Slice): Add custom handling of attribute
+ Image and similar in CodePeer mode. This complements the
+ existing custom handling of these attributes in
+ Expand_N_Attribute_Reference.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Is_Variable): Add check for implicitly
+ dereferenced access types
+ (Is_Dependent_Component_Of_Mutable_Object): Set Prefix_Type when
+ not specified.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/the_gnat_compilation_model.rst (Binding generation):
+ Document specific behavior for /include/-ending paths and update.
+ * gnat_ugn.texi: Regenerate.
+
+2021-10-04 Arnaud Charlet <charlet@adacore.com>
+
+ PR ada/102073
+ * socket.c (__gnat_gethostbyaddr, __gnat_inet_pton): Add missing
+ return statements.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Function_Or_Allocator_Level): Properly handle
+ direct function calls in the default alternative accessibility
+ checking mode.
+
+2021-10-04 Javier Miranda <miranda@adacore.com>
+
+ * sem_util.adb (Is_Library_Level_Entity): Return False for
+ entities defined in E_Loop scopes. This change is not required
+ by the frontend; it is required by tools that depend on the
+ frontend sources.
+ * einfo-utils.adb (Is_Dynamic_Scope): Code cleanup.
+
+2021-10-04 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Accessibility_Level): Add a case to handle
+ renamed subprograms in addition to renamed objects.
+
+2021-10-04 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads (tlsKeyCreate): Return int.
+ * libgnarl/s-tpopsp__vxworks-rtp.adb (ERROR): Declare from
+ System.VxWorks.Ext.ERROR.
+ (Initialize): Declare IERR. Assert it.
+ * libgnarl/s-tpopsp__vxworks.adb (ERROR): Declare from
+ System.VxWorks.Ext.ERROR.
+ (Is_Valid_Task): Declare IERR. Test return.
+ * libgnarl/s-vxwext__kernel.adb (semDelete): Return STATUS.
+
+2021-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_disp.adb (Make_DT): Copy the Needs_Debug_Info flag from the
+ type onto the TSD object.
+
+2021-10-04 Steve Baird <baird@adacore.com>
+
+ * sem_util.adb (Is_Repeatedly_Evaluated): Handle the case of an
+ Old attribute reference that occurs within what was originally a
+ quantified expression but which expansion has transformed into
+ an Expression_With_Actions.
+
+2021-10-04 Steve Baird <baird@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Indexed_Component): The two improvements
+ described above.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.adb (Expand_Call_Helper): Do not call
+ Check_Subprogram_Variant if the subprogram is an ignored ghost
+ entity. Otherwise the compiler crashes (in debug builds) or
+ gives strange error messages (in production builds).
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * gnat_cuda.adb (Empty_CUDA_Global_Subprograms): New procedure.
+ (Expand_CUDA_Package): Call Empty_CUDA_Global_Subprograms.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * checks.ads: Define a type Dimension_Set. Add an out-mode
+ parameter of this new type to Generate_Index_Checks so that
+ callers can know for which dimensions a check was generated. Add
+ an in-mode parameter of this new type to
+ Apply_Subscript_Validity_Checks so that callers can indicate
+ that no check is needed for certain dimensions.
+ * checks.adb (Generate_Index_Checks): Implement new
+ Checks_Generated parameter.
+ (Apply_Subscript_Validity_Checks): Implement new No_Check_Needed
+ parameter.
+ * exp_ch4.adb (Expand_N_Indexed_Component): Call
+ Apply_Subscript_Validity_Checks in more cases than before. This
+ includes declaring two new local functions,
+ (Is_Renamed_Variable_Name,
+ Type_Requires_Subscript_Validity_Checks_For_Reads): To help in
+ deciding whether to call Apply_Subscript_Validity_Checks.
+ Adjust to parameter profile changes in Generate_Index_Checks and
+ Apply_Subscript_Validity_Checks.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Document
+ the rounding mode assumed for dynamic computations as per 3.5.7(16).
+ * gnat_rm.texi: Regenerate.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * table.ads (Table_Type): Remove "aliased"; no longer needed by
+ Atree. Besides it contradicted the comment a few lines above,
+ "-- Note: We do not make the table components aliased...".
+ * types.ads: Move type Slot to Atree.
+ * atree.ads: Move type Slot fromt Types to here. Move type
+ Node_Header from Seinfo to here.
+ * atree.adb: Avoid the need for aliased components of the Slots
+ table. Instead of 'Access, use a getter and setter. Misc
+ cleanups.
+ (Print_Statistics): Print statistics about node and entity kind
+ frequencies. Give 3 digit fractions instead of percentages.
+ * (Get_Original_Node_Count, Set_Original_Node_Count): Statistics
+ for calls to Original_Node and Set_Original_Node.
+ (Original_Node, Set_Original_Node): Gather statistics by calling
+ the above.
+ (Print_Field_Statistics): Print Original_Node statistics.
+ (Update_Kind_Statistics): Remove, and put all statistics
+ gathering under "if Atree_Statistics_Enabled", which is a flag
+ generated in Seinfo by Gen_IL.
+ * gen_il-gen.adb (Compute_Field_Offsets): Choose offsets of
+ Nkind, Ekind, and Homonym first. This causes a slight efficiency
+ improvement. Misc cleanups. Do not generate Node_Header; it is
+ now hand-written in Atree. When choosing the order in which to
+ assign offsets, weight by the frequency of the node type, so the
+ more common nodes get their field offsets assigned earlier. Add
+ more special cases.
+ (Compute_Type_Sizes): Remove this and related things.
+ There was a comment: "At some point we can instrument Atree to
+ print out accurate size statistics, and remove this code." We
+ have Atree statistics, so we now remove this code.
+ (Put_Seinfo): Generate Atree_Statistics_Enabled, which is equal
+ to Statistics_Enabled. This allows Atree to say "if
+ Atree_Statistics_Enabled then <gather statistics>" for
+ efficiency. When Atree_Statistics_Enabled is False, the "if ..."
+ will be optimized away.
+ * gen_il-internals.ads (Type_Frequency): New table of kind
+ frequencies.
+ * gen_il-internals.adb: Minor comment improvement.
+ * gen_il-fields.ads: Remove unused subtypes. Suppress style
+ checks in the Type_Frequency table. If we regenerate this
+ table (see -gnatd.A) we don't want to have to fiddle with
+ casing.
+ * impunit.adb: Minor.
+ * sinfo-utils.adb: Minor.
+ * debug.adb: Minor comment improvement.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_type.adb (Specific_Type): Check that the type is tagged
+ before calling Interface_Present_In_Ancestor on it.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * debug.adb (d.8): Document usage.
+ * fe.h (Debug_Flag_Dot_8): Declare.
+
+2021-10-01 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_util.adb (Enter_Name): Suppress hiding warning when in an
+ instance.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute, case Type_Key): Attribute can
+ be applied to a formal type.
+ * sem_ch5.adb (Analyze_Case_Statement): If Extensions_Allowed is
+ not enabled, verify that the type of the expression is discrete.
+
+2021-10-01 Justin Squirek <squirek@adacore.com>
+
+ * exp_dbug.adb (Debug_Renaming_Declaration): Add check for
+ Entity present for Ren to prevent looking at unanalyzed nodes
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * atree.adb (Print_Statistics): Help CodePeer see Total as
+ greater than zero.
+ * gen_il-gen.adb (One_Comp): Annotate Field_Table as Modified.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_entities.adb (Evaluable_Kind,
+ Global_Name_Kind): Add.
+ * gen_il-types.ads (Evaluable_Kind, Global_Name_Kind): Likewise.
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * aspects.ads: Add CUDA_Device aspect.
+ * gnat_cuda.ads (Add_CUDA_Device_Entity): New subprogram.
+ * gnat_cuda.adb:
+ (Add_CUDA_Device_Entity): New subprogram.
+ (CUDA_Device_Entities_Table): New hashmap for CUDA_Device
+ entities.
+ (Get_CUDA_Device_Entities): New internal subprogram.
+ (Set_CUDA_Device_Entities): New internal subprogram.
+ * par-prag.adb (Prag): Handle pragma id Pragma_CUDA_Device.
+ * sem_prag.ads (Aspect_Specifying_Pragma): Mark CUDA_Device as
+ being both aspect and pragma.
+ * sem_prag.adb (Analyze_Pragma): Add CUDA_Device entities to
+ list of CUDA_Entities belonging to package N.
+ (Sig_Flags): Signal CUDA_Device entities as referenced.
+ * snames.ads-tmpl: Create CUDA_Device names and pragmas.
+
+2021-10-01 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_util.adb (Build_DIC_Procedure_Body): Remove inappropriate
+ Assert pragma. Remove unneeded and dead code related to derived
+ private types.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Alternative, N_Is_Case_Choice):
+ Add.
+ (N_Is_Exception_Choice, N_Is_Range): Likewise.
+ * gen_il-types.ads: Add above names.
+ * gen_il-gen.adb (Put_Union_Membership): Write both declarations
+ and definitions of union functions.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Expand_Array_Aggregate,
+ Two_Pass_Aggregate_Expansion): Increment index for element
+ insertion within the loop, only if upper bound has not been
+ reached.
+
+2021-10-01 Javier Miranda <miranda@adacore.com>
+
+ * contracts.ads (Make_Class_Precondition_Subps): New subprogram.
+ (Merge_Class_Conditions): New subprogram.
+ (Process_Class_Conditions_At_Freeze_Point): New subprogram.
+ * contracts.adb (Check_Class_Condition): New subprogram.
+ (Set_Class_Condition): New subprogram.
+ (Analyze_Contracts): Remove code analyzing class-wide-clone
+ subprogram since it is no longer built.
+ (Process_Spec_Postconditions): Avoid processing twice seen
+ subprograms.
+ (Process_Preconditions): Simplify its functionality to
+ non-class-wide preconditions.
+ (Process_Preconditions_For): No action needed for wrappers and
+ helpers.
+ (Make_Class_Precondition_Subps): New subprogram.
+ (Process_Class_Conditions_At_Freeze_Point): New subprogram.
+ (Merge_Class_Conditions): New subprogram.
+ * exp_ch6.ads (Install_Class_Preconditions_Check): New
+ subprogram.
+ * exp_ch6.adb (Expand_Call_Helper): Install class-wide
+ preconditions check on dispatching primitives that have or
+ inherit class-wide preconditions.
+ (Freeze_Subprogram): Remove code for null procedures with
+ preconditions.
+ (Install_Class_Preconditions_Check): New subprogram.
+ * exp_util.ads (Build_Class_Wide_Expression): Lower the
+ complexity of this subprogram; out-mode formal Needs_Wrapper
+ since this functionality is now provided by a new subprogram.
+ (Get_Mapped_Entity): New subprogram.
+ (Map_Formals): New subprogram.
+ * exp_util.adb (Build_Class_Wide_Expression): Lower the
+ complexity of this subprogram. Its previous functionality is now
+ provided by subprograms Needs_Wrapper and Check_Class_Condition.
+ (Add_Parent_DICs): Map the overridden primitive to the
+ overriding one.
+ (Get_Mapped_Entity): New subprogram.
+ (Map_Formals): New subprogram.
+ (Update_Primitives_Mapping): Adding assertion.
+ * freeze.ads (Check_Inherited_Conditions): Subprogram made
+ public with added formal to support late overriding.
+ * freeze.adb (Check_Inherited_Conditions): New implementation;
+ builds the dispatch table wrapper required for class-wide
+ pre/postconditions; added support for late overriding.
+ (Needs_Wrapper): New subprogram.
+ * sem.ads (Inside_Class_Condition_Preanalysis): New global
+ variable.
+ * sem_disp.ads (Covered_Interface_Primitives): New subprogram.
+ * sem_disp.adb (Covered_Interface_Primitives): New subprogram.
+ (Check_Dispatching_Context): Skip checking context of
+ dispatching calls during preanalysis of class-wide conditions
+ since at that stage the expression is not installed yet on its
+ definite context.
+ (Check_Dispatching_Call): Skip checking 6.1.1(18.2/5) by
+ AI12-0412 on helpers and wrappers internally built for
+ supporting class-wide conditions; for late-overriding
+ subprograms call Check_Inherited_Conditions to build the
+ dispatch-table wrapper (if required).
+ (Propagate_Tag): Adding call to
+ Install_Class_Preconditions_Check.
+ * sem_util.ads (Build_Class_Wide_Clone_Body): Removed.
+ (Build_Class_Wide_Clone_Call): Removed.
+ (Build_Class_Wide_Clone_Decl): Removed.
+ (Class_Condition): New subprogram.
+ (Nearest_Class_Condition_Subprogram): New subprogram.
+ * sem_util.adb (Build_Class_Wide_Clone_Body): Removed.
+ (Build_Class_Wide_Clone_Call): Removed.
+ (Build_Class_Wide_Clone_Decl): Removed.
+ (Class_Condition): New subprogram.
+ (Nearest_Class_Condition_Subprogram): New subprogram.
+ (Eligible_For_Conditional_Evaluation): No need to evaluate
+ class-wide conditions during preanalysis since the expression is
+ not installed on its definite context.
+ * einfo.ads (Class_Wide_Clone): Removed.
+ (Class_Postconditions): New attribute.
+ (Class_Preconditions): New attribute.
+ (Class_Preconditions_Subprogram): New attribute.
+ (Dynamic_Call_Helper): New attribute.
+ (Ignored_Class_Postconditions): New attribute.
+ (Ignored_Class_Preconditions): New attribute.
+ (Indirect_Call_Wrapper): New attribute.
+ (Is_Dispatch_Table_Wrapper): New attribute.
+ (Static_Call_Helper): New attribute.
+ * exp_attr.adb (Expand_N_Attribute_Reference): When the prefix
+ is of an access-to-subprogram type that has class-wide
+ preconditions and an indirect-call wrapper of such subprogram is
+ available, replace the prefix by the wrapper.
+ * exp_ch3.adb (Build_Class_Condition_Subprograms): New
+ subprogram.
+ (Register_Dispatch_Table_Wrappers): New subprogram.
+ * exp_disp.adb (Build_Class_Wide_Check): Removed; class-wide
+ precondition checks now rely on internally built helpers.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Set initial
+ value of attributes Class_Preconditions, Class_Postconditions,
+ Ignored_Class_Preconditions and Ignored_Class_Postconditions.
+ These values are later updated with the full pre/postcondition
+ by Merge_Class_Conditions.
+ (Freeze_Entity_Checks): Call
+ Process_Class_Conditions_At_Freeze_Point.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Remove code
+ building the body of the class-wide clone subprogram since it is
+ no longer required.
+ (Install_Entity): Adding assertion.
+ * sem_prag.adb (Analyze_Pre_Post_Condition_In_Decl_Part): Remove
+ code building and analyzing the class-wide clone subprogram; no
+ longer required.
+ (Build_Pragma_Check_Equivalent): Adjust call to
+ Build_Class_Wide_Expression since the formal named Needs_Wrapper
+ has been removed.
+ * sem_attr.adb (Analyze_Attribute_Old_Result): Skip processing
+ these attributes during preanalysis of class-wide conditions
+ since at that stage the expression is not installed yet on its
+ definite context.
+ * sem_res.adb (Resolve_Actuals): Skip applying RM 3.9.2(9/1) and
+ SPARK RM 6.1.7(3) on actuals of internal helpers and wrappers
+ built to support class-wide preconditions.
+ * sem_ch5.adb (Process_Bounds): Do not generate a constant
+ declaration for the bounds when we are preanalyzing a class-wide
+ condition.
+ (Analyze_Loop_Parameter_Specification): Handle preanalysis of
+ quantified expression placed in the outermost expression of a
+ class-wide condition.
+ * ghost.adb (Check_Ghost_Context): No check required during
+ preanalysis of class-wide conditions.
+ * gen_il-fields.ads (Opt_Field_Enum): Adding
+ Class_Postconditions, Class_Preconditions,
+ Class_Preconditions_Subprogram, Dynamic_Call_Helper,
+ Ignored_Class_Postconditions, Ignored_Class_Preconditions,
+ Indirect_Call_Wrapper, Is_Dispatch_Table_Wrapper,
+ Static_Call_Helper.
+ * gen_il-gen-gen_entities.adb (Is_Dispatch_Table_Wrapper):
+ Adding semantic flag Is_Dispatch_Table_Wrapper; removing
+ semantic field Class_Wide_Clone; adding semantic fields for
+ Class_Postconditions, Class_Preconditions,
+ Class_Preconditions_Subprogram, Dynamic_Call_Helper,
+ Ignored_Class_Postconditions, Indirect_Call_Wrapper,
+ Ignored_Class_Preconditions, and Static_Call_Helper.
+
+2021-10-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * comperr.adb (Delete_SCIL_Files): Handle generic subprogram
+ declarations and renaming just like generic package declarations
+ and renamings, respectively; handle
+ N_Subprogram_Renaming_Declaration.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * bcheck.adb (Check_Versions): Add support for the case where
+ the .ali file contains both a primary and a secondary version
+ number, as in "GNAT Lib v22.20210809".
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * sem_res.adb (Resolve): Two separate fixes. In the case where
+ Find_Aspect for a literal aspect returns the aspect for a
+ different (ancestor) type, call Corresponding_Primitive_Op to
+ get the right callee. In the case where a downward tagged type
+ conversion appears to be needed, generate a null extension
+ aggregate instead, as per Ada RM 3.4(27).
+ * sem_util.ads, sem_util.adb: Add new Corresponding_Primitive_Op
+ function. It maps a primitive op of a tagged type and a
+ descendant type of that tagged type to the corresponding
+ primitive op of the descendant type. The body of this function
+ was written by Javier Miranda.
+
+2021-10-01 Bob Duff <duff@adacore.com>
+
+ * atree.adb: Gather and print statistics about frequency of
+ getter and setter calls.
+ * atree.ads (Print_Statistics): New procedure for printing
+ statistics.
+ * debug.adb: Document -gnatd.A switch.
+ * gen_il-gen.adb: Generate code for statistics gathering.
+ Choose the offset of Homonym early. Misc cleanup. Put more
+ comments in the generated code.
+ * gen_il-internals.ads (Unknown_Offset): New value to indicate
+ that the offset has not yet been chosen.
+ * gnat1drv.adb: Call Print_Statistics.
+ * libgnat/s-imglli.ads: Minor comment fix.
+ * output.ads (Write_Int_64): New procedure to write a 64-bit
+ value. Needed for new statistics, and could come in handy
+ elsewhere.
+ * output.adb (Write_Int_64): Likewise.
+ * sinfo.ads: Remove obsolete comment. The xtreeprs program no
+ longer exists.
+ * types.ads: New 64-bit types needed for new statistics.
+
+2021-10-01 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/memtrack.adb (Putc): New routine wrapped around fputc
+ with error check.
+ (Write): New routine wrapped around fwrite with error check.
+ Remove bound functions fopen, fwrite, fputs, fclose, OS_Exit.
+ Use the similar routines from System.CRTL and System.OS_Lib.
+
+2021-10-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Must_Slide): If the aggregate only contains an
+ others_clause no sliding id involved. Otherwise sliding is
+ required if any bound of the aggregate or the context subtype is
+ non-static.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Is_Decl): Add.
+ * gen_il-types.ads (N_Is_Decl): Likewise.
+
+2021-10-01 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Entity_Name): Add.
+ * gen_il-types.ads (N_Entity_Name): Likewise.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * bcheck.adb (Check_Versions): In the case of an ali file
+ version mismatch, if distinct integer values can be extracted
+ from the two version strings then include those values in the
+ generated error message.
+
+2021-10-01 Steve Baird <baird@adacore.com>
+
+ * sem_elab.adb (Is_Safe_Call): Return True in the case of a
+ (possibly rewritten) call to an expression function.
+
+2021-10-01 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_aggr.adb (Resolve_Iterated_Component_Association):
+ Initialize Id_Typ to Any_Type by default.
+
+2021-10-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/gnat_and_program_execution.rst (gnatmem): Document
+ that it works only with fixed-position executables.
+
+2021-10-01 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/s-parame__vxworks.ads (time_t_bits): Change to
+ Long_Long_Integer'Size.
+
+2021-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Fix comment.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * gen_il-gen-gen_entities.adb (Subprogram_Body_Or_Type): Add.
+ * gen_il-types.ads (Subprogram_Body_Or_Type): Likewise.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * einfo-utils.adb (Next_Index): Verify input and output are
+ N_Is_Index.
+ * gen_il-gen-gen_nodes.adb (N_Has_Bounds, N_Is_Index): Add.
+ * gen_il-types.ads (N_Has_Bounds, N_Is_Index): Likewise.
+ * sem_ch3.adb (Array_Type_Declaration): Use Next, not
+ Next_Index.
+ * sem_ch12.adb (Formal_Dimensions): Likewise.
+ * sem_util.adb (Is_Valid_Renaming): Likewise.
+
+2021-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst (gnatsymbolize):
+ Document new --load option and -g1 as minimal compilation
+ requirement.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Only keep the bounds
+ for internally generated attributes; otherwise, compute them
+ anew.
+
+2021-09-23 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch3.adb (Build_Access_Subprogram_Wrapper): Decorate the
+ wrapper with attribute Is_Wrapper, and move its declaration to
+ the freezing actions of its type declaration; done to facilitate
+ identifying it at later stages to avoid handling it as a
+ primitive operation of a tagged type; otherwise it may be
+ handled as a dispatching operation and erroneously registered in
+ a dispatch table.
+ (Make_Index): Add missing decoration of field Parent.
+ * sem_disp.adb (Check_Dispatching_Operation): Complete
+ decoration of late-overriding dispatching primitives.
+ (Is_Access_To_Subprogram_Wrapper): New subprogram.
+ (Inherited_Subprograms): Prevent cascaded errors; adding missing
+ support for private types.
+ * sem_type.adb (Add_One_Interp): Add missing support for the
+ first interpretation of a primitive of an inmediate ancestor
+ interface.
+ * sem_util.adb (Check_Result_And_Post_State_In_Pragma): Do not
+ report missing reference in postcondition placed in internally
+ built wrappers.
+ * exp_disp.adb (Expand_Dispatching_Call): Adding assertion.
+
+2021-09-23 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Check the validity of
+ an array aggregate all of whose components are iterated
+ component associations.
+ * exp_aggr.adb (Expand_Array_Aggregate,
+ Two_Pass_Aggregate_Expansion): implement two-pass algorithm and
+ replace original aggregate with resulting temporary, to ensure
+ that a proper length check is performed if context is
+ constrained. Use attributes Pos and Val to handle index types of
+ any discrete type.
+
+2021-09-23 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb: Set the number of concrete nodes that have the
+ Homonym field to a higher number than any other field. This
+ isn't true, but it forces Homonym's offset to be chosen first,
+ so it will be at offset zero and hence slot zero.
+
+2021-09-23 Richard Kenner <kenner@adacore.com>
+
+ * atree.adb (Relocate_Node): If relocating a subprgram call and
+ we're doing unnesting, make a new Parameter_Associations, if
+ any.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-strbou.ads (Generic_Bounded_Length): Remove explicit
+ Initializes contract.
+
+2021-09-23 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb: Generate getters and setters with much of the
+ code inlined. Generate code for storing a few fields in the node
+ header, to avoid the extra level of indirection for those
+ fields. We generate the header type, so we don't have to
+ duplicate hand-written Ada and C code to depend on the number of
+ header fields. Declare constants for slot size. Use short names
+ because these are used all over. Remove
+ Put_Low_Level_Accessor_Instantiations, Put_Low_Level_C_Getter,
+ which are no longer needed. Rename
+ Put_High_Level_C_Getter-->Put_C_Getter.
+ * atree.ads, atree.adb: Take into account the header slots.
+ Take into account the single Node_Or_Entity_Field type. Remove
+ "pragma Assertion_Policy (Ignore);", because the routines in
+ this package are no longer efficiency critical.
+ * atree.h: Remove low-level getters, which are no longer used by
+ sinfo.h and einfo.h.
+ * einfo-utils.adb: Avoid crash in Known_Alignment.
+ * live.adb, sem_eval.adb: Remove code that prevents Node_Id from
+ having a predicate. We don't actually add a predicate to
+ Node_Id, but we want to be able to for temporary debugging.
+ * sinfo-utils.adb: Remove code that prevents Node_Id from having
+ a predicate. Take into account the single Node_Or_Entity_Field
+ type.
+ * sinfo-utils.ads: Minor.
+ * table.ads (Table_Type): Make the components aliased, because
+ low-level setters in Atree need to take 'Access.
+ * treepr.adb: Take into account the single Node_Or_Entity_Field
+ type. Make some code more robust, so we can print out
+ half-baked nodes.
+ * types.ads: Move types here for visibility purposes.
+ * gcc-interface/gigi.h, gcc-interface/trans.c: Take into account
+ the Node_Header change in the GNAT front end.
+ * gcc-interface/cuintp.c, gcc-interface/targtyps.c: Add because
+ gigi.h now refers to type Node_Header, which is in sinfo.h.
+
+2021-09-23 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strfix.adb (Delete, Insert, Overwrite,
+ Replace_Slice): Remove SPARK_Mode Off.
+ * libgnat/a-strfix.ads (Insert, Overwrite, Replace_Slice):
+ Strengthen precondition.
+
+2021-09-23 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-strbou.ads (Generic_Bounded_Length): Remove non-null
+ Global contracts.
+
+2021-09-23 Steve Baird <baird@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Update
+ this section to reflect the current version of Ada RM M.2.
+ * gnat_rm.texi: Regenerate.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strfix.ads (Trim): Simplify contracts.
+ * libgnat/a-strfix.adb (Trim): Remove white space.
+
+2021-09-22 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Op_Eq): Reuse Is_Attribute_Result.
+ * exp_prag.adb (Expand_Attributes): Reuse Is_Attribute_Old.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb (Analyze_Object_Declaration): Do not insert a
+ predicate check after a deferred constant declaration.
+
+2021-09-22 Bob Duff <duff@adacore.com>
+
+ * contracts.adb, einfo-utils.adb, einfo-utils.ads, exp_ch7.adb,
+ exp_ch9.adb, exp_disp.adb, exp_prag.adb, exp_smem.adb,
+ exp_util.adb, freeze.adb, sem_aggr.adb, sem_attr.adb,
+ sem_ch8.adb, sem_prag.ads, sem_util.adb, sem_util.ads: Fix
+ conformance errors.
+ * errout.adb, erroutc.adb: Remove pragmas Suppress.
+ * err_vars.ads: Initialize variables that were previously being
+ read uninitialized.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-strunb.ads: Mark package in SPARK with private part
+ not in SPARK.
+ (Free): Mark not in SPARK.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * snames.ads-tmpl: Update status of some attributes.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-interr__vxworks.adb (Interfaces.C): Remove as
+ unused.
+ (System.VxWorks.Ext): Import.
+ (System.VxWorks.Ext.STATUS): use type.
+ (STATUS): New subtype.
+ (OK): New constant.
+ (Interrupt_Connector): Return STATUS type vice int.
+ (Interrupt_Connect, Notify_Interrupt, Unbind_Handler,
+ Interrupt_Server_Task): Rename Status to Result. Assert Result =
+ OK.
+ * libgnarl/s-osinte__vxworks.adb (To_Clock_Ticks): Define constant
+ IERR, and return it vice ERROR.
+ (Binary_Semaphore_Delete): Return STATUS type vice int.
+ (Binary_Semaphore_Obtain): Likewise.
+ (Binary_Semaphore_Release): Likewise.
+ (Binary_Semaphore_Flush): Likewise.
+ * libgnarl/s-osinte__vxworks.ads (SVE): Renaming of
+ System.VxWorks.Ext.
+ (STATUS): Use SVE in declaration of subtype.
+ (BOOL): Likewise.
+ (vx_freq_t): Likewise.
+ (t_id): Likewise.
+ (gitpid): Use SVE in renaming of subprogram
+ (Task_Stop): Likewise.
+ (Task_Cont): Likewise.
+ (Int_Lock): Likewise.
+ (Int_Unlock): Likewise.
+ (Set_Time_Slice): Likewise.
+ (semDelete): Likewise.
+ (taskCpuAffinitySet): Likewise.
+ (taskMaskAffinitySet): Likewise.
+ (sigset_t): Use SVE in declaration of type.
+ (OK): Remove as unused.
+ (ERROR): Likewise.
+ (taskOptionsGet): return STATUS vice int.
+ (taskSuspend): Likewise.
+ (taskResume): Likewise.
+ (taskDelay): Likewise.
+ (taskVarAdd): Likewise.
+ (taskVarDelete): Likewise.
+ (taskVarSet): Likewise.
+ (tlkKeyCreate): Likewise.
+ (taskPrioritySet): Likewise.
+ (semGive): Likewise.
+ (semTake): Likewise.
+ (Binary_Semaphore_Delete): Likewise.
+ (Binary_Semaphore_Obtain): Likewise.
+ (Binary_Semaphore_Release): Likewise.
+ (Binary_Semaphore_Flush): Likewise.
+ (Interrupt_Connect): Likewise.
+ * libgnarl/s-taprop__vxworks.adb
+ (System.VxWorks.Ext.STATUS): use type.
+ (int): Syntactically align subtype.
+ (STATUS): New subtype.
+ (OK): New constant.
+ (Finalize_Lock): Check STATUS vice int. Assert OK.
+ (Finalize_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Write_Lock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Unlock): Likewise.
+ (Sleep): Likewise.
+ (Sleep): Likewise.
+ (Sleep): Likewise.
+ (Timed_Sleep): Likewise and test Result.
+ (Timed_Delay): Likewise and test Result.
+ (Wakeup): Likewise.
+ (Yield): Likewise.
+ (Finalize_TCB): Likewise.
+ (Suspend_Until_True): Check OK.
+ (Stop_All_Tasks): Declare Dummy STATUS vice in. Check OK.
+ (Is_Task_Context): Use OSI renaming.
+ (Initialize): Use STATUS vice int.
+ * libgnarl/s-vxwext.adb
+ (IERR): Renamed from ERROR.
+ (taskCpuAffinitySet): Return IERR (int).
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ * libgnarl/s-vxwext__kernel-smp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): Return IERR.
+ (semDelete): Return STATUS.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ * libgnarl/s-vxwext__kernel.adb
+ (IERR): Renamed from ERROR.
+ (semDelete): Return STATUS.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (taskCpuAffinitySet): Return IERR (int)
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext__kernel.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ (Interrupt_Connect): Return STATUS
+ (semDelete): Likewise.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (Set_Time_Slice): Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): return IERR constant vice ERROR.
+ (Interrupt_Connect): Return STATUS.
+ (semDelete): Likewise.
+ (Set_Time_Slice): Likewise.
+ * libgnarl/s-vxwext__rtp.adb
+ (IERR): Renamed from ERROR.
+ (Int_Lock): return IERR constant vice ERROR.
+ (Int_Unlock): Return STATUS.
+ (semDelete): Likewise.
+ (Set_Time_Slice): Likewise.
+ (taskCpuAffinitySet): Return IERR (int)
+ (taskMaskAffinitySet): Likewise.
+ * libgnarl/s-vxwext__rtp.ads
+ (STATUS): New subtype.
+ (OK): New STATUS constant.
+ (ERROR): Likewise.
+ (Interrupt_Connect): Return STATUS
+ (semDelete): Likewise.
+ (Task_Cont): Likewise.
+ (Task_Stop): Likewise.
+ (Set_Time_Slice): Likewise.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * prep.adb (Preprocess): Allow for more flexibility when
+ Relaxed_RM_Semantics is set.
+
+2021-09-22 Pierre-Alexandre Bazin <bazin@adacore.com>
+
+ * libgnat/a-strbou.adb: Turn SPARK_Mode on.
+ * libgnat/a-strbou.ads: Write contracts.
+ * libgnat/a-strfix.ads (Index): Fix grammar error in a comment.
+ * libgnat/a-strsea.ads (Index): Likewise.
+ * libgnat/a-strsup.adb: Rewrite the body to take into account
+ the new definition of Super_String using Relaxed_Initialization
+ and a predicate.
+ (Super_Replicate, Super_Translate, Times): Added loop
+ invariants, and ghost lemmas for Super_Replicate and Times.
+ (Super_Trim): Rewrite the body using search functions to
+ determine the cutting points.
+ (Super_Element, Super_Length, Super_Slice, Super_To_String):
+ Remove (now written as expression functions in a-strsup.ads).
+ * libgnat/a-strsup.ads: Added contracts.
+ (Super_Element, Super_Length, Super_Slice, Super_To_String):
+ Rewrite as expression functions.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functions): Add guard.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-vxwext.ads (BOOL): New int type.
+ (Interrupt_Context): Change return type to BOOL.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+ * libgnarl/s-osinte__vxworks.adb (Interrupt_Context): Change
+ return type to BOOL.
+ * libgnarl/s-osinte__vxworks.ads (BOOL) New subtype.
+ (taskIsSuspended): Change return type to BOOL.
+ (Interrupt_Context): Change return type to BOOL. Adjust comments
+ accordingly.
+ * libgnarl/s-taprop__vxworks.adb (System.VxWorks.Ext.BOOL):
+ use type.
+ (Is_Task_Context): Test Interrupt_Context against 0.
+ * libgnat/i-vxwork.ads (BOOL): New int.
+ (intContext): Change return type to BOOL. Adjust comments.
+ * libgnat/i-vxwork__x86.ads: Likewise.
+
+2021-09-22 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aux.adb, sem_aux.ads (Package_Body): Moved from GNATprove.
+ * sem_elab.adb (Spec_And_Body_From_Entity): Refine type of parameter.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * doc/gnat_ugn/platform_specific_information.rst: Improve doc
+ on permission and containers.
+ * gnat_ugn.texi: Regenerate.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * atree.adb (Rewrite): Fix parent node of shared aspects.
+ * atree.ads (Rewrite): Add ??? comment on incorrect
+ documentation.
+ * einfo-utils.adb (Known_Esize): Fix logic.
+ * sem_ch13.adb (Alignment_Check_For_Size_Change,
+ Analyze_Attribute_Definition_Clause): Protect against unset
+ Size.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * freeze.adb (Build_Renamed_Body): Special case for GNATprove.
+ * sem_ch6.adb (Analyze_Expression_Function): Remove useless test
+ for a node to come from source, which becomes harmful otherwise.
+
+2021-09-22 Justin Squirek <squirek@adacore.com>
+
+ * ali.adb, ali.ads (Scan_ALI): Remove use of deprecated
+ parameter Ignore_ED, and all specification for Lower in call to
+ Get_File_Name.
+ * ali-util.adb (Read_Withed_ALIs): Modify call to Scan_ALI.
+ * clean.adb (Clean_Executables): Likewise.
+ * gnatbind.adb (Add_Artificial_ALI_File, Executable section):
+ Likewise.
+ * gnatlink.adb (Executable section): Likewise.
+ * gnatls.adb (Executable section): Likewise.
+ * make.adb (Check, Wait_For_Available_Slot): Likewise.
+ * aspects.ads: Add Aspect_No_Controlled_Parts to
+ Nonoverridable_Aspect_Id
+ * opt.ads: Remove function pointers used as a workaround for
+ ASIS.
+ * osint-c.adb (Executable section): Remove setting of function
+ pointer workarounds needed for ASIS.
+ * osint.adb (Read_Default_Search_Dirs): Correct behavior to
+ detect EOL characters.
+ * par_sco.adb (Output_Header): Remove comment regarding use of
+ First_Sloc.
+ (Traverse_Sync_Definition): Renamed to
+ Traverse_Protected_Or_Task_Definition.
+ * pprint.adb (Interal_List_Name): Add description about purpose,
+ and refactor conditional statement.
+ (Prepend): Removed.
+ * repinfo.adb (List_Rep_Info, Write_Info_Line): Remove use of
+ subprogram pointer.
+ * scng.adb (Scan): Remove CODEFIX question, and minor comment
+ change.
+ * sem_attr.adb (Analyze_Image_Attribute): Remove special
+ processing for 'Img.
+ * sem_ch6.adb (Check_Untagged_Equality): Add RM reference.
+ (FCE): Add comment describing behavior.
+ (Is_Non_Overriding_Operation): Minor comment formatting change.
+ * sem_type.adb (Is_Actual_Subprogram): Add comment about
+ Comes_From_Source test.
+ (Matching_Types): Describe non-matching cases.
+ * sem_util.adb (Is_Confirming): Add stub case for
+ No_Controlled_Parts.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functions): Access
+ Predicated_Parent only on subtypes.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_prag.adb (Process_Import_Or_Interface): Relax error when
+ Relaxed_RM_Semantics.
+
+2021-09-22 Steve Baird <baird@adacore.com>
+
+ * libgnat/s-regpat.adb (Match): Handle the case where Self.First
+ is not NUL (so we know the first character we are looking for),
+ but case-insensitive matching has
+ been specified.
+ (Optimize): In the case of an EXACTF Op, set Self.First as is
+ done in the EXACT case, except with the addition of a call to
+ Lower_Case.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-imenne.ads, libgnat/s-imenne.adb: Delete.
+ * gcc-interface/Make-lang.in (GNAT_ADA_OBJS): Remove s-imenne.o.
+ (GNATBIND_OBJS): Likewise.
+
+2021-09-22 Yannick Moy <moy@adacore.com>
+
+ * einfo.ads: Fix comments.
+ * exp_aggr.adb: Fix variable name.
+ * exp_util.adb: Fix comments.
+ * sem_ch13.adb: Fix comments.
+ * sem_ch3.adb: Fix comments and variable name.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads: Make procedure vice function.
+ * libgnarl/s-vxwext.ads: Likewise.
+ * libgnarl/s-vxwext__kernel-smp.adb: Likewise.
+ * libgnarl/s-vxwext__kernel.adb: Likewise.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp-smp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.adb: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+ * libgnarl/s-taprop__vxworks.adb (Stop_All_Tasks): Call
+ Int_Unlock as a procedure.
+
+2021-09-22 Doug Rupp <rupp@adacore.com>
+
+ * libgnarl/s-osinte__vxworks.ads (SVE): New package renaming
+ (vx_freq_t): New subtype.
+ (sysClkRateGet): Return vx_freq_t.
+ * libgnarl/s-vxwext.ads (vx_freq_t): New type.
+ * libgnarl/s-vxwext__kernel.ads: Likewise.
+ * libgnarl/s-vxwext__rtp.ads: Likewise.
+
+2021-09-22 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_case.adb (Composite_Case_Ops): Replace 'Image with
+ Error_Msg_Uint.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch4.adb (Expand_N_If_Expression): Generate an intermediate
+ temporary when the expression is a condition in an outer decision
+ and control-flow optimizations are suppressed.
+
+2021-09-22 Steve Baird <baird@adacore.com>
+
+ * exp_ch5.adb (Expand_General_Case_Statement.Pattern_Match): Add
+ new function Indexed_Element to handle array element
+ comparisons. Handle case choices that are array aggregates,
+ string literals, or names denoting constants.
+ * sem_case.adb (Composite_Case_Ops.Array_Case_Ops): New package
+ providing utilities needed for casing on arrays.
+ (Composite_Case_Ops.Choice_Analysis): If necessary, include
+ array length as a "component" (like a discriminant) when
+ traversing components. We do not (yet) partition choice analysis
+ to deal with unequal length choices separately. Instead, we
+ embed everything in the minimum-dimensionality Cartesian product
+ space needed to handle all choices properly; this is determined
+ by the length of the longest choice pattern.
+ (Composite_Case_Ops.Choice_Analysis.Traverse_Discrete_Parts):
+ Include length as a "component" in the traversal if necessary.
+ (Composite_Case_Ops.Choice_Analysis.Parse_Choice.Traverse_Choice):
+ Add support for case choices that are string literals or names
+ denoting constants.
+ (Composite_Case_Ops.Choice_Analysis): Include length as a
+ "component" in the analysis if necessary.
+ (Check_Choices.Check_Case_Pattern_Choices.Ops.Value_Sets.Value_Index_Count):
+ Improve error message when capacity exceeded.
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Update
+ documentation to reflect current implementation status.
+ * gnat_rm.texi: Regenerate.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * freeze.adb (Check_Component_Storage_Order): Give a specific error
+ message for non-byte-aligned component in the packed case. Replace
+ "composite" with "record" in both cases.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/a-tasini.ads, libgnarl/a-tasini.adb: Make compatible
+ with No_Elaboration_Code_All.
+ * libgnarl/s-taskin.ads, libgnarl/s-tassta.adb: Adjust
+ accordingly.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch6.adb (Check_Returns): Change message on missing return.
+
+2021-09-22 Arnaud Charlet <charlet@adacore.com>
+
+ * gnatfind.adb, gnatxref.adb: Mark these tools as obsolete
+ before removing them completely.
+
+2021-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (range_cannot_be_superflat): Tweak comments.
+
+2021-09-21 Doug Rupp <rupp@adacore.com>
+
+ * init.c (__gnat_error_handler) [LynxOS]: Add a comment about
+ missing optional args.
+
+2021-09-21 Yannick Moy <moy@adacore.com>
+
+ * gen_il-gen.adb (Put_Opt_Subtype): Add suffix.
+
+2021-09-21 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb (Accessibility_Level): Remove spurious special
+ case for protected type components.
+ * exp_ch4.adb (Generate_Accessibility_Check): Use general
+ Accessibility_Level instead of the low-level function
+ Type_Access_Level.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat_ugn.texi: Regenerate.
+
+2021-09-21 Matthieu Eyraud <eyraud@adacore.com>
+
+ * par_sco.adb (Traverse_One): Add support for pragma Invariant /
+ Type_Invariant.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen.adb (Put_Opt_Subtype): Print out subtypes of the
+ form:
+ subtype Opt_N_Declaration is
+ Node_Id with Predicate =>
+ Opt_N_Declaration = Empty or else
+ Opt_N_Declaration in N_Declaration_Id;
+ One for each node or entity type, with the predicate allowing
+ Empty.
+ * atree.adb (Parent, Set_Parent): Remove unnecessary "Atree.".
+
+2021-09-21 Patrick Bernardi <bernardi@adacore.com>
+
+ * bindgen.adb (Gen_Adainit): For targets that suppress the
+ standard library: set the default stack size global variable if
+ a value is provided via the -d switch, and generate a call to
+ __gnat_initialize_stack_limit if stack checking using stack
+ limits is enabled.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * sem_ch13.adb (Stream_Size): Print message about allowed stream
+ sizes even if other error were already found. This avoids
+ falling into the 'else', which prints "Stream_Size cannot be
+ given for...", which is misleading -- the Size COULD be given if
+ it were correct.
+
+2021-09-21 Daniel Mercier <mercier@adacore.com>
+
+ * exp_util.adb (Build_Temporary): In case of an external DISCR
+ symbol, set the related expression for CodePeer so that a more
+ comprehensible message can be emitted to the user.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (Parse_Header): Tweak comments.
+ (Read_Entry_Format_Array): Tweak exception message.
+ (Symbolic_Address.Set_Result): Likewise.
+
+2021-09-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch7.adb (Make_Init_Call): Add guard to protect against a
+ missing initialization procedure for a type.
+
+2021-09-21 Doug Rupp <rupp@adacore.com>
+
+ * Makefile.rtl: Remove unused VxWorks sections.
+ * libgnarl/s-vxwext__noints.adb: Remove.
+ * libgnarl/s-vxwext__vthreads.ads: Remove.
+ * libgnat/a-elchha__vxworks-ppc-full.adb: Remove.
+ * libgnat/s-osprim__vxworks.adb: Remove.
+ * libgnat/s-osvers__vxworks-653.ads: Remove.
+ * libgnat/system-vxworks-e500-vthread.ads: Remove.
+ * libgnat/system-vxworks-ppc-vthread.ads: Remove.
+ * libgnat/system-vxworks-x86-vthread.ads: Remove.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * uintp.ads, uintp.adb (UI_Is_In_Int_Range): Change the type of
+ the formal parameter to Valid_Uint. Remove code that preserved
+ the previous behavior, and replace it with an assertion. The
+ previous behavior is no longer needed given the recent change to
+ gigi.
+ (No, Present): Add comment.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * sem_eval.adb (Fold_Shift): Replace an if_expression with an
+ if_statement.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * uintp.ads, uintp.adb: Add assertions.
+ (Ubool, Opt_Ubool): New "boolean" subtypes.
+ (UI_Is_In_Int_Range): The parameter should probably be
+ Valid_Uint, but we don't change that for now, because it causes
+ failures in gigi.
+ * sem_util.ads, sem_util.adb (Is_True, Is_False,
+ Static_Boolean): Use Opt_Ubool subtype. Document the fact that
+ Is_True (No_Uint) = True. Implement Is_False in terms of
+ Is_True. We considered changing Static_Boolean to return Uint_1
+ in case of error, but that doesn't fit in well with
+ Static_Integer.
+ (Has_Compatible_Alignment_Internal): Deal with cases where Offs
+ is No_Uint. Change one "and" to "and then" to ensure we don't
+ pass No_Uint to ">", which would violate the new assertions.
+ * exp_util.adb, freeze.adb, sem_ch13.adb: Avoid violating new
+ assertions in Uintp.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (To_File_Name): Fetch only the last string
+ from the .debug_line_str section.
+ (Symbolic_Address.Set_Result): Likewise.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.adb (Skip_Form): Fix cases of DW_FORM_addrx
+ and DW_FORM_implicit_const. Replace Constraint_Error with
+ Dwarf_Error.
+
+2021-09-21 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * exp_pakd.adb (Expand_Packed_Not): Replace expression with
+ statement.
+
+2021-09-21 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_eval.adb (Is_Static_Subtype): Take predicates created
+ through "predicate" pragma into account.
+
+2021-09-21 Frederic Konrad <konrad@adacore.com>
+
+ * Makefile.rtl (aarch64-rtems*): Add GNATRTL_128BIT_PAIRS to
+ the LIBGNAT_TARGET_PAIRS list and also GNATRTL_128BIT_OBJS to
+ the EXTRA_GNATRTL_NONTASKING_OBJS list.
+
+2021-09-21 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch4.adb (Remove_Abstract_Operations): Add condition to
+ test for an E_Operator as part of criteria for setting
+ Abstract_Op on interpretations involving predefined operators.
+
+2021-09-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch6.adb (Expand_Simple_Function_Return): For explicit
+ dereference of type conversion, enable code that ensures that
+ the tag of the result is that of the result type.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * einfo-utils.adb: Add support (currently disabled) for using
+ "initial zero" instead of "Uint_0" to represent "unknown". Call
+ Known_ functions, instead of evilly duplicating their code
+ inline.
+ * fe.h (No_Uint_To_0): New function to convert No_Uint to
+ Uint_0, in order to preserve existing behavior.
+ (Copy_Esize, Copy_RM_Size): New imports from Einfo.Utils.
+ * cstand.adb: Set size fields of Standard_Debug_Renaming_Type
+ and Standard_Exception_Type.
+ * checks.adb, exp_attr.adb, exp_ch3.adb, exp_ch5.adb,
+ exp_ch6.adb, exp_pakd.adb, exp_util.adb, freeze.adb, itypes.adb,
+ layout.adb, repinfo.adb, sem_attr.adb, sem_ch12.adb,
+ sem_ch13.adb, sem_ch13.ads, sem_ch3.adb, sem_ch7.adb,
+ sem_util.adb: Protect calls with Known_..., use Copy_... Remove
+ assumption that Uint_0 represents "unknown".
+ * types.ads (Nonzero_Int): New subtype.
+ * gcc-interface/decl.c, gcc-interface/trans.c: Protect calls
+ with Known_... and use Copy_... as appropriate, to avoid
+ blowing up in unknown cases. Similarly, call No_Uint_To_0 to
+ preserve existing behavior.
+
+2021-09-21 Steve Baird <baird@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add a new nested
+ function, Directly_Specified, and then use it in the
+ implementation of the required check.
+
+2021-09-21 Steve Baird <baird@adacore.com>
+
+ * libgnat/a-costso.ads, libgnat/a-costso.adb: A new library
+ unit, Ada.Containers.Stable_Sorting, which exports a pair of
+ generics (one within the other) which are instantiated by each
+ of the 5 doubly-linked list container generics to implement
+ their respective Sort procedures. We use a pair of generics,
+ rather than a single generic, in order to further reduce code
+ duplication. The outer generic takes a formal private Node_Ref
+ type representing a reference to a linked list element. For some
+ instances, the corresponding actual parameter will be an access
+ type; for others, it will be the index type for an array.
+ * Makefile.rtl: Include new Ada.Containers.Stable_Sorting unit.
+ * libgnat/a-cbdlli.adb, libgnat/a-cdlili.adb,
+ libgnat/a-cfdlli.adb, libgnat/a-cidlli.adb, libgnat/a-crdlli.adb
+ (Sort): Replace existing Sort implementation with a call to an
+ instance of
+ Ada.Containers.Stable_Sorting.Doubly_Linked_List_Sort. Declare
+ the (trivial) actual parameters needed to declare that instance.
+ * libgnat/a-cfdlli.ads: Fix a bug encountered during testing in
+ the postcondition for M_Elements_Sorted. With a partial
+ ordering, it is possible for all three of (X < Y), (Y < X),
+ and (X = Y) to be simultaneously false, so that case needs to
+ handled correctly.
+
+2021-09-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * errout.adb (Error_Msg_Internal): Fix references to Sptr and
+ Optr in comment; fix grammar of "low-level" where it is used as
+ an adjective.
+
+2021-09-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * errout.adb (Write_Source_Code_Lines): Use Cur_Loc before
+ incrementing it, so that we don't need to decrement it.
+
+2021-09-21 Yannick Moy <moy@adacore.com>
+
+ * errout.adb (Get_Line_End): Do not allow the result to go past
+ the end of the buffer.
+
+2021-09-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Process_Discriminant_Expressions): If the
+ constraint is for a Component_Definition that appears in a
+ Component_Declaration, the entity to be used to create the
+ potentially global symbol is the Defining_Identifier of the
+ Component_Declaration.
+
+2021-09-21 Bob Duff <duff@adacore.com>
+
+ * libgnat/a-stbufi.ads, libgnat/a-stbufi.adb: Change all
+ occurrences of GNAT.OS_Lib to System.OS_Lib.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * inline.adb (Has_Excluded_Declaration): Remove redundant guard;
+ the guarded code will call First on a No_List, which is
+ well-defined and gives Empty.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * inline.adb (Has_Excluded_Declaration): Rename and reduce scope
+ of a local variable.
+
+2021-09-20 Bob Duff <duff@adacore.com>
+
+ * uintp.ads, uintp.adb (Present, No): New functions for
+ comparing with No_Uint.
+ * checks.adb, einfo-utils.adb, exp_aggr.adb, exp_attr.adb,
+ exp_ch3.adb, exp_ch4.adb, exp_dbug.adb, exp_disp.adb,
+ exp_util.adb, repinfo.adb, repinfo-input.adb, scn.adb,
+ sem_attr.adb, sem_ch13.adb, sem_eval.adb, sem_util.adb,
+ sinfo-utils.adb, treepr.adb: Use Present (...) instead of "...
+ /= No_Uint", and No (...) instead of "... = No_Uint".
+
+2021-09-20 Claire Dross <dross@adacore.com>
+
+ * libgnat/s-ficobl.ads: The entire package has a SPARK_Mode =>
+ Off aspect.
+
+2021-09-20 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/a-calend.adb: Remove time_t, replace with OS_Time.
+ * libgnat/s-os_lib.ads: Fix comments regarding time_t conversion
+ functions to reflect the use of To_Ada in in Ada.Calendar
+ package body.
+ * sysdep.c (__gnat_localtime_tzoff): Use OS_Time instead of
+ time_t.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Actual): Remove
+
+2021-09-20 Bob Duff <duff@adacore.com>
+
+ * einfo-utils.ads, einfo-utils.adb, fe.h, einfo.ads,
+ gen_il-fields.ads: Remove unused and no-longer-used routines.
+ Move related routines together. Rewrite incorrect
+ documentation, and documentation that will be incorrect when
+ e.g. Esize-related routines are fixed. Remove unused field
+ Normalized_Position_Max.
+ * cstand.adb, exp_pakd.adb, freeze.adb,
+ gen_il-gen-gen_entities.adb, itypes.adb, layout.adb,
+ sem_ch10.adb, sem_ch12.adb, sem_ch13.adb, sem_ch3.adb,
+ sem_ch7.adb, sem_ch8.adb, sem_ch9.adb, sem_prag.adb,
+ sem_util.adb, ttypes.ads: Update calls to routines removed from
+ or renamed in Einfo.Utils.
+ * uintp.ads (Upos): Fix this subtype, which was unintentionally
+ declared to include Uint_0.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch7.adb (Expand_N_Package_Declaration): Fix wording in
+ comment.
+ * exp_disp.adb (Mark_DT): Remove unnecessary initialization of
+ I_Depth.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * contracts.adb (Add_Contract_Item): Accept volatile-related
+ properties on constants.
+ (Analyze_Object_Contract): Check external properties on
+ constants; accept volatile constants.
+ (Check_Type_Or_Object_External_Properties): Replace "variable"
+ with "object" in error messages; replace Decl_Kind with a local
+ constant.
+ * sem_prag.adb (Analyze_Pragma): Accept volatile-related
+ properties on constants.
+
+2021-09-20 Pierre-Alexandre Bazin <bazin@adacore.com>
+
+ * libgnat/a-strfix.adb ("*"): Added loop invariants and lemmas
+ for proof.
+ (Delete): Added assertions for proof, and conditions to avoid
+ overflow.
+ (Head): Added loop invariant.
+ (Insert): Same as Delete.
+ (Move): Declared with SPARK_Mode Off.
+ (Overwrite): Added assertions for proof, and conditions to avoid
+ overflow.
+ (Replace_Slice): Added assertions for proof, and conditions to
+ avoid overflow.
+ (Tail): Added loop invariant and avoided overflows.
+ (Translate): Added loop invariants.
+ (Trim): Ensured empty strings returned start at 1.
+ * libgnat/a-strfix.ads (Index): Rewrote contract cases for
+ easier proof.
+ (Index_Non_Blank): Separated the null string case.
+ (Count): Specified Mapping shouldn't be null.
+ (Find_Token): Specified Source'First should be Positive when no
+ From is given.
+ (Translate): Specified Mapping shouldn't be null.
+ ("*"): Rewrote postcondition for easier proof.
+ * libgnat/a-strsea.adb (Belongs): Added postcondition.
+ (Count): Rewrote loops and added loop invariants to avoid
+ overflows.
+ (Find_Token): Added loop invariants.
+ (Index): Rewrote loops to avoid overflows and added loop
+ invariants for proof.
+ (Index_Non_Blank): Added loop invariants.
+ (Is_Identity): New function isolated without SPARK_Mode.
+ * libgnat/a-strsea.ads: Fix starting comment as package is no
+ longer private.
+ (Match): Declared ghost expression function Match.
+ (Is_Identity): Described identity in the postcondition.
+ (Index, Index_Non_Blank, Count, Find_Token): Added contract from
+ a-strfix.ads.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Resolve_Aspect_Aggregate): Move comments after
+ specs; fix typo in header box; cleanup whitespace.
+
+2021-09-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-objrea.adb (Get_Load_Address): Return 0 for ELF.
+
+2021-09-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * adaint.c (__gnat_get_executable_load_address): Add Win32 support.
+ * libgnat/s-objrea.ads (Get_Xcode_Bounds): Fix typo in comment.
+ (Object_File): Minor reformatting.
+ (ELF_Object_File): Uncomment predicate.
+ (PECOFF_Object_File): Likewise.
+ (XCOFF32_Object_File): Likewise.
+ * libgnat/s-objrea.adb: Minor reformatting throughout.
+ (Get_Load_Address): Implement for PE-COFF.
+ * libgnat/s-dwalin.ads: Remove clause for System.Storage_Elements
+ and use consistent wording in comments.
+ (Dwarf_Context): Set type of Low, High and Load_Address to Address.
+ * libgnat/s-dwalin.adb (Get_Load_Displacement): New function.
+ (Is_Inside): Call Get_Load_Displacement.
+ (Low_Address): Likewise.
+ (Open): Adjust to type change.
+ (Aranges_Lookup): Change type of Addr to Address.
+ (Read_Aranges_Entry): Likewise for Start and adjust.
+ (Enable_Cach): Adjust to type change.
+ (Symbolic_Address): Change type of Addr to Address.
+ (Symbolic_Traceback): Call Get_Load_Displacement.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_disp.adb (Make_DT): Move call to Set_Has_Dispatch_Table,
+ so it is executed regardless of the Generate_SCIL mode.
+
+2021-09-20 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_util.ads (Force_Evaluation): Add formal parameter
+ Discr_Number, to indicate discriminant expression for which an
+ external name must be created.
+ (Remove_Side_Effects): Ditto.
+ * exp_util.adb (Force_Evaluation): Call Remove_Side_Effects with
+ added parameter.
+ (Remove_Side_Effects, Build_Temporary): If Discr_Number is
+ positive, create an external name with suffix DISCR and the
+ given discriminant number, analogous to what is done for
+ temporaries for array type bounds.
+ * sem_ch3.adb (Process_Discriminant_Expressions): If the
+ constraint is for an object or component declaration and the
+ corresponding entity may be visible in another unit, invoke
+ Force_Evaluation with the new parameter.
+
+2021-09-20 Arnaud Charlet <charlet@adacore.com>
+
+ * gen_il-internals.ads (Invalid_Val): Remove, unused and
+ generates warnings.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_aggr.adb, exp_ch4.adb, exp_ch5.adb, sprint.adb: Refine
+ types of local constants.
+
+2021-09-20 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference): Fold
+ Preelaborable_Initialization attribute in cases where it hasn't
+ been folded by the analyzer.
+ * exp_disp.adb (Original_View_In_Visible_Part): This function is
+ removed and moved to sem_util.adb.
+ * sem_attr.adb (Attribute_22): Add
+ Attribute_Preelaborable_Initialization as an Ada 2022 attribute.
+ (Analyze_Attribute, Attribute_Preelaborable_Initialization):
+ Check that the prefix of the attribute is either a formal
+ private or derived type, or a composite type declared within the
+ visible part of a package or generic package.
+ (Eval_Attribute): Perform folding of
+ Preelaborable_Initialization attribute based on
+ Has_Preelaborable_Initialization applied to the prefix type.
+ * sem_ch3.adb (Resolve_Aspects): Add specialized code for
+ Preelaborable_Initialization used at the end of a package
+ visible part for setting Known_To_Have_Preelab_Init on types
+ that are specified with True or that have a conjunction of one
+ or more P_I attributes applied to formal types.
+ * sem_ch7.adb (Analyze_Package_Specification): On call to
+ Has_Preelaborable_Initialization, pass True for new formal
+ Formal_Types_Have_Preelab_Init, so that error checking treats
+ subcomponents that are declared within types in generics as
+ having preelaborable initialization when the subcomponents are
+ of formal types.
+ * sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Add test for
+ P_I to prevent calling Make_Pragma_From_Boolean_Aspect, since
+ this aspect is handled specially and the
+ Known_To_Have_Preelab_Init flag will get set on types that have
+ the aspect by other means.
+ (Analyze_Aspect_Specifications.Analyze_One_Aspect): Add test for
+ Aspect_Preelaborable_Initialization for allowing the aspect to
+ be specified on formal type declarations.
+ (Is_Operational_Item): Treat Attribute_Put_Image as an
+ operational attribute. The need for this was encountered while
+ working on these changes.
+ * sem_util.ads (Has_Preelaborable_Initialization): Add
+ Formal_Types_Have_Preelab_Init as a new formal parameter that
+ defaults to False.
+ (Is_Conjunction_Of_Formal_Preelab_Init_Attributes): New
+ function.
+ (Original_View_In_Visible_Part): Moved here from exp_disp.adb,
+ so it can be called by Analyze_Attribute.
+ * sem_util.adb (Has_Preelaborable_Initialization): Return True
+ for formal private and derived types when new formal
+ Formal_Types_Have_Preelab_Init is True, and pass along the
+ Formal_Types_Have_Preelab_Init flag in the array component case.
+ (Check_Components): Pass along Formal_Types_Have_Preelab_Init
+ flag on call to Has_Preelaborable_Initialization.
+ (Is_Conjunction_Of_Formal_Preelab_Init_Attributes): New function
+ that returns True when passed an expression that includes one or
+ more attributes for Preelaborable_Initialization applied to
+ prefixes that denote formal types.
+ (Is_Formal_Preelab_Init_Attribute): New utility function nested
+ within Is_Conjunction_Of_Formal_Preelab_Init_Attributes that
+ determines whether a node is a P_I attribute applied to a
+ generic formal type.
+ (Original_View_In_Visible_Part): Moved here from exp_util.adb,
+ so it can be called by Analyze_Attribute.
+ * snames.ads-tmpl: Add note near the start of spec giving
+ details about what needs to be done when adding a name that
+ corresponds to both an attribute and a pragma. Delete existing
+ occurrence of Name_Preelaborable_Initialization, and add a note
+ comment in the list of Name_* constants at that place,
+ indicating that it's included in type Pragma_Id, etc., echoing
+ other such comments for names that are both an attribute and a
+ pragma. Insert Name_Preelaborable_Initialization in the
+ alphabetized set of Name_* constants corresponding to
+ attributes (between First_Attribute_Name and
+ Last_Attribute_Name).
+ (type Attribute_Id): Add new literal
+ Attribute_Preelaborable_Initialization.
+ (type Pragma_Id): Move Pragma_Preelaborable_Initialization from
+ its current position to the end of the type, in the special set
+ of pragma literals that have corresponding atttributes. Add to
+ accompanying comment, indicating that functions Get_Pragma_Id
+ and Is_Pragma_Name need to be updated when adding a pragma
+ literal to the special set.
+ * snames.adb-tmpl (Get_Pragma_Id): Add case alternative for
+ Pragma_Preelaborable_Initialization.
+ (Is_Pragma_Name): Add test for
+ Name_Preelaborable_Initialization.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_ch4.adb (Finc_Non_Universal_Interpretations): Fix check.
+
+2021-09-20 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Build_Discriminant_Constraints): Exit once a
+ first discriminant is found and the Discrim_Present flag is set.
+
+2021-09-20 Bob Duff <duff@adacore.com>
+
+ * gnat1drv.adb (Gnat1drv): Avoid calling List_Rep_Info in
+ Generate_SCIL and GNATprove_Mode.
+ * repinfo.adb (List_Common_Type_Info): Fix comment.
+
+2021-09-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-dwalin.ads: Remove clause for Ada.Exceptions.Traceback,
+ add clause for System.Traceback_Entries and alphabetize.
+ (AET): Delete.
+ (STE): New package renaming.
+ (Symbolic_Traceback): Adjust.
+ * libgnat/s-dwalin.adb: Remove clauses for Ada.Exceptions.Traceback
+ and System.Traceback_Entries.
+ (Symbolic_Traceback): Adjust.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_ch4.adb (Find_Non_Universal_Interpretations): Check if
+ types are compatible before adding interpretation.
+
+2021-09-20 Justin Squirek <squirek@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Type_Conversion): Add guard to protect
+ against calculating accessibility levels against internal
+ compiler-generated types.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_dim.adb (Dimensions_Msg_Of): Capitalize comment.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * adabkend.adb (Scan_Back_End_Switches): Replace switch-scanning
+ logic with call to Backend_Utils.Scan_Common_Back_End_Switches.
+ * back_end.adb (Scan_Back_End_Switches): Replace switch-scanning
+ logic with call to Backend_Utils.Scan_Common_Back_End_Switches.
+ * backend_utils.adb: New file.
+ * backend_utils.ads: New file.
+ * gcc-interface/Make-lang.in: Add ada/backend_utils.o.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * atree.adb (Get_32_Bit_Field): Declare result before returning.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * exp_ch7.adb (Expand_N_Package_Body): Replace
+ Build_And_Insert_Cuda_Initialization with Expand_CUDA_Package.
+ * gnat_cuda.adb (Expand_CUDA_Package): New procedure.
+ (Build_And_Insert_Cuda_Initialization): Make internal.
+ * gnat_cuda.ads (Expand_CUDA_Package): New procedure.
+ (Build_And_Insert_Cuda_Initialization): Remove from spec.
+
+2021-09-20 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * usage.adb (Usage): Update -gnatw.c messages.
+
+2021-09-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_aux.adb (Is_By_Reference_Type): Do not test Error_Posted.
+
+2021-09-15 Alexandre Oliva <oliva@adacore.com>
+
+ * gcc-interface/utils.c: Include opts.h.
+ (handle_zero_call_used_regs_attribute): New.
+ (gnat_internal_attribute_table): Add zero_call_used_regs.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/101970
+ * exp_attr.adb (Expand_N_Attribute_Reference) <Attribute_Enum_Rep>:
+ Use an unchecked conversion instead of a regular conversion in the
+ enumeration case and remove Conversion_OK flag in the integer case.
+ <Attribute_Pos>: Remove superfluous test.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (validate_size): Do not issue an error if the
+ old size has overflowed.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): For vector types, make
+ the representative array the debug type.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_subprog_type): Turn variable
+ into constant. Capitalize GCC in warning message.
+ (intrin_arglists_compatible_p): Change parameter to pointer-to-const
+ Adjust warning messages. Turn warning into error for vector types.
+ (intrin_return_compatible_p): Likewise.
+ (intrin_profiles_compatible_p): Change parameter to pointer-to-const
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-atopri.ads (bool): Delete.
+ (Atomic_Test_And_Set): Replace bool with Boolean.
+ (Atomic_Always_Lock_Free): Likewise.
+ * libgnat/s-aoinar.adb (Is_Lock_Free): Adjust.
+ * libgnat/s-aomoar.adb (Is_Lock_Free): Likewise.
+ * libgnat/s-aotase.adb (Atomic_Test_And_Set): Likewise.
+ * libgnat/s-atopex.adb (Atomic_Compare_And_Exchange): Likewise.
+ * gcc-interface/decl.c: Include gimple-expr.h.
+ (intrin_types_incompatible_p): Delete.
+ (intrin_arglists_compatible_p): Call types_compatible_p.
+ (intrin_return_compatible_p): Likewise.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (update_pointer_to): Set TYPE_CANONICAL on
+ pointer and reference types.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/101385
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (-Wall): Minor fixes.
+ (-w): Likewise.
+ (-Werror): Document that it also sets -gnatwe by default.
+ * gcc-interface/lang-specs.h (ada): Expand -gnatwe if -Werror is
+ passed and move expansion of -gnatw switches to before -gnatez.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (can_materialize_object_renaming_p): Do not
+ call UI_Is_In_Int_Range on the result of Normalized_First_Bit.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <is_type>: Declare new
+ constant. Adjust error message issued by validate_size in the case
+ of by-reference types.
+ (validate_size): Always use the error strings passed by the caller.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc-interface/misc.c (gnat_post_options): Issue an error for
+ -fexcess-precision=16.
+
2021-08-19 Arnaud Charlet <charlet@adacore.com>
PR ada/101924
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index fb851a6..7fef517 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -162,6 +162,7 @@ GNATRTL_NONTASKING_OBJS= \
a-coormu$(objext) \
a-coorse$(objext) \
a-coprnu$(objext) \
+ a-costso$(objext) \
a-coteio$(objext) \
a-crbltr$(objext) \
a-crbtgk$(objext) \
@@ -1083,7 +1084,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe
a-nuaufl.ads<libgnat/a-nuaufl__wraplf.ads \
a-nashfl.ads<libgnat/a-nashfl__wraplf.ads \
s-dorepr.adb<libgnat/s-dorepr__fma.adb \
- s-inmaop.adb<libgnarl/s-inmaop__vxworks.adb \
+ s-inmaop.adb<libgnarl/s-inmaop__hwint.adb \
s-intman.ads<libgnarl/s-intman__vxworks.ads \
s-intman.adb<libgnarl/s-intman__vxworks.adb \
s-osinte.ads<libgnarl/s-osinte__vxworks.ads \
@@ -1195,136 +1196,6 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe
endif
endif
-# PowerPC and e500v2 VxWorks 653
-ifeq ($(strip $(filter-out powerpc% wrs vxworksae vxworksaespe,$(target_cpu) $(target_vendor) $(target_os))),)
-
- ifeq ($(strip $(filter-out e500%, $(target_alias))),)
- ARCH_STR=e500
- # gcc config translates the target e500v2-wrs-vxworks to
- # powerpc-wrs-vxworksspe. Let's keep the original alias here when
- # generating s-oscons.ads.
- target=$(target_alias)
- else
- ARCH_STR=ppc
- endif
-
- # target pairs for vthreads runtime
- LIBGNAT_TARGET_PAIRS = \
- a-elchha.adb<libgnat/a-elchha__vxworks-ppc-full.adb \
- a-intnam.ads<libgnarl/a-intnam__vxworks.ads \
- a-naliop.ads<libgnat/a-naliop__nolibm.ads \
- a-nuaufl.ads<libgnat/a-nuaufl__wraplf.ads \
- a-nashfl.ads<libgnat/a-nashfl__wraplf.ads \
- g-io.adb<hie/g-io__vxworks-cert.adb \
- s-dorepr.adb<libgnat/s-dorepr__fma.adb \
- s-inmaop.adb<libgnarl/s-inmaop__vxworks.adb \
- s-interr.adb<libgnarl/s-interr__vxworks.adb \
- s-intman.ads<libgnarl/s-intman__vxworks.ads \
- s-intman.adb<libgnarl/s-intman__vxworks.adb \
- s-osinte.adb<libgnarl/s-osinte__vxworks.adb \
- s-osinte.ads<libgnarl/s-osinte__vxworks.ads \
- s-osprim.adb<libgnat/s-osprim__vxworks.adb \
- s-parame.ads<libgnat/s-parame__ae653.ads \
- s-parame.adb<libgnat/s-parame__vxworks.adb \
- s-taprop.adb<libgnarl/s-taprop__vxworks.adb \
- s-tasinf.ads<libgnarl/s-tasinf__vxworks.ads \
- s-taspri.ads<libgnarl/s-taspri__vxworks.ads \
- s-tpopsp.adb<libgnarl/s-tpopsp__vxworks.adb \
- s-vxwext.adb<libgnarl/s-vxwext__noints.adb \
- s-vxwext.ads<libgnarl/s-vxwext__vthreads.ads \
- s-vxwork.ads<libgnarl/s-vxwork__ppc.ads \
- $(ATOMICS_TARGET_PAIRS) \
- $(ATOMICS_BUILTINS_TARGET_PAIRS) \
- system.ads<libgnat/system-vxworks-$(ARCH_STR)-vthread.ads
-
- EH_MECHANISM=-gcc
-
- TOOLS_TARGET_PAIRS=indepsw.adb<indepsw-gnu.adb
-
- EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o
- EXTRA_GNATRTL_TASKING_OBJS=i-vxinco.o s-vxwork.o s-vxwext.o
-
- EXTRA_LIBGNAT_OBJS+=sigtramp-vxworks.o
- EXTRA_LIBGNAT_SRCS+=$(VX_SIGTRAMP_EXTRA_SRCS)
-
- # Extra pairs for the vthreads runtime
- ifeq ($(strip $(filter-out vthreads,$(THREAD_KIND))),)
- LIBGNAT_TARGET_PAIRS += \
- s-thread.adb<libgnat/s-thread__ae653.adb \
- s-osvers.ads<libgnat/s-osvers__vxworks-653.ads \
- $(DUMMY_SOCKETS_TARGET_PAIRS)
-
- GNATRTL_SOCKETS_OBJS =
- EXTRA_GNATRTL_NONTASKING_OBJS += s-thread.o s-osvers.o
- else
- LIBGNAT_TARGET_PAIRS += \
- g-socthi.ads<libgnat/g-socthi__vxworks.ads \
- g-socthi.adb<libgnat/g-socthi__vxworks.adb \
- g-sopowa.adb<libgnat/g-sopowa__posix.adb \
- g-stsifd.adb<libgnat/g-stsifd__sockets.adb
- endif
-
-endif
-
-# VxWorksae / VxWorks 653 for x86 (vxsim) - ?? VxWorks mils not implemented
-ifeq ($(strip $(filter-out %86 wrs vxworksae,$(target_cpu) $(target_vendor) $(target_os))),)
- # target pairs for kernel + vthreads runtime
- LIBGNAT_TARGET_PAIRS = \
- a-elchha.adb<libgnat/a-elchha__vxworks-ppc-full.adb \
- a-intnam.ads<libgnarl/a-intnam__vxworks.ads \
- a-naliop.ads<libgnat/a-naliop__nolibm.ads \
- a-nuaufl.ads<libgnat/a-nuaufl__wraplf.ads \
- a-nashfl.ads<libgnat/a-nashfl__wraplf.ads \
- g-io.adb<hie/g-io__vxworks-cert.adb \
- s-inmaop.adb<libgnarl/s-inmaop__vxworks.adb \
- s-interr.adb<libgnarl/s-interr__vxworks.adb \
- s-intman.ads<libgnarl/s-intman__vxworks.ads \
- s-intman.adb<libgnarl/s-intman__vxworks.adb \
- s-osinte.adb<libgnarl/s-osinte__vxworks.adb \
- s-osinte.ads<libgnarl/s-osinte__vxworks.ads \
- s-osprim.adb<libgnat/s-osprim__vxworks.adb \
- s-parame.ads<libgnat/s-parame__ae653.ads \
- s-parame.adb<libgnat/s-parame__vxworks.adb \
- s-taprop.adb<libgnarl/s-taprop__vxworks.adb \
- s-tasinf.ads<libgnarl/s-tasinf__vxworks.ads \
- s-taspri.ads<libgnarl/s-taspri__vxworks.ads \
- s-tpopsp.adb<libgnarl/s-tpopsp__vxworks.adb \
- s-vxwext.adb<libgnarl/s-vxwext__noints.adb \
- s-vxwext.ads<libgnarl/s-vxwext__vthreads.ads \
- s-vxwork.ads<libgnarl/s-vxwork__x86.ads \
- system.ads<libgnat/system-vxworks-x86-vthread.ads \
- $(ATOMICS_TARGET_PAIRS) \
- $(ATOMICS_BUILTINS_TARGET_PAIRS)
-
- EH_MECHANISM=-gcc
-
- TOOLS_TARGET_PAIRS=indepsw.adb<indepsw-gnu.adb
-
- EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-thread.o
- EXTRA_GNATRTL_TASKING_OBJS=i-vxinco.o s-vxwork.o s-vxwext.o
-
- EXTRA_LIBGNAT_OBJS+=vx_stack_info.o
- GNATRTL_SOCKETS_OBJS =
-
- # Extra pairs for the vthreads runtime
- ifeq ($(strip $(filter-out vthreads,$(THREAD_KIND))),)
- LIBGNAT_TARGET_PAIRS += \
- s-thread.adb<libgnat/s-thread__ae653.adb \
- s-osvers.ads<libgnat/s-osvers__vxworks-653.ads \
- $(DUMMY_SOCKETS_TARGET_PAIRS)
-
- GNATRTL_SOCKETS_OBJS =
- EXTRA_GNATRTL_NONTASKING_OBJS += s-thread.o s-osvers.o
- else
- LIBGNAT_TARGET_PAIRS += \
- g-socthi.ads<libgnat/g-socthi__vxworks.ads \
- g-socthi.adb<libgnat/g-socthi__vxworks.adb \
- g-sopowa.adb<libgnat/g-sopowa__posix.adb \
- g-stsifd.adb<libgnat/g-stsifd__sockets.adb
- endif
-
-endif
-
# x86/x86_64 VxWorks
ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(target_vendor) $(target_os))),)
@@ -1336,7 +1207,7 @@ ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(targ
a-nashfl.ads<libgnat/a-nashfl__wraplf.ads \
s-osinte.adb<libgnarl/s-osinte__vxworks.adb \
s-osinte.ads<libgnarl/s-osinte__vxworks.ads \
- s-inmaop.adb<libgnarl/s-inmaop__vxworks.adb \
+ s-inmaop.adb<libgnarl/s-inmaop__hwint.adb \
s-intman.ads<libgnarl/s-intman__vxworks.ads \
s-intman.adb<libgnarl/s-intman__vxworks.adb \
s-osprim.adb<libgnat/s-osprim__posix.adb \
@@ -1480,7 +1351,7 @@ ifeq ($(strip $(filter-out aarch64 arm% coff wrs vx%,$(target_cpu) $(target_vend
a-naliop.ads<libgnat/a-naliop__nolibm.ads \
a-nuaufl.ads<libgnat/a-nuaufl__wraplf.ads \
a-nashfl.ads<libgnat/a-nashfl__wraplf.ads \
- s-inmaop.adb<libgnarl/s-inmaop__vxworks.adb \
+ s-inmaop.adb<libgnarl/s-inmaop__hwint.adb \
s-interr.adb<libgnarl/s-interr__vxworks.adb \
s-intman.ads<libgnarl/s-intman__vxworks.ads \
s-intman.adb<libgnarl/s-intman__vxworks.adb \
@@ -2176,25 +2047,32 @@ ifeq ($(strip $(filter-out rtems%,$(target_os))),)
LIBGNAT_TARGET_PAIRS = \
system.ads<libgnat/system-rtems.ads \
a-intnam.ads<libgnarl/a-intnam__rtems.ads \
- s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
- s-intman.adb<libgnarl/s-intman__posix.adb \
+ s-inmaop.adb<libgnarl/s-inmaop__hwint.adb \
+ s-intman.adb<libgnarl/s-intman__rtems.adb \
+ s-intman.ads<libgnarl/s-intman__rtems.ads \
s-osinte.adb<libgnarl/s-osinte__rtems.adb \
s-osinte.ads<libgnarl/s-osinte__rtems.ads \
s-osprim.adb<libgnat/s-osprim__rtems.adb \
s-parame.adb<libgnat/s-parame__rtems.adb \
s-parame.ads<libgnat/s-parame__posix2008.ads \
- s-taprop.adb<libgnarl/s-taprop__posix.adb \
+ s-taprop.adb<libgnarl/s-taprop__rtems.adb \
s-taspri.ads<libgnarl/s-taspri__posix.ads \
s-tpopsp.adb<libgnarl/s-tpopsp__tls.adb \
- s-stchop.adb<libgnat/s-stchop__rtems.adb \
s-interr.adb<libgnarl/s-interr__hwint.adb
+ EXTRA_GNATRTL_NONTASKING_OBJS += s-stchop.o
+
ifeq ($(strip $(filter-out arm%, $(target_cpu))),)
EH_MECHANISM=-arm
else
EH_MECHANISM=-gcc
endif
+ ifeq ($(strip $(filter-out aarch64%,$(target_cpu))),)
+ LIBGNAT_TARGET_PAIRS += $(GNATRTL_128BIT_PAIRS)
+ EXTRA_GNATRTL_NONTASKING_OBJS += $(GNATRTL_128BIT_OBJS)
+ endif
+
ifeq ($(strip $(filter-out aarch64% riscv%,$(target_cpu))),)
LIBGNAT_TARGET_PAIRS += a-nallfl.ads<libgnat/a-nallfl__wraplf.ads
endif
diff --git a/gcc/ada/adabkend.adb b/gcc/ada/adabkend.adb
index 2ad58ef..118ca95 100644
--- a/gcc/ada/adabkend.adb
+++ b/gcc/ada/adabkend.adb
@@ -22,15 +22,16 @@
-- This is the version of the Back_End package for back ends written in Ada
-with Atree; use Atree;
+with Atree; use Atree;
+with Backend_Utils; use Backend_Utils;
with Debug;
with Lib;
-with Opt; use Opt;
-with Output; use Output;
-with Osint; use Osint;
-with Osint.C; use Osint.C;
-with Switch.C; use Switch.C;
-with Types; use Types;
+with Opt; use Opt;
+with Output; use Output;
+with Osint; use Osint;
+with Osint.C; use Osint.C;
+with Switch.C; use Switch.C;
+with Types; use Types;
with System.OS_Lib; use System.OS_Lib;
@@ -182,48 +183,11 @@ package body Adabkend is
return;
- -- Special check, the back-end switch -fno-inline also sets the
- -- front end flags to entirely inhibit all inlining. So we store it
- -- and set the appropriate flags.
-
- elsif Switch_Chars (First .. Last) = "fno-inline" then
- Lib.Store_Compilation_Switch (Switch_Chars);
- Opt.Disable_FE_Inline := True;
- return;
-
- -- Similar processing for -fpreserve-control-flow
-
- elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then
- Lib.Store_Compilation_Switch (Switch_Chars);
- Opt.Suppress_Control_Flow_Optimizations := True;
- return;
-
- -- Recognize -gxxx switches
-
- elsif Switch_Chars (First) = 'g' then
- Debugger_Level := 2;
-
- if First < Last then
- case Switch_Chars (First + 1) is
- when '0' =>
- Debugger_Level := 0;
- when '1' =>
- Debugger_Level := 1;
- when '2' =>
- Debugger_Level := 2;
- when '3' =>
- Debugger_Level := 3;
- when others =>
- null;
- 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
+ elsif Scan_Common_Back_End_Switch (Switch_Chars)
+ or else Is_Back_End_Switch (Switch_Chars)
+ then
null;
-- Give error for junk switch
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index 06a4895..60cfa93 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -98,6 +98,7 @@
#ifdef __QNX__
#include <sys/syspage.h>
+#include <sys/time.h>
#endif
#ifdef IN_RTS
@@ -3542,6 +3543,9 @@ __gnat_get_executable_load_address (void)
return (const void *)map->l_addr;
+#elif defined (_WIN32)
+ return GetModuleHandle (NULL);
+
#else
return NULL;
#endif
diff --git a/gcc/ada/ali-util.adb b/gcc/ada/ali-util.adb
index 9074a9a..6c567c3 100644
--- a/gcc/ada/ali-util.adb
+++ b/gcc/ada/ali-util.adb
@@ -249,7 +249,6 @@ package body ALI.Util is
Scan_ALI
(F => Afile,
T => Text,
- Ignore_ED => False,
Err => False);
Free (Text);
diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb
index 24f1677..88cc247 100644
--- a/gcc/ada/ali.adb
+++ b/gcc/ada/ali.adb
@@ -892,7 +892,6 @@ package body ALI is
function Scan_ALI
(F : File_Name_Type;
T : Text_Buffer_Ptr;
- Ignore_ED : Boolean;
Err : Boolean;
Ignore_Lines : String := "X";
Ignore_Errors : Boolean := False;
@@ -964,19 +963,18 @@ package body ALI is
-- special characters are included in the returned name.
function Get_Name
- (Ignore_Spaces : Boolean := False;
- Ignore_Special : Boolean := False;
+ (Ignore_Special : Boolean := False;
May_Be_Quoted : Boolean := False) return Name_Id;
-- Skip blanks, then scan out a name (name is left in Name_Buffer with
-- length in Name_Len, as well as being returned in Name_Id form).
-- If Lower is set to True then the Name_Buffer will be converted to
-- all lower case, for systems where file names are not case sensitive.
-- This ensures that gnatbind works correctly regardless of the case
- -- of the file name on all systems. The termination condition depends
- -- on the settings of Ignore_Spaces and Ignore_Special:
+ -- of the file name on all systems.
--
- -- If Ignore_Spaces is False (normal case), then scan is terminated
- -- by the normal end of field condition (EOL, space, horizontal tab)
+ -- The scan is terminated by the normal end of field condition
+ -- (EOL, space, horizontal tab). Furthermore, the termination condition
+ -- depends on the setting of Ignore_Special:
--
-- If Ignore_Special is False (normal case), the scan is terminated by
-- a typeref bracket or an equal sign except for the special case of
@@ -987,7 +985,6 @@ package body ALI is
-- the name is 'unquoted'. In this case Ignore_Special is ignored and
-- assumed to be True.
--
- -- It is an error to set both Ignore_Spaces and Ignore_Special to True.
-- This function handles wide characters properly.
function Get_Nat return Nat;
@@ -1241,8 +1238,7 @@ package body ALI is
--------------
function Get_Name
- (Ignore_Spaces : Boolean := False;
- Ignore_Special : Boolean := False;
+ (Ignore_Special : Boolean := False;
May_Be_Quoted : Boolean := False) return Name_Id
is
Char : Character;
@@ -1299,7 +1295,7 @@ package body ALI is
loop
Add_Char_To_Name_Buffer (Getc);
- exit when At_End_Of_Field and then not Ignore_Spaces;
+ exit when At_End_Of_Field;
if not Ignore_Special then
if Name_Buffer (1) = '"' then
@@ -1319,8 +1315,7 @@ package body ALI is
exit when Nextc = ',';
-- Terminate if left bracket not part of wide char
- -- sequence Note that we only recognize brackets
- -- notation so far ???
+ -- sequence.
exit when Nextc = '[' and then T (P + 1) /= '"';
@@ -2938,9 +2933,7 @@ package body ALI is
-- Store AD indication unless ignore required
- if not Ignore_ED then
- Withs.Table (Withs.Last).Elab_All_Desirable := True;
- end if;
+ Withs.Table (Withs.Last).Elab_All_Desirable := True;
elsif Nextc = 'E' then
P := P + 1;
@@ -2957,12 +2950,9 @@ package body ALI is
Checkc ('D');
Check_At_End_Of_Field;
- -- Store ED indication unless ignore required
+ -- Store ED indication
- if not Ignore_ED then
- Withs.Table (Withs.Last).Elab_Desirable :=
- True;
- end if;
+ Withs.Table (Withs.Last).Elab_Desirable := True;
end if;
else
@@ -3213,13 +3203,10 @@ package body ALI is
Skip_Space;
Sdep.Increment_Last;
- -- In the following call, Lower is not set to True, this is either
- -- a bug, or it deserves a special comment as to why this is so???
-
-- The file/path name may be quoted
Sdep.Table (Sdep.Last).Sfile :=
- Get_File_Name (May_Be_Quoted => True);
+ Get_File_Name (Lower => True, May_Be_Quoted => True);
Sdep.Table (Sdep.Last).Stamp := Get_Stamp;
Sdep.Table (Sdep.Last).Dummy_Entry :=
diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads
index 3ac9f0e..175aea9 100644
--- a/gcc/ada/ali.ads
+++ b/gcc/ada/ali.ads
@@ -1389,7 +1389,6 @@ package ALI is
function Scan_ALI
(F : File_Name_Type;
T : Text_Buffer_Ptr;
- Ignore_ED : Boolean;
Err : Boolean;
Ignore_Lines : String := "X";
Ignore_Errors : Boolean := False;
@@ -1399,11 +1398,6 @@ package ALI is
-- table. Switch settings may be modified as described above in the
-- switch description settings.
--
- -- Ignore_ED is normally False. If set to True, it indicates that
- -- all AD/ED (elaboration desirable) indications in the ALI file are
- -- to be ignored. This parameter is obsolete now that the -f switch
- -- is removed from gnatbind, and should be removed ???
- --
-- Err determines the action taken on an incorrectly formatted file.
-- If Err is False, then an error message is output, and the program
-- is terminated. If Err is True, then no error message is output,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 0f9ed23..ab11bfd 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -89,6 +89,7 @@ package Aspects is
Aspect_Default_Storage_Pool,
Aspect_Default_Value,
Aspect_Depends, -- GNAT
+ Aspect_Designated_Storage_Model, -- GNAT
Aspect_Dimension, -- GNAT
Aspect_Dimension_System, -- GNAT
Aspect_Dispatching_Domain,
@@ -147,6 +148,7 @@ package Aspects is
Aspect_SPARK_Mode, -- GNAT
Aspect_Stable_Properties,
Aspect_Static_Predicate,
+ Aspect_Storage_Model_Type, -- GNAT
Aspect_Storage_Pool,
Aspect_Storage_Size,
Aspect_Stream_Size,
@@ -187,6 +189,7 @@ package Aspects is
Aspect_Atomic_Components,
Aspect_Disable_Controlled, -- GNAT
Aspect_Discard_Names,
+ Aspect_CUDA_Device, -- GNAT
Aspect_CUDA_Global, -- GNAT
Aspect_Exclusive_Functions,
Aspect_Export,
@@ -233,7 +236,7 @@ package Aspects is
Aspect_Implicit_Dereference | Aspect_Constant_Indexing |
Aspect_Variable_Indexing | Aspect_Aggregate |
Aspect_Max_Entry_Queue_Length
- -- | Aspect_No_Controlled_Parts
+ | Aspect_No_Controlled_Parts
-- ??? No_Controlled_Parts not yet in Aspect_Id enumeration
; -- see RM 13.1.1(18.7)
@@ -379,6 +382,7 @@ package Aspects is
Aspect_Default_Storage_Pool => Expression,
Aspect_Default_Value => Expression,
Aspect_Depends => Expression,
+ Aspect_Designated_Storage_Model => Name,
Aspect_Dimension => Expression,
Aspect_Dimension_System => Expression,
Aspect_Dispatching_Domain => Expression,
@@ -437,6 +441,7 @@ package Aspects is
Aspect_SPARK_Mode => Optional_Name,
Aspect_Stable_Properties => Expression,
Aspect_Static_Predicate => Expression,
+ Aspect_Storage_Model_Type => Expression,
Aspect_Storage_Pool => Name,
Aspect_Storage_Size => Expression,
Aspect_Stream_Size => Expression,
@@ -476,6 +481,7 @@ package Aspects is
Aspect_Contract_Cases => False,
Aspect_Convention => True,
Aspect_CPU => False,
+ Aspect_CUDA_Device => False,
Aspect_CUDA_Global => False,
Aspect_Default_Component_Value => True,
Aspect_Default_Initial_Condition => False,
@@ -483,6 +489,7 @@ package Aspects is
Aspect_Default_Storage_Pool => True,
Aspect_Default_Value => True,
Aspect_Depends => False,
+ Aspect_Designated_Storage_Model => True,
Aspect_Dimension => False,
Aspect_Dimension_System => False,
Aspect_Dispatching_Domain => False,
@@ -542,6 +549,7 @@ package Aspects is
Aspect_SPARK_Mode => False,
Aspect_Stable_Properties => False,
Aspect_Static_Predicate => False,
+ Aspect_Storage_Model_Type => False,
Aspect_Storage_Pool => True,
Aspect_Storage_Size => True,
Aspect_Stream_Size => True,
@@ -627,6 +635,7 @@ package Aspects is
Aspect_Contract_Cases => Name_Contract_Cases,
Aspect_Convention => Name_Convention,
Aspect_CPU => Name_CPU,
+ Aspect_CUDA_Device => Name_CUDA_Device,
Aspect_CUDA_Global => Name_CUDA_Global,
Aspect_Default_Component_Value => Name_Default_Component_Value,
Aspect_Default_Initial_Condition => Name_Default_Initial_Condition,
@@ -634,6 +643,7 @@ package Aspects is
Aspect_Default_Storage_Pool => Name_Default_Storage_Pool,
Aspect_Default_Value => Name_Default_Value,
Aspect_Depends => Name_Depends,
+ Aspect_Designated_Storage_Model => Name_Designated_Storage_Model,
Aspect_Dimension => Name_Dimension,
Aspect_Dimension_System => Name_Dimension_System,
Aspect_Disable_Controlled => Name_Disable_Controlled,
@@ -723,6 +733,7 @@ package Aspects is
Aspect_Stable_Properties => Name_Stable_Properties,
Aspect_Static => Name_Static,
Aspect_Static_Predicate => Name_Static_Predicate,
+ Aspect_Storage_Model_Type => Name_Storage_Model_Type,
Aspect_Storage_Pool => Name_Storage_Pool,
Aspect_Storage_Size => Name_Storage_Size,
Aspect_Stream_Size => Name_Stream_Size,
@@ -872,11 +883,13 @@ package Aspects is
Aspect_Attach_Handler => Always_Delay,
Aspect_Constant_Indexing => Always_Delay,
Aspect_CPU => Always_Delay,
+ Aspect_CUDA_Device => Always_Delay,
Aspect_CUDA_Global => Always_Delay,
Aspect_Default_Iterator => Always_Delay,
Aspect_Default_Storage_Pool => Always_Delay,
Aspect_Default_Value => Always_Delay,
Aspect_Default_Component_Value => Always_Delay,
+ Aspect_Designated_Storage_Model => Always_Delay,
Aspect_Discard_Names => Always_Delay,
Aspect_Dispatching_Domain => Always_Delay,
Aspect_Dynamic_Predicate => Always_Delay,
@@ -928,6 +941,7 @@ package Aspects is
Aspect_Simple_Storage_Pool => Always_Delay,
Aspect_Simple_Storage_Pool_Type => Always_Delay,
Aspect_Static_Predicate => Always_Delay,
+ Aspect_Storage_Model_Type => Always_Delay,
Aspect_Storage_Pool => Always_Delay,
Aspect_Stream_Size => Always_Delay,
Aspect_String_Literal => Always_Delay,
diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
index c7e295b..98614e8 100644
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -23,20 +23,12 @@
-- --
------------------------------------------------------------------------------
--- Assertions in this package are too slow, and are mostly needed when working
--- on this package itself, or on gen_il, so we disable them.
--- To debug low-level bugs in this area, comment out the following pragma,
--- and run with -gnatd_v.
-
-pragma Assertion_Policy (Ignore);
-
with Aspects; use Aspects;
with Debug; use Debug;
with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
with Output; use Output;
-with Seinfo; use Seinfo;
with Sinfo.Utils; use Sinfo.Utils;
with System.Storage_Elements;
@@ -153,7 +145,11 @@ package body Atree is
function Size_In_Slots (N : Node_Or_Entity_Id) return Slot_Count;
-- Number of slots belonging to N. This can be less than
- -- Size_In_Slots_To_Alloc for entities.
+ -- Size_In_Slots_To_Alloc for entities. Includes both header
+ -- and dynamic slots.
+
+ function Size_In_Slots_Dynamic (N : Node_Or_Entity_Id) return Slot_Count;
+ -- Just counts the number of dynamic slots
function Size_In_Slots_To_Alloc (N : Node_Or_Entity_Id) return Slot_Count;
function Size_In_Slots_To_Alloc (Kind : Node_Kind) return Slot_Count;
@@ -161,35 +157,47 @@ package body Atree is
-- to allocate the max, because we don't know the Ekind when this is
-- called.
- function Off_0 (N : Node_Id) return Node_Offset;
- -- Offset of the first slot of N (offset 0) in Slots.Table
+ function Off_F (N : Node_Id) return Node_Offset with Inline;
+ -- Offset of the first dynamic slot of N in Slots.Table.
+ -- The actual offset of this slot from the start of the node
+ -- is not 0; this is logically the first slot after the header
+ -- slots.
- function Off_L (N : Node_Id) return Node_Offset;
+ function Off_0 (N : Node_Id) return Node_Offset'Base with Inline;
+ -- This is for zero-origin addressing of the dynamic slots.
+ -- It points to slot 0 of N in Slots.Table, which does not exist,
+ -- because the first few slots are stored in the header.
+
+ function Off_L (N : Node_Id) return Node_Offset with Inline;
-- Offset of the last slot of N in Slots.Table
- procedure Zero_Slots (First, Last : Node_Offset) with Inline;
- -- Set slots in the range F..L to zero
+ procedure Zero_Dynamic_Slots (First, Last : Node_Offset'Base) with Inline;
+ -- Set dynamic slots in the range First..Last to zero
+
+ procedure Zero_Header_Slots (N : Node_Or_Entity_Id) with Inline;
+ -- Zero the header slots belonging to N
procedure Zero_Slots (N : Node_Or_Entity_Id) with Inline;
- -- Zero the slots belonging to N
+ -- Zero the slots belonging to N (both header and dynamic)
- procedure Copy_Slots (From, To : Node_Offset; Num_Slots : Slot_Count)
+ procedure Copy_Dynamic_Slots
+ (From, To : Node_Offset; Num_Slots : Slot_Count)
with Inline;
-- Copy Num_Slots slots from From to To. Caller is responsible for ensuring
-- that the Num_Slots at To are a reasonable place to copy to.
procedure Copy_Slots (Source, Destination : Node_Id) with Inline;
- -- Copies the slots of Source to Destination; uses the node kind to
- -- determine the Num_Slots.
+ -- Copies the slots (both header and dynamic) of Source to Destination;
+ -- uses the node kind to determine the Num_Slots.
function Get_Field_Value
- (N : Node_Id; Field : Node_Field) return Field_Size_32_Bit;
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Field_Size_32_Bit;
-- Get any field value as a Field_Size_32_Bit. If the field is smaller than
-- 32 bits, convert it to Field_Size_32_Bit. The Field must be present in
-- the Nkind of N.
procedure Set_Field_Value
- (N : Node_Id; Field : Node_Field; Val : Field_Size_32_Bit);
+ (N : Node_Id; Field : Node_Or_Entity_Field; Val : Field_Size_32_Bit);
-- Set any field value as a Field_Size_32_Bit. If the field is smaller than
-- 32 bits, convert it from Field_Size_32_Bit, and Val had better be small
-- enough. The Field must be present in the Nkind of N.
@@ -199,10 +207,6 @@ package body Atree is
-- Called whenever Nkind is modified. Raises an exception if not all
-- vanishing fields are in their initial zero state.
- function Get_Field_Value
- (N : Entity_Id; Field : Entity_Field) return Field_Size_32_Bit;
- procedure Set_Field_Value
- (N : Entity_Id; Field : Entity_Field; Val : Field_Size_32_Bit);
procedure Check_Vanishing_Fields
(Old_N : Entity_Id; New_Kind : Entity_Kind);
-- Above are the same as the ones for nodes, but for entities
@@ -405,7 +409,8 @@ package body Atree is
pragma Assert (N'Valid);
pragma Assert (N <= Node_Offsets.Last);
- pragma Assert (Off_0 (N) <= Off_L (N));
+ pragma Assert (Off_L (N) >= Off_0 (N));
+ pragma Assert (Off_L (N) >= Off_F (N) - 1);
pragma Assert (Off_L (N) <= Slots.Last);
pragma Assert (Nkind (N)'Valid);
pragma Assert (Nkind (N) /= N_Unused_At_End);
@@ -469,8 +474,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_1_Bit, Field_Type);
+ Val : constant Field_Size_1_Bit := Get_1_Bit_Val (N, Offset);
begin
- return Cast (Get_1_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_1_Bit_Field;
function Get_2_Bit_Field
@@ -480,8 +486,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_2_Bit, Field_Type);
+ Val : constant Field_Size_2_Bit := Get_2_Bit_Val (N, Offset);
begin
- return Cast (Get_2_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_2_Bit_Field;
function Get_4_Bit_Field
@@ -491,8 +498,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_4_Bit, Field_Type);
+ Val : constant Field_Size_4_Bit := Get_4_Bit_Val (N, Offset);
begin
- return Cast (Get_4_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_4_Bit_Field;
function Get_8_Bit_Field
@@ -502,8 +510,9 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_8_Bit, Field_Type);
+ Val : constant Field_Size_8_Bit := Get_8_Bit_Val (N, Offset);
begin
- return Cast (Get_8_Bit_Val (N, Offset));
+ return Cast (Val);
end Get_8_Bit_Field;
function Get_32_Bit_Field
@@ -513,8 +522,14 @@ package body Atree is
function Cast is new
Unchecked_Conversion (Field_Size_32_Bit, Field_Type);
+
+ Val : constant Field_Size_32_Bit := Get_32_Bit_Val (N, Offset);
+ Result : constant Field_Type := Cast (Val);
+ -- Note: declaring Result here instead of directly returning
+ -- Cast (...) helps CodePeer understand that there are no issues
+ -- around uninitialized variables.
begin
- return Cast (Get_32_Bit_Val (N, Offset));
+ return Result;
end Get_32_Bit_Field;
function Get_32_Bit_Field_With_Default
@@ -607,138 +622,228 @@ package body Atree is
Set_32_Bit_Val (N, Offset, Cast (Val));
end Set_32_Bit_Field;
+ pragma Style_Checks ("M90");
+
+ -----------------------------------
+ -- Low-level getters and setters --
+ -----------------------------------
+
+ -- In the getters and setters below, we use shifting and masking to
+ -- simulate packed arrays. F_Size is the field size in bits. Mask is
+ -- that number of 1 bits in the low-order bits. F_Per_Slot is the number
+ -- of fields per slot. Slot_Off is the offset of the slot of interest.
+ -- S is the slot at that offset. V is the amount to shift by.
+
+ function In_NH (Slot_Off : Field_Offset) return Boolean is
+ (Slot_Off < N_Head);
+ -- In_NH stands for "in Node_Header", not "in New Hampshire"
+
+ function Get_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset)
+ return Slot is
+ (if In_NH (Slot_Off) then
+ Node_Offsets.Table (N).Slots (Slot_Off)
+ else Slots.Table (Node_Offsets.Table (N).Offset + Slot_Off));
+ -- Get the slot value, either directly from the node header, or
+ -- indirectly from the Slots table.
+
+ procedure Set_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset; S : Slot);
+ -- Set the slot value, either directly from the node header, or
+ -- indirectly from the Slots table, to S.
+
function Get_1_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_1_Bit
is
- -- We wish we were using packed arrays, but instead we're simulating
- -- them with modular integers. L here (and elsewhere) is the 'Length
- -- of that simulated array.
- L : constant Field_Offset := Slot_Size / 1;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 1;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_1_Bit :=
+ Field_Size_1_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_1_Bit (Shift_Right (S, V) and 1);
+ return Raw;
end Get_1_Bit_Val;
function Get_2_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_2_Bit
is
- L : constant Field_Offset := Slot_Size / 2;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 2;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_2_Bit :=
+ Field_Size_2_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_2_Bit (Shift_Right (S, V) and 3);
+ return Raw;
end Get_2_Bit_Val;
function Get_4_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_4_Bit
is
- L : constant Field_Offset := Slot_Size / 4;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 4;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_4_Bit :=
+ Field_Size_4_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_4_Bit (Shift_Right (S, V) and 15);
+ return Raw;
end Get_4_Bit_Val;
function Get_8_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_8_Bit
is
- L : constant Field_Offset := Slot_Size / 8;
-
- pragma Debug (Validate_Node_And_Offset (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 8;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_8_Bit :=
+ Field_Size_8_Bit (Shift_Right (S, V) and Mask);
begin
- return Field_Size_8_Bit (Shift_Right (S, V) and 255);
+ return Raw;
end Get_8_Bit_Val;
function Get_32_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_Size_32_Bit
is
- pragma Debug (Validate_Node_And_Offset (N, Offset));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
+ F_Size : constant := 32;
+ -- No Mask needed
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ pragma Debug (Validate_Node_And_Offset (N, Slot_Off));
+ Raw : constant Field_Size_32_Bit :=
+ Field_Size_32_Bit (S);
begin
- return Field_Size_32_Bit (S);
+ return Raw;
end Get_32_Bit_Val;
+ procedure Set_Slot
+ (N : Node_Or_Entity_Id; Slot_Off : Field_Offset; S : Slot) is
+ begin
+ if In_NH (Slot_Off) then
+ Node_Offsets.Table (N).Slots (Slot_Off) := S;
+ else
+ Slots.Table (Node_Offsets.Table (N).Offset + Slot_Off) := S;
+ end if;
+ end Set_Slot;
+
procedure Set_1_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_1_Bit)
is
- L : constant Field_Offset := Slot_Size / 1;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 1;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (1, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_1_Bit_Val;
procedure Set_2_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_2_Bit)
is
- L : constant Field_Offset := Slot_Size / 2;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 2;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (3, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_2_Bit_Val;
procedure Set_4_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_4_Bit)
is
- L : constant Field_Offset := Slot_Size / 4;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 4;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (15, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_4_Bit_Val;
procedure Set_8_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_8_Bit)
is
- L : constant Field_Offset := Slot_Size / 8;
-
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
- V : constant Natural := Natural ((Offset mod L) * (Slot_Size / L));
+ F_Size : constant := 8;
+ Mask : constant := 2**F_Size - 1;
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ S : constant Slot := Get_Slot (N, Slot_Off);
+ V : constant Natural := Natural ((Offset mod F_Per_Slot) * F_Size);
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := (S and not Shift_Left (255, V)) or Shift_Left (Slot (Val), V);
+ Set_Slot
+ (N, Slot_Off,
+ (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Val), V));
end Set_8_Bit_Val;
procedure Set_32_Bit_Val
(N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_Size_32_Bit)
is
- pragma Debug (Validate_Node_And_Offset_Write (N, Offset));
-
- S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
+ F_Size : constant := 32;
+ -- No Mask needed; this one doesn't do read-modify-write
+ F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;
+ Slot_Off : constant Field_Offset := Offset / F_Per_Slot;
+ pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));
begin
- S := Slot (Val);
+ Set_Slot (N, Slot_Off, Slot (Val));
end Set_32_Bit_Val;
+ ----------------------
+ -- Print_Atree_Info --
+ ----------------------
+
+ procedure Print_Atree_Info (N : Node_Or_Entity_Id) is
+ function Cast is new Unchecked_Conversion (Slot, Int);
+ begin
+ Write_Int (Int (Size_In_Slots (N)));
+ Write_Str (" slots (");
+ Write_Int (Int (Off_0 (N)));
+ Write_Str (" .. ");
+ Write_Int (Int (Off_L (N)));
+ Write_Str ("):");
+
+ for Off in Off_0 (N) .. Off_L (N) loop
+ Write_Str (" ");
+ Write_Int (Cast (Get_Slot (N, Off)));
+ end loop;
+
+ Write_Eol;
+ end Print_Atree_Info;
+
end Atree_Private_Part;
- ---------------
- -- Set_Field --
- ---------------
+ ---------------------
+ -- Get_Field_Value --
+ ---------------------
function Get_Node_Field_Union is new Get_32_Bit_Field (Union_Id)
with Inline;
@@ -746,10 +851,9 @@ package body Atree is
-- etc.
function Get_Field_Value
- (N : Node_Id; Field : Node_Field) return Field_Size_32_Bit
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Field_Size_32_Bit
is
- pragma Assert (Field_Checking.Field_Present (Nkind (N), Field));
- Desc : Field_Descriptor renames Node_Field_Descriptors (Field);
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
begin
case Field_Size (Desc.Kind) is
@@ -761,11 +865,14 @@ package body Atree is
end case;
end Get_Field_Value;
+ ---------------------
+ -- Set_Field_Value --
+ ---------------------
+
procedure Set_Field_Value
- (N : Node_Id; Field : Node_Field; Val : Field_Size_32_Bit)
+ (N : Node_Id; Field : Node_Or_Entity_Field; Val : Field_Size_32_Bit)
is
- pragma Assert (Field_Checking.Field_Present (Nkind (N), Field));
- Desc : Field_Descriptor renames Node_Field_Descriptors (Field);
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
begin
case Field_Size (Desc.Kind) is
@@ -777,13 +884,15 @@ package body Atree is
end case;
end Set_Field_Value;
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Field) is
+ procedure Reinit_Field_To_Zero
+ (N : Node_Id; Field : Node_Or_Entity_Field)
+ is
begin
Set_Field_Value (N, Field, 0);
end Reinit_Field_To_Zero;
function Field_Is_Initial_Zero
- (N : Node_Id; Field : Node_Field) return Boolean is
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Boolean is
begin
return Get_Field_Value (N, Field) = 0;
end Field_Is_Initial_Zero;
@@ -809,7 +918,7 @@ package body Atree is
Old_Kind : constant Node_Kind := Nkind (Old_N);
-- If this fails, it means you need to call Reinit_Field_To_Zero before
- -- calling Set_Nkind.
+ -- calling Mutate_Nkind.
begin
for J in Node_Field_Table (Old_Kind)'Range loop
@@ -834,47 +943,6 @@ package body Atree is
end loop;
end Check_Vanishing_Fields;
- function Get_Field_Value
- (N : Entity_Id; Field : Entity_Field) return Field_Size_32_Bit
- is
- pragma Assert (Field_Checking.Field_Present (Ekind (N), Field));
- Desc : Field_Descriptor renames Entity_Field_Descriptors (Field);
- begin
- case Field_Size (Desc.Kind) is
- when 1 => return Field_Size_32_Bit (Get_1_Bit_Val (N, Desc.Offset));
- when 2 => return Field_Size_32_Bit (Get_2_Bit_Val (N, Desc.Offset));
- when 4 => return Field_Size_32_Bit (Get_4_Bit_Val (N, Desc.Offset));
- when 8 => return Field_Size_32_Bit (Get_8_Bit_Val (N, Desc.Offset));
- when others => return Get_32_Bit_Val (N, Desc.Offset); -- 32
- end case;
- end Get_Field_Value;
-
- procedure Set_Field_Value
- (N : Entity_Id; Field : Entity_Field; Val : Field_Size_32_Bit)
- is
- pragma Assert (Field_Checking.Field_Present (Ekind (N), Field));
- Desc : Field_Descriptor renames Entity_Field_Descriptors (Field);
- begin
- case Field_Size (Desc.Kind) is
- when 1 => Set_1_Bit_Val (N, Desc.Offset, Field_Size_1_Bit (Val));
- when 2 => Set_2_Bit_Val (N, Desc.Offset, Field_Size_2_Bit (Val));
- when 4 => Set_4_Bit_Val (N, Desc.Offset, Field_Size_4_Bit (Val));
- when 8 => Set_8_Bit_Val (N, Desc.Offset, Field_Size_8_Bit (Val));
- when others => Set_32_Bit_Val (N, Desc.Offset, Val); -- 32
- end case;
- end Set_Field_Value;
-
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Entity_Field) is
- begin
- Set_Field_Value (N, Field, 0);
- end Reinit_Field_To_Zero;
-
- function Field_Is_Initial_Zero
- (N : Entity_Id; Field : Entity_Field) return Boolean is
- begin
- return Get_Field_Value (N, Field) = 0;
- end Field_Is_Initial_Zero;
-
procedure Check_Vanishing_Fields
(Old_N : Entity_Id; New_Kind : Entity_Kind)
is
@@ -913,13 +981,17 @@ package body Atree is
end Check_Vanishing_Fields;
Nkind_Offset : constant Field_Offset :=
- Node_Field_Descriptors (F_Nkind).Offset;
+ Field_Descriptors (F_Nkind).Offset;
procedure Set_Node_Kind_Type is new Set_8_Bit_Field (Node_Kind) with Inline;
procedure Init_Nkind (N : Node_Id; Val : Node_Kind) is
pragma Assert (Field_Is_Initial_Zero (N, F_Nkind));
begin
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Nkind) + 1;
+ end if;
+
Set_Node_Kind_Type (N, Nkind_Offset, Val);
end Init_Nkind;
@@ -938,35 +1010,47 @@ package body Atree is
if Old_Size < New_Size then
declare
Old_Last_Slot : constant Node_Offset := Slots.Last;
- Old_Off_0 : constant Node_Offset := Off_0 (N);
+ Old_Off_F : constant Node_Offset := Off_F (N);
begin
- if Old_Last_Slot = Old_Off_0 + Old_Size - 1 then
+ if Old_Last_Slot = Old_Off_F + Old_Size - 1 then
-- In this case, the slots are at the end of Slots.Table, so we
-- don't need to move them.
Slots.Set_Last (Old_Last_Slot + New_Size - Old_Size);
else
-- Move the slots
- All_Node_Offsets (N) := Alloc_Slots (New_Size);
- Copy_Slots (Old_Off_0, Off_0 (N), Old_Size);
- pragma Debug (Zero_Slots (Old_Off_0, Old_Off_0 + Old_Size - 1));
+
+ declare
+ New_Off_F : constant Node_Offset := Alloc_Slots (New_Size);
+ begin
+ All_Node_Offsets (N).Offset := New_Off_F - N_Head;
+ Copy_Dynamic_Slots (Old_Off_F, New_Off_F, Old_Size);
+ pragma Debug
+ (Zero_Dynamic_Slots (Old_Off_F, Old_Off_F + Old_Size - 1));
+ end;
end if;
end;
- Zero_Slots (Off_0 (N) + Old_Size, Slots.Last);
+ Zero_Dynamic_Slots (Off_F (N) + Old_Size, Slots.Last);
+ end if;
+
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Nkind) + 1;
end if;
Set_Node_Kind_Type (N, Nkind_Offset, Val);
pragma Debug (Validate_Node_Write (N));
+
+ New_Node_Debugging_Output (N);
end Mutate_Nkind;
procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) is
begin
- Mutate_Nkind (N, Val, Old_Size => Size_In_Slots (N));
+ Mutate_Nkind (N, Val, Old_Size => Size_In_Slots_Dynamic (N));
end Mutate_Nkind;
Ekind_Offset : constant Field_Offset :=
- Entity_Field_Descriptors (F_Ekind).Offset;
+ Field_Descriptors (F_Ekind).Offset;
procedure Set_Entity_Kind_Type is new Set_8_Bit_Field (Entity_Kind)
with Inline;
@@ -986,8 +1070,14 @@ package body Atree is
-- For now, we are allocating all entities with the same size, so we
-- don't need to reallocate slots here.
+ if Atree_Statistics_Enabled then
+ Set_Count (F_Nkind) := Set_Count (F_Ekind) + 1;
+ end if;
+
Set_Entity_Kind_Type (N, Ekind_Offset, Val);
pragma Debug (Validate_Node_Write (N));
+
+ New_Node_Debugging_Output (N);
end Mutate_Ekind;
-----------------------
@@ -1001,8 +1091,9 @@ package body Atree is
Sz : constant Slot_Count := Size_In_Slots_To_Alloc (Kind);
Sl : constant Node_Offset := Alloc_Slots (Sz);
begin
- Node_Offsets.Table (Result) := Sl;
- Zero_Slots (Sl, Sl + Sz - 1);
+ Node_Offsets.Table (Result).Offset := Sl - N_Head;
+ Zero_Dynamic_Slots (Sl, Sl + Sz - 1);
+ Zero_Header_Slots (Result);
end;
Init_Nkind (Result, Kind);
@@ -1040,7 +1131,7 @@ package body Atree is
pragma Assert (Nkind (N) not in N_Entity);
pragma Assert (New_Kind not in N_Entity);
- Old_Size : constant Slot_Count := Size_In_Slots (N);
+ Old_Size : constant Slot_Count := Size_In_Slots_Dynamic (N);
New_Size : constant Slot_Count := Size_In_Slots_To_Alloc (New_Kind);
Save_Sloc : constant Source_Ptr := Sloc (N);
@@ -1063,15 +1154,16 @@ package body Atree is
New_Offset : constant Field_Offset := Alloc_Slots (New_Size);
begin
pragma Debug (Zero_Slots (N));
- Node_Offsets.Table (N) := New_Offset;
- Zero_Slots (New_Offset, New_Offset + New_Size - 1);
+ Node_Offsets.Table (N).Offset := New_Offset - N_Head;
+ Zero_Dynamic_Slots (New_Offset, New_Offset + New_Size - 1);
+ Zero_Header_Slots (N);
end;
else
Zero_Slots (N);
end if;
- Mutate_Nkind (N, New_Kind, Old_Size);
+ Init_Nkind (N, New_Kind); -- Not Mutate, because of Zero_Slots above
Set_Sloc (N, Save_Sloc);
Set_In_List (N, Save_In_List);
@@ -1090,8 +1182,10 @@ package body Atree is
-- Copy_Slots --
----------------
- procedure Copy_Slots (From, To : Node_Offset; Num_Slots : Slot_Count) is
- pragma Assert (From /= To);
+ procedure Copy_Dynamic_Slots
+ (From, To : Node_Offset; Num_Slots : Slot_Count)
+ is
+ pragma Assert (if Num_Slots /= 0 then From /= To);
All_Slots : Slots.Table_Type renames
Slots.Table (Slots.First .. Slots.Last);
@@ -1104,21 +1198,21 @@ package body Atree is
begin
Destination_Slots := Source_Slots;
- end Copy_Slots;
+ end Copy_Dynamic_Slots;
procedure Copy_Slots (Source, Destination : Node_Id) is
pragma Debug (Validate_Node (Source));
- pragma Debug (Validate_Node_Write (Destination));
pragma Assert (Source /= Destination);
- S_Size : constant Slot_Count := Size_In_Slots (Source);
+ S_Size : constant Slot_Count := Size_In_Slots_Dynamic (Source);
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- Copy_Slots
- (All_Node_Offsets (Source), All_Node_Offsets (Destination), S_Size);
+ Copy_Dynamic_Slots
+ (Off_F (Source), Off_F (Destination), S_Size);
+ All_Node_Offsets (Destination).Slots := All_Node_Offsets (Source).Slots;
end Copy_Slots;
---------------
@@ -1147,14 +1241,14 @@ package body Atree is
if D_Size < S_Size then
pragma Debug (Zero_Slots (Destination)); -- destroy old slots
- Node_Offsets.Table (Destination) := Alloc_Slots (S_Size);
+ Node_Offsets.Table (Destination).Offset :=
+ Alloc_Slots (S_Size) - N_Head;
end if;
Copy_Slots (Source, Destination);
Set_In_List (Destination, Save_In_List);
Set_Link (Destination, Save_Link);
-
Set_Paren_Count_Of_Copy (Target => Destination, Source => Source);
end Copy_Node;
@@ -1366,7 +1460,7 @@ package body Atree is
(Is_Entity (E1) and then Is_Entity (E2)
and then not In_List (E1) and then not In_List (E2));
- Old_E1 : constant Node_Offset := Node_Offsets.Table (E1);
+ Old_E1 : constant Node_Header := Node_Offsets.Table (E1);
begin
Node_Offsets.Table (E1) := Node_Offsets.Table (E2);
@@ -1399,6 +1493,7 @@ package body Atree is
pragma Assert (not Is_Entity (Source));
Old_Kind : constant Node_Kind := Nkind (Source);
+ pragma Assert (Old_Kind in N_Direct_Name);
New_Kind : constant Node_Kind :=
(case Old_Kind is
when N_Character_Literal => N_Defining_Character_Literal,
@@ -1464,8 +1559,7 @@ package body Atree is
begin
for J in Fields'Range loop
declare
- Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Desc : Field_Descriptor renames Field_Descriptors (Fields (J));
begin
if Desc.Kind in Node_Id_Field | List_Id_Field then
Fix_Parent (Get_Node_Field_Union (Fix_Node, Desc.Offset));
@@ -1615,7 +1709,8 @@ package body Atree is
end if;
return New_Id : constant Node_Id := Alloc_Node_Id do
- Node_Offsets.Table (New_Id) := Alloc_Slots (S_Size);
+ Node_Offsets.Table (New_Id).Offset :=
+ Alloc_Slots (S_Size) - N_Head;
Orig_Nodes.Append (New_Id);
Copy_Slots (Source, New_Id);
@@ -1671,7 +1766,7 @@ package body Atree is
-- source nodes, then reset Current_Error_Node. This is useful
-- if we bomb during parsing to get a error location for the bomb.
- if New_Sloc > No_Location and then Comes_From_Source_Default then
+ if New_Sloc > No_Location and then Comes_From_Source_Default then
Current_Error_Node := New_Id;
end if;
@@ -1760,16 +1855,25 @@ package body Atree is
-- Off_0 --
-----------
- function Off_0 (N : Node_Id) return Node_Offset is
+ function Off_0 (N : Node_Id) return Node_Offset'Base is
pragma Debug (Validate_Node (N));
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- return All_Node_Offsets (N);
+ return All_Node_Offsets (N).Offset;
end Off_0;
-----------
+ -- Off_F --
+ -----------
+
+ function Off_F (N : Node_Id) return Node_Offset is
+ begin
+ return Off_0 (N) + N_Head;
+ end Off_F;
+
+ -----------
-- Off_L --
-----------
@@ -1779,7 +1883,7 @@ package body Atree is
All_Node_Offsets : Node_Offsets.Table_Type renames
Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
begin
- return All_Node_Offsets (N) + Size_In_Slots (N) - 1;
+ return All_Node_Offsets (N).Offset + Size_In_Slots (N) - 1;
end Off_L;
-------------------
@@ -1789,6 +1893,9 @@ package body Atree is
function Original_Node (Node : Node_Id) return Node_Id is
begin
pragma Debug (Validate_Node (Node));
+ if Atree_Statistics_Enabled then
+ Get_Original_Node_Count := Get_Original_Node_Count + 1;
+ end if;
return Orig_Nodes.Table (Node);
end Original_Node;
@@ -1823,7 +1930,7 @@ package body Atree is
function Parent (N : Node_Or_Entity_Id) return Node_Or_Entity_Id is
begin
- pragma Assert (Atree.Present (N));
+ pragma Assert (Present (N));
if Is_List_Member (N) then
return Parent (List_Containing (N));
@@ -1850,28 +1957,6 @@ package body Atree is
Set_Comes_From_Source (NewN, Comes_From_Source (OldN));
end Preserve_Comes_From_Source;
- ----------------------
- -- Print_Atree_Info --
- ----------------------
-
- procedure Print_Atree_Info (N : Node_Or_Entity_Id) is
- function Cast is new Unchecked_Conversion (Slot, Int);
- begin
- Write_Int (Int (Size_In_Slots (N)));
- Write_Str (" slots (");
- Write_Int (Int (Off_0 (N)));
- Write_Str (" .. ");
- Write_Int (Int (Off_L (N)));
- Write_Str ("):");
-
- for Off in Off_0 (N) .. Off_L (N) loop
- Write_Str (" ");
- Write_Int (Cast (Slots.Table (Off)));
- end loop;
-
- Write_Eol;
- end Print_Atree_Info;
-
-------------------
-- Relocate_Node --
-------------------
@@ -1903,6 +1988,22 @@ package body Atree is
Set_Original_Node (New_Node, Original_Node (Source));
end if;
+ -- If we're relocating a subprogram call and we're doing
+ -- unnesting, be sure we make a new copy of any parameter associations
+ -- so that we don't share them.
+
+ if Nkind (Source) in N_Subprogram_Call
+ and then Opt.Unnest_Subprogram_Mode
+ and then Present (Parameter_Associations (Source))
+ then
+ declare
+ New_Assoc : constant List_Id := Parameter_Associations (Source);
+ begin
+ Set_Parent (New_Assoc, New_Node);
+ Set_Parameter_Associations (New_Node, New_Assoc);
+ end;
+ end if;
+
return New_Node;
end Relocate_Node;
@@ -1921,7 +2022,7 @@ package body Atree is
procedure Destroy_New_Node is
begin
Zero_Slots (New_Node);
- Node_Offsets.Table (New_Node) := Field_Offset'Base'Last;
+ Node_Offsets.Table (New_Node).Offset := Field_Offset'Base'Last;
end Destroy_New_Node;
begin
@@ -2020,10 +2121,16 @@ package body Atree is
-- Both the old and new copies of the node will share the same list
-- of aspect specifications if aspect specifications are present.
+ -- Restore the parent link of the aspect list to the old node, which
+ -- is the one linked in the tree.
if Old_Has_Aspects then
- Set_Aspect_Specifications
- (Sav_Node, Aspect_Specifications (Old_Node));
+ declare
+ Aspects : constant List_Id := Aspect_Specifications (Old_Node);
+ begin
+ Set_Aspect_Specifications (Sav_Node, Aspects);
+ Set_Parent (Aspects, Old_Node);
+ end;
end if;
end if;
@@ -2084,6 +2191,9 @@ package body Atree is
procedure Set_Original_Node (N : Node_Id; Val : Node_Id) is
begin
pragma Debug (Validate_Node_Write (N));
+ if Atree_Statistics_Enabled then
+ Set_Original_Node_Count := Set_Original_Node_Count + 1;
+ end if;
Orig_Nodes.Table (N) := Val;
end Set_Original_Node;
@@ -2146,7 +2256,7 @@ package body Atree is
procedure Set_Parent (N : Node_Or_Entity_Id; Val : Node_Or_Entity_Id) is
begin
- pragma Assert (Atree.Present (N));
+ pragma Assert (Present (N));
pragma Assert (not In_List (N));
Set_Link (N, Union_Id (Val));
end Set_Parent;
@@ -2171,11 +2281,15 @@ package body Atree is
Rewriting_Proc := Proc;
end Set_Rewriting_Proc;
+ ----------------------------
+ -- Size_In_Slots_To_Alloc --
+ ----------------------------
+
function Size_In_Slots_To_Alloc (Kind : Node_Kind) return Slot_Count is
begin
return
(if Kind in N_Entity then Einfo.Entities.Max_Entity_Size
- else Sinfo.Nodes.Size (Kind));
+ else Sinfo.Nodes.Size (Kind)) - N_Head;
-- Unfortunately, we don't know the Entity_Kind, so we have to use the
-- max.
end Size_In_Slots_To_Alloc;
@@ -2186,6 +2300,10 @@ package body Atree is
return Size_In_Slots_To_Alloc (Nkind (N));
end Size_In_Slots_To_Alloc;
+ -------------------
+ -- Size_In_Slots --
+ -------------------
+
function Size_In_Slots (N : Node_Or_Entity_Id) return Slot_Count is
begin
pragma Assert (Nkind (N) /= N_Unused_At_Start);
@@ -2194,6 +2312,15 @@ package body Atree is
else Sinfo.Nodes.Size (Nkind (N)));
end Size_In_Slots;
+ ---------------------------
+ -- Size_In_Slots_Dynamic --
+ ---------------------------
+
+ function Size_In_Slots_Dynamic (N : Node_Or_Entity_Id) return Slot_Count is
+ begin
+ return Size_In_Slots (N) - N_Head;
+ end Size_In_Slots_Dynamic;
+
-------------------
-- Traverse_Func --
-------------------
@@ -2361,14 +2488,179 @@ package body Atree is
-- Zero_Slots --
----------------
- procedure Zero_Slots (First, Last : Node_Offset) is
+ procedure Zero_Dynamic_Slots (First, Last : Node_Offset'Base) is
begin
Slots.Table (First .. Last) := (others => 0);
- end Zero_Slots;
+ end Zero_Dynamic_Slots;
+
+ procedure Zero_Header_Slots (N : Node_Or_Entity_Id) is
+ All_Node_Offsets : Node_Offsets.Table_Type renames
+ Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
+ begin
+ All_Node_Offsets (N).Slots := (others => 0);
+ end Zero_Header_Slots;
procedure Zero_Slots (N : Node_Or_Entity_Id) is
begin
- Zero_Slots (Off_0 (N), Off_L (N));
+ Zero_Dynamic_Slots (Off_F (N), Off_L (N));
+ Zero_Header_Slots (N);
end Zero_Slots;
+ ----------------------
+ -- Print_Statistics --
+ ----------------------
+
+ procedure Print_Node_Statistics;
+ procedure Print_Field_Statistics;
+ -- Helpers for Print_Statistics
+
+ procedure Write_Ratio (X : Nat_64; Y : Pos_64);
+ -- Write the value of (X/Y) without using 'Image (approximately)
+
+ procedure Write_Ratio (X : Nat_64; Y : Pos_64) is
+ pragma Assert (X <= Y);
+ Ratio : constant Nat := Nat ((Long_Float (X) / Long_Float (Y)) * 1000.0);
+ begin
+ Write_Str (" (");
+
+ if Ratio = 0 then
+ Write_Str ("0.000");
+ elsif Ratio in 1 .. 9 then
+ Write_Str ("0.00");
+ Write_Int (Ratio);
+ elsif Ratio in 10 .. 99 then
+ Write_Str ("0.0");
+ Write_Int (Ratio);
+ elsif Ratio in 100 .. 999 then
+ Write_Str ("0.");
+ Write_Int (Ratio);
+ else
+ Write_Int (Ratio / 1000);
+ end if;
+
+ Write_Str (")");
+ end Write_Ratio;
+
+ procedure Print_Node_Statistics is
+ subtype Count is Nat_64;
+ Node_Counts : array (Node_Kind) of Count := (others => 0);
+ Entity_Counts : array (Entity_Kind) of Count := (others => 0);
+
+ All_Node_Offsets : Node_Offsets.Table_Type renames
+ Node_Offsets.Table (Node_Offsets.First .. Node_Offsets.Last);
+ begin
+ Write_Int (Int (Node_Offsets.Last));
+ Write_Line (" nodes (including entities)");
+ Write_Int (Int (Slots.Last));
+ Write_Line (" non-header slots");
+
+ for N in All_Node_Offsets'Range loop
+ declare
+ K : constant Node_Kind := Nkind (N);
+
+ begin
+ Node_Counts (K) := Node_Counts (K) + 1;
+
+ if K in N_Entity then
+ Entity_Counts (Ekind (N)) := Entity_Counts (Ekind (N)) + 1;
+ end if;
+ end;
+ end loop;
+
+ for K in Node_Kind loop
+ declare
+ Count : constant Nat_64 := Node_Counts (K);
+ begin
+ Write_Int_64 (Count);
+ Write_Ratio (Count, Int_64 (Node_Offsets.Last));
+ Write_Str (" ");
+ Write_Str (Node_Kind'Image (K));
+ Write_Str (" ");
+ Write_Int (Int (Sinfo.Nodes.Size (K)));
+ Write_Str (" slots");
+ Write_Eol;
+ end;
+ end loop;
+
+ for K in Entity_Kind loop
+ declare
+ Count : constant Nat_64 := Entity_Counts (K);
+ begin
+ Write_Int_64 (Count);
+ Write_Ratio (Count, Int_64 (Node_Offsets.Last));
+ Write_Str (" ");
+ Write_Str (Entity_Kind'Image (K));
+ Write_Str (" ");
+ Write_Int (Int (Einfo.Entities.Size (K)));
+ Write_Str (" slots");
+ Write_Eol;
+ end;
+ end loop;
+ end Print_Node_Statistics;
+
+ procedure Print_Field_Statistics is
+ Total, G_Total, S_Total : Call_Count := 0;
+ begin
+ Write_Int_64 (Get_Original_Node_Count);
+ Write_Str (" + ");
+ Write_Int_64 (Set_Original_Node_Count);
+ Write_Eol;
+ Write_Line (" Original_Node_Count getter and setter calls");
+ Write_Eol;
+
+ Write_Line ("Frequency of field getter and setter calls:");
+
+ for Field in Node_Or_Entity_Field loop
+ G_Total := G_Total + Get_Count (Field);
+ S_Total := S_Total + Set_Count (Field);
+ Total := G_Total + S_Total;
+ end loop;
+
+ -- This assertion helps CodePeer understand that Total cannot be 0 (this
+ -- is true because GNAT does not attempt to compile empty files).
+ pragma Assert (Total > 0);
+
+ Write_Int_64 (Total);
+ Write_Str (" (100%) = ");
+ Write_Int_64 (G_Total);
+ Write_Str (" + ");
+ Write_Int_64 (S_Total);
+ Write_Line (" total getter and setter calls");
+
+ for Field in Node_Or_Entity_Field loop
+ declare
+ G : constant Call_Count := Get_Count (Field);
+ S : constant Call_Count := Set_Count (Field);
+ GS : constant Call_Count := G + S;
+
+ Desc : Field_Descriptor renames Field_Descriptors (Field);
+ Slot : constant Field_Offset :=
+ (Field_Size (Desc.Kind) * Desc.Offset) / Slot_Size;
+
+ begin
+ Write_Int_64 (GS);
+ Write_Ratio (GS, Total);
+ Write_Str (" = ");
+ Write_Int_64 (G);
+ Write_Str (" + ");
+ Write_Int_64 (S);
+ Write_Str (" ");
+ Write_Str (Node_Or_Entity_Field'Image (Field));
+ Write_Str (" in slot ");
+ Write_Int (Int (Slot));
+ Write_Str (" size ");
+ Write_Int (Int (Field_Size (Desc.Kind)));
+ Write_Eol;
+ end;
+ end loop;
+ end Print_Field_Statistics;
+
+ procedure Print_Statistics is
+ begin
+ Write_Eol;
+ Write_Eol;
+ Print_Node_Statistics;
+ Print_Field_Statistics;
+ end Print_Statistics;
+
end Atree;
diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads
index 6fb5aa6..2f3ca40 100644
--- a/gcc/ada/atree.ads
+++ b/gcc/ada/atree.ads
@@ -48,6 +48,7 @@ with Alloc;
with Sinfo.Nodes; use Sinfo.Nodes;
with Einfo.Entities; use Einfo.Entities;
with Types; use Types;
+with Seinfo; use Seinfo;
with System; use System;
with Table;
with Unchecked_Conversion;
@@ -501,6 +502,7 @@ package Atree is
-- the contents of these two nodes fixing up the parent pointers of the
-- replaced node (we do not attempt to preserve parent pointers for the
-- original node). Neither Old_Node nor New_Node can be extended nodes.
+ -- ??? The above explanation is incorrect, instead Copy_Node is called.
--
-- Note: New_Node may not contain references to Old_Node, for example as
-- descendants, since the rewrite would make such references invalid. If
@@ -565,10 +567,9 @@ package Atree is
type Entity_Field_Set is array (Entity_Field) of Boolean with Pack;
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Field);
- procedure Reinit_Field_To_Zero (N : Node_Id; Field : Entity_Field);
+ procedure Reinit_Field_To_Zero (N : Node_Id; Field : Node_Or_Entity_Field);
-- When a node is created, all fields are initialized to zero, even if zero
- -- is not a valid value of the field type. These procedures put the field
+ -- is not a valid value of the field type. This procedure puts the field
-- back to its initial zero value. Note that you can't just do something
-- like Set_Some_Field (N, 0), if Some_Field is of (say) type Uintp,
-- because Uintp is a subrange that does not include 0.
@@ -582,9 +583,7 @@ package Atree is
-- this.
function Field_Is_Initial_Zero
- (N : Node_Id; Field : Node_Field) return Boolean;
- function Field_Is_Initial_Zero
- (N : Entity_Id; Field : Entity_Field) return Boolean;
+ (N : Node_Id; Field : Node_Or_Entity_Field) return Boolean;
-- True if the field value is the initial zero value
procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) with Inline;
@@ -610,10 +609,6 @@ package Atree is
-- always the same; for example we change from E_Void, to E_Variable, to
-- E_Void, to E_Constant.
- procedure Print_Atree_Info (N : Node_Or_Entity_Id);
- -- Called from Treepr to print out information about N that is private to
- -- Atree.
-
-----------------------------
-- Private Part Subpackage --
-----------------------------
@@ -638,7 +633,7 @@ package Atree is
-- The nodes of the tree are stored in two tables (i.e. growable
-- arrays).
- -- A Node_Id points to an element of Nodes, which contains a
+ -- A Node_Id points to an element of Node_Offsets, which contains a
-- Field_Offset that points to an element of Slots. Each slot can
-- contain a single 32-bit field, or multiple smaller fields.
-- An n-bit field is aligned on an n-bit boundary. The size of a node is
@@ -648,12 +643,40 @@ package Atree is
-- The reason for the extra level of indirection is that Copy_Node,
-- Exchange_Entities, and Rewrite all assume that nodes can be modified
-- in place.
+ --
+ -- As an optimization, we store a few slots directly in the Node_Offsets
+ -- table (see type Node_Header) rather than requiring the extra level of
+ -- indirection for accessing those slots. N_Head is the number of slots
+ -- stored in the Node_Header. N_Head can be adjusted by modifying
+ -- Gen_IL.Gen. If N_Head is (say) 3, then a node containing 7 slots will
+ -- have slots 0..2 in the header, and 3..6 stored indirect in the Slots
+ -- table. We use zero-origin addressing, so the Offset into the Slots
+ -- table will point 3 slots before slot 3.
+
+ pragma Assert (N_Head <= Min_Node_Size);
+ pragma Assert (N_Head <= Min_Entity_Size);
- subtype Node_Offset is Field_Offset'Base
- range 1 .. Field_Offset'Base'Last;
+ Slot_Size : constant := 32;
+ type Slot is mod 2**Slot_Size;
+ for Slot'Size use Slot_Size;
+
+ -- The type Slot is defined in Types as a 32-bit modular integer. It
+ -- is logically split into the appropriate numbers of components of
+ -- appropriate size, but this splitting is not explicit because packed
+ -- arrays cannot be properly interfaced in C/C++ and packed records are
+ -- way too slow.
+
+ type Node_Header_Slots is
+ array (Field_Offset range 0 .. N_Head - 1) of Slot;
+ type Node_Header is record
+ Slots : Node_Header_Slots;
+ Offset : Node_Offset'Base;
+ end record;
+ pragma Assert (Node_Header'Size = (N_Head + 1) * Slot_Size);
+ pragma Assert (Node_Header'Size = 16 * 8);
package Node_Offsets is new Table.Table
- (Table_Component_Type => Node_Offset,
+ (Table_Component_Type => Node_Header,
Table_Index_Type => Node_Id'Base,
Table_Low_Bound => First_Node_Id,
Table_Initial => Alloc.Node_Offsets_Initial,
@@ -667,15 +690,6 @@ package Atree is
-- Short names for use in gdb, not used in real code. Note that gdb
-- can't find Node_Offsets.Table without a full expanded name.
- -- We define the type Slot as a 32-bit modular integer. It is logically
- -- split into the appropriate numbers of components of appropriate size,
- -- but this splitting is not explicit because packed arrays cannot be
- -- properly interfaced in C/C++ and packed records are way too slow.
-
- Slot_Size : constant := 32;
- type Slot is mod 2**Slot_Size;
- for Slot'Size use Slot_Size;
-
function Shift_Left (S : Slot; V : Natural) return Slot;
pragma Import (Intrinsic, Shift_Left);
@@ -855,6 +869,22 @@ package Atree is
function Is_Valid_Node (U : Union_Id) return Boolean;
-- True if U is within the range of Node_Offsets
+ procedure Print_Atree_Info (N : Node_Or_Entity_Id);
+ -- Called from Treepr to print out information about N that is private
+ -- to Atree.
+
end Atree_Private_Part;
+ -- Statistics:
+
+ subtype Call_Count is Nat_64;
+ Get_Count, Set_Count : array (Node_Or_Entity_Field) of Call_Count :=
+ (others => 0);
+ -- Number of calls to each getter and setter. See documentaton for
+ -- -gnatd.A.
+
+ Get_Original_Node_Count, Set_Original_Node_Count : Call_Count := 0;
+
+ procedure Print_Statistics;
+
end Atree;
diff --git a/gcc/ada/atree.h b/gcc/ada/atree.h
index 08b791c..7fb3bcb 100644
--- a/gcc/ada/atree.h
+++ b/gcc/ada/atree.h
@@ -65,77 +65,6 @@ Present (Tree_Id N)
#define Current_Error_Node atree__current_error_node
extern Node_Id Current_Error_Node;
-/* The following code corresponds to the Get_n_Bit_Field functions (for
- various n) in package Atree. The low-level getters in sinfo.h call
- these even-lower-level getters. */
-
-extern Field_Offset *Node_Offsets_Ptr;
-extern any_slot *Slots_Ptr;
-
-INLINE unsigned int Get_1_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_2_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_4_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_8_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_32_Bit_Field (Node_Id, Field_Offset);
-INLINE unsigned int Get_32_Bit_Field_With_Default (Node_Id, Field_Offset,
- unsigned int);
-INLINE unsigned int Get_Valid_32_Bit_Field (Node_Id, Field_Offset);
-
-INLINE unsigned int
-Get_1_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 1;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 1;
-}
-
-INLINE unsigned int
-Get_2_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 2;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 3;
-}
-
-INLINE unsigned int
-Get_4_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 4;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 15;
-}
-
-INLINE unsigned int
-Get_8_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- const Field_Offset L = Slot_Size / 8;
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
- return (slot >> (Offset % L) * (Slot_Size / L)) & 255;
-}
-
-INLINE unsigned int
-Get_32_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- return slot;
-}
-
-INLINE unsigned int
-Get_32_Bit_Field_With_Default (Node_Id N, Field_Offset Offset,
- unsigned int Default_Value)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- return slot == Empty ? Default_Value : slot;
-}
-
-INLINE unsigned int
-Get_Valid_32_Bit_Field (Node_Id N, Field_Offset Offset)
-{
- any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset);
- gcc_assert (slot != Empty);
- return slot;
-}
-
#ifdef __cplusplus
}
#endif
diff --git a/gcc/ada/back_end.adb b/gcc/ada/back_end.adb
index 42d837d..abbd5ed 100644
--- a/gcc/ada/back_end.adb
+++ b/gcc/ada/back_end.adb
@@ -25,23 +25,24 @@
-- This is the version of the Back_End package for GCC back ends
-with Atree; use Atree;
-with Debug; use Debug;
-with Elists; use Elists;
-with Errout; use Errout;
-with Lib; use Lib;
-with Osint; use Osint;
-with Opt; use Opt;
-with Osint.C; use Osint.C;
-with Namet; use Namet;
-with Nlists; use Nlists;
-with Stand; use Stand;
-with Sinput; use Sinput;
-with Stringt; use Stringt;
-with Switch; use Switch;
-with Switch.C; use Switch.C;
-with System; use System;
-with Types; use Types;
+with Atree; use Atree;
+with Backend_Utils; use Backend_Utils;
+with Debug; use Debug;
+with Elists; use Elists;
+with Errout; use Errout;
+with Lib; use Lib;
+with Osint; use Osint;
+with Opt; use Opt;
+with Osint.C; use Osint.C;
+with Namet; use Namet;
+with Nlists; use Nlists;
+with Stand; use Stand;
+with Sinput; use Sinput;
+with Stringt; use Stringt;
+with Switch; use Switch;
+with Switch.C; use Switch.C;
+with System; use System;
+with Types; use Types;
with System.OS_Lib; use System.OS_Lib;
@@ -266,52 +267,20 @@ package body Back_End is
-- specific switches that the Ada front-end knows about.
else
- Store_Compilation_Switch (Switch_Chars);
-
- -- For gcc back ends, -fno-inline disables Inline pragmas only,
- -- not Inline_Always to remain consistent with the always_inline
- -- attribute behavior.
-
- if Switch_Chars (First .. Last) = "fno-inline" then
- Opt.Disable_FE_Inline := True;
-
- -- Back end switch -fpreserve-control-flow also sets the front end
- -- flag that inhibits improper control flow transformations.
-
- elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then
- Opt.Suppress_Control_Flow_Optimizations := True;
-
- -- Back end switch -fdiagnostics-format=json tells the frontend to
- -- output its error and warning messages in the same format GCC
- -- uses when passed -fdiagnostics-format=json.
-
- elsif Switch_Chars (First .. Last) = "fdiagnostics-format=json"
- then
- Opt.JSON_Output := True;
-
- -- Back end switch -fdump-scos, which exists primarily for C, is
- -- also accepted for Ada as a synonym of -gnateS.
-
- elsif Switch_Chars (First .. Last) = "fdump-scos" then
- Opt.Generate_SCO := True;
- Opt.Generate_SCO_Instance_Table := True;
-
- elsif Switch_Chars (First) = 'g' then
- Debugger_Level := 2;
-
- if First < Last then
- case Switch_Chars (First + 1) is
- when '0' =>
- Debugger_Level := 0;
- when '1' =>
- Debugger_Level := 1;
- when '2' =>
- Debugger_Level := 2;
- when '3' =>
- Debugger_Level := 3;
- when others =>
- null;
- end case;
+
+ if not Scan_Common_Back_End_Switch (Switch_Chars) then
+
+ -- Store compilation switch, as Scan_Common_Back_End_Switch
+ -- only stores switches it recognizes.
+
+ Store_Compilation_Switch (Switch_Chars);
+
+ -- Back end switch -fdump-scos, which exists primarily for C,
+ -- is also accepted for Ada as a synonym of -gnateS.
+
+ if Switch_Chars (First .. Last) = "fdump-scos" then
+ Opt.Generate_SCO := True;
+ Opt.Generate_SCO_Instance_Table := True;
end if;
end if;
end if;
diff --git a/gcc/ada/backend_utils.adb b/gcc/ada/backend_utils.adb
new file mode 100644
index 0000000..6f492fd
--- /dev/null
+++ b/gcc/ada/backend_utils.adb
@@ -0,0 +1,96 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B A C K E N D _ U T I L S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2021-2021, 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. --
+-- --
+------------------------------------------------------------------------------
+
+with Lib;
+with Opt; use Opt;
+with Switch; use Switch;
+
+package body Backend_Utils is
+
+ ---------------------------------
+ -- Scan_Common_Back_End_Switch --
+ ---------------------------------
+
+ function Scan_Common_Back_End_Switch (Switch_Chars : String) return Boolean
+ is
+ First : constant Positive := Switch_Chars'First + 1;
+ Last : constant Natural := Switch_Last (Switch_Chars);
+ begin
+
+ -- Recognize -gxxx switches
+
+ if Switch_Chars (First) = 'g' then
+ Debugger_Level := 2;
+
+ if First < Last then
+ case Switch_Chars (First + 1) is
+ when '0' =>
+ Debugger_Level := 0;
+ when '1' =>
+ Debugger_Level := 1;
+ when '2' =>
+ Debugger_Level := 2;
+ when '3' =>
+ Debugger_Level := 3;
+ when others =>
+ null;
+ end case;
+ end if;
+
+ -- Back end switch -fdiagnostics-format=json tells the frontend to
+ -- output its error and warning messages in the same format GCC
+ -- uses when passed -fdiagnostics-format=json.
+
+ elsif Switch_Chars (First .. Last) = "fdiagnostics-format=json" then
+ Opt.JSON_Output := True;
+
+ -- Back-end switch -fno-inline also sets the front end flags to entirely
+ -- inhibit all inlining. So we store it and set the appropriate
+ -- flags.
+ -- For gcc back ends, -fno-inline disables Inline pragmas only,
+ -- not Inline_Always to remain consistent with the always_inline
+ -- attribute behavior.
+
+ elsif Switch_Chars (First .. Last) = "fno-inline" then
+ Opt.Disable_FE_Inline := True;
+
+ -- Back end switch -fpreserve-control-flow also sets the front end
+ -- flag that inhibits improper control flow transformations.
+
+ elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then
+ Opt.Suppress_Control_Flow_Optimizations := True;
+
+ elsif Switch_Chars (First .. Last) = "S" then
+ Generate_Asm := True;
+
+ else
+ return False;
+ end if;
+
+ Lib.Store_Compilation_Switch (Switch_Chars);
+ return True;
+ end Scan_Common_Back_End_Switch;
+
+end Backend_Utils;
diff --git a/gcc/ada/backend_utils.ads b/gcc/ada/backend_utils.ads
new file mode 100644
index 0000000..71321ef
--- /dev/null
+++ b/gcc/ada/backend_utils.ads
@@ -0,0 +1,36 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B A C K E N D _ U T I L S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2021-2021, 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Procedures and functions used by both the Adabkend and Back_End packages.
+
+package Backend_Utils is
+
+ function Scan_Common_Back_End_Switch (Switch_Chars : String) return Boolean;
+ -- Scan back-end switches which are common to all back-ends and have an
+ -- effect in the front-end. Call Store_Compilation_Switch and return True
+ -- if Switch_Chars is recognized as a common back end switch. Return False
+ -- otherwise.
+
+end Backend_Utils;
diff --git a/gcc/ada/bcheck.adb b/gcc/ada/bcheck.adb
index 804e2fd..38bf2c2 100644
--- a/gcc/ada/bcheck.adb
+++ b/gcc/ada/bcheck.adb
@@ -29,6 +29,7 @@ with Binderr; use Binderr;
with Butil; use Butil;
with Casing; use Casing;
with Fname; use Fname;
+with Gnatvsn;
with Namet; use Namet;
with Opt; use Opt;
with Osint;
@@ -1324,11 +1325,136 @@ package body Bcheck is
or else ALIs.Table (A).Ver (1 .. VL) /=
ALIs.Table (ALIs.First).Ver (1 .. VL)
then
- Error_Msg_File_1 := ALIs.Table (A).Sfile;
- Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
+ -- Version mismatch found; generate error message.
- Consistency_Error_Msg
- ("{ and { compiled with different GNAT versions");
+ declare
+ use Gnatvsn;
+
+ Prefix : constant String :=
+ Verbose_Library_Version
+ (1 .. Verbose_Library_Version'Length
+ - Library_Version'Length);
+
+ type ALI_Version is record
+ Primary, Secondary : Int range -1 .. Int'Last;
+ end record;
+
+ No_Version : constant ALI_Version := (-1, -1);
+
+ function Remove_Prefix (S : String) return String is
+ (S (S'First + Prefix'Length .. S'Last));
+
+ function Extract_Version (S : String) return ALI_Version;
+ -- Attempts to extract and return a pair of nonnegative library
+ -- version numbers from the given string; if unsuccessful,
+ -- then returns No_Version.
+
+ ---------------------
+ -- Extract_Version --
+ ---------------------
+
+ function Extract_Version (S : String) return ALI_Version is
+ pragma Assert (S'First = 1);
+
+ function Int_Value (Img : String) return Int;
+ -- Using Int'Value leads to complications in
+ -- building the binder, so DIY.
+
+ ---------------
+ -- Int_Value --
+ ---------------
+
+ function Int_Value (Img : String) return Int is
+ Result : Nat := 0;
+ begin
+ if Img'Length in 1 .. 9
+ and then (for all C of Img => C in '0' .. '9')
+ then
+ for C of Img loop
+ Result := (10 * Result) +
+ (Character'Pos (C) - Character'Pos ('0'));
+ end loop;
+ return Result;
+ else
+ return -1;
+ end if;
+ end Int_Value;
+
+ begin
+ if S'Length > Prefix'Length
+ and then S (1 .. Prefix'Length) = Prefix
+ then
+ declare
+ Suffix : constant String := Remove_Prefix (S);
+ Dot_Found : Boolean := False;
+ Primary, Secondary : Int;
+ begin
+ for Dot_Index in Suffix'Range loop
+ if Suffix (Dot_Index) = '.' then
+ Dot_Found := True;
+ Primary :=
+ Int_Value (Suffix (Suffix'First
+ .. Dot_Index - 1));
+ Secondary :=
+ Int_Value (Suffix (Dot_Index + 1
+ .. Suffix'Last));
+ exit;
+ end if;
+ end loop;
+
+ if not Dot_Found then
+ Primary := Int_Value (Suffix);
+ Secondary := 0;
+ end if;
+
+ if (Primary /= -1) and (Secondary /= -1) then
+ return (Primary => Primary,
+ Secondary => Secondary);
+ end if;
+ end;
+ end if;
+ return No_Version;
+ end Extract_Version;
+
+ -- Local constants
+
+ V1_Text : constant String :=
+ ALIs.Table (A).Ver (1 .. ALIs.Table (A).Ver_Len);
+ V2_Text : constant String :=
+ ALIs.Table (ALIs.First).Ver (1 .. VL);
+ V1 : constant ALI_Version := Extract_Version (V1_Text);
+ V2 : constant ALI_Version := Extract_Version (V2_Text);
+
+ Include_Version_Numbers_In_Message : constant Boolean :=
+ (V1 /= V2) and (V1 /= No_Version) and (V2 /= No_Version);
+ begin
+ Error_Msg_File_1 := ALIs.Table (A).Sfile;
+ Error_Msg_File_2 := ALIs.Table (ALIs.First).Sfile;
+
+ if Include_Version_Numbers_In_Message then
+ if V1.Secondary = V2.Secondary then
+ -- Excluding equal secondary values from error
+ -- message text matters for generating reproducible
+ -- regression test outputs.
+
+ Error_Msg_Nat_1 := V1.Primary;
+ Error_Msg_Nat_2 := V2.Primary;
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions"
+ & ", v# and v#");
+ else
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions"
+ & ", v"
+ & Remove_Prefix (V1_Text)
+ & " and v"
+ & Remove_Prefix (V2_Text));
+ end if;
+ else
+ Consistency_Error_Msg
+ ("{ and { compiled with different GNAT versions");
+ end if;
+ end;
end if;
end loop;
end Check_Versions;
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index 0014f6a..049038b 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -588,6 +588,27 @@ package body Bindgen is
WBI ("");
end if;
+ -- Import the default stack object if a size has been provided to the
+ -- binder.
+
+ if Opt.Default_Stack_Size /= Opt.No_Stack_Size then
+ WBI (" Default_Stack_Size : Integer;");
+ WBI (" pragma Import (C, Default_Stack_Size, " &
+ """__gl_default_stack_size"");");
+ end if;
+
+ -- Initialize stack limit variable of the environment task if the
+ -- stack check method is stack limit and stack check is enabled.
+
+ if Stack_Check_Limits_On_Target
+ and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
+ then
+ WBI ("");
+ WBI (" procedure Initialize_Stack_Limit;");
+ WBI (" pragma Import (C, Initialize_Stack_Limit, " &
+ """__gnat_initialize_stack_limit"");");
+ end if;
+
if System_Secondary_Stack_Package_In_Closure then
-- System.Secondary_Stack is in the closure of the program
-- because the program uses the secondary stack or the restricted
@@ -619,6 +640,15 @@ package body Bindgen is
WBI (" begin");
+ -- Set the default stack size if provided to the binder
+
+ if Opt.Default_Stack_Size /= Opt.No_Stack_Size then
+ Set_String (" Default_Stack_Size := ");
+ Set_Int (Default_Stack_Size);
+ Set_String (";");
+ Write_Statement_Buffer;
+ end if;
+
if Main_Priority /= No_Main_Priority then
Set_String (" Main_Priority := ");
Set_Int (Main_Priority);
@@ -643,6 +673,7 @@ package body Bindgen is
end if;
if Main_Priority = No_Main_Priority
+ and then Opt.Default_Stack_Size = Opt.No_Stack_Size
and then Main_CPU = No_Main_CPU
and then not System_Tasking_Restricted_Stages_Used
then
diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb
index 011b0f4..0989981 100644
--- a/gcc/ada/bindo-graphs.adb
+++ b/gcc/ada/bindo-graphs.adb
@@ -4903,11 +4903,10 @@ package body Bindo.Graphs is
procedure Set_Is_Existing_Source_Target_Relation
(G : Invocation_Graph;
- Rel : Source_Target_Relation;
- Val : Boolean := True);
+ Rel : Source_Target_Relation);
pragma Inline (Set_Is_Existing_Source_Target_Relation);
-- Mark a source vertex and a target vertex described by relation Rel as
- -- already related in invocation graph G depending on value Val.
+ -- already related in invocation graph G.
procedure Set_IGE_Attributes
(G : Invocation_Graph;
@@ -5636,19 +5635,14 @@ package body Bindo.Graphs is
procedure Set_Is_Existing_Source_Target_Relation
(G : Invocation_Graph;
- Rel : Source_Target_Relation;
- Val : Boolean := True)
+ Rel : Source_Target_Relation)
is
begin
pragma Assert (Present (G));
pragma Assert (Present (Rel.Source));
pragma Assert (Present (Rel.Target));
- if Val then
- Relation_Sets.Insert (G.Relations, Rel);
- else
- Relation_Sets.Delete (G.Relations, Rel);
- end if;
+ Relation_Sets.Insert (G.Relations, Rel);
end Set_Is_Existing_Source_Target_Relation;
------------------------
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index cebeac5..a58a495 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -3552,9 +3552,12 @@ package body Checks is
-- Apply_Subscript_Validity_Checks --
-------------------------------------
- procedure Apply_Subscript_Validity_Checks (Expr : Node_Id) is
+ procedure Apply_Subscript_Validity_Checks
+ (Expr : Node_Id;
+ No_Check_Needed : Dimension_Set := Empty_Dimension_Set) is
Sub : Node_Id;
+ Dimension : Pos := 1;
begin
pragma Assert (Nkind (Expr) = N_Indexed_Component);
@@ -3568,11 +3571,16 @@ package body Checks is
-- for the subscript, and that convert will do the necessary validity
-- check.
- Ensure_Valid (Sub, Holes_OK => True);
+ if (No_Check_Needed = Empty_Dimension_Set)
+ or else not No_Check_Needed.Elements (Dimension)
+ then
+ Ensure_Valid (Sub, Holes_OK => True);
+ end if;
-- Move to next subscript
Next (Sub);
+ Dimension := Dimension + 1;
end loop;
end Apply_Subscript_Validity_Checks;
@@ -6892,6 +6900,7 @@ package body Checks is
elsif Is_Known_Valid (Typ) then
if Is_Entity_Name (Expr)
and then Ekind (Entity (Expr)) = E_Variable
+ and then Known_Esize (Entity (Expr))
and then Esize (Entity (Expr)) > Esize (Typ)
then
return False;
@@ -7232,7 +7241,10 @@ package body Checks is
-- Generate_Index_Checks --
---------------------------
- procedure Generate_Index_Checks (N : Node_Id) is
+ procedure Generate_Index_Checks
+ (N : Node_Id;
+ Checks_Generated : out Dimension_Set)
+ is
function Entity_Of_Prefix return Entity_Id;
-- Returns the entity of the prefix of N (or Empty if not found)
@@ -7267,6 +7279,8 @@ package body Checks is
-- Start of processing for Generate_Index_Checks
begin
+ Checks_Generated.Elements := (others => False);
+
-- Ignore call if the prefix is not an array since we have a serious
-- error in the sources. Ignore it also if index checks are suppressed
-- for array object or type.
@@ -7329,6 +7343,8 @@ package body Checks is
Prefix => New_Occurrence_Of (Etype (A), Loc),
Attribute_Name => Name_Range)),
Reason => CE_Index_Check_Failed));
+
+ Checks_Generated.Elements (1) := True;
end if;
-- General case
@@ -7415,6 +7431,8 @@ package body Checks is
Duplicate_Subexpr_Move_Checks (Sub)),
Right_Opnd => Range_N),
Reason => CE_Index_Check_Failed));
+
+ Checks_Generated.Elements (Ind) := True;
end if;
Next_Index (A_Idx);
@@ -9059,7 +9077,7 @@ package body Checks is
function In_Result_Range return Boolean is
begin
- if Lo = No_Uint or else Hi = No_Uint then
+ if No (Lo) or else No (Hi) then
return False;
elsif Is_OK_Static_Subtype (Etype (N)) then
@@ -9080,7 +9098,7 @@ package body Checks is
procedure Max (A : in out Uint; B : Uint) is
begin
- if A = No_Uint or else B > A then
+ if No (A) or else B > A then
A := B;
end if;
end Max;
@@ -9091,7 +9109,7 @@ package body Checks is
procedure Min (A : in out Uint; B : Uint) is
begin
- if A = No_Uint or else B < A then
+ if No (A) or else B < A then
A := B;
end if;
end Min;
@@ -9197,14 +9215,14 @@ package body Checks is
Minimize_Eliminate_Overflows
(Then_DE, Lo, Hi, Top_Level => False);
- if Lo = No_Uint then
+ if No (Lo) then
Bignum_Operands := True;
end if;
Minimize_Eliminate_Overflows
(Else_DE, Rlo, Rhi, Top_Level => False);
- if Rlo = No_Uint then
+ if No (Rlo) then
Bignum_Operands := True;
else
Long_Long_Integer_Operands :=
@@ -9279,7 +9297,7 @@ package body Checks is
Minimize_Eliminate_Overflows
(Aexp, Lo, Hi, Top_Level => False);
- if Lo = No_Uint then
+ if No (Lo) then
Bignum_Operands := True;
elsif Etype (Aexp) = LLIB then
Long_Long_Integer_Operands := True;
@@ -9368,7 +9386,7 @@ package body Checks is
-- numbers at compile time for very little gain (the number of cases
-- in which we could slip back from bignum mode is small).
- if Rlo = No_Uint or else (Binary and then Llo = No_Uint) then
+ if No (Rlo) or else (Binary and then No (Llo)) then
Lo := No_Uint;
Hi := No_Uint;
Bignum_Operands := True;
@@ -9441,7 +9459,7 @@ package body Checks is
-- 0 .. 1, but the cases are rare and it is not worth the effort.
-- Failing to do this switching back is only an efficiency issue.
- elsif Lo = No_Uint or else Lo < LLLo or else Hi > LLHi then
+ elsif No (Lo) or else Lo < LLLo or else Hi > LLHi then
-- OK, we are definitely outside the range of Long_Long_Integer. The
-- question is whether to move to Bignum mode, or stay in the domain
@@ -10382,7 +10400,7 @@ package body Checks is
Exptyp : Entity_Id;
Cond : Node_Id := Empty;
Do_Access : Boolean := False;
- Wnode : Node_Id := Warn_Node;
+ Wnode : Node_Id := Warn_Node;
Ret_Result : Check_Result := (Empty, Empty);
Num_Checks : Natural := 0;
@@ -11306,7 +11324,7 @@ package body Checks is
renames Alignment_Warnings.Table (J);
begin
if Known_Alignment (AWR.E)
- and then ((AWR.A /= No_Uint
+ and then ((Present (AWR.A)
and then AWR.A mod Alignment (AWR.E) = 0)
or else (Present (AWR.P)
and then Has_Compatible_Alignment
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 3b97bd0..6df752f 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -44,6 +44,14 @@ with Urealp; use Urealp;
package Checks is
+ type Bit_Vector is array (Pos range <>) of Boolean;
+ type Dimension_Set (Dimensions : Nat) is
+ record
+ Elements : Bit_Vector (1 .. Dimensions);
+ end record;
+ Empty_Dimension_Set : constant Dimension_Set
+ := (Dimensions => 0, Elements => (others => <>));
+
procedure Initialize;
-- Called for each new main source program, to initialize internal
-- variables used in the package body of the Checks unit.
@@ -721,11 +729,16 @@ package Checks is
-- Do_Range_Check flag, and if it is set, this routine is called, which
-- turns the flag off in code-generation mode.
- procedure Generate_Index_Checks (N : Node_Id);
+ procedure Generate_Index_Checks
+ (N : Node_Id;
+ Checks_Generated : out Dimension_Set);
-- This procedure is called to generate index checks on the subscripts for
-- the indexed component node N. Each subscript expression is examined, and
-- if the Do_Range_Check flag is set, an appropriate index check is
-- generated and the flag is reset.
+ -- The out-mode parameter Checks_Generated indicates the dimensions for
+ -- which checks were generated. Checks_Generated.Dimensions must match
+ -- the number of dimensions of the array type.
-- Similarly, we set the flag Do_Discriminant_Check in the semantic
-- analysis to indicate that a discriminant check is required for selected
@@ -858,10 +871,14 @@ package Checks is
-- The following procedures are used in handling validity checking
- procedure Apply_Subscript_Validity_Checks (Expr : Node_Id);
+ procedure Apply_Subscript_Validity_Checks
+ (Expr : Node_Id;
+ No_Check_Needed : Dimension_Set := Empty_Dimension_Set);
-- Expr is the node for an indexed component. If validity checking and
- -- range checking are enabled, all subscripts for this indexed component
- -- are checked for validity.
+ -- range checking are enabled, each subscript for this indexed component
+ -- whose dimension does not belong to the No_Check_Needed set is checked
+ -- for validity. No_Check_Needed.Dimensions must match the number of
+ -- dimensions of the array type or be zero.
procedure Check_Valid_Lvalue_Subscripts (Expr : Node_Id);
-- Expr is a lvalue, i.e. an expression representing the target of an
diff --git a/gcc/ada/clean.adb b/gcc/ada/clean.adb
index 03ca7a4..830a994 100644
--- a/gcc/ada/clean.adb
+++ b/gcc/ada/clean.adb
@@ -217,7 +217,7 @@ package body Clean is
if Text /= null then
The_ALI :=
- Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
+ Scan_ALI (Lib_File, Text, Err => True);
Free (Text);
-- If no error was produced while loading this ALI file,
diff --git a/gcc/ada/comperr.adb b/gcc/ada/comperr.adb
index 064fae0..e009c58 100644
--- a/gcc/ada/comperr.adb
+++ b/gcc/ada/comperr.adb
@@ -478,6 +478,7 @@ package body Comperr is
when N_Package_Declaration
| N_Subprogram_Body
| N_Subprogram_Declaration
+ | N_Subprogram_Renaming_Declaration
=>
Unit_Name := Defining_Unit_Name (Specification (Main));
@@ -489,10 +490,10 @@ package body Comperr is
=>
Unit_Name := Defining_Unit_Name (Main);
- -- No SCIL file generated for generic package declarations
+ -- No SCIL file generated for generic unit declarations
- when N_Generic_Package_Declaration
- | N_Generic_Package_Renaming_Declaration
+ when N_Generic_Declaration
+ | N_Generic_Renaming_Declaration
=>
return;
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index d096cbb..2726486 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -47,6 +47,8 @@ with Sem_Ch12; use Sem_Ch12;
with Sem_Ch13; use Sem_Ch13;
with Sem_Disp; use Sem_Disp;
with Sem_Prag; use Sem_Prag;
+with Sem_Res; use Sem_Res;
+with Sem_Type; use Sem_Type;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
@@ -66,6 +68,16 @@ package body Contracts is
--
-- Part_Of
+ procedure Check_Class_Condition
+ (Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Is_Precondition : Boolean);
+ -- Perform checking of class-wide pre/postcondition Cond inherited by Subp
+ -- from Par_Subp. Is_Precondition enables check specific for preconditions.
+ -- In SPARK_Mode, an inherited operation that is not overridden but has
+ -- inherited modified conditions pre/postconditions is illegal.
+
procedure Check_Type_Or_Object_External_Properties
(Type_Or_Obj_Id : Entity_Id);
-- Perform checking of external properties pragmas that is common to both
@@ -77,6 +89,12 @@ package body Contracts is
-- well as Contract_Cases, Subprogram_Variant, invariants and predicates.
-- Body_Id denotes the entity of the subprogram body.
+ procedure Set_Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id;
+ Cond : Node_Id);
+ -- Set the class-wide Kind condition of Subp
+
-----------------------
-- Add_Contract_Item --
-----------------------
@@ -144,7 +162,13 @@ package body Contracts is
-- Part_Of
if Ekind (Id) = E_Constant then
- if Prag_Nam = Name_Part_Of then
+ if Prag_Nam in Name_Async_Readers
+ | Name_Async_Writers
+ | Name_Effective_Reads
+ | Name_Effective_Writes
+ | Name_No_Caching
+ | Name_Part_Of
+ then
Add_Classification;
-- The pragma is not a proper contract item
@@ -380,23 +404,7 @@ package body Contracts is
| N_Generic_Subprogram_Declaration
| N_Subprogram_Declaration
then
- declare
- Subp_Id : constant Entity_Id := Defining_Entity (Decl);
-
- begin
- Analyze_Entry_Or_Subprogram_Contract (Subp_Id);
-
- -- If analysis of a class-wide pre/postcondition indicates
- -- that a class-wide clone is needed, analyze its declaration
- -- now. Its body is created when the body of the original
- -- operation is analyzed (and rewritten).
-
- if Is_Subprogram (Subp_Id)
- and then Present (Class_Wide_Clone (Subp_Id))
- then
- Analyze (Unit_Declaration_Node (Class_Wide_Clone (Subp_Id)));
- end if;
- end;
+ Analyze_Entry_Or_Subprogram_Contract (Defining_Entity (Decl));
-- Entry or subprogram bodies
@@ -778,25 +786,9 @@ package body Contracts is
procedure Check_Type_Or_Object_External_Properties
(Type_Or_Obj_Id : Entity_Id)
is
- function Decl_Kind (Is_Type : Boolean;
- Object_Kind : String) return String;
- -- Returns "type" or Object_Kind, depending on Is_Type
-
- ---------------
- -- Decl_Kind --
- ---------------
-
- function Decl_Kind (Is_Type : Boolean;
- Object_Kind : String) return String is
- begin
- if Is_Type then
- return "type";
- else
- return Object_Kind;
- end if;
- end Decl_Kind;
-
Is_Type_Id : constant Boolean := Is_Type (Type_Or_Obj_Id);
+ Decl_Kind : constant String :=
+ (if Is_Type_Id then "type" else "object");
-- Local variables
@@ -923,8 +915,7 @@ package body Contracts is
if not Is_Library_Level_Entity (Type_Or_Obj_Id) then
Error_Msg_N
("effectively volatile "
- & Decl_Kind (Is_Type => Is_Type_Id,
- Object_Kind => "variable")
+ & Decl_Kind
& " & must be declared at library level "
& "(SPARK RM 7.1.3(3))", Type_Or_Obj_Id);
@@ -935,10 +926,7 @@ package body Contracts is
and then not Is_Protected_Type (Obj_Typ)
then
Error_Msg_N
- ("discriminated "
- & Decl_Kind (Is_Type => Is_Type_Id,
- Object_Kind => "object")
- & " & cannot be volatile",
+ ("discriminated " & Decl_Kind & " & cannot be volatile",
Type_Or_Obj_Id);
end if;
@@ -1019,7 +1007,7 @@ package body Contracts is
Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
-- Save the SPARK_Mode-related data to restore on exit
- NC_Val : Boolean := False;
+ NC_Val : Boolean;
Items : Node_Id;
Prag : Node_Id;
Ref_Elmt : Elmt_Id;
@@ -1056,6 +1044,19 @@ package body Contracts is
Set_SPARK_Mode (Obj_Id);
end if;
+ -- Checks related to external properties, same for constants and
+ -- variables.
+
+ Check_Type_Or_Object_External_Properties (Type_Or_Obj_Id => Obj_Id);
+
+ -- Analyze the non-external volatility property No_Caching
+
+ Prag := Get_Pragma (Obj_Id, Pragma_No_Caching);
+
+ if Present (Prag) then
+ Analyze_External_Property_In_Decl_Part (Prag, NC_Val);
+ end if;
+
-- Constant-related checks
if Ekind (Obj_Id) = E_Constant then
@@ -1071,35 +1072,10 @@ package body Contracts is
Check_Missing_Part_Of (Obj_Id);
end if;
- -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
- -- This check is relevant only when SPARK_Mode is on, as it is not
- -- a standard Ada legality rule. Internally-generated constants that
- -- map generic formals to actuals in instantiations are allowed to
- -- be volatile.
-
- if SPARK_Mode = On
- and then Comes_From_Source (Obj_Id)
- and then Is_Effectively_Volatile (Obj_Id)
- and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
- then
- Error_Msg_N ("constant cannot be volatile", Obj_Id);
- end if;
-
-- Variable-related checks
else pragma Assert (Ekind (Obj_Id) = E_Variable);
- Check_Type_Or_Object_External_Properties
- (Type_Or_Obj_Id => Obj_Id);
-
- -- Analyze the non-external volatility property No_Caching
-
- Prag := Get_Pragma (Obj_Id, Pragma_No_Caching);
-
- if Present (Prag) then
- Analyze_External_Property_In_Decl_Part (Prag, NC_Val);
- end if;
-
-- The anonymous object created for a single task type carries
-- pragmas Depends and Global of the type.
@@ -1517,6 +1493,141 @@ package body Contracts is
(Type_Or_Obj_Id => Type_Id);
end Analyze_Type_Contract;
+ ---------------------------
+ -- Check_Class_Condition --
+ ---------------------------
+
+ procedure Check_Class_Condition
+ (Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Is_Precondition : Boolean)
+ is
+ function Check_Entity (N : Node_Id) return Traverse_Result;
+ -- Check reference to formal of inherited operation or to primitive
+ -- operation of root type.
+
+ ------------------
+ -- Check_Entity --
+ ------------------
+
+ function Check_Entity (N : Node_Id) return Traverse_Result is
+ New_E : Entity_Id;
+ Orig_E : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then
+ (Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
+ and then
+ (Nkind (Parent (N)) /= N_Attribute_Reference
+ or else Attribute_Name (Parent (N)) /= Name_Class)
+ then
+ -- These checks do not apply to dispatching calls within the
+ -- condition, but only to calls whose static tag is that of
+ -- the parent type.
+
+ if Is_Subprogram (Entity (N))
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then Present (Controlling_Argument (Parent (N)))
+ then
+ return OK;
+ end if;
+
+ -- Determine whether entity has a renaming
+
+ Orig_E := Entity (N);
+ New_E := Get_Mapped_Entity (Orig_E);
+
+ if Present (New_E) then
+
+ -- AI12-0166: A precondition for a protected operation
+ -- cannot include an internal call to a protected function
+ -- of the type. In the case of an inherited condition for an
+ -- overriding operation, both the operation and the function
+ -- are given by primitive wrappers.
+
+ if Is_Precondition
+ and then Ekind (New_E) = E_Function
+ and then Is_Primitive_Wrapper (New_E)
+ and then Is_Primitive_Wrapper (Subp)
+ and then Scope (Subp) = Scope (New_E)
+ then
+ Error_Msg_Node_2 := Wrapped_Entity (Subp);
+ Error_Msg_NE
+ ("internal call to& cannot appear in inherited "
+ & "precondition of protected operation&",
+ Subp, Wrapped_Entity (New_E));
+ end if;
+ end if;
+
+ -- Check that there are no calls left to abstract operations if
+ -- the current subprogram is not abstract.
+
+ if Present (New_E)
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then N = Name (Parent (N))
+ then
+ if not Is_Abstract_Subprogram (Subp)
+ and then Is_Abstract_Subprogram (New_E)
+ then
+ Error_Msg_Sloc := Sloc (Current_Scope);
+ Error_Msg_Node_2 := Subp;
+
+ if Comes_From_Source (Subp) then
+ Error_Msg_NE
+ ("cannot call abstract subprogram & in inherited "
+ & "condition for&#", Subp, New_E);
+ else
+ Error_Msg_NE
+ ("cannot call abstract subprogram & in inherited "
+ & "condition for inherited&#", Subp, New_E);
+ end if;
+
+ -- In SPARK mode, report error on inherited condition for an
+ -- inherited operation if it contains a call to an overriding
+ -- operation, because this implies that the pre/postconditions
+ -- of the inherited operation have changed silently.
+
+ elsif SPARK_Mode = On
+ and then Warn_On_Suspicious_Contract
+ and then Present (Alias (Subp))
+ and then Present (New_E)
+ and then Comes_From_Source (New_E)
+ then
+ Error_Msg_N
+ ("cannot modify inherited condition (SPARK RM 6.1.1(1))",
+ Parent (Subp));
+ Error_Msg_Sloc := Sloc (New_E);
+ Error_Msg_Node_2 := Subp;
+ Error_Msg_NE
+ ("\overriding of&# forces overriding of&",
+ Parent (Subp), New_E);
+ end if;
+ end if;
+ end if;
+
+ return OK;
+ end Check_Entity;
+
+ procedure Check_Condition_Entities is
+ new Traverse_Proc (Check_Entity);
+
+ -- Start of processing for Check_Class_Condition
+
+ begin
+ -- No check required if the subprograms match
+
+ if Par_Subp = Subp then
+ return;
+ end if;
+
+ Update_Primitives_Mapping (Par_Subp, Subp);
+ Map_Formals (Par_Subp, Subp);
+ Check_Condition_Entities (Cond);
+ end Check_Class_Condition;
+
-----------------------------
-- Create_Generic_Contract --
-----------------------------
@@ -1926,7 +2037,7 @@ package body Contracts is
procedure Add_Stable_Property_Contracts
(Subp_Id : Entity_Id; Class_Present : Boolean)
is
- Loc : constant Source_Ptr := Sloc (Subp_Id);
+ Loc : constant Source_Ptr := Sloc (Subp_Id);
procedure Insert_Stable_Property_Check
(Formal : Entity_Id; Property_Function : Entity_Id);
@@ -2578,13 +2689,38 @@ package body Contracts is
---------------------------------
procedure Process_Spec_Postconditions is
- Subps : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Spec_Id);
+ Seen : Subprogram_List (Subps'Range) := (others => Empty);
+
+ function Seen_Subp (Subp_Id : Entity_Id) return Boolean;
+ -- Return True if the contract of subprogram Subp_Id has been
+ -- processed.
+
+ ---------------
+ -- Seen_Subp --
+ ---------------
+
+ function Seen_Subp (Subp_Id : Entity_Id) return Boolean is
+ begin
+ for Index in Seen'Range loop
+ if Seen (Index) = Subp_Id then
+ return True;
+ end if;
+ end loop;
+
+ return False;
+ end Seen_Subp;
+
+ -- Local variables
+
Item : Node_Id;
Items : Node_Id;
Prag : Node_Id;
Subp_Id : Entity_Id;
+ -- Start of processing for Process_Spec_Postconditions
+
begin
-- Process the contract
@@ -2615,7 +2751,7 @@ package body Contracts is
Subp_Id := Ultimate_Alias (Subp_Id);
end if;
- -- Wrappers of class-wide pre/post conditions reference the
+ -- Wrappers of class-wide pre/postconditions reference the
-- parent primitive that has the inherited contract.
if Is_Wrapper (Subp_Id)
@@ -2626,7 +2762,9 @@ package body Contracts is
Items := Contract (Subp_Id);
- if Present (Items) then
+ if not Seen_Subp (Subp_Id) and then Present (Items) then
+ Seen (Index) := Subp_Id;
+
Prag := Pre_Post_Conditions (Items);
while Present (Prag) loop
if Pragma_Name (Prag) = Name_Postcondition
@@ -2683,10 +2821,6 @@ package body Contracts is
---------------------------
procedure Process_Preconditions is
- Class_Pre : Node_Id := Empty;
- -- The sole [inherited] class-wide precondition pragma that applies
- -- to the subprogram.
-
Insert_Node : Node_Id := Empty;
-- The insertion node after which all pragma Check equivalents are
-- inserted.
@@ -2695,21 +2829,12 @@ package body Contracts is
-- Determine whether arbitrary declaration Decl denotes a renaming of
-- a discriminant or protection field _object.
- procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
- -- Merge two class-wide preconditions by "or else"-ing them. The
- -- changes are accumulated in parameter Into. Update the error
- -- message of Into.
-
procedure Prepend_To_Decls (Item : Node_Id);
-- Prepend a single item to the declarations of the subprogram body
- procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
- -- Save a class-wide precondition into Class_Pre, or prepend a normal
- -- precondition to the declarations of the body and analyze it.
-
- procedure Process_Inherited_Preconditions;
- -- Collect all inherited class-wide preconditions and merge them into
- -- one big precondition to be evaluated as pragma Check.
+ procedure Prepend_Pragma_To_Decls (Prag : Node_Id);
+ -- Prepend a normal precondition to the declarations of the body and
+ -- analyze it.
procedure Process_Preconditions_For (Subp_Id : Entity_Id);
-- Collect all preconditions of subprogram Subp_Id and prepend their
@@ -2763,78 +2888,6 @@ package body Contracts is
return False;
end Is_Prologue_Renaming;
- -------------------------
- -- Merge_Preconditions --
- -------------------------
-
- procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
- function Expression_Arg (Prag : Node_Id) return Node_Id;
- -- Return the boolean expression argument of a precondition while
- -- updating its parentheses count for the subsequent merge.
-
- function Message_Arg (Prag : Node_Id) return Node_Id;
- -- Return the message argument of a precondition
-
- --------------------
- -- Expression_Arg --
- --------------------
-
- function Expression_Arg (Prag : Node_Id) return Node_Id is
- Args : constant List_Id := Pragma_Argument_Associations (Prag);
- Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
-
- begin
- if Paren_Count (Arg) = 0 then
- Set_Paren_Count (Arg, 1);
- end if;
-
- return Arg;
- end Expression_Arg;
-
- -----------------
- -- Message_Arg --
- -----------------
-
- function Message_Arg (Prag : Node_Id) return Node_Id is
- Args : constant List_Id := Pragma_Argument_Associations (Prag);
- begin
- return Get_Pragma_Arg (Last (Args));
- end Message_Arg;
-
- -- Local variables
-
- From_Expr : constant Node_Id := Expression_Arg (From);
- From_Msg : constant Node_Id := Message_Arg (From);
- Into_Expr : constant Node_Id := Expression_Arg (Into);
- Into_Msg : constant Node_Id := Message_Arg (Into);
- Loc : constant Source_Ptr := Sloc (Into);
-
- -- Start of processing for Merge_Preconditions
-
- begin
- -- Merge the two preconditions by "or else"-ing them
-
- Rewrite (Into_Expr,
- Make_Or_Else (Loc,
- Right_Opnd => Relocate_Node (Into_Expr),
- Left_Opnd => From_Expr));
-
- -- Merge the two error messages to produce a single message of the
- -- form:
-
- -- failed precondition from ...
- -- also failed inherited precondition from ...
-
- if not Exception_Locations_Suppressed then
- Start_String (Strval (Into_Msg));
- Store_String_Char (ASCII.LF);
- Store_String_Chars (" also ");
- Store_String_Chars (Strval (From_Msg));
-
- Set_Strval (Into_Msg, End_String);
- end if;
- end Merge_Preconditions;
-
----------------------
-- Prepend_To_Decls --
----------------------
@@ -2855,28 +2908,27 @@ package body Contracts is
Prepend_To (Decls, Item);
end Prepend_To_Decls;
- ------------------------------
- -- Prepend_To_Decls_Or_Save --
- ------------------------------
+ -----------------------------
+ -- Prepend_Pragma_To_Decls --
+ -----------------------------
- procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
+ procedure Prepend_Pragma_To_Decls (Prag : Node_Id) is
Check_Prag : Node_Id;
begin
- Check_Prag := Build_Pragma_Check_Equivalent (Prag);
-
- -- Save the sole class-wide precondition (if any) for the next
- -- step, where it will be merged with inherited preconditions.
+ -- Skip the sole class-wide precondition (if any) since it is
+ -- processed by Merge_Class_Conditions.
if Class_Present (Prag) then
- pragma Assert (No (Class_Pre));
- Class_Pre := Check_Prag;
+ null;
-- Accumulate the corresponding Check pragmas at the top of the
-- declarations. Prepending the items ensures that they will be
-- evaluated in their original order.
else
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
if Present (Insert_Node) then
Insert_After (Insert_Node, Check_Prag);
else
@@ -2885,87 +2937,7 @@ package body Contracts is
Analyze (Check_Prag);
end if;
- end Prepend_To_Decls_Or_Save;
-
- -------------------------------------
- -- Process_Inherited_Preconditions --
- -------------------------------------
-
- procedure Process_Inherited_Preconditions is
- Subps : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
-
- Item : Node_Id;
- Items : Node_Id;
- Prag : Node_Id;
- Subp_Id : Entity_Id;
-
- begin
- -- Process the contracts of all inherited subprograms, looking for
- -- class-wide preconditions.
-
- for Index in Subps'Range loop
- Subp_Id := Subps (Index);
-
- if Present (Alias (Subp_Id)) then
- Subp_Id := Ultimate_Alias (Subp_Id);
- end if;
-
- -- Wrappers of class-wide pre/post conditions reference the
- -- parent primitive that has the inherited contract.
-
- if Is_Wrapper (Subp_Id)
- and then Present (LSP_Subprogram (Subp_Id))
- then
- Subp_Id := LSP_Subprogram (Subp_Id);
- end if;
-
- Items := Contract (Subp_Id);
-
- if Present (Items) then
- Prag := Pre_Post_Conditions (Items);
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition
- and then Class_Present (Prag)
- then
- Item :=
- Build_Pragma_Check_Equivalent
- (Prag => Prag,
- Subp_Id => Spec_Id,
- Inher_Id => Subp_Id);
-
- -- The pragma Check equivalent of the class-wide
- -- precondition is still created even though the
- -- pragma may be ignored because the equivalent
- -- performs semantic checks.
-
- if Is_Checked (Prag) then
-
- -- The spec of an inherited subprogram already
- -- yielded a class-wide precondition. Merge the
- -- existing precondition with the current one
- -- using "or else".
-
- if Present (Class_Pre) then
- Merge_Preconditions (Item, Class_Pre);
- else
- Class_Pre := Item;
- end if;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
- end if;
- end loop;
-
- -- Add the merged class-wide preconditions
-
- if Present (Class_Pre) then
- Prepend_To_Decls (Class_Pre);
- Analyze (Class_Pre);
- end if;
- end Process_Inherited_Preconditions;
+ end Prepend_Pragma_To_Decls;
-------------------------------
-- Process_Preconditions_For --
@@ -3009,7 +2981,7 @@ package body Contracts is
N => Body_Decl);
end if;
- Prepend_To_Decls_Or_Save (Prag);
+ Prepend_Pragma_To_Decls (Prag);
end if;
Prag := Next_Pragma (Prag);
@@ -3034,7 +3006,7 @@ package body Contracts is
if Pragma_Name (Decl) = Name_Precondition
and then Is_Checked (Decl)
then
- Prepend_To_Decls_Or_Save (Decl);
+ Prepend_Pragma_To_Decls (Decl);
end if;
-- Skip internally generated code
@@ -3099,22 +3071,21 @@ package body Contracts is
Next (Decl);
end loop;
- end if;
- -- The processing of preconditions is done in reverse order (body
- -- first), because each pragma Check equivalent is inserted at the
- -- top of the declarations. This ensures that the final order is
- -- consistent with following diagram:
+ -- The processing of preconditions is done in reverse order (body
+ -- first), because each pragma Check equivalent is inserted at the
+ -- top of the declarations. This ensures that the final order is
+ -- consistent with following diagram:
- -- <inherited preconditions>
- -- <preconditions from spec>
- -- <preconditions from body>
+ -- <inherited preconditions>
+ -- <preconditions from spec>
+ -- <preconditions from body>
- Process_Preconditions_For (Body_Id);
+ Process_Preconditions_For (Body_Id);
+ end if;
if Present (Spec_Id) then
Process_Preconditions_For (Spec_Id);
- Process_Inherited_Preconditions;
end if;
end Process_Preconditions;
@@ -3165,6 +3136,12 @@ package body Contracts is
elsif Is_Ignored_Ghost_Entity (Subp_Id) then
return;
+ -- No action needed for helpers and indirect-call wrapper built to
+ -- support class-wide preconditions.
+
+ elsif Present (Class_Preconditions_Subprogram (Subp_Id)) then
+ return;
+
-- Do not re-expand the same contract. This scenario occurs when a
-- construct is rewritten into something else during its analysis
-- (expression functions for instance).
@@ -3466,7 +3443,7 @@ package body Contracts is
-- Get_Postcond_Enabled --
--------------------------
- function Get_Postcond_Enabled (Subp : Entity_Id) return Node_Id is
+ function Get_Postcond_Enabled (Subp : Entity_Id) return Entity_Id is
Decl : Node_Id;
begin
Decl :=
@@ -3491,7 +3468,7 @@ package body Contracts is
------------------------------------
function Get_Result_Object_For_Postcond
- (Subp : Entity_Id) return Node_Id
+ (Subp : Entity_Id) return Entity_Id
is
Decl : Node_Id;
begin
@@ -3516,7 +3493,7 @@ package body Contracts is
-- Get_Return_Success_For_Postcond --
-------------------------------------
- function Get_Return_Success_For_Postcond (Subp : Entity_Id) return Node_Id
+ function Get_Return_Success_For_Postcond (Subp : Entity_Id) return Entity_Id
is
Decl : Node_Id;
begin
@@ -3631,6 +3608,1112 @@ package body Contracts is
end if;
end Instantiate_Subprogram_Contract;
+ -----------------------------------
+ -- Make_Class_Precondition_Subps --
+ -----------------------------------
+
+ procedure Make_Class_Precondition_Subps
+ (Subp_Id : Entity_Id;
+ Late_Overriding : Boolean := False)
+ is
+ Loc : constant Source_Ptr := Sloc (Subp_Id);
+ Tagged_Type : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
+ procedure Add_Indirect_Call_Wrapper;
+ -- Build the indirect-call wrapper and append it to the freezing actions
+ -- of Tagged_Type.
+
+ procedure Add_Call_Helper
+ (Helper_Id : Entity_Id;
+ Is_Dynamic : Boolean);
+ -- Factorizes code for building a call helper with the given identifier
+ -- and append it to the freezing actions of Tagged_Type. Is_Dynamic
+ -- controls building the static or dynamic version of the helper.
+
+ -------------------------------
+ -- Add_Indirect_Call_Wrapper --
+ -------------------------------
+
+ procedure Add_Indirect_Call_Wrapper is
+
+ function Build_ICW_Body return Node_Id;
+ -- Build the body of the indirect call wrapper
+
+ function Build_ICW_Decl return Node_Id;
+ -- Build the declaration of the indirect call wrapper
+
+ --------------------
+ -- Build_ICW_Body --
+ --------------------
+
+ function Build_ICW_Body return Node_Id is
+ ICW_Id : constant Entity_Id := Indirect_Call_Wrapper (Subp_Id);
+ Spec : constant Node_Id := Parent (ICW_Id);
+ Body_Spec : Node_Id;
+ Call : Node_Id;
+ ICW_Body : Node_Id;
+
+ begin
+ Body_Spec := Copy_Subprogram_Spec (Spec);
+
+ -- Build call to wrapped subprogram
+
+ declare
+ Actuals : constant List_Id := Empty_List;
+ Formal_Spec : Entity_Id :=
+ First (Parameter_Specifications (Spec));
+ begin
+ -- Build parameter association & call
+
+ while Present (Formal_Spec) loop
+ Append_To (Actuals,
+ New_Occurrence_Of
+ (Defining_Identifier (Formal_Spec), Loc));
+ Next (Formal_Spec);
+ end loop;
+
+ if Ekind (ICW_Id) = E_Procedure then
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Subp_Id, Loc),
+ Parameter_Associations => Actuals);
+ else
+ Call :=
+ Make_Simple_Return_Statement (Loc,
+ Expression =>
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Subp_Id, Loc),
+ Parameter_Associations => Actuals));
+ end if;
+ end;
+
+ ICW_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification => Body_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call)));
+
+ -- The new operation is internal and overriding indicators do not
+ -- apply.
+
+ Set_Must_Override (Body_Spec, False);
+
+ return ICW_Body;
+ end Build_ICW_Body;
+
+ --------------------
+ -- Build_ICW_Decl --
+ --------------------
+
+ function Build_ICW_Decl return Node_Id is
+ ICW_Id : constant Entity_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "ICW",
+ Suffix_Index => Source_Offset (Loc)));
+ Decl : Node_Id;
+ Spec : Node_Id;
+
+ begin
+ Spec := Copy_Subprogram_Spec (Parent (Subp_Id));
+ Set_Must_Override (Spec, False);
+ Set_Must_Not_Override (Spec, False);
+ Set_Defining_Unit_Name (Spec, ICW_Id);
+ Mutate_Ekind (ICW_Id, Ekind (Subp_Id));
+ Set_Is_Public (ICW_Id);
+
+ -- The indirect call wrapper is commonly used for indirect calls
+ -- but inlined for direct calls performed from the DTW.
+
+ Set_Is_Inlined (ICW_Id);
+
+ if Nkind (Spec) = N_Procedure_Specification then
+ Set_Null_Present (Spec, False);
+ end if;
+
+ Decl := Make_Subprogram_Declaration (Loc, Spec);
+
+ -- Link original subprogram to indirect wrapper and vice versa
+
+ Set_Indirect_Call_Wrapper (Subp_Id, ICW_Id);
+ Set_Class_Preconditions_Subprogram (ICW_Id, Subp_Id);
+
+ -- Inherit debug info flag to allow debugging the wrapper
+
+ if Needs_Debug_Info (Subp_Id) then
+ Set_Debug_Info_Needed (ICW_Id);
+ end if;
+
+ return Decl;
+ end Build_ICW_Decl;
+
+ -- Local Variables
+
+ ICW_Body : Node_Id;
+ ICW_Decl : Node_Id;
+
+ -- Start of processing for Add_Indirect_Call_Wrapper
+
+ begin
+ pragma Assert (No (Indirect_Call_Wrapper (Subp_Id)));
+
+ ICW_Decl := Build_ICW_Decl;
+
+ Ensure_Freeze_Node (Tagged_Type);
+ Append_Freeze_Action (Tagged_Type, ICW_Decl);
+ Analyze (ICW_Decl);
+
+ ICW_Body := Build_ICW_Body;
+ Append_Freeze_Action (Tagged_Type, ICW_Body);
+
+ -- We cannot defer the analysis of this ICW wrapper when it is
+ -- built as a consequence of building its partner DTW wrapper
+ -- at the freezing point of the tagged type.
+
+ if Is_Dispatch_Table_Wrapper (Subp_Id) then
+ Analyze (ICW_Body);
+ end if;
+ end Add_Indirect_Call_Wrapper;
+
+ ---------------------
+ -- Add_Call_Helper --
+ ---------------------
+
+ procedure Add_Call_Helper
+ (Helper_Id : Entity_Id;
+ Is_Dynamic : Boolean)
+ is
+ function Build_Call_Helper_Body return Node_Id;
+ -- Build the body of a call helper
+
+ function Build_Call_Helper_Decl return Node_Id;
+ -- Build the declaration of a call helper
+
+ function Build_Call_Helper_Spec (Spec_Id : Entity_Id) return Node_Id;
+ -- Build the specification of the helper
+
+ ----------------------------
+ -- Build_Call_Helper_Body --
+ ----------------------------
+
+ function Build_Call_Helper_Body return Node_Id is
+
+ function Copy_And_Update_References
+ (Expr : Node_Id) return Node_Id;
+ -- Copy Expr updating references to formals of Helper_Id; update
+ -- also references to loop identifiers of quantified expressions.
+
+ --------------------------------
+ -- Copy_And_Update_References --
+ --------------------------------
+
+ function Copy_And_Update_References
+ (Expr : Node_Id) return Node_Id
+ is
+ Assoc_List : constant Elist_Id := New_Elmt_List;
+
+ procedure Map_Quantified_Expression_Loop_Identifiers;
+ -- Traverse Expr and append to Assoc_List the mapping of loop
+ -- identifers of quantified expressions with its new copy.
+
+ ------------------------------------------------
+ -- Map_Quantified_Expression_Loop_Identifiers --
+ ------------------------------------------------
+
+ procedure Map_Quantified_Expression_Loop_Identifiers is
+ function Map_Loop_Param (N : Node_Id) return Traverse_Result;
+ -- Append to Assoc_List the mapping of loop identifers of
+ -- quantified expressions with its new copy.
+
+ --------------------
+ -- Map_Loop_Param --
+ --------------------
+
+ function Map_Loop_Param (N : Node_Id) return Traverse_Result
+ is
+ begin
+ if Nkind (N) = N_Loop_Parameter_Specification
+ and then Nkind (Parent (N)) = N_Quantified_Expression
+ then
+ declare
+ Def_Id : constant Entity_Id :=
+ Defining_Identifier (N);
+ begin
+ Append_Elmt (Def_Id, Assoc_List);
+ Append_Elmt (New_Copy (Def_Id), Assoc_List);
+ end;
+ end if;
+
+ return OK;
+ end Map_Loop_Param;
+
+ procedure Map_Quantified_Expressions is
+ new Traverse_Proc (Map_Loop_Param);
+
+ begin
+ Map_Quantified_Expressions (Expr);
+ end Map_Quantified_Expression_Loop_Identifiers;
+
+ -- Local variables
+
+ Subp_Formal_Id : Entity_Id := First_Formal (Subp_Id);
+ Helper_Formal_Id : Entity_Id := First_Formal (Helper_Id);
+
+ -- Start of processing for Copy_And_Update_References
+
+ begin
+ while Present (Subp_Formal_Id) loop
+ Append_Elmt (Subp_Formal_Id, Assoc_List);
+ Append_Elmt (Helper_Formal_Id, Assoc_List);
+
+ Next_Formal (Subp_Formal_Id);
+ Next_Formal (Helper_Formal_Id);
+ end loop;
+
+ Map_Quantified_Expression_Loop_Identifiers;
+
+ return New_Copy_Tree (Expr, Map => Assoc_List);
+ end Copy_And_Update_References;
+
+ -- Local variables
+
+ Helper_Decl : constant Node_Id := Parent (Parent (Helper_Id));
+ Body_Id : Entity_Id;
+ Body_Spec : Node_Id;
+ Body_Stmts : Node_Id;
+ Helper_Body : Node_Id;
+ Return_Expr : Node_Id;
+
+ -- Start of processing for Build_Call_Helper_Body
+
+ begin
+ pragma Assert (Analyzed (Unit_Declaration_Node (Helper_Id)));
+ pragma Assert (No (Corresponding_Body (Helper_Decl)));
+
+ Body_Id := Make_Defining_Identifier (Loc, Chars (Helper_Id));
+ Body_Spec := Build_Call_Helper_Spec (Body_Id);
+
+ Set_Corresponding_Body (Helper_Decl, Body_Id);
+ Set_Must_Override (Body_Spec, False);
+
+ if Present (Class_Preconditions (Subp_Id)) then
+ Return_Expr :=
+ Copy_And_Update_References (Class_Preconditions (Subp_Id));
+
+ -- When the subprogram is compiled with assertions disabled the
+ -- helper just returns True; done to avoid reporting errors at
+ -- link time since a unit may be compiled with assertions disabled
+ -- and another (which depends on it) compiled with assertions
+ -- enabled.
+
+ else
+ pragma Assert (Present (Ignored_Class_Preconditions (Subp_Id)));
+ Return_Expr := New_Occurrence_Of (Standard_True, Loc);
+ end if;
+
+ Body_Stmts :=
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Simple_Return_Statement (Loc, Return_Expr)));
+
+ Helper_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification => Body_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence => Body_Stmts);
+
+ return Helper_Body;
+ end Build_Call_Helper_Body;
+
+ ----------------------------
+ -- Build_Call_Helper_Decl --
+ ----------------------------
+
+ function Build_Call_Helper_Decl return Node_Id is
+ Decl : Node_Id;
+ Spec : Node_Id;
+
+ begin
+ Spec := Build_Call_Helper_Spec (Helper_Id);
+ Set_Must_Override (Spec, False);
+ Set_Must_Not_Override (Spec, False);
+ Set_Is_Inlined (Helper_Id);
+ Set_Is_Public (Helper_Id);
+
+ Decl := Make_Subprogram_Declaration (Loc, Spec);
+
+ -- Inherit debug info flag from Subp_Id to Helper_Id to allow
+ -- debugging of the helper subprogram.
+
+ if Needs_Debug_Info (Subp_Id) then
+ Set_Debug_Info_Needed (Helper_Id);
+ end if;
+
+ return Decl;
+ end Build_Call_Helper_Decl;
+
+ ----------------------------
+ -- Build_Call_Helper_Spec --
+ ----------------------------
+
+ function Build_Call_Helper_Spec (Spec_Id : Entity_Id) return Node_Id
+ is
+ Spec : constant Node_Id := Parent (Subp_Id);
+ Def_Id : constant Node_Id := Defining_Unit_Name (Spec);
+ Formal : Entity_Id;
+ Func_Formals : constant List_Id := New_List;
+ P_Spec : constant List_Id := Parameter_Specifications (Spec);
+ Par_Formal : Node_Id;
+ Param : Node_Id;
+ Param_Type : Node_Id;
+
+ begin
+ -- Create a list of formal parameters with the same types as the
+ -- original subprogram but changing the controlling formal.
+
+ Param := First (P_Spec);
+ Formal := First_Formal (Def_Id);
+ while Present (Formal) loop
+ Par_Formal := Parent (Formal);
+
+ if Is_Dynamic and then Is_Controlling_Formal (Formal) then
+ if Nkind (Parameter_Type (Par_Formal))
+ = N_Access_Definition
+ then
+ Param_Type :=
+ Copy_Separate_Tree (Parameter_Type (Par_Formal));
+ Rewrite (Subtype_Mark (Param_Type),
+ Make_Attribute_Reference (Loc,
+ Prefix => Relocate_Node (Subtype_Mark (Param_Type)),
+ Attribute_Name => Name_Class));
+
+ else
+ Param_Type :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Etype (Formal), Loc),
+ Attribute_Name => Name_Class);
+ end if;
+ else
+ Param_Type := New_Occurrence_Of (Etype (Formal), Loc);
+ end if;
+
+ Append_To (Func_Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Chars (Formal)),
+ In_Present => In_Present (Par_Formal),
+ Out_Present => Out_Present (Par_Formal),
+ Null_Exclusion_Present => Null_Exclusion_Present
+ (Par_Formal),
+ Parameter_Type => Param_Type));
+
+ Next (Param);
+ Next_Formal (Formal);
+ end loop;
+
+ return
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name => Spec_Id,
+ Parameter_Specifications => Func_Formals,
+ Result_Definition =>
+ New_Occurrence_Of (Standard_Boolean, Loc));
+ end Build_Call_Helper_Spec;
+
+ -- Local variables
+
+ Helper_Body : Node_Id;
+ Helper_Decl : Node_Id;
+
+ -- Start of processing for Add_Call_Helper
+
+ begin
+ Helper_Decl := Build_Call_Helper_Decl;
+ Mutate_Ekind (Helper_Id, Ekind (Subp_Id));
+
+ -- Add the helper to the freezing actions of the tagged type
+
+ Ensure_Freeze_Node (Tagged_Type);
+ Append_Freeze_Action (Tagged_Type, Helper_Decl);
+ Analyze (Helper_Decl);
+
+ Helper_Body := Build_Call_Helper_Body;
+ Append_Freeze_Action (Tagged_Type, Helper_Body);
+
+ -- If this helper is built as part of building the DTW at the
+ -- freezing point of its tagged type then we cannot defer
+ -- its analysis.
+
+ if Late_Overriding then
+ pragma Assert (Is_Dispatch_Table_Wrapper (Subp_Id));
+ Analyze (Helper_Body);
+ end if;
+ end Add_Call_Helper;
+
+ -- Local variables
+
+ Helper_Id : Entity_Id;
+
+ -- Start of processing for Make_Class_Precondition_Subps
+
+ begin
+ if Present (Class_Preconditions (Subp_Id))
+ or Present (Ignored_Class_Preconditions (Subp_Id))
+ then
+ pragma Assert
+ (Comes_From_Source (Subp_Id)
+ or else Is_Dispatch_Table_Wrapper (Subp_Id));
+
+ if No (Dynamic_Call_Helper (Subp_Id)) then
+
+ -- Build and add to the freezing actions of Tagged_Type its
+ -- dynamic-call helper.
+
+ Helper_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "DP",
+ Suffix_Index => Source_Offset (Loc)));
+ Add_Call_Helper (Helper_Id, Is_Dynamic => True);
+
+ -- Link original subprogram to helper and vice versa
+
+ Set_Dynamic_Call_Helper (Subp_Id, Helper_Id);
+ Set_Class_Preconditions_Subprogram (Helper_Id, Subp_Id);
+ end if;
+
+ if not Is_Abstract_Subprogram (Subp_Id)
+ and then No (Static_Call_Helper (Subp_Id))
+ then
+ -- Build and add to the freezing actions of Tagged_Type its
+ -- static-call helper.
+
+ Helper_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Subp_Id),
+ Suffix => "SP",
+ Suffix_Index => Source_Offset (Loc)));
+
+ Add_Call_Helper (Helper_Id, Is_Dynamic => False);
+
+ -- Link original subprogram to helper and vice versa
+
+ Set_Static_Call_Helper (Subp_Id, Helper_Id);
+ Set_Class_Preconditions_Subprogram (Helper_Id, Subp_Id);
+
+ -- Build and add to the freezing actions of Tagged_Type the
+ -- indirect-call wrapper.
+
+ Add_Indirect_Call_Wrapper;
+ end if;
+ end if;
+ end Make_Class_Precondition_Subps;
+
+ ----------------------------------------------
+ -- Process_Class_Conditions_At_Freeze_Point --
+ ----------------------------------------------
+
+ procedure Process_Class_Conditions_At_Freeze_Point (Typ : Entity_Id) is
+
+ procedure Check_Class_Conditions (Spec_Id : Entity_Id);
+ -- Check class-wide pre/postconditions of Spec_Id
+
+ function Has_Class_Postconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean;
+ -- Return True if Spec_Id has (or inherits) a postconditions subprogram.
+
+ function Has_Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean;
+ -- Return True if Spec_Id has (or inherits) a preconditions subprogram.
+
+ ----------------------------
+ -- Check_Class_Conditions --
+ ----------------------------
+
+ procedure Check_Class_Conditions (Spec_Id : Entity_Id) is
+ Par_Subp : Entity_Id;
+
+ begin
+ for Kind in Condition_Kind loop
+ Par_Subp := Nearest_Class_Condition_Subprogram (Kind, Spec_Id);
+
+ if Present (Par_Subp) then
+ Check_Class_Condition
+ (Cond => Class_Condition (Kind, Par_Subp),
+ Subp => Spec_Id,
+ Par_Subp => Par_Subp,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ end if;
+ end loop;
+ end Check_Class_Conditions;
+
+ -----------------------------------------
+ -- Has_Class_Postconditions_Subprogram --
+ -----------------------------------------
+
+ function Has_Class_Postconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean is
+ begin
+ return
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Class_Postcondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Ignored_Class_Postcondition));
+ end Has_Class_Postconditions_Subprogram;
+
+ ----------------------------------------
+ -- Has_Class_Preconditions_Subprogram --
+ ----------------------------------------
+
+ function Has_Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id) return Boolean is
+ begin
+ return
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Class_Precondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Spec_Id,
+ Kind => Ignored_Class_Precondition));
+ end Has_Class_Preconditions_Subprogram;
+
+ -- Local variables
+
+ Prim_Elmt : Elmt_Id := First_Elmt (Primitive_Operations (Typ));
+ Prim : Entity_Id;
+
+ -- Start of processing for Process_Class_Conditions_At_Freeze_Point
+
+ begin
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ if Has_Class_Preconditions_Subprogram (Prim)
+ or else Has_Class_Postconditions_Subprogram (Prim)
+ then
+ if Comes_From_Source (Prim) then
+ if Has_Significant_Contract (Prim) then
+ Merge_Class_Conditions (Prim);
+ end if;
+
+ -- Handle wrapper of protected operation
+
+ elsif Is_Primitive_Wrapper (Prim) then
+ Merge_Class_Conditions (Prim);
+
+ -- Check inherited class-wide conditions, excluding internal
+ -- entities built for mapping of interface primitives.
+
+ elsif Is_Derived_Type (Typ)
+ and then Present (Alias (Prim))
+ and then No (Interface_Alias (Prim))
+ then
+ Check_Class_Conditions (Prim);
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Process_Class_Conditions_At_Freeze_Point;
+
+ ----------------------------
+ -- Merge_Class_Conditions --
+ ----------------------------
+
+ procedure Merge_Class_Conditions (Spec_Id : Entity_Id) is
+
+ procedure Preanalyze_Condition
+ (Subp : Entity_Id;
+ Expr : Node_Id);
+ -- Preanalyze the class-wide condition Expr of Subp
+
+ procedure Process_Inherited_Conditions (Kind : Condition_Kind);
+ -- Collect all inherited class-wide conditions of Spec_Id and merge
+ -- them into one big condition.
+
+ --------------------------
+ -- Preanalyze_Condition --
+ --------------------------
+
+ procedure Preanalyze_Condition
+ (Subp : Entity_Id;
+ Expr : Node_Id)
+ is
+ procedure Clear_Unset_References;
+ -- Clear unset references on formals of Subp since preanalysis
+ -- occurs in a place unrelated to the actual code.
+
+ procedure Remove_Controlling_Arguments;
+ -- Traverse Expr and clear the Controlling_Argument of calls to
+ -- nonabstract functions.
+
+ procedure Remove_Formals (Id : Entity_Id);
+ -- Remove formals from homonym chains and make them not visible
+
+ ----------------------------
+ -- Clear_Unset_References --
+ ----------------------------
+
+ procedure Clear_Unset_References is
+ F : Entity_Id := First_Formal (Subp);
+
+ begin
+ while Present (F) loop
+ Set_Unset_Reference (F, Empty);
+ Next_Formal (F);
+ end loop;
+ end Clear_Unset_References;
+
+ ----------------------------------
+ -- Remove_Controlling_Arguments --
+ ----------------------------------
+
+ procedure Remove_Controlling_Arguments is
+ function Remove_Ctrl_Arg (N : Node_Id) return Traverse_Result;
+ -- Reset the Controlling_Argument of calls to nonabstract
+ -- function calls.
+
+ ---------------------
+ -- Remove_Ctrl_Arg --
+ ---------------------
+
+ function Remove_Ctrl_Arg (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) = N_Function_Call
+ and then Present (Controlling_Argument (N))
+ and then not Is_Abstract_Subprogram (Entity (Name (N)))
+ then
+ Set_Controlling_Argument (N, Empty);
+ end if;
+
+ return OK;
+ end Remove_Ctrl_Arg;
+
+ procedure Remove_Ctrl_Args is new Traverse_Proc (Remove_Ctrl_Arg);
+ begin
+ Remove_Ctrl_Args (Expr);
+ end Remove_Controlling_Arguments;
+
+ --------------------
+ -- Remove_Formals --
+ --------------------
+
+ procedure Remove_Formals (Id : Entity_Id) is
+ F : Entity_Id := First_Formal (Id);
+
+ begin
+ while Present (F) loop
+ Set_Is_Immediately_Visible (F, False);
+ Remove_Homonym (F);
+ Next_Formal (F);
+ end loop;
+ end Remove_Formals;
+
+ -- Start of processing for Preanalyze_Condition
+
+ begin
+ pragma Assert (Present (Expr));
+ pragma Assert (Inside_Class_Condition_Preanalysis = False);
+
+ Push_Scope (Subp);
+ Install_Formals (Subp);
+ Inside_Class_Condition_Preanalysis := True;
+
+ Preanalyze_And_Resolve (Expr, Standard_Boolean);
+
+ Inside_Class_Condition_Preanalysis := False;
+ Remove_Formals (Subp);
+ Pop_Scope;
+
+ -- Traverse Expr and clear the Controlling_Argument of calls to
+ -- nonabstract functions. Required since the preanalyzed condition
+ -- is not yet installed on its definite context and will be cloned
+ -- and extended in derivations with additional conditions.
+
+ Remove_Controlling_Arguments;
+
+ -- Clear also attribute Unset_Reference; again because preanalysis
+ -- occurs in a place unrelated to the actual code.
+
+ Clear_Unset_References;
+ end Preanalyze_Condition;
+
+ ----------------------------------
+ -- Process_Inherited_Conditions --
+ ----------------------------------
+
+ procedure Process_Inherited_Conditions (Kind : Condition_Kind) is
+ Tag_Typ : constant Entity_Id := Find_Dispatching_Type (Spec_Id);
+ Subps : constant Subprogram_List := Inherited_Subprograms (Spec_Id);
+ Seen : Subprogram_List (Subps'Range) := (others => Empty);
+
+ function Inherit_Condition
+ (Par_Subp : Entity_Id;
+ Subp : Entity_Id) return Node_Id;
+ -- Inherit the class-wide condition from Par_Subp to Subp and adjust
+ -- all the references to formals in the inherited condition.
+
+ procedure Merge_Conditions (From : Node_Id; Into : Node_Id);
+ -- Merge two class-wide preconditions or postconditions (the former
+ -- are merged using "or else", and the latter are merged using "and-
+ -- then"). The changes are accumulated in parameter Into.
+
+ function Seen_Subp (Id : Entity_Id) return Boolean;
+ -- Return True if the contract of subprogram Id has been processed
+
+ -----------------------
+ -- Inherit_Condition --
+ -----------------------
+
+ function Inherit_Condition
+ (Par_Subp : Entity_Id;
+ Subp : Entity_Id) return Node_Id
+ is
+ Installed_Calls : constant Elist_Id := New_Elmt_List;
+
+ procedure Install_Original_Selected_Component (Expr : Node_Id);
+ -- Traverse the given expression searching for dispatching calls
+ -- to functions whose original nodes was a selected component,
+ -- and replacing them temporarily by a copy of their original
+ -- node. Modified calls are stored in the list Installed_Calls
+ -- (to undo this work later).
+
+ procedure Restore_Dispatching_Calls (Expr : Node_Id);
+ -- Undo the work done by Install_Original_Selected_Component.
+
+ -----------------------------------------
+ -- Install_Original_Selected_Component --
+ -----------------------------------------
+
+ procedure Install_Original_Selected_Component (Expr : Node_Id) is
+ function Install_Node (N : Node_Id) return Traverse_Result;
+ -- Process a single node
+
+ ------------------
+ -- Install_Node --
+ ------------------
+
+ function Install_Node (N : Node_Id) return Traverse_Result is
+ New_N : Node_Id;
+ Orig_Nod : Node_Id;
+
+ begin
+ if Nkind (N) = N_Function_Call
+ and then Nkind (Original_Node (N)) = N_Selected_Component
+ and then Is_Dispatching_Operation (Entity (Name (N)))
+ then
+ Orig_Nod := Original_Node (N);
+
+ -- Temporarily use the original node field to keep the
+ -- reference to this node (to undo this work later!).
+
+ New_N := New_Copy (N);
+ Set_Original_Node (New_N, Orig_Nod);
+ Append_Elmt (New_N, Installed_Calls);
+
+ Rewrite (N, Orig_Nod);
+ Set_Original_Node (N, New_N);
+ end if;
+
+ return OK;
+ end Install_Node;
+
+ procedure Install_Nodes is new Traverse_Proc (Install_Node);
+
+ begin
+ Install_Nodes (Expr);
+ end Install_Original_Selected_Component;
+
+ -------------------------------
+ -- Restore_Dispatching_Calls --
+ -------------------------------
+
+ procedure Restore_Dispatching_Calls (Expr : Node_Id) is
+ function Restore_Node (N : Node_Id) return Traverse_Result;
+ -- Process a single node
+
+ ------------------
+ -- Restore_Node --
+ ------------------
+
+ function Restore_Node (N : Node_Id) return Traverse_Result is
+ Orig_Sel_N : Node_Id;
+
+ begin
+ if Nkind (N) = N_Selected_Component
+ and then Nkind (Original_Node (N)) = N_Function_Call
+ and then Contains (Installed_Calls, Original_Node (N))
+ then
+ Orig_Sel_N := Original_Node (Original_Node (N));
+ pragma Assert (Nkind (Orig_Sel_N) = N_Selected_Component);
+ Rewrite (N, Original_Node (N));
+ Set_Original_Node (N, Orig_Sel_N);
+ end if;
+
+ return OK;
+ end Restore_Node;
+
+ procedure Restore_Nodes is new Traverse_Proc (Restore_Node);
+
+ begin
+ Restore_Nodes (Expr);
+ end Restore_Dispatching_Calls;
+
+ -- Local variables
+
+ Assoc_List : constant Elist_Id := New_Elmt_List;
+ Par_Formal_Id : Entity_Id := First_Formal (Par_Subp);
+ Subp_Formal_Id : Entity_Id := First_Formal (Subp);
+ New_Expr : Node_Id;
+ Class_Cond : Node_Id;
+
+ -- Start of processing for Inherit_Condition
+
+ begin
+ while Present (Par_Formal_Id) loop
+ Append_Elmt (Par_Formal_Id, Assoc_List);
+ Append_Elmt (Subp_Formal_Id, Assoc_List);
+
+ Next_Formal (Par_Formal_Id);
+ Next_Formal (Subp_Formal_Id);
+ end loop;
+
+ -- In order to properly preanalyze an inherited preanalyzed
+ -- condition that has occurrences of the Object.Operation
+ -- notation we must restore the original node; otherwise we
+ -- would report spurious errors.
+
+ Class_Cond := Class_Condition (Kind, Par_Subp);
+
+ Install_Original_Selected_Component (Class_Cond);
+ New_Expr := New_Copy_Tree (Class_Cond);
+ Restore_Dispatching_Calls (Class_Cond);
+
+ return New_Copy_Tree (New_Expr, Map => Assoc_List);
+ end Inherit_Condition;
+
+ ----------------------
+ -- Merge_Conditions --
+ ----------------------
+
+ procedure Merge_Conditions (From : Node_Id; Into : Node_Id) is
+ function Expression_Arg (Expr : Node_Id) return Node_Id;
+ -- Return the boolean expression argument of a condition while
+ -- updating its parentheses count for the subsequent merge.
+
+ --------------------
+ -- Expression_Arg --
+ --------------------
+
+ function Expression_Arg (Expr : Node_Id) return Node_Id is
+ begin
+ if Paren_Count (Expr) = 0 then
+ Set_Paren_Count (Expr, 1);
+ end if;
+
+ return Expr;
+ end Expression_Arg;
+
+ -- Local variables
+
+ From_Expr : constant Node_Id := Expression_Arg (From);
+ Into_Expr : constant Node_Id := Expression_Arg (Into);
+ Loc : constant Source_Ptr := Sloc (Into);
+
+ -- Start of processing for Merge_Conditions
+
+ begin
+ case Kind is
+
+ -- Merge the two preconditions by "or else"-ing them
+
+ when Ignored_Class_Precondition
+ | Class_Precondition
+ =>
+ Rewrite (Into_Expr,
+ Make_Or_Else (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+
+ -- Merge the two postconditions by "and then"-ing them
+
+ when Ignored_Class_Postcondition
+ | Class_Postcondition
+ =>
+ Rewrite (Into_Expr,
+ Make_And_Then (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+ end case;
+ end Merge_Conditions;
+
+ ---------------
+ -- Seen_Subp --
+ ---------------
+
+ function Seen_Subp (Id : Entity_Id) return Boolean is
+ begin
+ for Index in Seen'Range loop
+ if Seen (Index) = Id then
+ return True;
+ end if;
+ end loop;
+
+ return False;
+ end Seen_Subp;
+
+ -- Local variables
+
+ Class_Cond : Node_Id;
+ Cond : Node_Id;
+ Subp_Id : Entity_Id;
+ Par_Prim : Entity_Id := Empty;
+ Par_Iface_Prims : Elist_Id := No_Elist;
+
+ -- Start of processing for Process_Inherited_Conditions
+
+ begin
+ Class_Cond := Class_Condition (Kind, Spec_Id);
+
+ -- Process parent primitives looking for nearest ancestor with
+ -- class-wide conditions.
+
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if No (Par_Prim)
+ and then Is_Ancestor (Find_Dispatching_Type (Subp_Id), Tag_Typ)
+ then
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract and help
+ -- us to climb fast.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if not Seen_Subp (Subp_Id)
+ and then Present (Class_Condition (Kind, Subp_Id))
+ then
+ Seen (Index) := Subp_Id;
+ Par_Prim := Subp_Id;
+ Par_Iface_Prims := Covered_Interface_Primitives (Par_Prim);
+
+ Cond := Inherit_Condition
+ (Subp => Spec_Id,
+ Par_Subp => Subp_Id);
+
+ if Present (Class_Cond) then
+ Merge_Conditions (Cond, Class_Cond);
+ else
+ Class_Cond := Cond;
+ end if;
+
+ Check_Class_Condition
+ (Cond => Class_Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ Build_Class_Wide_Expression
+ (Pragma_Or_Expr => Class_Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Adjust_Sloc => False);
+
+ -- We are done as soon as we process the nearest ancestor
+
+ exit;
+ end if;
+ end if;
+ end loop;
+
+ -- Process the contract of interface primitives not covered by
+ -- the nearest ancestor.
+
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Is_Interface (Find_Dispatching_Type (Subp_Id)) then
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ if not Seen_Subp (Subp_Id)
+ and then Present (Class_Condition (Kind, Subp_Id))
+ and then not Contains (Par_Iface_Prims, Subp_Id)
+ then
+ Seen (Index) := Subp_Id;
+
+ Cond := Inherit_Condition
+ (Subp => Spec_Id,
+ Par_Subp => Subp_Id);
+
+ Check_Class_Condition
+ (Cond => Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Is_Precondition => Kind in Ignored_Class_Precondition
+ | Class_Precondition);
+ Build_Class_Wide_Expression
+ (Pragma_Or_Expr => Cond,
+ Subp => Spec_Id,
+ Par_Subp => Subp_Id,
+ Adjust_Sloc => False);
+
+ if Present (Class_Cond) then
+ Merge_Conditions (Cond, Class_Cond);
+ else
+ Class_Cond := Cond;
+ end if;
+ end if;
+ end if;
+ end loop;
+
+ Set_Class_Condition (Kind, Spec_Id, Class_Cond);
+ end Process_Inherited_Conditions;
+
+ -- Local variables
+
+ Cond : Node_Id;
+
+ -- Start of processing for Merge_Class_Conditions
+
+ begin
+ for Kind in Condition_Kind loop
+ Cond := Class_Condition (Kind, Spec_Id);
+
+ -- If this subprogram has class-wide conditions then preanalyze
+ -- them before processing inherited conditions since conditions
+ -- are checked and merged from right to left.
+
+ if Present (Cond) then
+ Preanalyze_Condition (Spec_Id, Cond);
+ end if;
+
+ Process_Inherited_Conditions (Kind);
+
+ -- Preanalyze merged inherited conditions
+
+ if Cond /= Class_Condition (Kind, Spec_Id) then
+ Preanalyze_Condition (Spec_Id,
+ Class_Condition (Kind, Spec_Id));
+ end if;
+ end loop;
+ end Merge_Class_Conditions;
+
----------------------------------------
-- Save_Global_References_In_Contract --
----------------------------------------
@@ -3648,10 +4731,9 @@ package body Contracts is
------------------------------------
procedure Save_Global_References_In_List (First_Prag : Node_Id) is
- Prag : Node_Id;
+ Prag : Node_Id := First_Prag;
begin
- Prag := First_Prag;
while Present (Prag) loop
if Is_Generic_Contract_Pragma (Prag) then
Save_Global_References (Prag);
@@ -3688,4 +4770,29 @@ package body Contracts is
Pop_Scope;
end Save_Global_References_In_Contract;
+ -------------------------
+ -- Set_Class_Condition --
+ -------------------------
+
+ procedure Set_Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id;
+ Cond : Node_Id)
+ is
+ begin
+ case Kind is
+ when Class_Postcondition =>
+ Set_Class_Postconditions (Subp, Cond);
+
+ when Class_Precondition =>
+ Set_Class_Preconditions (Subp, Cond);
+
+ when Ignored_Class_Postcondition =>
+ Set_Ignored_Class_Postconditions (Subp, Cond);
+
+ when Ignored_Class_Precondition =>
+ Set_Ignored_Class_Preconditions (Subp, Cond);
+ end case;
+ end Set_Class_Condition;
+
end Contracts;
diff --git a/gcc/ada/contracts.ads b/gcc/ada/contracts.ads
index bfd482e..eb26ebf 100644
--- a/gcc/ada/contracts.ads
+++ b/gcc/ada/contracts.ads
@@ -216,6 +216,31 @@ package Contracts is
-- subprogram declaration template denoted by Templ. The instantiated
-- pragmas are added to list L.
+ procedure Make_Class_Precondition_Subps
+ (Subp_Id : Entity_Id;
+ Late_Overriding : Boolean := False);
+ -- Build helpers that at run time evaluate statically and dynamically the
+ -- class-wide preconditions of Subp_Id; build also the indirect-call
+ -- wrapper (ICW) required to check class-wide preconditions when the
+ -- subprogram is invoked through an access-to-subprogram, or when it
+ -- overrides an inherited class-wide precondition (see AI12-0195-1).
+ -- Late_Overriding enables special handling required for late-overriding
+ -- subprograms.
+
+ procedure Merge_Class_Conditions (Spec_Id : Entity_Id);
+ -- Merge and preanalyze all class-wide conditions of Spec_Id (class-wide
+ -- preconditions merged with operator or-else; class-wide postconditions
+ -- merged with operator and-then). Ignored pre/postconditions are also
+ -- merged since, although they are not required to generate code, their
+ -- preanalysis is required to perform semantic checks. Resulting merged
+ -- expressions are later installed by the expander in helper subprograms
+ -- which are invoked from the caller side; they are also used to build
+ -- the dispatch-table wrapper (DTW), if required.
+
+ procedure Process_Class_Conditions_At_Freeze_Point (Typ : Entity_Id);
+ -- Merge, preanalyze, and check class-wide pre/postconditions of Typ
+ -- primitives.
+
procedure Save_Global_References_In_Contract
(Templ : Node_Id;
Gen_Id : Entity_Id);
diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb
index 44cb69c..41de2a5 100644
--- a/gcc/ada/cstand.adb
+++ b/gcc/ada/cstand.adb
@@ -149,8 +149,7 @@ package body CStand is
function New_Operator (Op : Name_Id; Typ : Entity_Id) return Entity_Id;
-- Build entity for standard operator with given name and type
- function New_Standard_Entity
- (New_Node_Kind : Node_Kind := N_Defining_Identifier) return Entity_Id;
+ function New_Standard_Entity return Entity_Id;
-- Builds a new entity for Standard
function New_Standard_Entity (Nam : String) return Entity_Id;
@@ -205,7 +204,7 @@ package body CStand is
Mutate_Ekind (E, E_Floating_Point_Type);
Set_Etype (E, E);
- Init_Digits_Value (E, Digs);
+ Set_Digits_Value (E, UI_From_Int (Digs));
Set_Float_Rep (E, Rep);
Init_Size (E, Siz);
Set_Elem_Alignment (E, Align);
@@ -578,6 +577,8 @@ package body CStand is
Set_Has_Pragma_Pack (String_Type, True);
end Pack_String_Type;
+ Char_Size : constant Unat := UI_From_Int (Standard_Character_Size);
+
-- Start of processing for Create_Standard
begin
@@ -652,8 +653,8 @@ package body CStand is
Mutate_Ekind (Standard_Boolean, E_Enumeration_Type);
Set_First_Literal (Standard_Boolean, Standard_False);
Set_Etype (Standard_Boolean, Standard_Boolean);
- Init_Esize (Standard_Boolean, Standard_Character_Size);
- Init_RM_Size (Standard_Boolean, 1);
+ Set_Esize (Standard_Boolean, Char_Size);
+ Set_RM_Size (Standard_Boolean, Uint_1);
Set_Elem_Alignment (Standard_Boolean);
Set_Is_Unsigned_Type (Standard_Boolean);
@@ -757,8 +758,8 @@ package body CStand is
Mutate_Ekind (Standard_Character, E_Enumeration_Type);
Set_Etype (Standard_Character, Standard_Character);
- Init_Esize (Standard_Character, Standard_Character_Size);
- Init_RM_Size (Standard_Character, 8);
+ Set_Esize (Standard_Character, Char_Size);
+ Set_RM_Size (Standard_Character, Uint_8);
Set_Elem_Alignment (Standard_Character);
Set_Has_Pragma_Ordered (Standard_Character);
@@ -912,7 +913,7 @@ package body CStand is
Set_Etype (Standard_String, Standard_String);
Set_Component_Type (Standard_String, Standard_Character);
Set_Component_Size (Standard_String, Uint_8);
- Init_Size_Align (Standard_String);
+ Reinit_Size_Align (Standard_String);
Set_Alignment (Standard_String, Uint_1);
Pack_String_Type (Standard_String);
@@ -956,7 +957,7 @@ package body CStand is
Set_Etype (Standard_Wide_String, Standard_Wide_String);
Set_Component_Type (Standard_Wide_String, Standard_Wide_Character);
Set_Component_Size (Standard_Wide_String, Uint_16);
- Init_Size_Align (Standard_Wide_String);
+ Reinit_Size_Align (Standard_Wide_String);
Pack_String_Type (Standard_Wide_String);
-- Set index type of Wide_String
@@ -993,7 +994,7 @@ package body CStand is
Set_Component_Type (Standard_Wide_Wide_String,
Standard_Wide_Wide_Character);
Set_Component_Size (Standard_Wide_Wide_String, Uint_32);
- Init_Size_Align (Standard_Wide_Wide_String);
+ Reinit_Size_Align (Standard_Wide_Wide_String);
Set_Is_Ada_2005_Only (Standard_Wide_Wide_String);
Pack_String_Type (Standard_Wide_Wide_String);
@@ -1009,10 +1010,10 @@ package body CStand is
-- Setup entity for Natural
- Mutate_Ekind (Standard_Natural, E_Signed_Integer_Subtype);
- Set_Etype (Standard_Natural, Base_Type (Standard_Integer));
- Init_Esize (Standard_Natural, Standard_Integer_Size);
- Init_RM_Size (Standard_Natural, Standard_Integer_Size - 1);
+ Mutate_Ekind (Standard_Natural, E_Signed_Integer_Subtype);
+ Set_Etype (Standard_Natural, Base_Type (Standard_Integer));
+ Set_Esize (Standard_Natural, UI_From_Int (Standard_Integer_Size));
+ Set_RM_Size (Standard_Natural, UI_From_Int (Standard_Integer_Size - 1));
Set_Elem_Alignment (Standard_Natural);
Set_Size_Known_At_Compile_Time
(Standard_Natural);
@@ -1024,10 +1025,11 @@ package body CStand is
-- Setup entity for Positive
- Mutate_Ekind (Standard_Positive, E_Signed_Integer_Subtype);
- Set_Etype (Standard_Positive, Base_Type (Standard_Integer));
- Init_Esize (Standard_Positive, Standard_Integer_Size);
- Init_RM_Size (Standard_Positive, Standard_Integer_Size - 1);
+ Mutate_Ekind (Standard_Positive, E_Signed_Integer_Subtype);
+ Set_Etype (Standard_Positive, Base_Type (Standard_Integer));
+ Set_Esize (Standard_Positive, UI_From_Int (Standard_Integer_Size));
+ Set_RM_Size
+ (Standard_Positive, UI_From_Int (Standard_Integer_Size - 1));
Set_Elem_Alignment (Standard_Positive);
Set_Size_Known_At_Compile_Time (Standard_Positive);
@@ -1132,7 +1134,7 @@ package body CStand is
Init_Size (Standard_A_String, System_Address_Size * 2);
end if;
- Init_Alignment (Standard_A_String);
+ pragma Assert (not Known_Alignment (Standard_A_String));
Set_Directly_Designated_Type
(Standard_A_String, Standard_String);
@@ -1156,14 +1158,14 @@ package body CStand is
Mutate_Ekind (Standard_Debug_Renaming_Type, E_Signed_Integer_Subtype);
Set_Scope (Standard_Debug_Renaming_Type, Standard_Standard);
Set_Etype (Standard_Debug_Renaming_Type, Base_Type (Standard_Integer));
- Init_Esize (Standard_Debug_Renaming_Type, 0);
- Init_RM_Size (Standard_Debug_Renaming_Type, 0);
+ Set_Esize (Standard_Debug_Renaming_Type, Uint_0);
+ Set_RM_Size (Standard_Debug_Renaming_Type, Uint_0);
Set_Size_Known_At_Compile_Time (Standard_Debug_Renaming_Type);
- Set_Integer_Bounds (Standard_Debug_Renaming_Type,
- Typ => Base_Type (Standard_Debug_Renaming_Type),
+ Set_Integer_Bounds (Standard_Debug_Renaming_Type,
+ Typ => Base_Type (Standard_Debug_Renaming_Type),
Lb => Uint_1,
Hb => Uint_0);
- Set_Is_Constrained (Standard_Debug_Renaming_Type);
+ Set_Is_Constrained (Standard_Debug_Renaming_Type);
Set_Has_Size_Clause (Standard_Debug_Renaming_Type);
-- Note on type names. The type names for the following special types
@@ -1186,8 +1188,8 @@ package body CStand is
Mutate_Ekind (Any_Id, E_Variable);
Set_Scope (Any_Id, Standard_Standard);
Set_Etype (Any_Id, Any_Type);
- Init_Esize (Any_Id);
- Init_Alignment (Any_Id);
+ pragma Assert (not Known_Esize (Any_Id));
+ pragma Assert (not Known_Alignment (Any_Id));
Any_Access := New_Standard_Entity ("an access type");
Mutate_Ekind (Any_Access, E_Access_Type);
@@ -1204,8 +1206,8 @@ package body CStand is
Set_Etype (Any_Character, Any_Character);
Set_Is_Unsigned_Type (Any_Character);
Set_Is_Character_Type (Any_Character);
- Init_Esize (Any_Character, Standard_Character_Size);
- Init_RM_Size (Any_Character, 8);
+ Set_Esize (Any_Character, Char_Size);
+ Set_RM_Size (Any_Character, Uint_8);
Set_Elem_Alignment (Any_Character);
Set_Scalar_Range (Any_Character, Scalar_Range (Standard_Character));
@@ -1214,15 +1216,15 @@ package body CStand is
Set_Scope (Any_Array, Standard_Standard);
Set_Etype (Any_Array, Any_Array);
Set_Component_Type (Any_Array, Any_Character);
- Init_Size_Align (Any_Array);
+ Reinit_Size_Align (Any_Array);
Make_Dummy_Index (Any_Array);
Any_Boolean := New_Standard_Entity ("a boolean type");
Mutate_Ekind (Any_Boolean, E_Enumeration_Type);
Set_Scope (Any_Boolean, Standard_Standard);
Set_Etype (Any_Boolean, Standard_Boolean);
- Init_Esize (Any_Boolean, Standard_Character_Size);
- Init_RM_Size (Any_Boolean, 1);
+ Set_Esize (Any_Boolean, Char_Size);
+ Set_RM_Size (Any_Boolean, Uint_1);
Set_Elem_Alignment (Any_Boolean);
Set_Is_Unsigned_Type (Any_Boolean);
Set_Scalar_Range (Any_Boolean, Scalar_Range (Standard_Boolean));
@@ -1233,7 +1235,7 @@ package body CStand is
Set_Etype (Any_Composite, Any_Composite);
Set_Component_Size (Any_Composite, Uint_0);
Set_Component_Type (Any_Composite, Standard_Integer);
- Init_Size_Align (Any_Composite);
+ Reinit_Size_Align (Any_Composite);
Any_Discrete := New_Standard_Entity ("a discrete type");
Mutate_Ekind (Any_Discrete, E_Signed_Integer_Type);
@@ -1297,7 +1299,7 @@ package body CStand is
Set_Scope (Any_String, Standard_Standard);
Set_Etype (Any_String, Any_String);
Set_Component_Type (Any_String, Any_Character);
- Init_Size_Align (Any_String);
+ Reinit_Size_Align (Any_String);
Make_Dummy_Index (Any_String);
Raise_Type := New_Standard_Entity ("raise type");
@@ -1506,7 +1508,7 @@ package body CStand is
Set_Scope (Standard_Exception_Type, Standard_Standard);
Set_Stored_Constraint
(Standard_Exception_Type, No_Elist);
- Init_Size_Align (Standard_Exception_Type);
+ Set_RM_Size (Standard_Exception_Type, Uint_0);
Set_Size_Known_At_Compile_Time
(Standard_Exception_Type, True);
@@ -1726,7 +1728,7 @@ package body CStand is
Mutate_Ekind (Id, E_Component);
Set_Etype (Id, Typ);
Set_Scope (Id, Rec);
- Init_Component_Location (Id);
+ Reinit_Component_Location (Id);
Set_Original_Record_Component (Id, Id);
Set_Is_Aliased (Id);
Set_Is_Independent (Id);
@@ -1790,10 +1792,9 @@ package body CStand is
-- New_Standard_Entity --
-------------------------
- function New_Standard_Entity
- (New_Node_Kind : Node_Kind := N_Defining_Identifier) return Entity_Id
+ function New_Standard_Entity return Entity_Id
is
- E : constant Entity_Id := New_Entity (New_Node_Kind, Stloc);
+ E : constant Entity_Id := New_Entity (N_Defining_Identifier, Stloc);
begin
-- All standard entities are Pure and Public
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index 5245feb3..8873000 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -112,7 +112,7 @@ package body Debug is
-- d.y Disable implicit pragma Elaborate_All on task bodies
-- d.z Restore previous support for frontend handling of Inline_Always
- -- d.A
+ -- d.A Enable statistics printing in Atree
-- d.B Generate a bug box on abort_statement
-- d.C Generate concatenation call, do not generate inline code
-- d.D Disable errors on use of overriding keyword in Ada 95 mode
@@ -158,7 +158,7 @@ package body Debug is
-- d_q
-- d_r
-- d_s Stop elaboration checks on synchronous suspension
- -- d_t
+ -- d_t In LLVM-based CCG, dump LLVM IR after transformations are done
-- d_u
-- d_v Enable additional checks and debug printouts in Atree
-- d_w
@@ -210,7 +210,7 @@ package body Debug is
-- d.5 Do not generate imported subprogram definitions in C code
-- d.6 Do not avoid declaring unreferenced types in C code
-- d.7 Disable unsound heuristics in gnat2scil (for CP as SPARK prover)
- -- d.8
+ -- d.8 Disable unconditional inlining of expression functions
-- d.9 Disable build-in-place for nonlimited types
-- d_1
@@ -830,6 +830,11 @@ package body Debug is
-- handling of Inline_Always by the front end on such targets. For the
-- targets that do not use the GCC back end, this switch is ignored.
+ -- d.A Enable statistics printing in Atree. First set Statistics_Enabled
+ -- in gen_il-gen.adb to True, then rebuild, then run the compiler
+ -- with -gnatd.A. You might want to apply "sort -nr" to parts of the
+ -- output.
+
-- d.B Generate a bug box when we see an abort_statement, even though
-- there is no bug. Useful for testing Comperr.Compiler_Abort: write
-- some code containing an abort_statement, and compile it with
@@ -992,6 +997,10 @@ package body Debug is
-- a call to routine Ada.Synchronous_Task_Control.Suspend_Until_True
-- or Ada.Synchronous_Barriers.Wait_For_Release.
+ -- d_t In the LLVM-based CCG, do an additional dump of the LLVM IR
+ -- after the pass that does transformations to the IR into a
+ -- filename ending with .trans.ll.
+
-- d_v Enable additional checks and debug printouts in Atree
-- d_x The compiler does not expand in line the Image attribute for user-
@@ -1101,6 +1110,10 @@ package body Debug is
-- issues (e.g., assuming that a low bound of an array parameter
-- of an unconstrained subtype belongs to the index subtype).
+ -- d.8 By default calls to expression functions are always inlined.
+ -- This debug flag turns off this behavior, making them subject
+ -- to the usual inlining heuristics of the code generator.
+
-- d.9 Disable build-in-place for function calls returning nonlimited
-- types.
diff --git a/gcc/ada/doc/gnat_rm.rst b/gcc/ada/doc/gnat_rm.rst
index 97f7e4d..7743ef8 100644
--- a/gcc/ada/doc/gnat_rm.rst
+++ b/gcc/ada/doc/gnat_rm.rst
@@ -55,6 +55,7 @@ GNAT Reference Manual
gnat_rm/specialized_needs_annexes
gnat_rm/implementation_of_specific_ada_features
gnat_rm/implementation_of_ada_2012_features
+ gnat_rm/security_hardening_features
gnat_rm/obsolescent_features
gnat_rm/compatibility_and_porting_guide
diff --git a/gcc/ada/doc/gnat_rm/about_this_guide.rst b/gcc/ada/doc/gnat_rm/about_this_guide.rst
index b48785ee..9defee8 100644
--- a/gcc/ada/doc/gnat_rm/about_this_guide.rst
+++ b/gcc/ada/doc/gnat_rm/about_this_guide.rst
@@ -96,6 +96,9 @@ This reference manual contains the following chapters:
* :ref:`Implementation_of_Ada_2012_Features`, describes the status of the
GNAT implementation of the Ada 2012 language standard.
+* :ref:`Security_Hardening_Features` documents GNAT extensions aimed
+ at security hardening.
+
* :ref:`Obsolescent_Features` documents implementation dependent features,
including pragmas and attributes, which are considered obsolescent, since
there are other preferred ways of achieving the same results. These
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
index 8d0be38..c5c7dfb 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
@@ -53,7 +53,8 @@ Any *code_statement* can potentially cause external interactions.
See separate section on source representation.
*
- "The control functions allowed in comments. See 2.1(14)."
+ "The semantics of an Ada program whose text is not in
+ Normalization Form C. See 2.1(4)."
See separate section on source representation.
@@ -86,14 +87,14 @@ parameter, checks that the optimization flag is set, and aborts if it is
not.
*
- "The sequence of characters of the value returned by
- ``S'Image`` when some of the graphic characters of
- ``S'Wide_Image`` are not defined in ``Character``. See
- 3.5(37)."
+ "The message string associated with the Assertion_Error exception raised
+ by the failure of a predicate check if there is no applicable
+ Predicate_Failure aspect. See 3.2.4(31)."
-The sequence of characters is as defined by the wide character encoding
-method used for the source. See section on source representation for
-further details.
+In the case of a Dynamic_Predicate aspect, the string is
+"Dynamic_Predicate failed at <source position>", where
+"<source position>" might be something like "foo.adb:123".
+The Static_Predicate case is handled analogously.
*
"The predefined integer types declared in
@@ -146,12 +147,12 @@ Type Representation
IEEE 80-bit Extended on x86 architecture
====================== ===============================================
-The default rounding mode specified by the IEEE 754 Standard is assumed for
-static computations, i.e. round to nearest, ties to even. The input routines
-yield correctly rounded values for Short_Float, Float and Long_Float at least.
-The output routines can compute up to twice as many exact digits as the value
-of ``T'Digits`` for any type, for example 30 digits for Long_Float; if more
-digits are requested, zeros are printed.
+The default rounding mode specified by the IEEE 754 Standard is assumed both
+for static and dynamic computations (that is, round to nearest, ties to even).
+The input routines yield correctly rounded values for Short_Float, Float, and
+Long_Float at least. The output routines can compute up to twice as many exact
+digits as the value of ``T'Digits`` for any type, for example 30 digits for
+Long_Float; if more digits are requested, zeros are printed.
*
"The small of an ordinary fixed point type. See 3.5.9(8)."
@@ -192,24 +193,79 @@ Block numbers of the form :samp:`B{nnn}`, where *nnn* is a
decimal integer are allocated.
*
+ "The sequence of characters of the value returned by Tags.Expanded_Name
+ (respectively, Tags.Wide_Expanded_Name) when some of the graphic
+ characters of Tags.Wide_Wide_Expanded_Name are not defined in Character
+ (respectively, Wide_Character). See 3.9(10.1)."
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+*
"Implementation-defined attributes. See 4.1.4(12)."
See :ref:`Implementation_Defined_Attributes`.
*
+ "The value of the parameter to Empty for some container aggregates.
+ See 4.3.5(40)."
+
+As per the suggestion given in the Annotated Ada RM, the default value
+of the formal parameter is used if one exists and zero is used otherwise.
+
+*
+ "The maximum number of chunks for a parallel reduction expression without
+ a chunk_specification. See 4.5.10(21)."
+
+Feature unimplemented.
+
+*
+ "Rounding of real static expressions which are exactly half-way between
+ two machine numbers. See 4.9(38)."
+
+Round to even is used in all such cases.
+
+*
+ "The maximum number of chunks for a parallel generalized iterator without
+ a chunk_specification. See 5.5.2(10)."
+
+Feature unimplemented.
+
+*
+ "The number of chunks for an array component iterator. See 5.5.2(11)."
+
+Feature unimplemented.
+
+*
+ "Any extensions of the Global aspect. See 6.1.2(43)."
+
+Feature unimplemented.
+
+*
+ "The circumstances the implementation passes in the null value for a view
+ conversion of an access type used as an out parameter. See 6.4.1(19)."
+
+Difficult to characterize.
+
+*
+ "Any extensions of the Default_Initial_Condition aspect. See 7.3.3(11)."
+
+SPARK allows specifying *null* as the Default_Initial_Condition
+aspect of a type. See the SPARK reference manual for further details.
+
+*
"Any implementation-defined time types. See 9.6(6)."
There are no implementation-defined time types.
*
- "The time base associated with relative delays."
+ "The time base associated with relative delays. See 9.6(20)."
See 9.6(20). The time base used is that provided by the C library
function ``gettimeofday``.
*
- "The time base of the type ``Calendar.Time``. See
- 9.6(23)."
+ "The time base of the type ``Calendar.Time``. See 9.6(23)."
The time base used is that provided by the C library function
``gettimeofday``.
@@ -229,13 +285,15 @@ setting for local time, as accessed by the C library function
There are no such limits.
*
- "Whether or not two non-overlapping parts of a composite
- object are independently addressable, in the case where packing, record
- layout, or ``Component_Size`` is specified for the object. See
- 9.10(1)."
+ "The result of Calendar.Formatting.Image if its argument represents more
+ than 100 hours. See 9.6.1(86)."
+
+Calendar.Time_Error is raised.
+
+*
+ "Implementation-defined conflict check policies. See 9.10.1(5)."
-Separate components are independently addressable if they do not share
-overlapping storage units.
+There are no implementation-defined conflict check policies.
*
"The representation for a compilation. See 10.1(2)."
@@ -281,9 +339,8 @@ options, refer to *GNAT Make Program gnatmake* in the
:title:`GNAT User's Guide`.
*
- "The implementation-defined means, if any, of specifying
- which compilation units are needed by a given compilation unit. See
- 10.2(2)."
+ "The implementation-defined means, if any, of specifying which compilation
+ units are needed by a given compilation unit. See 10.2(2)."
The units needed by a given compilation unit are as defined in
the Ada Reference Manual section 10.2(2-6). There are no
@@ -298,17 +355,13 @@ The main program is designated by providing the name of the
corresponding :file:`ALI` file as the input parameter to the binder.
*
- "The order of elaboration of *library_items*. See
- 10.2(18)."
+ "The order of elaboration of *library_items*. See 10.2(18)."
The first constraint on ordering is that it meets the requirements of
Chapter 10 of the Ada Reference Manual. This still leaves some
-implementation dependent choices, which are resolved by first
-elaborating bodies as early as possible (i.e., in preference to specs
-where there is a choice), and second by evaluating the immediate with
-clauses of a unit to determine the probably best choice, and
-third by elaborating in alphabetical order of unit names
-where a choice still remains.
+implementation-dependent choices, which are resolved by analyzing
+the elaboration code of each unit and identifying implicit
+elaboration-order dependencies.
*
"Parameter passing and function return for the main
@@ -320,13 +373,12 @@ value is the return code of the program (overriding any value that
may have been set by a call to ``Ada.Command_Line.Set_Exit_Status``).
*
- "The mechanisms for building and running partitions. See
- 10.2(24)."
+ "The mechanisms for building and running partitions. See 10.2(24)."
-GNAT itself supports programs with only a single partition. The GNATDIST
+GNAT itself supports programs with only a single partition. The GNATDIST
tool provided with the GLADE package (which also includes an implementation
of the PCS) provides a completely flexible method for building and running
-programs consisting of multiple partitions. See the separate GLADE manual
+programs consisting of multiple partitions. See the separate GLADE manual
for details.
*
@@ -340,12 +392,11 @@ See separate section on compilation model.
implementation. See 10.2(28)."
Passive partitions are supported on targets where shared memory is
-provided by the operating system. See the GLADE reference manual for
+provided by the operating system. See the GLADE reference manual for
further details.
*
- "The information returned by ``Exception_Message``. See
- 11.4.1(10)."
+ "The information returned by ``Exception_Message``. See 11.4.1(10)."
Exception message returns the null string unless a specific message has
been passed by the program.
@@ -391,6 +442,38 @@ where
the last line is a single ``LF`` character (``16#0A#``).
*
+ "The sequence of characters of the value returned by
+ Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name)
+ when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name
+ are not defined in Character (respectively, Wide_Character).
+ See 11.4.1(12.1)."
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+*
+ "The information returned by Exception_Information. See 11.4.1(13)."
+
+The exception name and the source location at which the exception was
+raised are included.
+
+*
+ "Implementation-defined policy_identifiers and assertion_aspect_marks
+ allowed in a pragma Assertion_Policy. See 11.4.2(9)."
+
+Implementation-defined assertion_aspect_marks include Assert_And_Cut,
+Assume, Contract_Cases, Debug, Ghost, Initial_Condition, Loop_Invariant,
+Loop_Variant, Postcondition, Precondition, Predicate, Refined_Post,
+Statement_Assertions, and Subprogram_Variant. Implementation-defined
+policy_identifiers include Ignore and Suppressible.
+
+*
+ "The default assertion policy. See 11.4.2(10)."
+
+The default assertion policy is Ignore, although this can be overridden
+via compiler switches such as "-gnata".
+
+*
"Implementation-defined check names. See 11.5(27)."
The implementation defined check names include Alignment_Check,
@@ -400,28 +483,54 @@ program can add implementation-defined check names by means of the pragma
Check_Name. See the description of pragma ``Suppress`` for full details.
*
- "The interpretation of each aspect of representation. See
- 13.1(20)."
+ "Existence and meaning of second parameter of pragma Unsuppress.
+ See 11.5(27.1)."
+
+The legality rules for and semantics of the second parameter of pragma
+Unsuppress match those for the second argument of pragma Suppress.
+
+*
+ "The cases that cause conflicts between the representation of the
+ ancestors of a type_declaration. See 13.1(13.1)."
+
+No such cases exist.
+
+*
+ "The interpretation of each representation aspect. See 13.1(20)."
See separate section on data representations.
*
- "Any restrictions placed upon representation items. See
- 13.1(20)."
+ "Any restrictions placed upon the specification of representation aspects.
+ See 13.1(20)."
See separate section on data representations.
*
- "The meaning of ``Size`` for indefinite subtypes. See
- 13.3(48)."
+ "Implementation-defined aspects, including the syntax for specifying
+ such aspects and the legality rules for such aspects. See 13.1.1(38)."
+
+See :ref:`Implementation_Defined_Aspects`.
+
+*
+ "The set of machine scalars. See 13.3(8.1)."
+
+See separate section on data representations.
+
+*
+ "The meaning of ``Size`` for indefinite subtypes. See 13.3(48)."
+
+The Size attribute of an indefinite subtype is not less than the Size
+attribute of any object of that type.
+
+*
+ "The meaning of Object_Size for indefinite subtypes. See 13.3(58)."
-Size for an indefinite subtype is the maximum possible size, except that
-for the case of a subprogram parameter, the size of the parameter object
-is the actual size.
+The Object_Size attribute of an indefinite subtype is not less than the
+Object_Size attribute of any object of that type.
*
- "The default external representation for a type tag. See
- 13.3(75)."
+ "The default external representation for a type tag. See 13.3(75)."
The default external representation for a type tag is the fully expanded
name of the type in upper case letters.
@@ -448,12 +557,10 @@ implementation, so no non-default bit ordering is supported. The default
bit ordering corresponds to the natural endianness of the target architecture.
*
- "The contents of the visible part of package ``System``
- and its language-defined children. See 13.7(2)."
+ "The contents of the visible part of package ``System``. See 13.7(2)."
-See the definition of these packages in files :file:`system.ads` and
-:file:`s-stoele.ads`. Note that two declarations are added to package
-System.
+See the definition of package System in :file:`system.ads`.
+Note that two declarations are added to package System.
.. code-block:: ada
@@ -461,14 +568,21 @@ System.
Max_Interrupt_Priority : constant Positive := Interrupt_Priority'Last;
*
- "The contents of the visible part of package
- ``System.Machine_Code``, and the meaning of
- *code_statements*. See 13.8(7)."
+ "The range of Storage_Elements.Storage_Offset, the modulus of
+ Storage_Elements.Storage_Element, and the declaration of
+ Storage_Elements.Integer_Address. See 13.7.1(11)."
+
+See the definition of package System.Storage_Elements in :file:`s-stoele.ads`.
+
+*
+ "The contents of the visible part of package ``System.Machine_Code``,
+ and the meaning of *code_statements*. See 13.8(7)."
See the definition and documentation in file :file:`s-maccod.ads`.
*
- "The effect of unchecked conversion. See 13.9(11)."
+ "The result of unchecked conversion for instances with scalar result
+ types whose result is not defined by the language. See 13.9(11)."
Unchecked conversion between types of the same size
results in an uninterpreted transmission of the bits from one type
@@ -485,69 +599,43 @@ greater than the source alignment, then a copy of the result is
made with appropriate alignment
*
- "The semantics of operations on invalid representations.
- See 13.9.2(10-11)."
-
-For assignments and other operations where the use of invalid values cannot
-result in erroneous behavior, the compiler ignores the possibility of invalid
-values. An exception is raised at the point where an invalid value would
-result in erroneous behavior. For example executing:
+ "The result of unchecked conversion for instances with nonscalar result
+ types whose result is not defined by the language. See 13.9(11)."
-.. code-block:: ada
-
- procedure invalidvals is
- X : Integer := -1;
- Y : Natural range 1 .. 10;
- for Y'Address use X'Address;
- Z : Natural range 1 .. 10;
- A : array (Natural range 1 .. 10) of Integer;
- begin
- Z := Y; -- no exception
- A (Z) := 3; -- exception raised;
- end;
-
-As indicated, an exception is raised on the array assignment, but not
-on the simple assignment of the invalid negative value from Y to Z.
+See preceding definition for the scalar result case.
*
- "The manner of choosing a storage pool for an access type
- when ``Storage_Pool`` is not specified for the type. See 13.11(17)."
+ "Whether or not the implementation provides user-accessible
+ names for the standard pool type(s). See 13.11(17)."
There are 3 different standard pools used by the compiler when
``Storage_Pool`` is not specified depending whether the type is local
to a subprogram or defined at the library level and whether
-``Storage_Size``is specified or not. See documentation in the runtime
+``Storage_Size``is specified or not. See documentation in the runtime
library units ``System.Pool_Global``, ``System.Pool_Size`` and
``System.Pool_Local`` in files :file:`s-poosiz.ads`,
:file:`s-pooglo.ads` and :file:`s-pooloc.ads` for full details on the
-default pools used.
-
-*
- "Whether or not the implementation provides user-accessible
- names for the standard pool type(s). See 13.11(17)."
-
-See documentation in the sources of the run time mentioned in the previous
-paragraph. All these pools are accessible by means of `with`\ ing
+default pools used. All these pools are accessible by means of `with`\ ing
these units.
*
- "The meaning of ``Storage_Size``. See 13.11(18)."
+ "The meaning of ``Storage_Size`` when neither the Storage_Size nor the
+ Storage_Pool is specified for an access type. See 13.11(18)."
``Storage_Size`` is measured in storage units, and refers to the
total space available for an access type collection, or to the primary
stack space for a task.
*
- "Implementation-defined aspects of storage pools. See
- 13.11(22)."
+ "The effect of specifying aspect Default_Storage_Pool on an instance
+ of a language-defined generic unit. See 13.11.3(5)."
-See documentation in the sources of the run time mentioned in the
-paragraph about standard storage pools above
-for details on GNAT-defined aspects of storage pools.
+Instances of language-defined generic units are treated the same as other
+instances with respect to the Default_Storage_Pool aspect.
*
- "The set of restrictions allowed in a pragma
- ``Restrictions``. See 13.12(7)."
+ "Implementation-defined restrictions allowed in a pragma
+ ``Restrictions``. See 13.12(8.7)."
See :ref:`Standard_and_Implementation_Defined_Restrictions`.
@@ -555,14 +643,19 @@ See :ref:`Standard_and_Implementation_Defined_Restrictions`.
"The consequences of violating limitations on
``Restrictions`` pragmas. See 13.12(9)."
-Restrictions that can be checked at compile time result in illegalities
-if violated. Currently there are no other consequences of violating
-restrictions.
+Restrictions that can be checked at compile time are enforced at
+compile time; violations are illegal. For other restrictions, any
+violation during program execution results in erroneous execution.
*
- "The representation used by the ``Read`` and
- ``Write`` attributes of elementary types in terms of stream
- elements. See 13.13.2(9)."
+ "Implementation-defined usage profiles allowed in a pragma Profile.
+ See 13.12(15)."
+
+See :ref:`Implementation_Defined_Pragmas`.
+
+*
+ "The contents of the stream elements read and written by the Read and
+ Write attributes of elementary types. See 13.13.2(9)."
The representation is the in-memory representation of the base type of
the type, using the number of bits corresponding to the
@@ -575,12 +668,29 @@ the type, using the number of bits corresponding to the
See items describing the integer and floating-point types supported.
*
- "The string returned by ``Character_Set_Version``.
- See A.3.5(3)."
+ "The values returned by Strings.Hash. See A.4.9(3)."
+
+This hash function has predictable collisions and is subject to
+equivalent substring attacks. It is not suitable for construction of a
+hash table keyed on possibly malicious user input.
+
+*
+ "The value returned by a call to a Text_Buffer Get procedure if any
+ character in the returned sequence is not defined in Character.
+ See A.4.12(34)."
+
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Get is the result of passing that
+UTF_8 string to UTF_Encoding.Strings.Decode.
+
+*
+ "The value returned by a call to a Text_Buffer Wide_Get procedure if
+ any character in the returned sequence is not defined in Wide_Character.
+ See A.4.12(34)."
-``Ada.Wide_Characters.Handling.Character_Set_Version`` returns
-the string "Unicode 4.0", referring to version 4.0 of the
-Unicode specification.
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Wide_Get is the result of passing that
+UTF_8 string to UTF_Encoding.Wide_Strings.Decode.
*
"The accuracy actually achieved by the elementary
@@ -610,14 +720,6 @@ Maximum image width is 6864, see library file :file:`s-rannum.ads`.
Maximum image width is 6864, see library file :file:`s-rannum.ads`.
*
- "The algorithms for random number generation. See
- A.5.2(32)."
-
-The algorithm is the Mersenne Twister, as documented in the source file
-:file:`s-rannum.adb`. This version of the algorithm has a period of
-2**19937-1.
-
-*
"The string representation of a random number generator's
state. See A.5.2(38)."
@@ -626,32 +728,16 @@ the fixed-width decimal representations of the 624 32-bit integers
of the state vector.
*
- "The minimum time interval between calls to the
- time-dependent Reset procedure that are guaranteed to initiate different
- random number sequences. See A.5.2(45)."
-
-The minimum period between reset calls to guarantee distinct series of
-random numbers is one microsecond.
-
-*
"The values of the ``Model_Mantissa``,
``Model_Emin``, ``Model_Epsilon``, ``Model``,
``Safe_First``, and ``Safe_Last`` attributes, if the Numerics
Annex is not supported. See A.5.3(72)."
-Run the compiler with *-gnatS* to produce a listing of package
-``Standard``, has the values of all numeric attributes.
+Running the compiler with *-gnatS* to produce a listing of package
+``Standard`` displays the values of these attributes.
*
- "Any implementation-defined characteristics of the
- input-output packages. See A.7(14)."
-
-There are no special implementation defined characteristics for these
-packages.
-
-*
- "The value of ``Buffer_Size`` in ``Storage_IO``. See
- A.9(10)."
+ "The value of ``Buffer_Size`` in ``Storage_IO``. See A.9(10)."
All type representations are contiguous, and the ``Buffer_Size`` is
the value of ``type'Size`` rounded up to the next storage unit
@@ -662,17 +748,22 @@ boundary.
standard error See A.10(5)."
These files are mapped onto the files provided by the C streams
-libraries. See source file :file:`i-cstrea.ads` for further details.
+libraries. See source file :file:`i-cstrea.ads` for further details.
*
- "The accuracy of the value produced by ``Put``. See
- A.10.9(36)."
+ "The accuracy of the value produced by ``Put``. See A.10.9(36)."
If more digits are requested in the output than are represented by the
precision of the value, zeroes are output in the corresponding least
significant digit positions.
*
+ "Current size for a stream file for which positioning is not supported.
+ See A.12.1(1.1)."
+
+Positioning is supported.
+
+*
"The meaning of ``Argument_Count``, ``Argument``, and
``Command_Name``. See A.15(1)."
@@ -680,80 +771,66 @@ These are mapped onto the ``argv`` and ``argc`` parameters of the
main program in the natural manner.
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Create_Directory``. See A.16(56)."
+ "The interpretation of file names and directory names. See A.16(46)."
-The ``Form`` parameter is not used.
+These names are interpreted consistently with the underlying file system.
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Create_Path``. See A.16(60)."
+ "The maxium value for a file size in Directories. See A.16(87)."
-The ``Form`` parameter is not used.
+Directories.File_Size'Last is equal to Long_Long_Integer'Last .
*
- "The interpretation of the ``Form`` parameter in procedure
- ``Copy_File``. See A.16(68)."
+ "The result for Directories.Size for a directory or special file.
+ See A.16(93)."
-The ``Form`` parameter is case-insensitive.
-Two fields are recognized in the ``Form`` parameter::
+Name_Error is raised.
- *preserve=<value>*
- *mode=<value>*
+*
+ "The result for Directories.Modification_Time for a directory or special file.
+ See A.16(93)."
-<value> starts immediately after the character '=' and ends with the
-character immediately preceding the next comma (',') or with the last
-character of the parameter.
+Name_Error is raised.
-The only possible values for preserve= are:
+*
+ "The interpretation of a nonnull search pattern in Directories.
+ See A.16(104)."
-================== ===================================================================
-Value Meaning
-================== ===================================================================
-*no_attributes* Do not try to preserve any file attributes. This is the
- default if no preserve= is found in Form.
-*all_attributes* Try to preserve all file attributes (timestamps, access rights).
-*timestamps* Preserve the timestamp of the copied file, but not the other
- file attributes.
-================== ===================================================================
+When the ``Pattern`` parameter is not the null string, it is interpreted
+according to the syntax of regular expressions as defined in the
+``GNAT.Regexp`` package.
-The only possible values for mode= are:
+See :ref:`GNAT.Regexp_(g-regexp.ads)`.
-============== ===============================================================================
-Value Meaning
-============== ===============================================================================
-*copy* Only do the copy if the destination file does not already exist.
- If it already exists, Copy_File fails.
-*overwrite* Copy the file in all cases. Overwrite an already existing destination file.
-*append* Append the original file to the destination file. If the destination file
- does not exist, the destination file is a copy of the source file.
- When mode=append, the field preserve=, if it exists, is not taken into account.
-============== ===============================================================================
+*
+ "The results of a Directories search if the contents of the directory are
+ altered while a search is in progress. See A.16(110)."
-If the Form parameter includes one or both of the fields and the value or
-values are incorrect, Copy_file fails with Use_Error.
+The effect of a call to Get_Next_Entry is determined by the current
+state of the directory.
-Examples of correct Forms::
+*
+ "The definition and meaning of an environment variable. See A.17(1)."
- Form => "preserve=no_attributes,mode=overwrite" (the default)
- Form => "mode=append"
- Form => "mode=copy, preserve=all_attributes"
+This definition is determined by the underlying operating system.
-Examples of incorrect Forms::
+*
+ "The circumstances where an environment variable cannot be defined.
+ See A.17(16)."
- Form => "preserve=junk"
- Form => "mode=internal, preserve=timestamps"
+ There are no such implementation-defined circumstances.
*
- "The interpretation of the ``Pattern`` parameter, when not the null string,
- in the ``Start_Search`` and ``Search`` procedures.
- See A.16(104) and A.16(112)."
+ "Environment names for which Set has the effect of Clear. See A.17(17)."
-When the ``Pattern`` parameter is not the null string, it is interpreted
-according to the syntax of regular expressions as defined in the
-``GNAT.Regexp`` package.
+There are no such names.
-See :ref:`GNAT.Regexp_(g-regexp.ads)`.
+*
+ "The value of Containers.Hash_Type'Modulus. The value of
+ Containers.Count_Type'Last. See A.18.1(7)."
+
+Containers.Hash_Type'Modulus is 2**32.
+Containers.Count_Type'Last is 2**31 - 1.
*
"Implementation-defined convention names. See B.1(11)."
@@ -806,9 +883,8 @@ Convention Name Interpretation
Link names are the actual names used by the linker.
*
- "The manner of choosing link names when neither the link
- name nor the address of an imported or exported entity is specified. See
- B.1(36)."
+ "The manner of choosing link names when neither the link name nor the
+ address of an imported or exported entity is specified. See B.1(36)."
The default linker name is that which would be assigned by the relevant
external language, interpreting the Ada name as being in all lower case
@@ -845,6 +921,12 @@ See files with prefix :file:`i-` in the distributed library.
See files with prefix :file:`i-` in the distributed library.
*
+ "The definitions of certain types and constants in Interfaces.C.
+ See B.3(41)."
+
+See source file :file:`i-c.ads`.
+
+*
"The types ``Floating``, ``Long_Floating``,
``Binary``, ``Long_Binary``, ``Decimal_ Element``, and
``COBOL_Character``; and the initialization of the variables
@@ -865,45 +947,54 @@ COBOL Ada
For initialization, see the file :file:`i-cobol.ads` in the distributed library.
*
- "Support for access to machine instructions. See C.1(1)."
+ "The types Fortran_Integer, Real, Double_Precision, and Character_Set
+ in Interfaces.Fortran. See B.5(17)."
-See documentation in file :file:`s-maccod.ads` in the distributed library.
+See source file :file:`i-fortra.ads`. These types are derived, respectively,
+from Integer, Float, Long_Float, and Character.
*
- "Implementation-defined aspects of access to machine
- operations. See C.1(9)."
+ "Implementation-defined intrinsic subprograms. See C.1(1)."
-See documentation in file :file:`s-maccod.ads` in the distributed library.
+See separate section on Intrinsic Subprograms.
*
- "Implementation-defined aspects of interrupts. See C.3(2)."
+ "Any restrictions on a protected procedure or its containing type when an
+ aspect Attach_handler or Interrupt_Handler is specified. See C.3.1(17)."
-Interrupts are mapped to signals or conditions as appropriate. See
-definition of unit
-``Ada.Interrupt_Names`` in source file :file:`a-intnam.ads` for details
-on the interrupts supported on a particular target.
+There are no such restrictions.
*
- "Implementation-defined aspects of pre-elaboration. See
- C.4(13)."
+ "Any other forms of interrupt handler supported by the Attach_Handler and
+ Interrupt_Handler aspects. See C.3.1(19)."
-GNAT does not permit a partition to be restarted without reloading,
-except under control of the debugger.
+There are no such forms.
*
- "The semantics of pragma ``Discard_Names``. See C.5(7)."
+ "The semantics of some attributes and functions of an entity for which
+ aspect Discard_Names is True. See C.5(7)."
-Pragma ``Discard_Names`` causes names of enumeration literals to
-be suppressed. In the presence of this pragma, the Image attribute
+If Discard_Names is True for an enumeration type, the Image attribute
provides the image of the Pos of the literal, and Value accepts
Pos values.
-For tagged types, when pragmas ``Discard_Names`` and ``No_Tagged_Streams``
-simultaneously apply, their Expanded_Name and External_Tag are initialized
-with empty strings. This is useful to avoid exposing entity names at binary
+If both of the aspects``Discard_Names`` and ``No_Tagged_Streams`` are true
+for a tagged type, its Expanded_Name and External_Tag values are
+empty strings. This is useful to avoid exposing entity names at binary
level.
*
+ "The modulus and size of Test_and_Set_Flag. See C.6.3(8)."
+
+The modulus is 2**8. The size is 8.
+
+*
+ "The value used to represent the set value for Atomic_Test_and_Set.
+ See C.6.3(10)."
+
+The value is 1.
+
+*
"The result of the ``Task_Identification.Image``
attribute. See C.7.1(7)."
@@ -939,32 +1030,11 @@ Protected entries or interrupt handlers can be executed by any
convenient thread, so the value of ``Current_Task`` is undefined.
*
- "The effect of calling ``Current_Task`` from an entry
- body or interrupt handler. See C.7.1(19)."
+ "Granularity of locking for Task_Attributes. See C.7.2(16)."
-When GNAT can determine statically that ``Current_Task`` is called directly in
-the body of an entry (or barrier) then a warning is emitted and ``Program_Error``
-is raised at run time. Otherwise, the effect of calling ``Current_Task`` from an
-entry body or interrupt handler is to return the identification of the task
-currently executing the code.
-
-*
- "Implementation-defined aspects of
- ``Task_Attributes``. See C.7.2(19)."
-
-There are no implementation-defined aspects of ``Task_Attributes``.
-
-*
- "Values of all ``Metrics``. See D(2)."
-
-The metrics information for GNAT depends on the performance of the
-underlying operating system. The sources of the run-time for tasking
-implementation, together with the output from *-gnatG* can be
-used to determine the exact sequence of operating systems calls made
-to implement various tasking constructs. Together with appropriate
-information on the performance of the underlying operating system,
-on the exact target in use, this information can be used to determine
-the required metrics.
+No locking is needed if the formal type Attribute has the size and
+alignment of either Integer or System.Address and the bit representation
+of Initial_Value is all zeroes. Otherwise, locking is performed.
*
"The declarations of ``Any_Priority`` and
@@ -993,23 +1063,14 @@ and appropriate, these threads correspond to native threads of the
underlying operating system.
*
- "Implementation-defined *policy_identifiers* allowed
- in a pragma ``Task_Dispatching_Policy``. See D.2.2(3)."
-
-There are no implementation-defined policy-identifiers allowed in this
-pragma.
-
-*
- "Implementation-defined aspects of priority inversion. See
- D.2.2(16)."
+ "Implementation-defined task dispatching policies. See D.2.2(3)."
-Execution of a task cannot be preempted by the implementation processing
-of delay expirations for lower priority tasks.
+There are no implementation-defined task dispatching policies.
*
- "Implementation-defined task dispatching. See D.2.2(18)."
+ "The value of Default_Quantum in Dispatching.Round_Robin. See D.2.5(4)."
-The policy is the same as that of the underlying threads implementation.
+The value is 10 milliseconds.
*
"Implementation-defined *policy_identifiers* allowed
@@ -1045,12 +1106,9 @@ The ceiling priority of internal protected objects is
There are no implementation-defined queuing policies.
*
- "On a multiprocessor, any conditions that cause the
- completion of an aborted construct to be delayed later than what is
- specified for a single processor. See D.6(3)."
+ "Implementation-defined admission policies. See D.4.1(1)."
-The semantics for abort on a multi-processor is the same as on a single
-processor, there are no further delays.
+There are no implementation-defined admission policies.
*
"Any operations that implicitly require heap storage
@@ -1060,43 +1118,75 @@ The only operation that implicitly requires heap storage allocation is
task creation.
*
- "What happens when a task terminates in the presence of
- pragma ``No_Task_Termination``. See D.7(15)."
+ "When restriction No_Dynamic_CPU_Assignment applies to a partition, the
+ processor on which a task with a CPU value of a Not_A_Specific_CPU will
+ execute. See D.7(10)."
+
+Unknown.
+
+*
+ "When restriction No_Task_Termination applies to a partition, what happens
+ when a task terminates. See D.7(15.1)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Storage_At_Blocking is violated.
+ See D.7(17)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Asynchronous_Select_Nesting is violated.
+ See D.7(18)."
+
+Execution is erroneous in that case.
+
+*
+ "The behavior when restriction Max_Tasks is violated. See D.7(19)."
Execution is erroneous in that case.
+* "Whether the use of pragma Restrictions results in a reduction in program
+ code or data size or execution time. See D.7(20)."
+
+ Yes it can, but the precise circumstances and properties of such reductions
+ are difficult to characterize.
+
+*
+ "The value of Barrier_Limit'Last in Synchronous_Barriers. See D.10.1(4)."
+
+Synchronous_Barriers.Barrier_Limit'Last is Integer'Last .
+
*
- "Implementation-defined aspects of pragma
- ``Restrictions``. See D.7(20)."
+ "When an aborted task that is waiting on a Synchronous_Barrier is aborted.
+ See D.10.1(13)."
-There are no such implementation-defined aspects.
+Difficult to characterize.
*
- "Implementation-defined aspects of package
- ``Real_Time``. See D.8(17)."
+ "The value of Min_Handler_Ceiling in Execution_Time.Group_Budgets.
+ See D.14.2(7)."
-There are no implementation defined aspects of package ``Real_Time``.
+See source file :file:`a-etgrbu.ads`.
*
- "Implementation-defined aspects of
- *delay_statements*. See D.9(8)."
+ "The value of CPU_Range'Last in System.Multiprocessors. See D.16(4)."
-Any difference greater than one microsecond will cause the task to be
-delayed (see D.9(7)).
+See source file :file:`s-multip.ads`.
*
- "The upper bound on the duration of interrupt blocking
- caused by the implementation. See D.12(5)."
+ "The processor on which the environment task executes in the absence
+ of a value for the aspect CPU. See D.16(13)."
-The upper bound is determined by the underlying operating system. In
-no cases is it more than 10 milliseconds.
+Unknown.
*
"The means for creating and executing distributed
programs. See E(5)."
The GLADE package provides a utility GNATDIST for creating and executing
-distributed programs. See the GLADE reference manual for further details.
+distributed programs. See the GLADE reference manual for further details.
*
"Any events that can result in a partition becoming
@@ -1105,24 +1195,13 @@ distributed programs. See the GLADE reference manual for further details.
See the GLADE reference manual for full details on such events.
*
- "The scheduling policies, treatment of priorities, and
- management of shared resources between partitions in certain cases. See
- E.1(11)."
+ "The scheduling policies, treatment of priorities, and management of
+ shared resources between partitions in certain cases. See E.1(11)."
See the GLADE reference manual for full details on these aspects of
multi-partition execution.
*
- "Events that cause the version of a compilation unit to
- change. See E.3(5)."
-
-Editing the source file of a compilation unit, or the source files of
-any units on which it is dependent in a significant way cause the version
-to change. No other actions cause the version number to change. All changes
-are significant except those which affect only layout, capitalization or
-comments.
-
-*
"Whether the execution of the remote subprogram is
immediately aborted as a result of cancellation. See E.4(13)."
@@ -1130,14 +1209,12 @@ See the GLADE reference manual for details on the effect of abort in
a distributed application.
*
- "Implementation-defined aspects of the PCS. See E.5(25)."
+ "The range of type System.RPC.Partition_Id. See E.5(14)."
-See the GLADE reference manual for a full description of all implementation
-defined aspects of the PCS.
+System.RPC.Partion_ID'Last is Integer'Last. See source file :file:`s-rpc.ads`.
*
- "Implementation-defined interfaces in the PCS. See
- E.5(26)."
+ "Implementation-defined interfaces in the PCS. See E.5(26)."
See the GLADE reference manual for a full description of all
implementation defined interfaces.
@@ -1228,9 +1305,8 @@ properly generated.
Not relevant, division is IEEE exact.
*
- "The definition of close result set, which determines the
- accuracy of certain fixed point multiplications and divisions. See
- G.2.3(5)."
+ "The definition of close result set, which determines the accuracy of
+ certain fixed point multiplications and divisions. See G.2.3(5)."
Operations in the close result set are performed using IEEE long format
floating-point arithmetic. The input operands are converted to
@@ -1291,28 +1367,20 @@ IEEE infinite and Nan values are produced as appropriate.
Information on those subjects is not yet available.
*
- "Information regarding bounded errors and erroneous
- execution. See H.2(1)."
-
-Information on this subject is not yet available.
-
-*
- "Implementation-defined aspects of pragma
- ``Inspection_Point``. See H.3.2(8)."
+ "The accuracy requirements for the subprograms Solve, Inverse,
+ Determinant, Eigenvalues and Eigensystem for type Real_Matrix.
+ See G.3.1(81)."
-Pragma ``Inspection_Point`` ensures that the variable is live and can
-be examined by the debugger at the inspection point.
+Information on those subjects is not yet available.
*
- "Implementation-defined aspects of pragma
- ``Restrictions``. See H.4(25)."
+ "The accuracy requirements for the subprograms Solve, Inverse,
+ Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.
+ See G.3.2(149)."
-There are no implementation-defined aspects of pragma ``Restrictions``. The
-use of pragma ``Restrictions [No_Exceptions]`` has no effect on the
-generated code. Checks must suppressed by use of pragma ``Suppress``.
+Information on those subjects is not yet available.
*
- "Any restrictions on pragma ``Restrictions``. See
- H.4(27)."
+ "The consequences of violating No_Hidden_Indirect_Globals. See H.4(23.9)."
-There are no restrictions on pragma ``Restrictions``.
+Execution is erroneous in that case.
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
index 6c81ca7..0375982 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
@@ -2270,8 +2270,15 @@ of GNAT specific extensions are recognized as follows:
values of the composite type shall be covered. The composite type of the
selector shall be a nonlimited untagged (but possibly discriminated)
record type, all of whose subcomponent subtypes are either static discrete
- subtypes or record types that meet the same restrictions. Support for arrays
- is planned, but not yet implemented.
+ subtypes or record types that meet the same restrictions.
+
+ Support for casing on arrays (and on records that contain arrays) is
+ currently subject to some restrictions. Non-positional
+ array aggregates are not supported as (or within) case choices. Likewise
+ for array type and subtype names. The current implementation exceeds
+ compile-time capacity limits in some annoyingly common scenarios; the
+ message generated in such cases is usually "Capacity exceeded in compiling
+ case statement with composite selector type".
In addition, pattern bindings are supported. This is a mechanism
for binding a name to a component of a matching value for use within
@@ -2280,7 +2287,8 @@ of GNAT specific extensions are recognized as follows:
"is <identifier>". In the special case of a "box" component association,
the identifier may instead be provided within the box. Either of these
indicates that the given identifer denotes (a constant view of) the matching
- subcomponent of the case selector.
+ subcomponent of the case selector. Binding is not yet supported for arrays
+ or subcomponents thereof.
Consider this example (which uses type Rec from the previous example):
@@ -4908,43 +4916,6 @@ aspects, but is prepared to ignore the pragmas. The assertion
policy that controls this pragma is ``Post'Class``, not
``Post_Class``.
-Pragma Rename_Pragma
-============================
-.. index:: Pragmas, synonyms
-
-Syntax:
-
-
-::
-
- pragma Rename_Pragma (
- [New_Name =>] IDENTIFIER,
- [Renamed =>] pragma_IDENTIFIER);
-
-This pragma provides a mechanism for supplying new names for existing
-pragmas. The ``New_Name`` identifier can subsequently be used as a synonym for
-the Renamed pragma. For example, suppose you have code that was originally
-developed on a compiler that supports Inline_Only as an implementation defined
-pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
-least very similar to) the GNAT implementation defined pragma
-Inline_Always. You could globally replace Inline_Only with Inline_Always.
-
-However, to avoid that source modification, you could instead add a
-configuration pragma:
-
-.. code-block:: ada
-
- pragma Rename_Pragma (
- New_Name => Inline_Only,
- Renamed => Inline_Always);
-
-
-Then GNAT will treat "pragma Inline_Only ..." as if you had written
-"pragma Inline_Always ...".
-
-Pragma Inline_Only will not necessarily mean the same thing as the other Ada
-compiler; it's up to you to make sure the semantics are close enough.
-
Pragma Pre
==========
.. index:: Pre
@@ -5729,6 +5700,43 @@ In the generic unit, the formal type is subject to all restrictions
pertaining to remote access to class-wide types. At instantiation, the
actual type must be a remote access to class-wide type.
+Pragma Rename_Pragma
+============================
+.. index:: Pragmas, synonyms
+
+Syntax:
+
+
+::
+
+ pragma Rename_Pragma (
+ [New_Name =>] IDENTIFIER,
+ [Renamed =>] pragma_IDENTIFIER);
+
+This pragma provides a mechanism for supplying new names for existing
+pragmas. The ``New_Name`` identifier can subsequently be used as a synonym for
+the Renamed pragma. For example, suppose you have code that was originally
+developed on a compiler that supports Inline_Only as an implementation defined
+pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
+least very similar to) the GNAT implementation defined pragma
+Inline_Always. You could globally replace Inline_Only with Inline_Always.
+
+However, to avoid that source modification, you could instead add a
+configuration pragma:
+
+.. code-block:: ada
+
+ pragma Rename_Pragma (
+ New_Name => Inline_Only,
+ Renamed => Inline_Always);
+
+
+Then GNAT will treat "pragma Inline_Only ..." as if you had written
+"pragma Inline_Always ...".
+
+Pragma Inline_Only will not necessarily mean the same thing as the other Ada
+compiler; it's up to you to make sure the semantics are close enough.
+
Pragma Restricted_Run_Time
==========================
diff --git a/gcc/ada/doc/gnat_rm/security_hardening_features.rst b/gcc/ada/doc/gnat_rm/security_hardening_features.rst
new file mode 100644
index 0000000..1c46e3a4
--- /dev/null
+++ b/gcc/ada/doc/gnat_rm/security_hardening_features.rst
@@ -0,0 +1,89 @@
+.. _Security_Hardening_Features:
+
+***************************
+Security Hardening Features
+***************************
+
+This chapter describes Ada extensions aimed at security hardening that
+are provided by GNAT.
+
+.. Register Scrubbing:
+
+Register Scrubbing
+==================
+
+GNAT can generate code to zero-out hardware registers before returning
+from a subprogram.
+
+It can be enabled with the *-fzero-call-used-regs* command line
+option, to affect all subprograms in a compilation, and with a
+:samp:`Machine_Attribute` pragma, to affect only specific subprograms.
+
+.. code-block:: ada
+
+ procedure Foo;
+ pragma Machine_Attribute (Foo, "zero_call_used_regs", "used");
+ -- Before returning, Foo scrubs only call-clobbered registers
+ -- that it uses itself.
+
+ function Bar return Integer;
+ pragma Machine_Attribute (Bar, "zero_call_used_regs", "all");
+ -- Before returning, Bar scrubs all call-clobbered registers.
+
+
+For usage and more details on the command line option, and on the
+``zero_call_used_regs`` attribute, see :title:`Using the GNU Compiler
+Collection (GCC)`.
+
+
+.. Stack Scrubbing:
+
+Stack Scrubbing
+===============
+
+GNAT can generate code to zero-out stack frames used by subprograms.
+
+It can be activated with the :samp:`Machine_Attribute` pragma, on
+specific subprograms and variables.
+
+.. code-block:: ada
+
+ function Foo returns Integer;
+ pragma Machine_Attribute (Foo, "strub");
+ -- Foo and its callers are modified so as to scrub the stack
+ -- space used by Foo after it returns.
+
+ procedure Bar;
+ pragma Machine_Attribute (Bar, "strub", "internal");
+ -- Bar is turned into a wrapper for its original body,
+ -- and they scrub the stack used by the original body.
+
+ Var : Integer;
+ pragma Machine_Attribute (Var, "strub");
+ -- Reading from Var in a subprogram enables stack scrubbing
+ -- of the stack space used by the subprogram.
+
+
+There are also *-fstrub* command line options to control default
+settings. For usage and more details on the command line option, and
+on the ``strub`` attribute, see :title:`Using the GNU Compiler
+Collection (GCC)`.
+
+Note that Ada secondary stacks are not scrubbed. The restriction
+``No_Secondary_Stack`` avoids their use, and thus their accidental
+preservation of data that should be scrubbed.
+
+Also note that the machine attribute is not integrated in the Ada type
+system. Though it may modify subprogram and variable interfaces, it
+is not fully reflected in Ada types, ``Access`` attributes, renaming
+and overriding. Every access type, renaming, and overriding and
+overridden dispatching operations that may refer to an entity with an
+attribute-modified interface must be annotated with the same
+interface-modifying attribute, or with an interface-compatible one.
+
+Even then, the pragma is currently only functional when applied to
+subprograms and scalar variables; other uses, such as directly on
+types and subtypes, may be silently ignored. Specifically, it is not
+currently recommended to rely on any effects this pragma might be
+expected to have when calling subprograms through access-to-subprogram
+variables.
diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
index 3e7dc051..cbd780b 100644
--- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
+++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
@@ -870,6 +870,44 @@ used, the compiler is allowed to suppress the elaboration counter normally
associated with the unit. This counter is typically used to check for access
before elaboration and to control multiple elaboration attempts.
+No_Dynamic_Accessibility_Checks
+-------------------------------
+.. index:: No_Dynamic_Accessibility_Checks
+
+[GNAT] No dynamic accessibility checks are generated when this restriction is
+in effect. Instead, dangling references are prevented via more conservative
+compile-time checking. More specifically, existing compile-time checks are
+enforced but with more conservative assumptions about the accessibility levels
+of the relevant entities. These conservative assumptions eliminate the need for
+dynamic accessibility checks.
+
+These new rules for computing (at compile-time) the accessibility level of an
+anonymous access type T are as follows:
+
+*
+ If T is a function result type then, from the caller's perspective, its level
+ is that of the innermost master enclosing the function call. From the callee's
+ perspective, the level of parameters and local variables of the callee is
+ statically deeper than the level of T.
+
+ For any other accessibility level L such that the level of parameters and local
+ variables of the callee is statically deeper than L, the level of T (from the
+ callee's perspective) is also statically deeper than L.
+*
+ If T is the type of a formal parameter then, from the caller's perspective,
+ its level is at least as deep as that of the type of the corresponding actual
+ parameter (whatever that actual parameter might be). From the callee's
+ perspective, the level of parameters and local variables of the callee is
+ statically deeper than the level of T.
+*
+ If T is the type of a discriminant then its level is that of the discriminated
+ type.
+*
+ If T is the type of a stand-alone object then its level is the level of the
+ object.
+*
+ In all other cases, the level of T is as defined by the existing rules of Ada.
+
No_Dynamic_Sized_Objects
------------------------
.. index:: No_Dynamic_Sized_Objects
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 07c38df..67fd130 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
@@ -1497,9 +1497,10 @@ Alphabetical List of All Switches
:switch:`-gnateA`
Check that the actual parameters of a subprogram call are not aliases of one
- another. To qualify as aliasing, the actuals must denote objects of a composite
- type, their memory locations must be identical or overlapping, and at least one
- of the corresponding formal parameters must be of mode OUT or IN OUT.
+ another. To qualify as aliasing, their memory locations must be identical or
+ overlapping, at least one of the corresponding formal parameters must be of
+ mode OUT or IN OUT, and at least one of the corresponding formal parameters
+ must have its parameter passing mechanism not specified.
.. code-block:: ada
@@ -4157,16 +4158,16 @@ of the pragma in the :title:`GNAT_Reference_manual`).
This switch enables most warnings from the GCC back end.
The code generator detects a number of warning situations that are missed
by the GNAT front end, and this switch can be used to activate them.
- The use of this switch also sets the default front end warning mode to
- :switch:`-gnatwa`, that is, most front end warnings activated as well.
+ The use of this switch also sets the default front-end warning mode to
+ :switch:`-gnatwa`, that is, most front-end warnings are activated as well.
.. index:: -w (gcc)
:switch:`-w`
Conversely, this switch suppresses warnings from the GCC back end.
- The use of this switch also sets the default front end warning mode to
- :switch:`-gnatws`, that is, front end warnings suppressed as well.
+ The use of this switch also sets the default front-end warning mode to
+ :switch:`-gnatws`, that is, front-end warnings are suppressed as well.
.. index:: -Werror (gcc)
@@ -4175,6 +4176,9 @@ of the pragma in the :title:`GNAT_Reference_manual`).
This switch causes warnings from the GCC back end to be treated as
errors. The warning string still appears, but the warning messages are
counted as errors, and prevent the generation of an object file.
+ The use of this switch also sets the default front-end warning mode to
+ :switch:`-gnatwe`, that is, front-end warning messages and style check
+ messages are treated as errors as well.
A string of warning parameters can be used in the same parameter. For example::
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 c4f186e..24ef9d6 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
@@ -3680,8 +3680,9 @@ execution of this erroneous program:
The ``gnatmem`` utility monitors dynamic allocation and
deallocation activity in a program, and displays information about
incorrect deallocations and possible sources of memory leaks.
- It is designed to work in association with a static runtime library
- only and in this context provides three types of information:
+ It is designed to work for fixed-position executables in association
+ with a static runtime library only and in this context provides three
+ types of information:
* General information concerning memory management, such as the total
number of allocations and deallocations, the amount of allocated
@@ -3711,15 +3712,16 @@ execution of this erroneous program:
$ gnatmem [ switches ] [ DEPTH ] user_program
- The program must have been linked with the instrumented version of the
+ The user program must be linked with the instrumented version of the
allocation and deallocation routines. This is done by linking with the
:file:`libgmem.a` library. For correct symbolic backtrace information,
- the user program should be compiled with debugging options
- (see :ref:`Switches_for_gcc`). For example to build :file:`my_program`:
+ the user program should also both be compiled with debugging options
+ (see :ref:`Switches_for_gcc`) and be linked at a fixed position. For
+ example to build :file:`my_program` with ``gnatmake``:
::
- $ gnatmake -g my_program -largs -lgmem
+ $ gnatmake -g my_program -largs -lgmem -no-pie
As library :file:`libgmem.a` contains an alternate body for package
``System.Memory``, :file:`s-memory.adb` should not be compiled and linked
diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
index f152ce3..d030cd4 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
@@ -4294,10 +4294,13 @@ building specialized scripts.
Standard Output. Has no effect otherwise.
:switch:`--count={N}`
- If specified, compute the symbolic traceback ``N`` times in a row.
- This option is mostly useful for measuring the performance of
- ``gnatsymbolize``, particularly in the case where the cache is
- being used.
+ Compute the symbolic traceback ``N`` times in a row. This option
+ is mostly useful for measuring the performance of ``gnatsymbolize``,
+ particularly in the case where the cache is being used.
+
+ :switch:`--load`
+ Interpret the first address as the load address of the executable.
+ This is needed for position-independent executables on Windows.
Requirements for Correct Operation
----------------------------------
@@ -4311,12 +4314,7 @@ building specialized scripts.
This program provides a functionality similar to ``addr2line``.
It has fewer options to tailor its output, but has been designed
to require fewer of the DWARF sections to be present in the
- executable. In particular, the following sections can be
- stripped from the executable without impact to ``gnatsymbolize``'s
- functionality:
-
- * ``.debug_str``
- * ``.debug_ranges``
+ executable. In particular, it works for code compiled with ``-g1``.
.. only:: PRO or GPL
diff --git a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
index 13993b8..4f68d25 100644
--- a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
+++ b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst
@@ -217,7 +217,10 @@ this in a library package body in your application:
(if geteuid = 0 then True else raise Program_Error with "must be root");
It gets the effective user id, and if it's not 0 (i.e. root), it raises
-Program_Error.
+Program_Error. Note that if you re running the code in a container, this may
+not be sufficient, as you may have sufficient priviledge on the container,
+but not on the host machine running the container, so check that you also
+have sufficient priviledge for running the container image.
.. index:: Linux
.. index:: GNU/Linux
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 39b9ca1..4a3b84d 100644
--- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
+++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
@@ -1409,16 +1409,12 @@ recognized by GNAT::
Check_Float_Overflow
Check_Name
Check_Policy
- Compile_Time_Error
- Compile_Time_Warning
- Compiler_Unit
- Compiler_Unit_Warning
Component_Alignment
Convention_Identifier
Debug_Policy
- Detect_Blocking
Default_Scalar_Storage_Order
Default_Storage_Pool
+ Detect_Blocking
Disable_Atomic_Synchronization
Discard_Names
Elaboration_Checks
@@ -1437,7 +1433,6 @@ recognized by GNAT::
Locking_Policy
No_Component_Reordering
No_Heap_Finalization
- No_Run_Time
No_Strict_Aliasing
Normalize_Scalars
Optimize_Alignment
@@ -1449,17 +1444,12 @@ recognized by GNAT::
Priority_Specific_Dispatching
Profile
Profile_Warnings
- Propagate_Exceptions
Queuing_Policy
- Rational
- Ravenscar
Rename_Pragma
- Restricted_Run_Time
Restrictions
- Restrictions_Warnings
+ Restriction_Warnings
Reviewable
Short_Circuit_And_Or
- Short_Descriptors
Source_File_Name
Source_File_Name_Project
SPARK_Mode
@@ -1468,7 +1458,6 @@ recognized by GNAT::
Suppress_Exception_Locations
Task_Dispatching_Policy
Unevaluated_Use_Of_Old
- Universal_Data
Unsuppress
Use_VADS_Size
Validity_Checks
@@ -1514,7 +1503,7 @@ only to the unit in which the pragma appears, and not to any other units.
The exception is No_Elaboration_Code which always applies to the entire
object file from a compilation, i.e. to the body, spec, and all subunits.
This restriction can be specified in a configuration pragma file, or it
-can be on the body and/or the spec (in eithe case it applies to all the
+can be on the body and/or the spec (in either case it applies to all the
relevant units). It can appear on a subunit only if it has previously
appeared in the body of spec.
@@ -4526,8 +4515,8 @@ Some of the known limitations include:
constants. Function macros (macros with arguments) are partially translated
as comments, to be completed manually if needed.
* some extensions (e.g. vector types) are not supported
-* pointers to pointers or complex structures are mapped to System.Address
-* identifiers with identical name (except casing) will generate compilation
+* pointers to pointers are mapped to System.Address
+* identifiers with identical name (except casing) may generate compilation
errors (e.g. ``shm_get`` vs ``SHM_GET``).
The code is generated using Ada 2012 syntax, which makes it easier to interface
@@ -4546,14 +4535,17 @@ header files needed by these files transitively. For example:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec -C /usr/include/time.h
+ $ gcc -c -fdump-ada-spec -C /usr/include/time.h
$ gcc -c *.ads
will generate, under GNU/Linux, the following files: :file:`time_h.ads`,
:file:`bits_time_h.ads`, :file:`stddef_h.ads`, :file:`bits_types_h.ads` which
correspond to the files :file:`/usr/include/time.h`,
-:file:`/usr/include/bits/time.h`, etc..., and will then compile these Ada specs
-in Ada 2005 mode.
+:file:`/usr/include/bits/time.h`, etc..., and then compile these Ada specs.
+That is to say, the name of the Ada specs is in keeping with the relative path
+under :file:`/usr/include/` of the header files. This behavior is specific to
+paths ending with :file:`/include/`; in all the other cases, the name of the
+Ada specs is derived from the simple name of the header files instead.
The :switch:`-C` switch tells ``gcc`` to extract comments from headers,
and will attempt to generate corresponding Ada comments.
@@ -4564,39 +4556,8 @@ can use instead the :switch:`-fdump-ada-spec-slim` switch.
You can optionally specify a parent unit, of which all generated units will
be children, using :switch:`-fada-spec-parent={unit}`.
-Note that we recommend when possible to use the *g++* driver to
-generate bindings, even for most C headers, since this will in general
-generate better Ada specs. For generating bindings for C++ headers, it is
-mandatory to use the *g++* command, or *gcc -x c++* which
-is equivalent in this case. If *g++* cannot work on your C headers
-because of incompatibilities between C and C++, then you can fallback to
-``gcc`` instead.
-
-For an example of better bindings generated from the C++ front-end,
-the name of the parameters (when available) are actually ignored by the C
-front-end. Consider the following C header:
-
-.. code-block:: c
-
- extern void foo (int variable);
-
-with the C front-end, ``variable`` is ignored, and the above is handled as:
-
-.. code-block:: c
-
- extern void foo (int);
-
-generating a generic:
-
-.. code-block:: ada
-
- procedure foo (param1 : int);
-
-with the C++ front-end, the name is available, and we generate:
-
-.. code-block:: ada
-
- procedure foo (variable : int);
+The simple ``gcc```-based command works only for C headers. For C++ headers
+you need to use either the ``g++`` command or the combination ``gcc -x c++```.
In some cases, the generated bindings will be more complete or more meaningful
when defining some macros, which you can do via the :switch:`-D` switch. This
@@ -4604,7 +4565,7 @@ is for example the case with :file:`Xlib.h` under GNU/Linux:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
+ $ gcc -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
The above will generate more complete bindings than a straight call without
the :switch:`-DXLIB_ILLEGAL_ACCESS` switch.
@@ -4626,7 +4587,7 @@ and then generate Ada bindings from this file:
.. code-block:: sh
- $ g++ -c -fdump-ada-spec readline1.h
+ $ gcc -c -fdump-ada-spec readline1.h
.. _Generating_bindings_for_C++_headers:
@@ -4851,7 +4812,7 @@ GNAT and Other Compilation Models
=================================
This section compares the GNAT model with the approaches taken in
-other environents, first the C/C++ model and then the mechanism that
+other environments, first the C/C++ model and then the mechanism that
has been used in other Ada systems, in particular those traditionally
used for Ada 83.
diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb
index 4690c8f..0274e6b 100644
--- a/gcc/ada/einfo-utils.adb
+++ b/gcc/ada/einfo-utils.adb
@@ -358,131 +358,180 @@ package body Einfo.Utils is
return Ekind (Id) in Type_Kind;
end Is_Type;
- -----------------------------------
- -- Field Initialization Routines --
- -----------------------------------
+ ------------------------------------------
+ -- Type Representation Attribute Fields --
+ ------------------------------------------
- procedure Init_Alignment (Id : E) is
+ function Known_Alignment (E : Entity_Id) return B is
begin
- Reinit_Field_To_Zero (Id, F_Alignment);
- end Init_Alignment;
+ -- For some reason, Empty is passed to this sometimes
+
+ return No (E) or else not Field_Is_Initial_Zero (E, F_Alignment);
+ end Known_Alignment;
- procedure Init_Alignment (Id : E; V : Int) is
+ procedure Reinit_Alignment (Id : E) is
begin
- Set_Alignment (Id, UI_From_Int (V));
- end Init_Alignment;
+ Reinit_Field_To_Zero (Id, F_Alignment);
+ end Reinit_Alignment;
- procedure Init_Component_Bit_Offset (Id : E) is
+ procedure Copy_Alignment (To, From : E) is
begin
- Set_Component_Bit_Offset (Id, No_Uint);
- end Init_Component_Bit_Offset;
+ if Known_Alignment (From) then
+ Set_Alignment (To, Alignment (From));
+ else
+ Reinit_Alignment (To);
+ end if;
+ end Copy_Alignment;
- procedure Init_Component_Bit_Offset (Id : E; V : Int) is
+ function Known_Component_Bit_Offset (E : Entity_Id) return B is
begin
- Set_Component_Bit_Offset (Id, UI_From_Int (V));
- end Init_Component_Bit_Offset;
+ return Present (Component_Bit_Offset (E));
+ end Known_Component_Bit_Offset;
- procedure Init_Component_Size (Id : E) is
+ function Known_Static_Component_Bit_Offset (E : Entity_Id) return B is
begin
- Set_Component_Size (Id, Uint_0);
- end Init_Component_Size;
+ return Present (Component_Bit_Offset (E))
+ and then Component_Bit_Offset (E) >= Uint_0;
+ end Known_Static_Component_Bit_Offset;
- procedure Init_Component_Size (Id : E; V : Int) is
+ function Known_Component_Size (E : Entity_Id) return B is
begin
- Set_Component_Size (Id, UI_From_Int (V));
- end Init_Component_Size;
+ return Component_Size (E) /= Uint_0
+ and then Present (Component_Size (E));
+ end Known_Component_Size;
- procedure Init_Digits_Value (Id : E) is
+ function Known_Static_Component_Size (E : Entity_Id) return B is
begin
- Set_Digits_Value (Id, Uint_0);
- end Init_Digits_Value;
+ return Component_Size (E) > Uint_0;
+ end Known_Static_Component_Size;
+
+ Use_New_Unknown_Rep : constant Boolean := False;
+ -- If False, we represent "unknown" as Uint_0, which is wrong.
+ -- We intend to make it True (and remove it), and represent
+ -- "unknown" as Field_Is_Initial_Zero. We also need to change
+ -- the type of Esize and RM_Size from Uint to Valid_Uint.
- procedure Init_Digits_Value (Id : E; V : Int) is
+ function Known_Esize (E : Entity_Id) return B is
begin
- Set_Digits_Value (Id, UI_From_Int (V));
- end Init_Digits_Value;
+ if Use_New_Unknown_Rep then
+ return not Field_Is_Initial_Zero (E, F_Esize);
+ else
+ return Present (Esize (E)) and then Esize (E) /= Uint_0;
+ end if;
+ end Known_Esize;
- procedure Init_Esize (Id : E) is
+ function Known_Static_Esize (E : Entity_Id) return B is
begin
- Set_Esize (Id, Uint_0);
- end Init_Esize;
+ return Known_Esize (E)
+ and then Esize (E) >= Uint_0
+ and then not Is_Generic_Type (E);
+ end Known_Static_Esize;
- procedure Init_Esize (Id : E; V : Int) is
+ procedure Reinit_Esize (Id : E) is
begin
- Set_Esize (Id, UI_From_Int (V));
- end Init_Esize;
+ if Use_New_Unknown_Rep then
+ Reinit_Field_To_Zero (Id, F_Esize);
+ else
+ Set_Esize (Id, Uint_0);
+ end if;
+ end Reinit_Esize;
- procedure Init_Normalized_First_Bit (Id : E) is
+ procedure Copy_Esize (To, From : E) is
begin
- Set_Normalized_First_Bit (Id, No_Uint);
- end Init_Normalized_First_Bit;
+ if Known_Esize (From) then
+ Set_Esize (To, Esize (From));
+ else
+ Reinit_Esize (To);
+ end if;
+ end Copy_Esize;
- procedure Init_Normalized_First_Bit (Id : E; V : Int) is
+ function Known_Normalized_First_Bit (E : Entity_Id) return B is
begin
- Set_Normalized_First_Bit (Id, UI_From_Int (V));
- end Init_Normalized_First_Bit;
+ return Present (Normalized_First_Bit (E));
+ end Known_Normalized_First_Bit;
- procedure Init_Normalized_Position (Id : E) is
+ function Known_Static_Normalized_First_Bit (E : Entity_Id) return B is
begin
- Set_Normalized_Position (Id, No_Uint);
- end Init_Normalized_Position;
+ return Present (Normalized_First_Bit (E))
+ and then Normalized_First_Bit (E) >= Uint_0;
+ end Known_Static_Normalized_First_Bit;
- procedure Init_Normalized_Position (Id : E; V : Int) is
+ function Known_Normalized_Position (E : Entity_Id) return B is
begin
- Set_Normalized_Position (Id, UI_From_Int (V));
- end Init_Normalized_Position;
+ return Present (Normalized_Position (E));
+ end Known_Normalized_Position;
- procedure Init_Normalized_Position_Max (Id : E) is
+ function Known_Static_Normalized_Position (E : Entity_Id) return B is
begin
- Set_Normalized_Position_Max (Id, No_Uint);
- end Init_Normalized_Position_Max;
+ return Present (Normalized_Position (E))
+ and then Normalized_Position (E) >= Uint_0;
+ end Known_Static_Normalized_Position;
- procedure Init_Normalized_Position_Max (Id : E; V : Int) is
+ function Known_RM_Size (E : Entity_Id) return B is
begin
- Set_Normalized_Position_Max (Id, UI_From_Int (V));
- end Init_Normalized_Position_Max;
+ if Use_New_Unknown_Rep then
+ return not Field_Is_Initial_Zero (E, F_RM_Size);
+ else
+ return Present (RM_Size (E))
+ and then (RM_Size (E) /= Uint_0
+ or else Is_Discrete_Type (E)
+ or else Is_Fixed_Point_Type (E));
+ end if;
+ end Known_RM_Size;
- procedure Init_RM_Size (Id : E) is
+ function Known_Static_RM_Size (E : Entity_Id) return B is
begin
- Set_RM_Size (Id, Uint_0);
- end Init_RM_Size;
+ if Use_New_Unknown_Rep then
+ return Known_RM_Size (E)
+ and then RM_Size (E) >= Uint_0
+ and then not Is_Generic_Type (E);
+ else
+ return (RM_Size (E) > Uint_0
+ or else Is_Discrete_Type (E)
+ or else Is_Fixed_Point_Type (E))
+ and then not Is_Generic_Type (E);
+ end if;
+ end Known_Static_RM_Size;
- procedure Init_RM_Size (Id : E; V : Int) is
+ procedure Reinit_RM_Size (Id : E) is
begin
- Set_RM_Size (Id, UI_From_Int (V));
- end Init_RM_Size;
+ if Use_New_Unknown_Rep then
+ Reinit_Field_To_Zero (Id, F_RM_Size);
+ else
+ Set_RM_Size (Id, Uint_0);
+ end if;
+ end Reinit_RM_Size;
- procedure Copy_Alignment (To, From : E) is
+ procedure Copy_RM_Size (To, From : E) is
begin
- if Known_Alignment (From) then
- Set_Alignment (To, Alignment (From));
+ if Known_RM_Size (From) then
+ Set_RM_Size (To, RM_Size (From));
else
- Init_Alignment (To);
+ Reinit_RM_Size (To);
end if;
- end Copy_Alignment;
+ end Copy_RM_Size;
- -----------------------------
- -- Init_Component_Location --
- -----------------------------
+ -------------------------------
+ -- Reinit_Component_Location --
+ -------------------------------
- procedure Init_Component_Location (Id : E) is
+ procedure Reinit_Component_Location (Id : E) is
begin
- Set_Normalized_First_Bit (Id, No_Uint);
- Set_Normalized_Position_Max (Id, No_Uint);
+ Set_Normalized_First_Bit (Id, No_Uint);
Set_Component_Bit_Offset (Id, No_Uint);
- Set_Esize (Id, Uint_0);
+ Reinit_Esize (Id);
Set_Normalized_Position (Id, No_Uint);
- end Init_Component_Location;
+ end Reinit_Component_Location;
- ----------------------------
- -- Init_Object_Size_Align --
- ----------------------------
+ ------------------------------
+ -- Reinit_Object_Size_Align --
+ ------------------------------
- procedure Init_Object_Size_Align (Id : E) is
+ procedure Reinit_Object_Size_Align (Id : E) is
begin
- Init_Esize (Id);
- Init_Alignment (Id);
- end Init_Object_Size_Align;
+ Reinit_Esize (Id);
+ Reinit_Alignment (Id);
+ end Reinit_Object_Size_Align;
---------------
-- Init_Size --
@@ -491,120 +540,25 @@ package body Einfo.Utils is
procedure Init_Size (Id : E; V : Int) is
begin
pragma Assert (Is_Type (Id));
- pragma Assert
- (not Known_Esize (Id) or else Esize (Id) = V);
- pragma Assert
- (RM_Size (Id) = No_Uint
- or else RM_Size (Id) = Uint_0
- or else RM_Size (Id) = V);
+ pragma Assert (not Known_Esize (Id) or else Esize (Id) = V);
+ if Use_New_Unknown_Rep then
+ pragma Assert (not Known_RM_Size (Id) or else RM_Size (Id) = V);
+ end if;
Set_Esize (Id, UI_From_Int (V));
Set_RM_Size (Id, UI_From_Int (V));
end Init_Size;
- ---------------------
- -- Init_Size_Align --
- ---------------------
+ -----------------------
+ -- Reinit_Size_Align --
+ -----------------------
- procedure Init_Size_Align (Id : E) is
+ procedure Reinit_Size_Align (Id : E) is
begin
pragma Assert (Ekind (Id) in Type_Kind | E_Void);
- Init_Esize (Id);
- Init_RM_Size (Id);
- Init_Alignment (Id);
- end Init_Size_Align;
-
- ----------------------------------------------
- -- Type Representation Attribute Predicates --
- ----------------------------------------------
-
- function Known_Alignment (E : Entity_Id) return B is
- Result : constant B := not Field_Is_Initial_Zero (E, F_Alignment);
- begin
- return Result;
- end Known_Alignment;
-
- function Known_Component_Bit_Offset (E : Entity_Id) return B is
- begin
- return Component_Bit_Offset (E) /= No_Uint;
- end Known_Component_Bit_Offset;
-
- function Known_Component_Size (E : Entity_Id) return B is
- begin
- return Component_Size (E) /= Uint_0
- and then Component_Size (E) /= No_Uint;
- end Known_Component_Size;
-
- function Known_Esize (E : Entity_Id) return B is
- begin
- return Esize (E) /= Uint_0
- and then Esize (E) /= No_Uint;
- end Known_Esize;
-
- function Known_Normalized_First_Bit (E : Entity_Id) return B is
- begin
- return Normalized_First_Bit (E) /= No_Uint;
- end Known_Normalized_First_Bit;
-
- function Known_Normalized_Position (E : Entity_Id) return B is
- begin
- return Normalized_Position (E) /= No_Uint;
- end Known_Normalized_Position;
-
- function Known_Normalized_Position_Max (E : Entity_Id) return B is
- begin
- return Normalized_Position_Max (E) /= No_Uint;
- end Known_Normalized_Position_Max;
-
- function Known_RM_Size (E : Entity_Id) return B is
- begin
- return RM_Size (E) /= No_Uint
- and then (RM_Size (E) /= Uint_0
- or else Is_Discrete_Type (E)
- or else Is_Fixed_Point_Type (E));
- end Known_RM_Size;
-
- function Known_Static_Component_Bit_Offset (E : Entity_Id) return B is
- begin
- return Component_Bit_Offset (E) /= No_Uint
- and then Component_Bit_Offset (E) >= Uint_0;
- end Known_Static_Component_Bit_Offset;
-
- function Known_Static_Component_Size (E : Entity_Id) return B is
- begin
- return Component_Size (E) > Uint_0;
- end Known_Static_Component_Size;
-
- function Known_Static_Esize (E : Entity_Id) return B is
- begin
- return Esize (E) > Uint_0
- and then not Is_Generic_Type (E);
- end Known_Static_Esize;
-
- function Known_Static_Normalized_First_Bit (E : Entity_Id) return B is
- begin
- return Normalized_First_Bit (E) /= No_Uint
- and then Normalized_First_Bit (E) >= Uint_0;
- end Known_Static_Normalized_First_Bit;
-
- function Known_Static_Normalized_Position (E : Entity_Id) return B is
- begin
- return Normalized_Position (E) /= No_Uint
- and then Normalized_Position (E) >= Uint_0;
- end Known_Static_Normalized_Position;
-
- function Known_Static_Normalized_Position_Max (E : Entity_Id) return B is
- begin
- return Normalized_Position_Max (E) /= No_Uint
- and then Normalized_Position_Max (E) >= Uint_0;
- end Known_Static_Normalized_Position_Max;
-
- function Known_Static_RM_Size (E : Entity_Id) return B is
- begin
- return (RM_Size (E) > Uint_0
- or else Is_Discrete_Type (E)
- or else Is_Fixed_Point_Type (E))
- and then not Is_Generic_Type (E);
- end Known_Static_RM_Size;
+ Reinit_Esize (Id);
+ Reinit_RM_Size (Id);
+ Reinit_Alignment (Id);
+ end Reinit_Size_Align;
--------------------
-- Address_Clause --
@@ -701,16 +655,21 @@ package body Einfo.Utils is
P := Parent (Id);
end if;
+ while Nkind (P) in N_Selected_Component | N_Expanded_Name
+ or else (Nkind (P) = N_Defining_Program_Unit_Name
+ and then Is_Child_Unit (Id))
loop
- if Nkind (P) in N_Selected_Component | N_Expanded_Name
- or else (Nkind (P) = N_Defining_Program_Unit_Name
- and then Is_Child_Unit (Id))
- then
- P := Parent (P);
- else
- return P;
- end if;
+ P := Parent (P);
end loop;
+
+ if Is_Itype (Id)
+ and then Nkind (P) not in
+ N_Full_Type_Declaration | N_Subtype_Declaration
+ then
+ P := Empty;
+ end if;
+
+ return P;
end Declaration_Node;
---------------------
@@ -749,7 +708,7 @@ package body Einfo.Utils is
-- Entry_Index_Type --
----------------------
- function Entry_Index_Type (Id : E) return N is
+ function Entry_Index_Type (Id : E) return E is
begin
pragma Assert (Ekind (Id) = E_Entry_Family);
return Etype (Discrete_Subtype_Definition (Parent (Id)));
@@ -1471,26 +1430,19 @@ package body Einfo.Utils is
function Is_Dynamic_Scope (Id : E) return B is
begin
- return
- Ekind (Id) = E_Block
- or else
- Ekind (Id) = E_Function
- or else
- Ekind (Id) = E_Procedure
- or else
- Ekind (Id) = E_Subprogram_Body
- or else
- Ekind (Id) = E_Task_Type
- or else
- (Ekind (Id) = E_Limited_Private_Type
- and then Present (Full_View (Id))
- and then Ekind (Full_View (Id)) = E_Task_Type)
- or else
- Ekind (Id) = E_Entry
- or else
- Ekind (Id) = E_Entry_Family
+ return Ekind (Id) in E_Block
+ -- Including an E_Block that came from an N_Expression_With_Actions
+ | E_Entry
+ | E_Entry_Family
+ | E_Function
+ | E_Procedure
+ | E_Return_Statement
+ | E_Subprogram_Body
+ | E_Task_Type
or else
- Ekind (Id) = E_Return_Statement;
+ (Ekind (Id) = E_Limited_Private_Type
+ and then Present (Full_View (Id))
+ and then Ekind (Full_View (Id)) = E_Task_Type);
end Is_Dynamic_Scope;
--------------------
@@ -1793,7 +1745,7 @@ package body Einfo.Utils is
-- Link_Entities --
-------------------
- procedure Link_Entities (First : Entity_Id; Second : Node_Id) is
+ procedure Link_Entities (First, Second : Entity_Id) is
begin
if Present (Second) then
Set_Prev_Entity (Second, First); -- First <-- Second
@@ -2022,6 +1974,8 @@ package body Einfo.Utils is
function Next_Index (Id : Node_Id) return Node_Id is
begin
+ pragma Assert (Nkind (Id) in N_Is_Index);
+ pragma Assert (No (Next (Id)) or else Nkind (Next (Id)) in N_Is_Index);
return Next (Id);
end Next_Index;
diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads
index a6517b9..8046722 100644
--- a/gcc/ada/einfo-utils.ads
+++ b/gcc/ada/einfo-utils.ads
@@ -310,75 +310,115 @@ package Einfo.Utils is
pragma Inline (Type_High_Bound);
pragma Inline (Type_Low_Bound);
- ----------------------------------------------
- -- Type Representation Attribute Predicates --
- ----------------------------------------------
-
- -- These predicates test the setting of the indicated attribute. The
- -- Known predicate is True if and only if the value has been set. The
- -- Known_Static predicate is True only if the value is set (Known) and is
- -- set to a compile time known value. Note that in the case of Alignment
- -- and Normalized_First_Bit, dynamic values are not possible, so we do not
- -- need a separate Known_Static calls in these cases. The not set (unknown)
- -- values are as follows:
-
- -- Alignment Uint_0 or No_Uint
- -- Component_Size Uint_0 or No_Uint
- -- Component_Bit_Offset No_Uint
- -- Digits_Value Uint_0 or No_Uint
- -- Esize Uint_0 or No_Uint
- -- Normalized_First_Bit No_Uint
- -- Normalized_Position No_Uint
- -- Normalized_Position_Max No_Uint
- -- RM_Size Uint_0 or No_Uint
-
- -- It would be cleaner to use No_Uint in all these cases, but historically
- -- we chose to use Uint_0 at first, and the change over will take time ???
- -- This is particularly true for the RM_Size field, where a value of zero
- -- is legitimate. We deal with this by a considering that the value is
- -- always known static for discrete types (and no other types can have
- -- an RM_Size value of zero).
-
+ ------------------------------------------
+ -- Type Representation Attribute Fields --
+ ------------------------------------------
+
+ -- Each of the following fields can be in a "known" or "unknown" state:
+
+ -- Alignment
+ -- Component_Size
+ -- Component_Bit_Offset
+ -- Digits_Value
+ -- Esize
+ -- Normalized_First_Bit
+ -- Normalized_Position
+ -- RM_Size
+ --
+ -- NOTE: "known" here does not mean "known at compile time". It means that
+ -- the compiler has computed the value of the field (either by default, or
+ -- by noting some representation clauses), and the field has not been
+ -- reinitialized.
+ --
+ -- We document the Esize functions here; the others are analogous:
+ --
+ -- Known_Esize: True if Set_Esize has been called without a subsequent
+ -- Reinit_Esize.
+ --
+ -- Known_Static_Esize: True if Known_Esize and the Esize is known at
+ -- compile time. (We're not using "static" in the Ada RM sense here. We
+ -- are using it to mean "known at compile time.)
+ --
+ -- Reinit_Esize: Set the Esize field to its initial unknown state.
+ --
+ -- Copy_Esize: Copies the Esize from From to To; Known_Esize (From) may
+ -- be False, in which case Known_Esize (To) becomes False.
+ --
+ -- Esize: This is the normal automatially-generated getter for Esize,
+ -- declared elsewhere. It is an error to call this if Set_Esize has not
+ -- yet been called, or if Reinit_Esize has been called subsequently.
+ --
+ -- Set_Esize: This is the normal automatially-generated setter for
+ -- Esize. After a call to this, Known_Esize is True. It is an error
+ -- to call this with a No_Uint value.
+ --
+ -- Normally, we call Set_Esize first, and then query Esize (and similarly
+ -- for other fields). However in some cases, we need to check Known_Esize
+ -- before calling Esize, because the code is written in such a way that we
+ -- don't know whether Set_Esize has already been called.
+ --
+ -- We intend to use the initial zero value to represent "unknown". Note
+ -- that this value is different from No_Uint, and different from Uint_0.
+ -- However, this is work in progress; we are still using No_Uint or Uint_0
+ -- to represent "unknown" in some cases. Using Uint_0 leads to several
+ -- bugs, because zero is a legitimate value (T'Size can be zero bits) --
+ -- Uint_0 shouldn't mean two different things.
+ --
-- In two cases, Known_Static_Esize and Known_Static_RM_Size, there is one
-- more consideration, which is that we always return False for generic
- -- types. Within a template, the size can look known, because of the fake
- -- size values we put in template types, but they are not really known and
- -- anyone testing if they are known within the template should get False as
- -- a result to prevent incorrect assumptions.
-
- function Known_Alignment (E : Entity_Id) return B;
- function Known_Component_Bit_Offset (E : Entity_Id) return B;
- function Known_Component_Size (E : Entity_Id) return B;
- function Known_Esize (E : Entity_Id) return B;
- function Known_Normalized_First_Bit (E : Entity_Id) return B;
- function Known_Normalized_Position (E : Entity_Id) return B;
- function Known_Normalized_Position_Max (E : Entity_Id) return B;
- function Known_RM_Size (E : Entity_Id) return B;
-
- function Known_Static_Component_Bit_Offset (E : Entity_Id) return B;
- function Known_Static_Component_Size (E : Entity_Id) return B;
- function Known_Static_Esize (E : Entity_Id) return B;
- function Known_Static_Normalized_First_Bit (E : Entity_Id) return B;
- function Known_Static_Normalized_Position (E : Entity_Id) return B;
- function Known_Static_Normalized_Position_Max (E : Entity_Id) return B;
- function Known_Static_RM_Size (E : Entity_Id) return B;
-
- pragma Inline (Known_Alignment);
- pragma Inline (Known_Component_Bit_Offset);
- pragma Inline (Known_Component_Size);
- pragma Inline (Known_Esize);
- pragma Inline (Known_Normalized_First_Bit);
- pragma Inline (Known_Normalized_Position);
- pragma Inline (Known_Normalized_Position_Max);
- pragma Inline (Known_RM_Size);
-
- pragma Inline (Known_Static_Component_Bit_Offset);
- pragma Inline (Known_Static_Component_Size);
- pragma Inline (Known_Static_Esize);
- pragma Inline (Known_Static_Normalized_First_Bit);
- pragma Inline (Known_Static_Normalized_Position);
- pragma Inline (Known_Static_Normalized_Position_Max);
- pragma Inline (Known_Static_RM_Size);
+ -- types. Within a template, the size can look Known_Static, because of the
+ -- fake size values we put in template types, but they are not really
+ -- Known_Static and anyone testing if they are Known_Static within the
+ -- template should get False as a result to prevent incorrect assumptions.
+
+ function Known_Alignment (E : Entity_Id) return B with Inline;
+ procedure Reinit_Alignment (Id : E) with Inline;
+ procedure Copy_Alignment (To, From : E);
+
+ function Known_Component_Bit_Offset (E : Entity_Id) return B with Inline;
+ function Known_Static_Component_Bit_Offset (E : Entity_Id) return B
+ with Inline;
+
+ function Known_Component_Size (E : Entity_Id) return B with Inline;
+ function Known_Static_Component_Size (E : Entity_Id) return B with Inline;
+
+ function Known_Esize (E : Entity_Id) return B with Inline;
+ function Known_Static_Esize (E : Entity_Id) return B with Inline;
+ procedure Reinit_Esize (Id : E) with Inline;
+ procedure Copy_Esize (To, From : E);
+
+ function Known_Normalized_First_Bit (E : Entity_Id) return B with Inline;
+ function Known_Static_Normalized_First_Bit (E : Entity_Id) return B
+ with Inline;
+
+ function Known_Normalized_Position (E : Entity_Id) return B with Inline;
+ function Known_Static_Normalized_Position (E : Entity_Id) return B
+ with Inline;
+
+ function Known_RM_Size (E : Entity_Id) return B with Inline;
+ function Known_Static_RM_Size (E : Entity_Id) return B with Inline;
+ procedure Reinit_RM_Size (Id : E) with Inline;
+ procedure Copy_RM_Size (To, From : E);
+
+ ---------------------------------------------------------
+ -- Procedures for setting multiple of the above fields --
+ ---------------------------------------------------------
+
+ procedure Reinit_Component_Location (Id : E);
+ -- Initializes all fields describing the location of a component
+ -- (Normalized_Position, Component_Bit_Offset, Normalized_First_Bit,
+ -- Esize) to all be Unknown.
+
+ procedure Init_Size (Id : E; V : Int);
+ -- Initialize both the Esize and RM_Size fields of E to V
+
+ procedure Reinit_Size_Align (Id : E);
+ -- This procedure initializes both size fields and the alignment
+ -- field to all be Unknown.
+
+ procedure Reinit_Object_Size_Align (Id : E);
+ -- Same as Reinit_Size_Align except RM_Size field (which is only for types)
+ -- is unaffected.
---------------------------------------------------
-- Access to Subprograms in Subprograms_For_Type --
@@ -404,89 +444,6 @@ package Einfo.Utils is
procedure Set_Predicate_Function (Id : E; V : E);
procedure Set_Predicate_Function_M (Id : E; V : E);
- -----------------------------------
- -- Field Initialization Routines --
- -----------------------------------
-
- -- These routines are overloadings of some of the above Set procedures
- -- where the argument is normally a Uint. The overloadings take an Int
- -- parameter instead, and appropriately convert it. There are also
- -- versions that implicitly initialize to the appropriate "not set"
- -- value. The not set (unknown) values are as follows:
-
- -- Alignment Uint_0
- -- Component_Size Uint_0
- -- Component_Bit_Offset No_Uint
- -- Digits_Value Uint_0
- -- Esize Uint_0
- -- Normalized_First_Bit No_Uint
- -- Normalized_Position No_Uint
- -- Normalized_Position_Max No_Uint
- -- RM_Size Uint_0
-
- -- It would be cleaner to use No_Uint in all these cases, but historically
- -- we chose to use Uint_0 at first, and the change over will take time ???
- -- This is particularly true for the RM_Size field, where a value of zero
- -- is legitimate and causes some special tests around the code.
-
- -- Contrary to the corresponding Set procedures above, these routines
- -- do NOT check the entity kind of their argument, instead they set the
- -- underlying Uint fields directly (this allows them to be used for
- -- entities whose Ekind has not been set yet).
-
- procedure Init_Alignment (Id : E; V : Int);
- procedure Init_Component_Bit_Offset (Id : E; V : Int);
- procedure Init_Component_Size (Id : E; V : Int);
- procedure Init_Digits_Value (Id : E; V : Int);
- procedure Init_Esize (Id : E; V : Int);
- procedure Init_Normalized_First_Bit (Id : E; V : Int);
- procedure Init_Normalized_Position (Id : E; V : Int);
- procedure Init_Normalized_Position_Max (Id : E; V : Int);
- procedure Init_RM_Size (Id : E; V : Int);
-
- procedure Init_Alignment (Id : E);
- procedure Init_Component_Bit_Offset (Id : E);
- procedure Init_Component_Size (Id : E);
- procedure Init_Digits_Value (Id : E);
- procedure Init_Esize (Id : E);
- procedure Init_Normalized_First_Bit (Id : E);
- procedure Init_Normalized_Position (Id : E);
- procedure Init_Normalized_Position_Max (Id : E);
- procedure Init_RM_Size (Id : E);
-
- -- The following Copy_xxx procedures copy the value of xxx from From to
- -- To. If xxx is set to its initial invalid (zero-bits) value, then it is
- -- reset to invalid in To. We only have Copy_Alignment so far, but more are
- -- planned.
-
- procedure Copy_Alignment (To, From : E);
-
- pragma Inline (Init_Alignment);
- pragma Inline (Init_Component_Bit_Offset);
- pragma Inline (Init_Component_Size);
- pragma Inline (Init_Digits_Value);
- pragma Inline (Init_Esize);
- pragma Inline (Init_Normalized_First_Bit);
- pragma Inline (Init_Normalized_Position);
- pragma Inline (Init_Normalized_Position_Max);
- pragma Inline (Init_RM_Size);
-
- procedure Init_Component_Location (Id : E);
- -- Initializes all fields describing the location of a component
- -- (Normalized_Position, Component_Bit_Offset, Normalized_First_Bit,
- -- Normalized_Position_Max, Esize) to all be Unknown.
-
- procedure Init_Size (Id : E; V : Int);
- -- Initialize both the Esize and RM_Size fields of E to V
-
- procedure Init_Size_Align (Id : E);
- -- This procedure initializes both size fields and the alignment
- -- field to all be Unknown.
-
- procedure Init_Object_Size_Align (Id : E);
- -- Same as Init_Size_Align except RM_Size field (which is only for types)
- -- is unaffected.
-
---------------
-- Iterators --
---------------
@@ -668,7 +625,7 @@ package Einfo.Utils is
-- WARNING: There is a matching C declaration of this subprogram in fe.h
- procedure Link_Entities (First : Entity_Id; Second : Entity_Id);
+ procedure Link_Entities (First, Second : Entity_Id);
-- Link entities First and Second in one entity chain.
--
-- NOTE: No updates are done to the First_Entity and Last_Entity fields
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index e87ce4c..0239a70 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -610,12 +610,23 @@ package Einfo is
-- tables must be consulted to determine if there actually is an active
-- Suppress or Unsuppress pragma that applies to the entity.
--- Class_Wide_Clone
--- Defined on subprogram entities. Set if the subprogram has a class-wide
--- pre- or postcondition, and the expression contains calls to other
--- primitive funtions of the type. Used to implement properly the
--- semantics of inherited operations whose class-wide condition may
--- be different from that of the ancestor (See AI012-0195).
+-- Class_Postconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- postconditions. Denotes the (and-then) expression built by merging
+-- inherited class-wide postconditions with its own class-wide
+-- postconditions.
+
+-- Class_Preconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the (or-else) expression built by merging
+-- inherited class-wide preconditions with its own class-wide
+-- preconditions.
+
+-- Class_Preconditions_Subprogram
+-- Defined on subprogram entities. Set on subprogram helpers and also on
+-- the indirect-call wrapper internally built for subprograms that have
+-- class-wide preconditions. References the subprogram that has the
+-- class-wide preconditions.
-- Class_Wide_Type
-- Defined in all type entities. For a tagged type or subtype, returns
@@ -746,9 +757,9 @@ package Einfo is
-- Corresponding_Record_Component
-- Defined in components of a derived untagged record type, including
--- discriminants. For a regular component or a girder discriminant,
+-- discriminants. For a regular component or a stored discriminant,
-- points to the corresponding component in the parent type. Set to
--- Empty for a non-girder discriminant. It is used by the back end to
+-- Empty for a non-stored discriminant. It is used by the back end to
-- ensure the layout of the derived type matches that of the parent
-- type when there is no representation clause on the derived type.
@@ -818,7 +829,9 @@ package Einfo is
-- a private type, then we obtain the declaration node denoted by the
-- full type, i.e. the full type declaration node. Also note that for
-- subprograms, this returns the {function,procedure}_specification, not
--- the subprogram_declaration.
+-- the subprogram_declaration. If the parent of an Itype is a type or
+-- subtype declaration, we return the declaration node as for any other
+-- type. For other Itypes, we return Empty.
-- Default_Aspect_Component_Value [base type only]
-- Defined in array types. Holds the static value specified in a
@@ -1029,6 +1042,11 @@ package Einfo is
-- associated with the tagged type. For an untagged record, contains
-- No_Elist.
+-- Dynamic_Call_Helper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the helper that evaluates at run time the
+-- class-wide preconditions performing dispatching calls.
+
-- DTC_Entity
-- Defined in function and procedure entities. Set to Empty unless
-- the subprogram is dispatching in which case it references the
@@ -2182,6 +2200,18 @@ package Einfo is
-- "off" and indicates that all SPARK_Mode pragmas found within must
-- be ignored.
+-- Ignored_Class_Postconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- postconditions. Denotes the (and-then) expression built by merging
+-- inherited ignored class-wide postconditions with its own ignored
+-- class-wide postconditions.
+
+-- Ignored_Class_Preconditions
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the (or-else) expression built by merging
+-- inherited ignored class-wide preconditions with its own ignored
+-- class-wide preconditions.
+
-- Implementation_Base_Type (synthesized)
-- Applies to all entities. For types, similar to Base_Type, but never
-- returns a private type when applied to a non-private type. Instead in
@@ -2216,6 +2246,12 @@ package Einfo is
-- is relocated to the corresponding package body, which must have a
-- corresponding nonlimited with_clause.
+-- Indirect_Call_Wrapper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the internal wrapper that checks preconditions
+-- and invokes the subprogram body. Subp'Access points to the indirect
+-- call wrapper if available.
+
-- Initialization_Statements
-- Defined in constants and variables. For a composite object initialized
-- with an aggregate that has been converted to a sequence of
@@ -2393,6 +2429,11 @@ package Einfo is
-- Is_Class_Wide_Type (synthesized)
-- Applies to all entities, true for class wide types and subtypes
+-- Is_Class_Wide_Wrapper
+-- Defined in subprogram entities. Indicates that it has been created as
+-- a wrapper in a generic/instance scenario involving a formal type and
+-- a generic primitive operation when the actual is a class-wide type.
+
-- Is_Compilation_Unit
-- Defined in all entities. Set if the entity is a package or subprogram
-- entity for a compilation unit other than a subunit (since we treat
@@ -2400,11 +2441,11 @@ package Einfo is
-- parent, we do not consider them to be separate units for this flag).
-- Is_Completely_Hidden
--- Defined on discriminants. Only set on girder discriminants of
--- untagged types. When set, the entity is a girder discriminant of a
+-- Defined on discriminants. Only set on stored discriminants of
+-- untagged types. When set, the entity is a stored discriminant of a
-- derived untagged type which is not directly visible in the derived
-- type because the derived type or one of its ancestors have renamed the
--- discriminants in the root type. Note: there are girder discriminants
+-- discriminants in the root type. Note: there are stored discriminants
-- which are not Completely_Hidden (e.g. discriminants of a root type).
-- Is_Composite_Type (synthesized)
@@ -2507,6 +2548,11 @@ package Einfo is
-- Applies to all entities. Set to indicate to the backend that this
-- entity is associated with a dispatch table.
+-- Is_Dispatch_Table_Wrapper
+-- Applies to all entities. Set on wrappers built when the subprogram has
+-- class-wide preconditions or class-wide postconditions affected by
+-- overriding (AI12-0195).
+
-- Is_Dispatching_Operation
-- Defined in all entities. Set for procedures, functions, generic
-- procedures, and generic functions if the corresponding operation
@@ -3652,7 +3698,7 @@ package Einfo is
-- Next_Discriminant (synthesized)
-- Applies to discriminants returned by First/Next_Discriminant. Returns
--- the next language-defined (i.e. perhaps non-girder) discriminant by
+-- the next language-defined (i.e. perhaps non-stored) discriminant by
-- following the chain of declared entities as long as the kind of the
-- entity corresponds to a discriminant. Note that the discriminants
-- might be the only components of the record. Returns Empty if there
@@ -3762,17 +3808,6 @@ package Einfo is
-- units from the start of the record to the lowest addressed storage
-- unit containing part or all of the field.
--- Normalized_Position_Max
--- Defined in components and discriminants. For almost all cases, this
--- is the same as Normalized_Position. The one exception is for the case
--- of a discriminated record containing one or more arrays whose length
--- depends on discriminants. In this case, the Normalized_Position_Max
--- field represents the maximum possible value of Normalized_Position
--- assuming min/max values for discriminant subscripts in all fields.
--- This is used by Layout in front end layout mode to properly compute
--- the maximum size of such records (needed for allocation purposes when
--- there are default discriminants, and also for the 'Size value).
-
-- Number_Dimensions (synthesized)
-- Applies to array types and subtypes. Returns the number of dimensions
-- of the array type or subtype as a value of type Pos.
@@ -3853,8 +3888,8 @@ package Einfo is
-- Rec_Ext.Comp -> Rec_Ext.Parent. ... .Parent.Comp
--
-- In base untagged types:
--- Always points to itself except for non-girder discriminants, where
--- it points to the girder discriminant it renames.
+-- Always points to itself except for non-stored discriminants, where
+-- it points to the stored discriminant it renames.
--
-- In subtypes (tagged and untagged):
-- Points to the component in the base type.
@@ -4412,6 +4447,11 @@ package Einfo is
-- Default_Scalar_Storage_Order (High_Order_First) was active at the time
-- the record or array was declared and therefore applies to it.
+-- Static_Call_Helper
+-- Defined on subprogram entities. Set if the subprogram has class-wide
+-- preconditions. Denotes the helper that evaluates at runtime the
+-- class-wide preconditions performing static calls.
+
-- Static_Discrete_Predicate
-- Defined in discrete types/subtypes with static predicates (with the
-- two flags Has_Predicates and Has_Static_Predicate set). Set if the
@@ -4889,6 +4929,7 @@ package Einfo is
-- Is_Discrim_SO_Function
-- Is_Discriminant_Check_Function
-- Is_Dispatch_Table_Entity
+ -- Is_Dispatch_Table_Wrapper
-- Is_Dispatching_Operation
-- Is_Entry_Formal
-- Is_Exported
@@ -5228,7 +5269,6 @@ package Einfo is
-- Linker_Section_Pragma $$$
-- Normalized_First_Bit
-- Current_Value (always Empty)
- -- Normalized_Position_Max
-- Component_Bit_Offset
-- Esize
-- Component_Clause
@@ -5328,7 +5368,6 @@ package Einfo is
-- E_Discriminant
-- Normalized_First_Bit
-- Current_Value (always Empty)
- -- Normalized_Position_Max
-- Component_Bit_Offset
-- Esize
-- Component_Clause
@@ -5497,7 +5536,14 @@ package Einfo is
-- Linker_Section_Pragma
-- Contract
-- Import_Pragma (non-generic case only)
- -- Class_Wide_Clone
+ -- Class_Postconditions
+ -- Class_Preconditions
+ -- Class_Preconditions_Subprogram
+ -- Dynamic_Call_Helper
+ -- Ignored_Class_Preconditions
+ -- Ignored_Class_Postconditions
+ -- Indirect_Call_Wrapper
+ -- Static_Call_Helper
-- Protected_Subprogram (non-generic case only)
-- SPARK_Pragma
-- Original_Protected_Subprogram
@@ -5521,6 +5567,7 @@ package Einfo is
-- Ignore_SPARK_Mode_Pragmas
-- Is_Abstract_Subprogram (non-generic case only)
-- Is_Called (non-generic case only)
+ -- Is_Class_Wide_Wrapper
-- Is_Constructor
-- Is_CUDA_Kernel (non-generic case only)
-- Is_DIC_Procedure (non-generic case only)
@@ -5693,6 +5740,7 @@ package Einfo is
-- Default_Expressions_Processed
-- Has_Nested_Subprogram
-- Ignore_SPARK_Mode_Pragmas
+ -- Is_Class_Wide_Wrapper
-- Is_Elaboration_Checks_OK_Id
-- Is_Elaboration_Warnings_OK_Id
-- Is_Intrinsic_Subprogram
@@ -5853,7 +5901,14 @@ package Einfo is
-- Linker_Section_Pragma
-- Contract
-- Import_Pragma (non-generic case only)
- -- Class_Wide_Clone
+ -- Class_Postconditions
+ -- Class_Preconditions
+ -- Class_Preconditions_Subprogram
+ -- Dynamic_Call_Helper
+ -- Ignored_Class_Preconditions
+ -- Ignored_Class_Postconditions
+ -- Indirect_Call_Wrapper
+ -- Static_Call_Helper
-- Protected_Subprogram (non-generic case only)
-- SPARK_Pragma
-- Original_Protected_Subprogram
@@ -5876,6 +5931,7 @@ package Einfo is
-- Is_Abstract_Subprogram (non-generic case only)
-- Is_Asynchronous
-- Is_Called (non-generic case only)
+ -- Is_Class_Wide_Wrapper
-- Is_Constructor
-- Is_CUDA_Kernel
-- Is_DIC_Procedure (non-generic case only)
diff --git a/gcc/ada/err_vars.ads b/gcc/ada/err_vars.ads
index 366df62..819d1ad 100644
--- a/gcc/ada/err_vars.ads
+++ b/gcc/ada/err_vars.ads
@@ -105,12 +105,15 @@ package Err_Vars is
-- of the following global variables to appropriate values before making a
-- call to one of the error message routines with a string containing the
-- insertion character to get the value inserted in an appropriate format.
+ --
+ -- Some of these are initialized below, because they are read before being
+ -- set by clients.
Error_Msg_Col : Column_Number;
-- Column for @ insertion character in message
Error_Msg_Uint_1 : Uint;
- Error_Msg_Uint_2 : Uint;
+ Error_Msg_Uint_2 : Uint := No_Uint;
-- Uint values for ^ insertion characters in message
-- WARNING: There is a matching C declaration of these variables in fe.h
@@ -119,21 +122,21 @@ package Err_Vars is
-- Source location for # insertion character in message
Error_Msg_Name_1 : Name_Id;
- Error_Msg_Name_2 : Name_Id;
- Error_Msg_Name_3 : Name_Id;
+ Error_Msg_Name_2 : Name_Id := No_Name;
+ Error_Msg_Name_3 : Name_Id := No_Name;
-- Name_Id values for % insertion characters in message
Error_Msg_File_1 : File_Name_Type;
- Error_Msg_File_2 : File_Name_Type;
- Error_Msg_File_3 : File_Name_Type;
+ Error_Msg_File_2 : File_Name_Type := No_File;
+ Error_Msg_File_3 : File_Name_Type := No_File;
-- File_Name_Type values for { insertion characters in message
Error_Msg_Unit_1 : Unit_Name_Type;
- Error_Msg_Unit_2 : Unit_Name_Type;
+ Error_Msg_Unit_2 : Unit_Name_Type := No_Unit_Name;
-- Unit_Name_Type values for $ insertion characters in message
Error_Msg_Node_1 : Node_Id;
- Error_Msg_Node_2 : Node_Id;
+ Error_Msg_Node_2 : Node_Id := Empty;
-- Node_Id values for & insertion characters in message
Error_Msg_Warn : Boolean;
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index 0122304..05a8266 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -106,15 +106,15 @@ package body Errout is
Opan : Source_Span;
Msg_Cont : Boolean;
Node : Node_Id);
- -- This is the low level routine used to post messages after dealing with
+ -- This is the low-level routine used to post messages after dealing with
-- the issue of messages placed on instantiations (which get broken up
- -- into separate calls in Error_Msg). Sptr is the location on which the
+ -- into separate calls in Error_Msg). Span is the location on which the
-- flag will be placed in the output. In the case where the flag is on
-- the template, this points directly to the template, not to one of the
- -- instantiation copies of the template. Optr is the original location
+ -- instantiation copies of the template. Opan is the original location
-- used to flag the error, and this may indeed point to an instantiation
- -- copy. So typically we can see Optr pointing to the template location
- -- in an instantiation copy when Sptr points to the source location of
+ -- copy. So typically we can see Opan pointing to the template location
+ -- in an instantiation copy when Span points to the source location of
-- the actual instantiation (i.e the line with the new). Msg_Cont is
-- set true if this is a continuation message. Node is the relevant
-- Node_Id for this message, to be used to compute the enclosing entity if
@@ -2473,7 +2473,8 @@ package body Errout is
function Get_Line_End
(Buf : Source_Buffer_Ptr;
Loc : Source_Ptr) return Source_Ptr;
- -- Get the source location for the end of the line in Buf for Loc
+ -- Get the source location for the end of the line in Buf for Loc. If
+ -- Loc is past the end of Buf already, return Buf'Last.
function Get_Line_Start
(Buf : Source_Buffer_Ptr;
@@ -2515,9 +2516,9 @@ package body Errout is
(Buf : Source_Buffer_Ptr;
Loc : Source_Ptr) return Source_Ptr
is
- Cur_Loc : Source_Ptr := Loc;
+ Cur_Loc : Source_Ptr := Source_Ptr'Min (Loc, Buf'Last);
begin
- while Cur_Loc <= Buf'Last
+ while Cur_Loc < Buf'Last
and then Buf (Cur_Loc) /= ASCII.LF
loop
Cur_Loc := Cur_Loc + 1;
@@ -2692,9 +2693,7 @@ package body Errout is
Write_Buffer_Char (Buf, Cur_Loc);
end if;
- Cur_Loc := Cur_Loc + 1;
-
- if Buf (Cur_Loc - 1) = ASCII.LF then
+ if Buf (Cur_Loc) = ASCII.LF then
Cur_Line := Cur_Line + 1;
-- Output ... for skipped lines
@@ -2719,6 +2718,8 @@ package body Errout is
Width);
end if;
end if;
+
+ Cur_Loc := Cur_Loc + 1;
end loop;
end;
@@ -3601,15 +3602,9 @@ package body Errout is
end if;
-- The following assignment ensures that a second ampersand insertion
- -- character will correspond to the Error_Msg_Node_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Node_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Node_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Node_1 := Error_Msg_Node_2;
- end;
+ Error_Msg_Node_1 := Error_Msg_Node_2;
end Set_Msg_Insertion_Node;
--------------------------------------
@@ -3789,15 +3784,9 @@ package body Errout is
end if;
-- The following assignment ensures that a second percent insertion
- -- character will correspond to the Error_Msg_Unit_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Unit_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Unit_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Unit_1 := Error_Msg_Unit_2;
- end;
+ Error_Msg_Unit_1 := Error_Msg_Unit_2;
end Set_Msg_Insertion_Unit_Name;
------------------
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index a2cd3c3..9e67b92 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -1119,17 +1119,11 @@ package body Erroutc is
end if;
-- The following assignments ensure that the second and third {
- -- insertion characters will correspond to the Error_Msg_File_2 and
- -- Error_Msg_File_3 values and We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_File_2 or
- -- Error_Msg_File_3 is not needed and has not been set.
+ -- insertion characters will correspond to the Error_Msg_File_2
+ -- and Error_Msg_File_3 values.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_File_1 := Error_Msg_File_2;
- Error_Msg_File_2 := Error_Msg_File_3;
- end;
+ Error_Msg_File_1 := Error_Msg_File_2;
+ Error_Msg_File_2 := Error_Msg_File_3;
end Set_Msg_Insertion_File_Name;
-----------------------------------
@@ -1299,16 +1293,10 @@ package body Erroutc is
-- The following assignments ensure that the second and third percent
-- insertion characters will correspond to the Error_Msg_Name_2 and
- -- Error_Msg_Name_3 as required. We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_Name_1/2 is not needed
- -- and has not been set.
+ -- Error_Msg_Name_3 as required.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Name_1 := Error_Msg_Name_2;
- Error_Msg_Name_2 := Error_Msg_Name_3;
- end;
+ Error_Msg_Name_1 := Error_Msg_Name_2;
+ Error_Msg_Name_2 := Error_Msg_Name_3;
end Set_Msg_Insertion_Name;
------------------------------------
@@ -1334,16 +1322,10 @@ package body Erroutc is
-- The following assignments ensure that the second and third % or %%
-- insertion characters will correspond to the Error_Msg_Name_2 and
- -- Error_Msg_Name_3 values and We suppress possible validity checks in
- -- case operating in -gnatVa mode, and Error_Msg_Name_2 or
- -- Error_Msg_Name_3 is not needed and has not been set.
+ -- Error_Msg_Name_3 values.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Name_1 := Error_Msg_Name_2;
- Error_Msg_Name_2 := Error_Msg_Name_3;
- end;
+ Error_Msg_Name_1 := Error_Msg_Name_2;
+ Error_Msg_Name_2 := Error_Msg_Name_3;
end Set_Msg_Insertion_Name_Literal;
-------------------------------------
@@ -1427,15 +1409,9 @@ package body Erroutc is
end loop;
-- The following assignment ensures that a second caret insertion
- -- character will correspond to the Error_Msg_Uint_2 parameter. We
- -- suppress possible validity checks in case operating in -gnatVa mode,
- -- and Error_Msg_Uint_2 is not needed and has not been set.
+ -- character will correspond to the Error_Msg_Uint_2 parameter.
- declare
- pragma Suppress (Range_Check);
- begin
- Error_Msg_Uint_1 := Error_Msg_Uint_2;
- end;
+ Error_Msg_Uint_1 := Error_Msg_Uint_2;
end Set_Msg_Insertion_Uint;
-----------------
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 1b08436..ebc7a87 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -124,7 +124,8 @@ package body Exp_Aggr is
-- constants that are done in place.
function Must_Slide
- (Obj_Type : Entity_Id;
+ (Aggr : Node_Id;
+ Obj_Type : Entity_Id;
Typ : Entity_Id) return Boolean;
-- A static array aggregate in an object declaration can in most cases be
-- expanded in place. The one exception is when the aggregate is given
@@ -504,7 +505,7 @@ package body Exp_Aggr is
-- Scalar types are OK if their size is a multiple of Storage_Unit
elsif Is_Scalar_Type (Ctyp) then
- pragma Assert (Csiz /= No_Uint);
+ pragma Assert (Present (Csiz));
if Csiz mod System_Storage_Unit /= 0 then
return False;
@@ -1776,7 +1777,7 @@ package body Exp_Aggr is
if Nkind (Parent (N)) = N_Assignment_Statement
and then Is_Array_Type (Comp_Typ)
and then Present (Component_Associations (Expr_Q))
- and then Must_Slide (Comp_Typ, Etype (Expr_Q))
+ and then Must_Slide (N, Comp_Typ, Etype (Expr_Q))
then
Set_Expansion_Delayed (Expr_Q, False);
Set_Analyzed (Expr_Q, False);
@@ -3208,6 +3209,8 @@ package body Exp_Aggr is
Init_Stmt : Node_Id;
begin
+ pragma Assert (Nkind (Init_Expr) in N_Subexpr);
+
-- Protect the initialization statements from aborts. Generate:
-- Abort_Defer;
@@ -3792,6 +3795,26 @@ package body Exp_Aggr is
With_Default_Init => True,
Constructor_Ref => Expression (Comp)));
+ elsif Box_Present (Comp)
+ and then Needs_Simple_Initialization (Etype (Selector))
+ then
+ Comp_Expr :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Copy_Tree (Target),
+ Selector_Name => New_Occurrence_Of (Selector, Loc));
+
+ Initialize_Record_Component
+ (Rec_Comp => Comp_Expr,
+ Comp_Typ => Etype (Selector),
+ Init_Expr => Get_Simple_Init_Val
+ (Typ => Etype (Selector),
+ N => Comp,
+ Size =>
+ (if Known_Esize (Selector)
+ then Esize (Selector)
+ else Uint_0)),
+ Stmts => L);
+
-- Ada 2005 (AI-287): For each default-initialized component generate
-- a call to the corresponding IP subprogram if available.
@@ -4003,7 +4026,7 @@ package body Exp_Aggr is
and then Present (First_Index (Etype (Expr_Q)))
then
declare
- Expr_Q_Type : constant Node_Id := Etype (Expr_Q);
+ Expr_Q_Type : constant Entity_Id := Etype (Expr_Q);
begin
Append_List_To (L,
Build_Array_Aggr_Code
@@ -5718,6 +5741,15 @@ package body Exp_Aggr is
-- built directly into the target of the assignment it must be free
-- of side effects. N is the LHS of an assignment.
+ procedure Two_Pass_Aggregate_Expansion (N : Node_Id);
+ -- If the aggregate consists only of iterated associations then the
+ -- aggregate is constructed in two steps:
+ -- a) Build an expression to compute the number of elements
+ -- generated by each iterator, and use the expression to allocate
+ -- the destination aggregate.
+ -- b) Generate the loops corresponding to each iterator to insert
+ -- the elements in their proper positions.
+
----------------------------
-- Build_Constrained_Type --
----------------------------
@@ -6334,6 +6366,197 @@ package body Exp_Aggr is
end if;
end Safe_Left_Hand_Side;
+ ----------------------------------
+ -- Two_Pass_Aggregate_Expansion --
+ ----------------------------------
+
+ procedure Two_Pass_Aggregate_Expansion (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Comp_Type : constant Entity_Id := Etype (N);
+ Index_Id : constant Entity_Id := Make_Temporary (Loc, 'I', N);
+ Index_Type : constant Entity_Id := Etype (First_Index (Etype (N)));
+ Size_Id : constant Entity_Id := Make_Temporary (Loc, 'I', N);
+ TmpE : constant Entity_Id := Make_Temporary (Loc, 'A', N);
+
+ Assoc : Node_Id := First (Component_Associations (N));
+ Incr : Node_Id;
+ Iter : Node_Id;
+ New_Comp : Node_Id;
+ One_Loop : Node_Id;
+
+ Size_Expr_Code : List_Id;
+ Insertion_Code : List_Id := New_List;
+
+ begin
+ Size_Expr_Code := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Size_Id,
+ Object_Definition => New_Occurrence_Of (Standard_Integer, Loc),
+ Expression => Make_Integer_Literal (Loc, 0)));
+
+ -- First pass: execute the iterators to count the number of elements
+ -- that will be generated.
+
+ while Present (Assoc) loop
+ Iter := Iterator_Specification (Assoc);
+ Incr := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Size_Id, Loc),
+ Expression =>
+ Make_Op_Add (Loc,
+ Left_Opnd => New_Occurrence_Of (Size_Id, Loc),
+ Right_Opnd => Make_Integer_Literal (Loc, 1)));
+
+ One_Loop := Make_Loop_Statement (Loc,
+ Iteration_Scheme =>
+ Make_Iteration_Scheme (Loc,
+ Iterator_Specification => New_Copy_Tree (Iter)),
+ Statements => New_List (Incr));
+
+ Append (One_Loop, Size_Expr_Code);
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Size_Expr_Code);
+
+ -- Build a constrained subtype with the calculated length
+ -- and declare the proper bounded aggregate object.
+ -- The index type is some discrete type, so the bounds of the
+ -- constructed array are computed as T'Val (T'Pos (ineger bound));
+
+ declare
+ Pos_Lo : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Pos,
+ Expressions => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_First)));
+
+ Aggr_Lo : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Val,
+ Expressions => New_List (New_Copy_Tree (Pos_Lo)));
+
+ -- Hi = Index_type'Pos (Lo + Size -1).
+
+ Pos_Hi : constant Node_Id :=
+ Make_Op_Add (Loc,
+ Left_Opnd => New_Copy_Tree (Pos_Lo),
+ Right_Opnd =>
+ Make_Op_Subtract (Loc,
+ Left_Opnd => New_Occurrence_Of (Size_Id, Loc),
+ Right_Opnd => Make_Integer_Literal (Loc, 1)));
+
+ -- Corresponding index value
+
+ Aggr_Hi : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Val,
+ Expressions => New_List (New_Copy_Tree (Pos_Hi)));
+
+ SubE : constant Entity_Id := Make_Temporary (Loc, 'T');
+ SubD : constant Node_Id :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => SubE,
+ Subtype_Indication =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Etype (Comp_Type), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint
+ (Loc,
+ Constraints =>
+ New_List (Make_Range (Loc, Aggr_Lo, Aggr_Hi)))));
+
+ -- Create a temporary array of the above subtype which
+ -- will be used to capture the aggregate assignments.
+
+ TmpD : constant Node_Id :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => TmpE,
+ Object_Definition => New_Occurrence_Of (SubE, Loc));
+ begin
+ Insert_Actions (N, New_List (SubD, TmpD));
+ end;
+
+ -- Second pass: use the iterators to generate the elements of the
+ -- aggregate. Insertion index starts at Index_Type'First. We
+ -- assume that the second evaluation of each iterator generates
+ -- the same number of elements as the first pass, and consider
+ -- that the execution is erroneous (even if the RM does not state
+ -- this explicitly) if the number of elements generated differs
+ -- between first and second pass.
+
+ Assoc := First (Component_Associations (N));
+
+ -- Initialize insertion position to first array component.
+
+ Insertion_Code := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Index_Id,
+ Object_Definition =>
+ New_Occurrence_Of (Index_Type, Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_First)));
+
+ while Present (Assoc) loop
+ Iter := Iterator_Specification (Assoc);
+ New_Comp := Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Indexed_Component (Loc,
+ Prefix => New_Occurrence_Of (TmpE, Loc),
+ Expressions =>
+ New_List (New_Occurrence_Of (Index_Id, Loc))),
+ Expression => New_Copy_Tree (Expression (Assoc)));
+
+ -- Advance index position for insertion.
+
+ Incr := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Index_Id, Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Succ,
+ Expressions =>
+ New_List (New_Occurrence_Of (Index_Id, Loc))));
+
+ -- Add guard to skip last increment when upper bound is reached.
+
+ Incr := Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Occurrence_Of (Index_Id, Loc),
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Index_Type, Loc),
+ Attribute_Name => Name_Last)),
+ Then_Statements => New_List (Incr));
+
+ One_Loop := Make_Loop_Statement (Loc,
+ Iteration_Scheme =>
+ Make_Iteration_Scheme (Loc,
+ Iterator_Specification => Copy_Separate_Tree (Iter)),
+ Statements => New_List (New_Comp, Incr));
+
+ Append (One_Loop, Insertion_Code);
+ Next (Assoc);
+ end loop;
+
+ Insert_Actions (N, Insertion_Code);
+
+ -- Depending on context this may not work for build-in-place
+ -- arrays ???
+
+ Rewrite (N, New_Occurrence_Of (TmpE, Loc));
+
+ end Two_Pass_Aggregate_Expansion;
+
-- Local variables
Tmp : Entity_Id;
@@ -6371,6 +6594,15 @@ package body Exp_Aggr is
then
return;
+ elsif Present (Component_Associations (N))
+ and then Nkind (First (Component_Associations (N))) =
+ N_Iterated_Component_Association
+ and then
+ Present (Iterator_Specification (First (Component_Associations (N))))
+ then
+ Two_Pass_Aggregate_Expansion (N);
+ return;
+
-- Do not attempt expansion if error already detected. We may reach this
-- point in spite of previous errors when compiling with -gnatq, to
-- force all possible errors (this is the usual ACATS mode).
@@ -6657,7 +6889,7 @@ package body Exp_Aggr is
and then Parent_Kind = N_Object_Declaration
and then Present (Expression (Parent_Node))
and then not
- Must_Slide (Etype (Defining_Identifier (Parent_Node)), Typ)
+ Must_Slide (N, Etype (Defining_Identifier (Parent_Node)), Typ)
and then not Is_Bit_Packed_Array (Typ)
then
In_Place_Assign_OK_For_Declaration := True;
@@ -7038,6 +7270,9 @@ package body Exp_Aggr is
-- or Element_Association with non-static bounds, build an expression
-- to be used as the allocated size of the container. This may be an
-- overestimate if a filter is present, but is a safe approximation.
+ -- If bounds are dynamic the aggregate is created in two passes, and
+ -- the first generates a loop for the sole purpose of computing the
+ -- number of elements that will be generated on the seocnd pass.
procedure Expand_Iterated_Component (Comp : Node_Id);
-- Handle iterated_component_association and iterated_Element
@@ -7185,7 +7420,11 @@ package body Exp_Aggr is
return Build_Siz_Exp (First (Discrete_Choices (Comp)));
elsif Nkind (Comp) = N_Iterated_Element_Association then
- return -1; -- ??? build expression for size of the domain
+ return -1;
+
+ -- ??? Need to create code for a loop and add to generated code,
+ -- as is done for array aggregates with iterated element
+ -- associations, instead of using Append operations.
else
return -1;
@@ -7217,7 +7456,7 @@ package body Exp_Aggr is
if Present (Iterator_Specification (Comp)) then
- -- Either an Iterator_Specification of a Loop_Parameter_
+ -- Either an Iterator_Specification or a Loop_Parameter_
-- Specification is present.
L_Iteration_Scheme :=
@@ -8046,7 +8285,7 @@ package body Exp_Aggr is
Discr : Entity_Id;
Decl : Node_Id;
Num_Disc : Nat := 0;
- Num_Gird : Nat := 0;
+ Num_Stor : Nat := 0;
-- Start of processing for Generate_Aggregate_For_Derived_Type
@@ -8082,13 +8321,13 @@ package body Exp_Aggr is
Discr := First_Stored_Discriminant (Base_Type (Typ));
while Present (Discr) loop
- Num_Gird := Num_Gird + 1;
+ Num_Stor := Num_Stor + 1;
Next_Stored_Discriminant (Discr);
end loop;
-- Case of more stored discriminants than new discriminants
- if Num_Gird > Num_Disc then
+ if Num_Stor > Num_Disc then
-- Create a proper subtype of the parent type, which is the
-- proper implementation type for the aggregate, and convert
@@ -8330,10 +8569,6 @@ package body Exp_Aggr is
Expr_Q : Node_Id;
begin
- if No (Comps) then
- return True;
- end if;
-
C := First (Comps);
while Present (C) loop
@@ -8684,46 +8919,41 @@ package body Exp_Aggr is
----------------------------
function Has_Default_Init_Comps (N : Node_Id) return Boolean is
- Comps : constant List_Id := Component_Associations (N);
- C : Node_Id;
+ Assoc : Node_Id;
Expr : Node_Id;
+ -- Component association and expression, respectively
begin
pragma Assert (Nkind (N) in N_Aggregate | N_Extension_Aggregate);
- if No (Comps) then
- return False;
- end if;
-
if Has_Self_Reference (N) then
return True;
end if;
- -- Check if any direct component has default initialized components
+ Assoc := First (Component_Associations (N));
+ while Present (Assoc) loop
+ -- Each component association has either a box or an expression
- C := First (Comps);
- while Present (C) loop
- if Box_Present (C) then
- return True;
- end if;
+ pragma Assert (Box_Present (Assoc) xor Present (Expression (Assoc)));
- Next (C);
- end loop;
+ -- Check if any direct component has default initialized components
+
+ if Box_Present (Assoc) then
+ return True;
- -- Recursive call in case of aggregate expression
+ -- Recursive call in case of aggregate expression
- C := First (Comps);
- while Present (C) loop
- Expr := Expression (C);
+ else
+ Expr := Expression (Assoc);
- if Present (Expr)
- and then Nkind (Expr) in N_Aggregate | N_Extension_Aggregate
- and then Has_Default_Init_Comps (Expr)
- then
- return True;
+ if Nkind (Expr) in N_Aggregate | N_Extension_Aggregate
+ and then Has_Default_Init_Comps (Expr)
+ then
+ return True;
+ end if;
end if;
- Next (C);
+ Next (Assoc);
end loop;
return False;
@@ -8770,11 +9000,8 @@ package body Exp_Aggr is
Kind := Nkind (Node);
end if;
- if Kind not in N_Aggregate | N_Extension_Aggregate then
- return False;
- else
- return Expansion_Delayed (Node);
- end if;
+ return Kind in N_Aggregate | N_Extension_Aggregate
+ and then Expansion_Delayed (Node);
end Is_Delayed_Aggregate;
--------------------------------
@@ -9411,13 +9638,16 @@ package body Exp_Aggr is
----------------
function Must_Slide
- (Obj_Type : Entity_Id;
+ (Aggr : Node_Id;
+ Obj_Type : Entity_Id;
Typ : Entity_Id) return Boolean
is
begin
-- No sliding if the type of the object is not established yet, if it is
-- an unconstrained type whose actual subtype comes from the aggregate,
- -- or if the two types are identical.
+ -- or if the two types are identical. If the aggregate contains only
+ -- an Others_Clause it gets its type from the context and no sliding
+ -- is involved either.
if not Is_Array_Type (Obj_Type) then
return False;
@@ -9428,8 +9658,13 @@ package body Exp_Aggr is
elsif Typ = Obj_Type then
return False;
+ elsif Is_Others_Aggregate (Aggr) then
+ return False;
+
else
-- Sliding can only occur along the first dimension
+ -- If any the bounds of non-static sliding is required
+ -- to force potential range checks.
declare
Bounds1 : constant Range_Nodes :=
@@ -9443,7 +9678,8 @@ package body Exp_Aggr is
not Is_OK_Static_Expression (Bounds1.Last) or else
not Is_OK_Static_Expression (Bounds2.Last)
then
- return False;
+ return True;
+
else
return Expr_Value (Bounds1.First) /= Expr_Value (Bounds2.First)
or else
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index f074521..096671f 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -165,8 +165,7 @@ package body Exp_Attr is
-- the appropriate instantiation of System.Fat_Gen. Float arguments in Args
-- have already been converted to the floating-point type for which Pkg was
-- instantiated. The Nam argument is the relevant attribute processing
- -- routine to be called. This is the same as the attribute name, except in
- -- the Unaligned_Valid case.
+ -- routine to be called. This is the same as the attribute name.
procedure Expand_Fpt_Attribute_R (N : Node_Id);
-- This procedure expands a call to a floating-point attribute function
@@ -2216,6 +2215,20 @@ package body Exp_Attr is
if Is_Access_Protected_Subprogram_Type (Btyp) then
Expand_Access_To_Protected_Op (N, Pref, Typ);
+ -- If prefix is a subprogram that has class-wide preconditions and
+ -- an indirect-call wrapper (ICW) of such subprogram is available
+ -- then replace the prefix by the ICW.
+
+ elsif Is_Access_Subprogram_Type (Btyp)
+ and then Is_Entity_Name (Pref)
+ and then Present (Class_Preconditions (Entity (Pref)))
+ and then Present (Indirect_Call_Wrapper (Entity (Pref)))
+ then
+ Rewrite (Pref,
+ New_Occurrence_Of
+ (Indirect_Call_Wrapper (Entity (Pref)), Loc));
+ Analyze_And_Resolve (N, Typ);
+
-- If prefix is a type name, this is a reference to the current
-- instance of the type, within its initialization procedure.
@@ -3252,14 +3265,15 @@ package body Exp_Attr is
-- If not constant-folded, Enum_Type'Enum_Rep (X) or X'Enum_Rep
-- expands to
- -- target-type (X)
+ -- target-type!(X)
- -- This is simply a direct conversion from the enumeration type to
- -- the target integer type, which is treated by the back end as a
- -- normal integer conversion, treating the enumeration type as an
- -- integer, which is exactly what we want. We set Conversion_OK to
- -- make sure that the analyzer does not complain about what otherwise
- -- might be an illegal conversion.
+ -- This is an unchecked conversion from the enumeration type to the
+ -- target integer type, which is treated by the back end as a normal
+ -- integer conversion, treating the enumeration type as an integer,
+ -- which is exactly what we want. Unlike for the Pos attribute, we
+ -- cannot use a regular conversion since the associated check would
+ -- involve comparing the converted bounds, i.e. would involve the use
+ -- of 'Pos instead 'Enum_Rep for these bounds.
-- However the target type is universal integer in most cases, which
-- is a very large type, so in the case of an enumeration type, we
@@ -3267,11 +3281,13 @@ package body Exp_Attr is
-- the size information.
if Is_Enumeration_Type (Ptyp) then
- Rewrite (N, OK_Convert_To (Get_Integer_Type (Ptyp), Expr));
+ Rewrite (N, Unchecked_Convert_To (Get_Integer_Type (Ptyp), Expr));
Convert_To_And_Rewrite (Typ, N);
+ -- Deal with integer types (replace by conversion)
+
else
- Rewrite (N, OK_Convert_To (Typ, Expr));
+ Rewrite (N, Convert_To (Typ, Expr));
end if;
Analyze_And_Resolve (N, Typ);
@@ -5420,7 +5436,7 @@ package body Exp_Attr is
-- Deal with integer types (replace by conversion)
- elsif Is_Integer_Type (Etyp) then
+ else
Rewrite (N, Convert_To (Typ, Expr));
end if;
@@ -5527,6 +5543,21 @@ package body Exp_Attr is
end if;
end Pred;
+ ----------------------------------
+ -- Preelaborable_Initialization --
+ ----------------------------------
+
+ when Attribute_Preelaborable_Initialization =>
+
+ -- This attribute should already be folded during analysis, but if
+ -- for some reason it hasn't been, we fold it now.
+
+ Fold_Uint
+ (N,
+ UI_From_Int
+ (Boolean'Pos (Has_Preelaborable_Initialization (Ptyp))),
+ Static => False);
+
--------------
-- Priority --
--------------
@@ -7336,7 +7367,7 @@ package body Exp_Attr is
if Nkind (P) in N_Has_Entity
and then Present (Entity (P))
and then Is_Object (Entity (P))
- and then Esize (Entity (P)) /= Uint_0
+ and then Known_Esize (Entity (P))
then
if Esize (Entity (P)) <= System_Max_Integer_Size then
Size := Esize (Entity (P));
@@ -8025,7 +8056,7 @@ package body Exp_Attr is
-- Common processing for record and array component case
- if Siz /= No_Uint and then Siz /= 0 then
+ if Present (Siz) and then Siz /= 0 then
declare
CS : constant Boolean := Comes_From_Source (N);
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index ad82e56..d4373ee 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -26,6 +26,7 @@
with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
+with Contracts; use Contracts;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
@@ -331,10 +332,9 @@ package body Exp_Ch3 is
-- no declarations and no statements.
function Predef_Stream_Attr_Spec
- (Loc : Source_Ptr;
- Tag_Typ : Entity_Id;
- Name : TSS_Name_Type;
- For_Body : Boolean := False) return Node_Id;
+ (Loc : Source_Ptr;
+ Tag_Typ : Entity_Id;
+ Name : TSS_Name_Type) return Node_Id;
-- Specialized version of Predef_Spec_Or_Body that apply to read, write,
-- input and output attribute whose specs are constructed in Exp_Strm.
@@ -3205,9 +3205,7 @@ package body Exp_Ch3 is
-- types moving any expanded code from the spec to the body of the
-- init procedure.
- if Is_Task_Record_Type (Rec_Type)
- or else Is_Protected_Record_Type (Rec_Type)
- then
+ if Is_Concurrent_Record_Type (Rec_Type) then
declare
Decl : constant Node_Id :=
Parent (Corresponding_Concurrent_Type (Rec_Type));
@@ -3421,7 +3419,8 @@ package body Exp_Ch3 is
Clean_Task_Names (Typ, Proc_Id);
- -- Simple initialization
+ -- Simple initialization. If the Esize is not yet set, we pass
+ -- Uint_0 as expected by Get_Simple_Init_Val.
elsif Component_Needs_Simple_Initialization (Typ) then
Actions :=
@@ -3431,7 +3430,9 @@ package body Exp_Ch3 is
Get_Simple_Init_Val
(Typ => Typ,
N => N,
- Size => Esize (Id)));
+ Size =>
+ (if Known_Esize (Id) then Esize (Id)
+ else Uint_0)));
-- Nothing needed for this case
@@ -3585,12 +3586,11 @@ package body Exp_Ch3 is
end loop;
end if;
end;
- end if;
-- For a protected type, add statements generated by
-- Make_Initialize_Protection.
- if Is_Protected_Record_Type (Rec_Type) then
+ elsif Is_Protected_Record_Type (Rec_Type) then
Append_List_To (Stmts,
Make_Initialize_Protection (Rec_Type));
end if;
@@ -5349,10 +5349,66 @@ package body Exp_Ch3 is
-------------------------------
procedure Expand_Freeze_Record_Type (N : Node_Id) is
+
+ procedure Build_Class_Condition_Subprograms (Typ : Entity_Id);
+ -- Create internal subprograms of Typ primitives that have class-wide
+ -- preconditions or postconditions; they are invoked by the caller to
+ -- evaluate the conditions.
+
procedure Build_Variant_Record_Equality (Typ : Entity_Id);
-- Create An Equality function for the untagged variant record Typ and
-- attach it to the TSS list.
+ procedure Register_Dispatch_Table_Wrappers (Typ : Entity_Id);
+ -- Register dispatch-table wrappers in the dispatch table of Typ
+
+ ---------------------------------------
+ -- Build_Class_Condition_Subprograms --
+ ---------------------------------------
+
+ procedure Build_Class_Condition_Subprograms (Typ : Entity_Id) is
+ Prim_List : constant Elist_Id := Primitive_Operations (Typ);
+ Prim_Elmt : Elmt_Id := First_Elmt (Prim_List);
+ Prim : Entity_Id;
+
+ begin
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ -- Primitive with class-wide preconditions
+
+ if Comes_From_Source (Prim)
+ and then Has_Significant_Contract (Prim)
+ and then
+ (Present (Class_Preconditions (Prim))
+ or else Present (Ignored_Class_Preconditions (Prim)))
+ then
+ if Expander_Active then
+ Make_Class_Precondition_Subps (Prim);
+ end if;
+
+ -- Wrapper of a primitive that has or inherits class-wide
+ -- preconditions.
+
+ elsif Is_Primitive_Wrapper (Prim)
+ and then
+ (Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Prim,
+ Kind => Class_Precondition))
+ or else
+ Present (Nearest_Class_Condition_Subprogram
+ (Spec_Id => Prim,
+ Kind => Ignored_Class_Precondition)))
+ then
+ if Expander_Active then
+ Make_Class_Precondition_Subps (Prim);
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Build_Class_Condition_Subprograms;
+
-----------------------------------
-- Build_Variant_Record_Equality --
-----------------------------------
@@ -5414,6 +5470,27 @@ package body Exp_Ch3 is
end if;
end Build_Variant_Record_Equality;
+ --------------------------------------
+ -- Register_Dispatch_Table_Wrappers --
+ --------------------------------------
+
+ procedure Register_Dispatch_Table_Wrappers (Typ : Entity_Id) is
+ Elmt : Elmt_Id := First_Elmt (Primitive_Operations (Typ));
+ Subp : Entity_Id;
+
+ begin
+ while Present (Elmt) loop
+ Subp := Node (Elmt);
+
+ if Is_Dispatch_Table_Wrapper (Subp) then
+ Append_Freeze_Actions (Typ,
+ Register_Primitive (Sloc (Subp), Subp));
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end Register_Dispatch_Table_Wrappers;
+
-- Local variables
Typ : constant Node_Id := Entity (N);
@@ -5663,6 +5740,13 @@ package body Exp_Ch3 is
if not Building_Static_DT (Typ) then
Append_Freeze_Actions (Typ, Make_DT (Typ));
+
+ -- Register dispatch table wrappers in the dispatch table.
+ -- It could not be done when these wrappers were built
+ -- because, at that stage, the dispatch table was not
+ -- available.
+
+ Register_Dispatch_Table_Wrappers (Typ);
end if;
end if;
@@ -5854,6 +5938,13 @@ package body Exp_Ch3 is
end loop;
end;
end if;
+
+ -- Build internal subprograms of primitives with class-wide
+ -- pre/postconditions.
+
+ if Is_Tagged_Type (Typ) then
+ Build_Class_Condition_Subprograms (Typ);
+ end if;
end Expand_Freeze_Record_Type;
------------------------------------
@@ -6507,7 +6598,8 @@ package body Exp_Ch3 is
Get_Simple_Init_Val
(Typ => Typ,
N => Obj_Def,
- Size => Esize (Def_Id)));
+ Size => (if Known_Esize (Def_Id) then Esize (Def_Id)
+ else Uint_0)));
Analyze_And_Resolve
(Expression (N), Typ, Suppress => All_Checks);
@@ -6534,7 +6626,8 @@ package body Exp_Ch3 is
Get_Simple_Init_Val
(Typ => Typ,
N => Obj_Def,
- Size => Esize (Def_Id)));
+ Size =>
+ (if Known_Esize (Def_Id) then Esize (Def_Id) else Uint_0)));
Analyze_And_Resolve (Expression (N), Typ);
end if;
@@ -8506,7 +8599,7 @@ package body Exp_Ch3 is
if Compile_Time_Known_Value (Lo) then
Lo_Val := Expr_Value (Lo);
- if Lo_Bound = No_Uint or else Lo_Bound < Lo_Val then
+ if No (Lo_Bound) or else Lo_Bound < Lo_Val then
Lo_Bound := Lo_Val;
end if;
end if;
@@ -8514,7 +8607,7 @@ package body Exp_Ch3 is
if Compile_Time_Known_Value (Hi) then
Hi_Val := Expr_Value (Hi);
- if Hi_Bound = No_Uint or else Hi_Bound > Hi_Val then
+ if No (Hi_Bound) or else Hi_Bound > Hi_Val then
Hi_Bound := Hi_Val;
end if;
end if;
@@ -8643,7 +8736,7 @@ package body Exp_Ch3 is
-- If zero is invalid, it is a convenient value to use that is for
-- sure an appropriate invalid value in all situations.
- elsif Lo_Bound /= No_Uint and then Lo_Bound > Uint_0 then
+ elsif Present (Lo_Bound) and then Lo_Bound > Uint_0 then
return Make_Integer_Literal (Loc, 0);
-- Unsigned types
@@ -8702,7 +8795,7 @@ package body Exp_Ch3 is
-- If zero is invalid, it is a convenient value to use that is for
-- sure an appropriate invalid value in all situations.
- if Lo_Bound /= No_Uint and then Lo_Bound > Uint_0 then
+ if Present (Lo_Bound) and then Lo_Bound > Uint_0 then
Expr := Make_Integer_Literal (Loc, 0);
-- Cases where all one bits is the appropriate invalid value
@@ -8741,7 +8834,7 @@ package body Exp_Ch3 is
-- For this exceptional case, use largest positive value
- if Lo_Bound /= No_Uint and then Hi_Bound /= No_Uint
+ if Present (Lo_Bound) and then Present (Hi_Bound)
and then Lo_Bound <= (-(2 ** Signed_Size))
and then Hi_Bound < 2 ** Signed_Size
then
@@ -8811,7 +8904,7 @@ package body Exp_Ch3 is
-- Determine the size of the object. This is either the size provided
-- by the caller, or the Esize of the scalar type.
- if Size = No_Uint or else Size <= Uint_0 then
+ if No (Size) or else Size <= Uint_0 then
Size_To_Use := UI_Max (Uint_1, Esize (Typ));
else
Size_To_Use := Size;
@@ -8821,7 +8914,7 @@ package body Exp_Ch3 is
-- will create values of type Long_Long_Long_Unsigned and the range
-- must fit this type.
- if Size_To_Use /= No_Uint
+ if Present (Size_To_Use)
and then Size_To_Use > System_Max_Integer_Size
then
Size_To_Use := UI_From_Int (System_Max_Integer_Size);
@@ -10518,11 +10611,9 @@ package body Exp_Ch3 is
-- Disp_Requeue
-- Disp_Timed_Select
- -- Disable the generation of these bodies if No_Dispatching_Calls,
- -- Ravenscar or ZFP is active.
+ -- Disable the generation of these bodies if Ravenscar or ZFP is active
if Ada_Version >= Ada_2005
- and then not Restriction_Active (No_Dispatching_Calls)
and then not Restriction_Active (No_Select_Statements)
and then RTE_Available (RE_Select_Specific_Data)
then
@@ -10813,10 +10904,9 @@ package body Exp_Ch3 is
-----------------------------
function Predef_Stream_Attr_Spec
- (Loc : Source_Ptr;
- Tag_Typ : Entity_Id;
- Name : TSS_Name_Type;
- For_Body : Boolean := False) return Node_Id
+ (Loc : Source_Ptr;
+ Tag_Typ : Entity_Id;
+ Name : TSS_Name_Type) return Node_Id
is
Ret_Type : Entity_Id;
@@ -10834,7 +10924,7 @@ package body Exp_Ch3 is
Tag_Typ => Tag_Typ,
Profile => Build_Stream_Attr_Profile (Loc, Tag_Typ, Name),
Ret_Type => Ret_Type,
- For_Body => For_Body);
+ For_Body => False);
end Predef_Stream_Attr_Spec;
---------------------------------
@@ -11002,8 +11092,7 @@ package body Exp_Ch3 is
-- The interface versions will have null bodies
- -- Disable the generation of these bodies if No_Dispatching_Calls,
- -- Ravenscar or ZFP is active.
+ -- Disable the generation of these bodies if Ravenscar or ZFP is active
-- In VM targets we define these primitives in all root tagged types
-- that are not interface types. Done because in VM targets we don't
@@ -11022,7 +11111,6 @@ package body Exp_Ch3 is
or else
(not Tagged_Type_Expansion
and then Tag_Typ = Root_Type (Tag_Typ)))
- and then not Restriction_Active (No_Dispatching_Calls)
and then not Restriction_Active (No_Select_Statements)
and then RTE_Available (RE_Select_Specific_Data)
then
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 16f513e..8dcfa85 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -23,6 +23,7 @@
-- --
------------------------------------------------------------------------------
+with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
with Debug; use Debug;
@@ -767,8 +768,7 @@ package body Exp_Ch4 is
Cond :=
Make_Op_Gt (Loc,
Left_Opnd => Cond,
- Right_Opnd =>
- Make_Integer_Literal (Loc, Type_Access_Level (PtrT)));
+ Right_Opnd => Accessibility_Level (N, Dynamic_Level));
-- Due to the complexity and side effects of the check, utilize an
-- if statement instead of the regular Program_Error circuitry.
@@ -2294,7 +2294,7 @@ package body Exp_Ch4 is
-- We can only do this if we in fact have full range information (which
-- won't be the case if either operand is bignum at this stage).
- if Llo /= No_Uint and then Rlo /= No_Uint then
+ if Present (Llo) and then Present (Rlo) then
case N_Op_Compare (Nkind (N)) is
when N_Op_Eq =>
if Llo = Lhi and then Rlo = Rhi and then Llo = Rlo then
@@ -4704,7 +4704,7 @@ package body Exp_Ch4 is
else
Set_Procedure_To_Call (N,
- Find_Prim_Op (Etype (Pool), Name_Allocate));
+ Find_Storage_Op (Etype (Pool), Name_Allocate));
end if;
end if;
end if;
@@ -6254,6 +6254,46 @@ package body Exp_Ch4 is
return;
end if;
+ -- For the sake of GNATcoverage, generate an intermediate temporary in
+ -- the case where the if-expression is a condition in an outer decision,
+ -- in order to make sure that no branch is shared between the decisions.
+
+ elsif Opt.Suppress_Control_Flow_Optimizations
+ and then Nkind (Original_Node (Parent (N))) in N_Case_Expression
+ | N_Case_Statement
+ | N_If_Expression
+ | N_If_Statement
+ | N_Goto_When_Statement
+ | N_Loop_Statement
+ | N_Return_When_Statement
+ | N_Short_Circuit
+ then
+ declare
+ Cnn : constant Entity_Id := Make_Temporary (Loc, 'C');
+ Acts : List_Id;
+
+ begin
+ -- Generate:
+ -- do
+ -- Cnn : constant Typ := N;
+ -- in Cnn end
+
+ Acts := New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Cnn,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (N)));
+
+ Rewrite (N,
+ Make_Expression_With_Actions (Loc,
+ Expression => New_Occurrence_Of (Cnn, Loc),
+ Actions => Acts));
+
+ Analyze_And_Resolve (N, Typ);
+ return;
+ end;
+
-- If no actions then no expansion needed, gigi will handle it using the
-- same approach as a C conditional expression.
@@ -6871,7 +6911,6 @@ package body Exp_Ch4 is
if Ada_Version >= Ada_2012
and then Is_Acc
and then Ekind (Ltyp) = E_Anonymous_Access_Type
- and then not No_Dynamic_Accessibility_Checks_Enabled (Lop)
then
declare
Expr_Entity : Entity_Id := Empty;
@@ -6888,11 +6927,26 @@ package body Exp_Ch4 is
end if;
end if;
+ -- When restriction No_Dynamic_Accessibility_Checks is in
+ -- effect, expand the membership test to a static value
+ -- since we cannot rely on dynamic levels.
+
+ if No_Dynamic_Accessibility_Checks_Enabled (Lop) then
+ if Static_Accessibility_Level
+ (Lop, Object_Decl_Level)
+ > Type_Access_Level (Rtyp)
+ then
+ Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
+ else
+ Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
+ end if;
+ Analyze_And_Resolve (N, Restyp);
+
-- If a conversion of the anonymous access value to the
-- tested type would be illegal, then the result is False.
- if not Valid_Conversion
- (Lop, Rtyp, Lop, Report_Errs => False)
+ elsif not Valid_Conversion
+ (Lop, Rtyp, Lop, Report_Errs => False)
then
Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
Analyze_And_Resolve (N, Restyp);
@@ -7048,11 +7102,123 @@ package body Exp_Ch4 is
--------------------------------
procedure Expand_N_Indexed_Component (N : Node_Id) is
+
+ Wild_Reads_May_Have_Bad_Side_Effects : Boolean
+ renames Validity_Check_Subscripts;
+ -- This Boolean needs to be True if reading from a bad address can
+ -- have a bad side effect (e.g., a segmentation fault that is not
+ -- transformed into a Storage_Error exception, or interactions with
+ -- memory-mapped I/O) that needs to be prevented. This refers to the
+ -- act of reading itself, not to any damage that might be caused later
+ -- by making use of whatever value was read. We assume here that
+ -- Validity_Check_Subscripts meets this requirement, but introduce
+ -- this declaration in order to document this assumption.
+
+ function Is_Renamed_Variable_Name (N : Node_Id) return Boolean;
+ -- Returns True if the given name occurs as part of the renaming
+ -- of a variable. In this case, the indexing operation should be
+ -- treated as a write, rather than a read, with respect to validity
+ -- checking. This is because the renamed variable can later be
+ -- written to.
+
+ function Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ : Entity_Id) return Boolean;
+ -- If Wild_Reads_May_Have_Bad_Side_Effects is False and we are indexing
+ -- into an array of characters in order to read an element, it is ok
+ -- if an invalid index value goes undetected. But if it is an array of
+ -- pointers or an array of tasks, the consequences of such a read are
+ -- potentially more severe and so we want to detect an invalid index
+ -- value. This function captures that distinction; this is intended to
+ -- be consistent with the "but does not by itself lead to erroneous
+ -- ... execution" rule of RM 13.9.1(11).
+
+ ------------------------------
+ -- Is_Renamed_Variable_Name --
+ ------------------------------
+
+ function Is_Renamed_Variable_Name (N : Node_Id) return Boolean is
+ Rover : Node_Id := N;
+ begin
+ if Is_Variable (N) then
+ loop
+ declare
+ Rover_Parent : constant Node_Id := Parent (Rover);
+ begin
+ case Nkind (Rover_Parent) is
+ when N_Object_Renaming_Declaration =>
+ return Rover = Name (Rover_Parent);
+
+ when N_Indexed_Component
+ | N_Slice
+ | N_Selected_Component
+ =>
+ exit when Rover /= Prefix (Rover_Parent);
+ Rover := Rover_Parent;
+
+ -- No need to check for qualified expressions or type
+ -- conversions here, mostly because of the Is_Variable
+ -- test. It is possible to have a view conversion for
+ -- which Is_Variable yields True and which occurs as
+ -- part of an object renaming, but only if the type is
+ -- tagged; in that case this function will not be called.
+
+ when others =>
+ exit;
+ end case;
+ end;
+ end loop;
+ end if;
+ return False;
+ end Is_Renamed_Variable_Name;
+
+ -------------------------------------------------------
+ -- Type_Requires_Subscript_Validity_Checks_For_Reads --
+ -------------------------------------------------------
+
+ function Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ : Entity_Id) return Boolean
+ is
+ -- a shorter name for recursive calls
+ function Needs_Check (Typ : Entity_Id) return Boolean renames
+ Type_Requires_Subscript_Validity_Checks_For_Reads;
+ begin
+ if Is_Access_Type (Typ)
+ or else Is_Tagged_Type (Typ)
+ or else Is_Concurrent_Type (Typ)
+ or else (Is_Array_Type (Typ)
+ and then Needs_Check (Component_Type (Typ)))
+ or else (Is_Scalar_Type (Typ)
+ and then Has_Aspect (Typ, Aspect_Default_Value))
+ then
+ return True;
+ end if;
+
+ if Is_Record_Type (Typ) then
+ declare
+ Comp : Entity_Id := First_Component_Or_Discriminant (Typ);
+ begin
+ while Present (Comp) loop
+ if Needs_Check (Etype (Comp)) then
+ return True;
+ end if;
+
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+ end;
+ end if;
+
+ return False;
+ end Type_Requires_Subscript_Validity_Checks_For_Reads;
+
+ -- Local constants
+
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
P : constant Node_Id := Prefix (N);
T : constant Entity_Id := Etype (P);
+ -- Start of processing for Expand_N_Indexed_Component
+
begin
-- A special optimization, if we have an indexed component that is
-- selecting from a slice, then we can eliminate the slice, since, for
@@ -7102,11 +7268,67 @@ package body Exp_Ch4 is
-- Generate index and validity checks
- Generate_Index_Checks (N);
+ declare
+ Dims_Checked : Dimension_Set (Dimensions =>
+ (if Is_Array_Type (T)
+ then Number_Dimensions (T)
+ else 1));
+ -- Dims_Checked is used to avoid generating two checks (one in
+ -- Generate_Index_Checks, one in Apply_Subscript_Validity_Checks)
+ -- for the same index value in cases where the index check eliminates
+ -- the need for the validity check. The Is_Array_Type test avoids
+ -- cascading errors.
- if Validity_Checks_On and then Validity_Check_Subscripts then
- Apply_Subscript_Validity_Checks (N);
- end if;
+ begin
+ Generate_Index_Checks (N, Checks_Generated => Dims_Checked);
+
+ if Validity_Checks_On
+ and then (Validity_Check_Subscripts
+ or else Wild_Reads_May_Have_Bad_Side_Effects
+ or else Type_Requires_Subscript_Validity_Checks_For_Reads
+ (Typ)
+ or else Is_Renamed_Variable_Name (N))
+ then
+ if Validity_Check_Subscripts then
+ -- If we index into an array with an uninitialized variable
+ -- and we generate an index check that passes at run time,
+ -- passing that check does not ensure that the variable is
+ -- valid (although it does in the common case where the
+ -- object's subtype matches the index subtype).
+ -- Consider an uninitialized variable with subtype 1 .. 10
+ -- used to index into an array with bounds 1 .. 20 when the
+ -- value of the uninitialized variable happens to be 15.
+ -- The index check will succeed but the variable is invalid.
+ -- If Validity_Check_Subscripts is True then we need to
+ -- ensure validity, so we adjust Dims_Checked accordingly.
+ Dims_Checked.Elements := (others => False);
+
+ elsif Is_Array_Type (T) then
+ -- We are only adding extra validity checks here to
+ -- deal with uninitialized variables (but this includes
+ -- assigning one uninitialized variable to another). Other
+ -- ways of producing invalid objects imply erroneousness, so
+ -- the compiler can do whatever it wants for those cases.
+ -- If an index type has the Default_Value aspect specified,
+ -- then we don't have to worry about the possibility of an
+ -- uninitialized variable, so no need for these extra
+ -- validity checks.
+
+ declare
+ Idx : Node_Id := First_Index (T);
+ begin
+ for No_Check_Needed of Dims_Checked.Elements loop
+ No_Check_Needed := No_Check_Needed
+ or else Has_Aspect (Etype (Idx), Aspect_Default_Value);
+ Next_Index (Idx);
+ end loop;
+ end;
+ end if;
+
+ Apply_Subscript_Validity_Checks
+ (N, No_Check_Needed => Dims_Checked);
+ end if;
+ end;
-- If selecting from an array with atomic components, and atomic sync
-- is not suppressed for this array type, set atomic sync flag.
@@ -7763,8 +7985,8 @@ package body Exp_Ch4 is
if Is_Unchecked_Union (Op_Type) then
declare
- Lhs_Type : constant Node_Id := Etype (L_Exp);
- Rhs_Type : constant Node_Id := Etype (R_Exp);
+ Lhs_Type : constant Entity_Id := Etype (L_Exp);
+ Rhs_Type : constant Entity_Id := Etype (R_Exp);
Lhs_Discr_Vals : Elist_Id;
-- List of inferred discriminant values for left operand.
@@ -8570,8 +8792,7 @@ package body Exp_Ch4 is
-- f'Machine (expr) to eliminate surprise from extra precision.
if Is_Floating_Point_Type (Typl)
- and then Nkind (Original_Node (Lhs)) = N_Attribute_Reference
- and then Attribute_Name (Original_Node (Lhs)) = Name_Result
+ and then Is_Attribute_Result (Original_Node (Lhs))
then
-- Stick in the Typ'Machine call if not already there
@@ -11339,7 +11560,7 @@ package body Exp_Ch4 is
then
Par := Parent (Par);
- -- Any other case is not what we are looking for
+ -- Any other case is not what we are looking for
else
return False;
@@ -11375,7 +11596,7 @@ package body Exp_Ch4 is
-- Local variables
- Pref : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
-- Start of processing for Expand_N_Slice
@@ -11401,7 +11622,7 @@ package body Exp_Ch4 is
-- situation correctly in the assignment statement expansion).
-- 2. Prefix of indexed component (the slide is optimized away in this
- -- case, see the start of Expand_N_Slice.)
+ -- case, see the start of Expand_N_Indexed_Component.)
-- 3. Object renaming declaration, since we want the name of the
-- slice, not the value.
@@ -12361,10 +12582,16 @@ package body Exp_Ch4 is
-- an instantiation, otherwise the conversion will already have been
-- rejected as illegal.
- -- Note: warnings are issued by the analyzer for the instance cases
+ -- Note: warnings are issued by the analyzer for the instance cases,
+ -- and, since we are late in expansion, a check is performed to
+ -- verify that neither the target type nor the operand type are
+ -- internally generated - as this can lead to spurious errors when,
+ -- for example, the operand type is a result of BIP expansion.
elsif In_Instance_Body
and then Statically_Deeper_Relation_Applies (Target_Type)
+ and then not Is_Internal (Target_Type)
+ and then not Is_Internal (Operand_Type)
and then
Type_Access_Level (Operand_Type) > Type_Access_Level (Target_Type)
then
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 8ac9662..21ac2a2 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -31,7 +31,6 @@ with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Elists; use Elists;
-with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
@@ -742,8 +741,8 @@ package body Exp_Ch5 is
-- in the front end.
declare
- L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
- R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
+ L_Index_Typ : constant Entity_Id := Etype (First_Index (L_Type));
+ R_Index_Typ : constant Entity_Id := Etype (First_Index (R_Type));
Left_Lo : constant Node_Id := Type_Low_Bound (L_Index_Typ);
Left_Hi : constant Node_Id := Type_High_Bound (L_Index_Typ);
@@ -1382,8 +1381,8 @@ package body Exp_Ch5 is
Loc : constant Source_Ptr := Sloc (N);
- L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
- R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
+ L_Index_Typ : constant Entity_Id := Etype (First_Index (L_Type));
+ R_Index_Typ : constant Entity_Id := Etype (First_Index (R_Type));
Left_Lo : constant Node_Id := Type_Low_Bound (L_Index_Typ);
Right_Lo : constant Node_Id := Type_Low_Bound (R_Index_Typ);
@@ -1698,8 +1697,8 @@ package body Exp_Ch5 is
(Etype (Left_Base_Index)))
and then RTE_Available (RE_Fast_Copy_Bitfield)
then
- pragma Assert (Esize (L_Type) /= 0);
- pragma Assert (Esize (R_Type) /= 0);
+ pragma Assert (Known_Esize (L_Type));
+ pragma Assert (Known_Esize (R_Type));
return Expand_Assign_Array_Bitfield_Fast (N, Larray, Rarray);
end if;
@@ -3365,6 +3364,30 @@ package body Exp_Ch5 is
renames Pattern_Match;
-- convenient rename for recursive calls
+ function Indexed_Element (Idx : Pos) return Node_Id;
+ -- Returns the Nth (well, ok, the Idxth) element of Object
+
+ ---------------------
+ -- Indexed_Element --
+ ---------------------
+
+ function Indexed_Element (Idx : Pos) return Node_Id is
+ Obj_Index : constant Node_Id :=
+ Make_Op_Add (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_First,
+ Prefix => New_Copy_Tree (Object)),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Idx - 1));
+ begin
+ return Make_Indexed_Component (Loc,
+ Prefix => New_Copy_Tree (Object),
+ Expressions => New_List (Obj_Index));
+ end Indexed_Element;
+
+ -- Start of processing for Pattern_Match
+
begin
if Choice_Index /= 0 and not Suppress_Choice_Index_Update then
pragma Assert (Present (Choice_Index_Decl));
@@ -3399,16 +3422,51 @@ package body Exp_Ch5 is
case Nkind (Pattern) is
when N_Aggregate =>
- return Result : Node_Id :=
- New_Occurrence_Of (Standard_True, Loc)
- do
+ declare
+ Result : Node_Id;
+ begin
if Is_Array_Type (Etype (Pattern)) then
- -- Calling Error_Msg_N during expansion is usually a
- -- mistake but is ok for an "unimplemented" message.
- Error_Msg_N
- ("array-valued case choices unimplemented",
- Pattern);
- return;
+
+ -- Nonpositional aggregates currently unimplemented.
+ -- We flag that case during analysis, so an assertion
+ -- is ok here.
+ --
+ pragma Assert
+ (not Is_Non_Empty_List
+ (Component_Associations (Pattern)));
+
+ declare
+ Agg_Length : constant Node_Id :=
+ Make_Integer_Literal (Loc,
+ List_Length (Expressions (Pattern)));
+
+ Obj_Length : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Length,
+ Prefix => New_Copy_Tree (Object));
+ begin
+ Result := Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Length,
+ Right_Opnd => Agg_Length);
+ end;
+
+ declare
+ Expr : Node_Id := First (Expressions (Pattern));
+ Idx : Pos := 1;
+ begin
+ while Present (Expr) loop
+ Result :=
+ Make_And_Then (Loc,
+ Left_Opnd => Result,
+ Right_Opnd =>
+ PM (Pattern => Expr,
+ Object => Indexed_Element (Idx)));
+ Next (Expr);
+ Idx := Idx + 1;
+ end loop;
+ end;
+
+ return Result;
end if;
-- positional notation should have been normalized
@@ -3425,6 +3483,8 @@ package body Exp_Ch5 is
Selector_Name => New_Occurrence_Of
(Entity (Choice), Loc)));
begin
+ Result := New_Occurrence_Of (Standard_True, Loc);
+
while Present (Component_Assoc) loop
Choice := First (Choices (Component_Assoc));
while Present (Choice) loop
@@ -3530,27 +3590,82 @@ package body Exp_Ch5 is
Next (Component_Assoc);
end loop;
end;
+ return Result;
+ end;
+
+ when N_String_Literal =>
+ return Result : Node_Id do
+ declare
+ Char_Type : constant Entity_Id :=
+ Root_Type (Component_Type (Etype (Pattern)));
+
+ -- If the component type is not a standard character
+ -- type then this string lit should have already been
+ -- transformed into an aggregate in
+ -- Resolve_String_Literal.
+ --
+ pragma Assert (Is_Standard_Character_Type (Char_Type));
+
+ Str : constant String_Id := Strval (Pattern);
+ Strlen : constant Nat := String_Length (Str);
+
+ Lit_Length : constant Node_Id :=
+ Make_Integer_Literal (Loc, Strlen);
+
+ Obj_Length : constant Node_Id :=
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Length,
+ Prefix => New_Copy_Tree (Object));
+ begin
+ Result := Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Length,
+ Right_Opnd => Lit_Length);
+
+ for Idx in 1 .. Strlen loop
+ declare
+ C : constant Char_Code :=
+ Get_String_Char (Str, Idx);
+ Obj_Element : constant Node_Id :=
+ Indexed_Element (Idx);
+ Char_Lit : Node_Id;
+ begin
+ Set_Character_Literal_Name (C);
+ Char_Lit :=
+ Make_Character_Literal (Loc,
+ Chars => Name_Find,
+ Char_Literal_Value => UI_From_CC (C));
+
+ Result :=
+ Make_And_Then (Loc,
+ Left_Opnd => Result,
+ Right_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd => Obj_Element,
+ Right_Opnd => Char_Lit));
+ end;
+ end loop;
+ end;
end return;
when N_Qualified_Expression =>
- -- Make a copy for one of the two uses of Object; the choice
- -- of where to use the original and where to use the copy
- -- is arbitrary.
-
return Make_And_Then (Loc,
Left_Opnd => Make_In (Loc,
Left_Opnd => New_Copy_Tree (Object),
Right_Opnd => New_Copy_Tree (Subtype_Mark (Pattern))),
Right_Opnd =>
PM (Pattern => Expression (Pattern),
- Object => Object));
+ Object => New_Copy_Tree (Object)));
when N_Identifier | N_Expanded_Name =>
if Is_Type (Entity (Pattern)) then
return Make_In (Loc,
- Left_Opnd => Object,
+ Left_Opnd => New_Copy_Tree (Object),
Right_Opnd => New_Occurrence_Of
(Entity (Pattern), Loc));
+ elsif Ekind (Entity (Pattern)) = E_Constant then
+ return PM (Pattern =>
+ Expression (Parent (Entity (Pattern))),
+ Object => Object);
end if;
when N_Others_Choice =>
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 59704a4..3f83685 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -73,8 +73,10 @@ with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
+with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
+with Stringt; use Stringt;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
with Validsw; use Validsw;
@@ -3141,6 +3143,13 @@ package body Exp_Ch6 is
function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean is
Actual : Node_Id;
+ function Augments_Other_Dynamic_Predicate (DP_Aspect_Spec : Node_Id)
+ return Boolean;
+ -- Given a Dynamic_Predicate aspect aspecification for a
+ -- discrete type, returns True iff another DP specification
+ -- applies (indirectly, via a subtype type or a derived type)
+ -- to the same entity that this aspect spec applies to.
+
function May_Fold (N : Node_Id) return Traverse_Result;
-- The predicate expression is foldable if it only contains operators
-- and literals. During this check, we also replace occurrences of
@@ -3148,6 +3157,36 @@ package body Exp_Ch6 is
-- value of the actual. This is done on a copy of the analyzed
-- expression for the predicate.
+ --------------------------------------
+ -- Augments_Other_Dynamic_Predicate --
+ --------------------------------------
+
+ function Augments_Other_Dynamic_Predicate (DP_Aspect_Spec : Node_Id)
+ return Boolean
+ is
+ Aspect_Bearer : Entity_Id := Entity (DP_Aspect_Spec);
+ begin
+ loop
+ Aspect_Bearer := Nearest_Ancestor (Aspect_Bearer);
+
+ if not Present (Aspect_Bearer) then
+ return False;
+ end if;
+
+ declare
+ Aspect_Spec : constant Node_Id :=
+ Find_Aspect (Aspect_Bearer, Aspect_Dynamic_Predicate);
+ begin
+ if Present (Aspect_Spec)
+ and then Aspect_Spec /= DP_Aspect_Spec
+ then
+ -- Found another Dynamic_Predicate aspect spec
+ return True;
+ end if;
+ end;
+ end loop;
+ end Augments_Other_Dynamic_Predicate;
+
--------------
-- May_Fold --
--------------
@@ -3190,7 +3229,7 @@ package body Exp_Ch6 is
function Try_Fold is new Traverse_Func (May_Fold);
- -- Other lLocal variables
+ -- Other Local variables
Subt : constant Entity_Id := Etype (First_Entity (P));
Aspect : Node_Id;
@@ -3218,6 +3257,11 @@ package body Exp_Ch6 is
or else Nkind (Actual) /= N_Integer_Literal
or else not Has_Dynamic_Predicate_Aspect (Subt)
or else No (Aspect)
+
+ -- Do not fold if multiple applicable predicate aspects
+ or else Present (Find_Aspect (Subt, Aspect_Static_Predicate))
+ or else Present (Find_Aspect (Subt, Aspect_Predicate))
+ or else Augments_Other_Dynamic_Predicate (Aspect)
or else CodePeer_Mode
then
return False;
@@ -4065,7 +4109,7 @@ package body Exp_Ch6 is
end;
end if;
- -- If the formal is class wide and the actual is an aggregate, force
+ -- If the formal is class-wide and the actual is an aggregate, force
-- evaluation so that the back end who does not know about class-wide
-- type, does not generate a temporary of the wrong size.
@@ -4250,6 +4294,16 @@ package body Exp_Ch6 is
Expand_Interface_Actuals (Call_Node);
end if;
+ -- Install class-wide preconditions runtime check when this is a
+ -- dispatching primitive that has or inherits class-wide preconditions;
+ -- otherwise no runtime check is installed.
+
+ if Nkind (Call_Node) in N_Subprogram_Call
+ and then Is_Dispatching_Operation (Subp)
+ then
+ Install_Class_Preconditions_Check (Call_Node);
+ end if;
+
-- Deals with Dispatch_Call if we still have a call, before expanding
-- extra actuals since this will be done on the re-analysis of the
-- dispatching call. Note that we do not try to shorten the actual list
@@ -4380,6 +4434,7 @@ package body Exp_Ch6 is
-- the current subprogram is called.
if Is_Subprogram (Subp)
+ and then not Is_Ignored_Ghost_Entity (Subp)
and then Same_Or_Aliased_Subprograms (Subp, Current_Scope)
then
Check_Subprogram_Variant;
@@ -4520,6 +4575,8 @@ package body Exp_Ch6 is
or else
(Is_Record_Type (Formal_Typ)
and then Is_Record_Type (Parent_Typ)))
+ and then Known_Esize (Formal_Typ)
+ and then Known_Esize (Parent_Typ)
and then
(Esize (Formal_Typ) /= Esize (Parent_Typ)
or else Has_Pragma_Pack (Formal_Typ) /=
@@ -7435,6 +7492,10 @@ package body Exp_Ch6 is
and then not Is_Class_Wide_Type (Utyp)
and then (Nkind (Exp) in
N_Type_Conversion | N_Unchecked_Type_Conversion
+ or else (Nkind (Exp) = N_Explicit_Dereference
+ and then Nkind (Prefix (Exp)) in
+ N_Type_Conversion |
+ N_Unchecked_Type_Conversion)
or else (Is_Entity_Name (Exp)
and then Is_Formal (Entity (Exp))))
then
@@ -7849,18 +7910,6 @@ package body Exp_Ch6 is
-- returned type may not be known yet (for private types).
Compute_Returns_By_Ref (Subp);
-
- -- When freezing a null procedure, analyze its delayed aspects now
- -- because we may not have reached the end of the declarative list when
- -- delayed aspects are normally analyzed. This ensures that dispatching
- -- calls are properly rewritten when the generated _Postcondition
- -- procedure is analyzed in the null procedure body.
-
- if Nkind (Parent (Subp)) = N_Procedure_Specification
- and then Null_Present (Parent (Subp))
- then
- Analyze_Entry_Or_Subprogram_Contract (Subp);
- end if;
end Freeze_Subprogram;
--------------------------
@@ -8095,6 +8144,367 @@ package body Exp_Ch6 is
end if;
end Insert_Post_Call_Actions;
+ ---------------------------------------
+ -- Install_Class_Preconditions_Check --
+ ---------------------------------------
+
+ procedure Install_Class_Preconditions_Check (Call_Node : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (Call_Node);
+
+ function Build_Dynamic_Check_Helper_Call return Node_Id;
+ -- Build call to the helper runtime function of the nearest ancestor
+ -- of the target subprogram that dynamically evaluates the merged
+ -- or-else preconditions.
+
+ function Build_Error_Message (Subp_Id : Entity_Id) return Node_Id;
+ -- Build message associated with the class-wide precondition of Subp_Id
+ -- indicating the call that caused it.
+
+ function Build_Static_Check_Helper_Call return Node_Id;
+ -- Build call to the helper runtime function of the nearest ancestor
+ -- of the target subprogram that dynamically evaluates the merged
+ -- or-else preconditions.
+
+ function Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id;
+ Dynamic : Boolean) return Node_Id;
+ -- Return the nearest ancestor of Spec_Id defining a helper function
+ -- that evaluates a combined or-else expression containing all the
+ -- inherited class-wide preconditions; Dynamic enables searching for
+ -- the helper that dynamically evaluates preconditions using dispatching
+ -- calls; if False it searches for the helper that statically evaluates
+ -- preconditions; return Empty when not available (which means that no
+ -- preconditions check is required).
+
+ -------------------------------------
+ -- Build_Dynamic_Check_Helper_Call --
+ -------------------------------------
+
+ function Build_Dynamic_Check_Helper_Call return Node_Id is
+ Spec_Id : constant Entity_Id := Entity (Name (Call_Node));
+ CW_Subp : constant Entity_Id :=
+ Class_Preconditions_Subprogram (Spec_Id,
+ Dynamic => True);
+ Helper_Id : constant Entity_Id :=
+ Dynamic_Call_Helper (CW_Subp);
+ Actuals : constant List_Id := New_List;
+ A : Node_Id := First_Actual (Call_Node);
+ F : Entity_Id := First_Formal (Helper_Id);
+
+ begin
+ while Present (A) loop
+
+ -- Ensure that the evaluation of the actuals will not produce
+ -- side effects.
+
+ Remove_Side_Effects (A);
+
+ Append_To (Actuals, New_Copy_Tree (A));
+ Next_Formal (F);
+ Next_Actual (A);
+ end loop;
+
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Helper_Id, Loc),
+ Parameter_Associations => Actuals);
+ end Build_Dynamic_Check_Helper_Call;
+
+ -------------------------
+ -- Build_Error_Message --
+ -------------------------
+
+ function Build_Error_Message (Subp_Id : Entity_Id) return Node_Id is
+
+ procedure Append_Message
+ (Id : Entity_Id;
+ Is_First : in out Boolean);
+ -- Build the fragment of the message associated with subprogram Id;
+ -- Is_First facilitates identifying continuation messages.
+
+ --------------------
+ -- Append_Message --
+ --------------------
+
+ procedure Append_Message
+ (Id : Entity_Id;
+ Is_First : in out Boolean)
+ is
+ Prag : constant Node_Id := Get_Class_Wide_Pragma (Id,
+ Pragma_Precondition);
+ Msg : Node_Id;
+ Str_Id : String_Id;
+
+ begin
+ if No (Prag) or else Is_Ignored (Prag) then
+ return;
+ end if;
+
+ Msg := Expression (Last (Pragma_Argument_Associations (Prag)));
+ Str_Id := Strval (Msg);
+
+ if Is_First then
+ Is_First := False;
+
+ Append (Global_Name_Buffer, Strval (Msg));
+
+ if Id /= Subp_Id
+ and then Name_Buffer (1 .. 19) = "failed precondition"
+ then
+ Insert_Str_In_Name_Buffer ("inherited ", 8);
+ end if;
+
+ else
+ declare
+ Str : constant String := To_String (Str_Id);
+ From_Idx : Integer;
+
+ begin
+ Append (Global_Name_Buffer, ASCII.LF);
+ Append (Global_Name_Buffer, " or ");
+
+ From_Idx := Name_Len;
+ Append (Global_Name_Buffer, Str_Id);
+
+ if Str (1 .. 19) = "failed precondition" then
+ Insert_Str_In_Name_Buffer ("inherited ", From_Idx + 8);
+ end if;
+ end;
+ end if;
+ end Append_Message;
+
+ -- Local variables
+
+ Str_Loc : constant String := Build_Location_String (Loc);
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Is_First : Boolean := True;
+
+ -- Start of processing for Build_Error_Message
+
+ begin
+ Name_Len := 0;
+ Append_Message (Subp_Id, Is_First);
+
+ for Index in Subps'Range loop
+ Append_Message (Subps (Index), Is_First);
+ end loop;
+
+ if Present (Controlling_Argument (Call_Node)) then
+ Append (Global_Name_Buffer, " in dispatching call at ");
+ else
+ Append (Global_Name_Buffer, " in call at ");
+ end if;
+
+ Append (Global_Name_Buffer, Str_Loc);
+
+ return Make_String_Literal (Loc, Name_Buffer (1 .. Name_Len));
+ end Build_Error_Message;
+
+ ------------------------------------
+ -- Build_Static_Check_Helper_Call --
+ ------------------------------------
+
+ function Build_Static_Check_Helper_Call return Node_Id is
+ Actuals : constant List_Id := New_List;
+ A : Node_Id;
+ Helper_Id : Entity_Id;
+ F : Entity_Id;
+ CW_Subp : Entity_Id;
+ Spec_Id : constant Entity_Id := Entity (Name (Call_Node));
+
+ begin
+ -- The target is the wrapper built to support inheriting body but
+ -- overriding pre/postconditions (AI12-0195).
+
+ if Is_Dispatch_Table_Wrapper (Spec_Id) then
+ CW_Subp := Spec_Id;
+
+ -- Common case
+
+ else
+ CW_Subp := Class_Preconditions_Subprogram (Spec_Id,
+ Dynamic => False);
+ end if;
+
+ Helper_Id := Static_Call_Helper (CW_Subp);
+
+ F := First_Formal (Helper_Id);
+ A := First_Actual (Call_Node);
+ while Present (A) loop
+
+ -- Ensure that the evaluation of the actuals will not produce
+ -- side effects.
+
+ Remove_Side_Effects (A);
+
+ if Is_Controlling_Actual (A)
+ and then Etype (F) /= Etype (A)
+ then
+ Append_To (Actuals,
+ Make_Unchecked_Type_Conversion (Loc,
+ New_Occurrence_Of (Etype (F), Loc),
+ New_Copy_Tree (A)));
+ else
+ Append_To (Actuals, New_Copy_Tree (A));
+ end if;
+
+ Next_Formal (F);
+ Next_Actual (A);
+ end loop;
+
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Helper_Id, Loc),
+ Parameter_Associations => Actuals);
+ end Build_Static_Check_Helper_Call;
+
+ ------------------------------------
+ -- Class_Preconditions_Subprogram --
+ ------------------------------------
+
+ function Class_Preconditions_Subprogram
+ (Spec_Id : Entity_Id;
+ Dynamic : Boolean) return Node_Id
+ is
+ Subp_Id : constant Entity_Id := Ultimate_Alias (Spec_Id);
+
+ begin
+ -- Prevent cascaded errors
+
+ if not Is_Dispatching_Operation (Subp_Id) then
+ return Empty;
+
+ -- No need to search if this subprogram has the helper we are
+ -- searching
+
+ elsif Dynamic then
+ if Present (Dynamic_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ else
+ if Present (Static_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end if;
+
+ -- Process inherited subprograms looking for class-wide
+ -- preconditions.
+
+ declare
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Subp_Id : Entity_Id;
+
+ begin
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if Dynamic then
+ if Present (Dynamic_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ else
+ if Present (Static_Call_Helper (Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end if;
+ end loop;
+ end;
+
+ return Empty;
+ end Class_Preconditions_Subprogram;
+
+ -- Local variables
+
+ Dynamic_Check : constant Boolean :=
+ Present (Controlling_Argument (Call_Node));
+ Class_Subp : Entity_Id;
+ Cond : Node_Id;
+ Subp : Entity_Id;
+
+ -- Start of processing for Install_Class_Preconditions_Check
+
+ begin
+ -- Do not expand the check if we are compiling under restriction
+ -- No_Dispatching_Calls; the semantic analyzer has previously
+ -- notified the violation of this restriction.
+
+ if Dynamic_Check
+ and then Restriction_Active (No_Dispatching_Calls)
+ then
+ return;
+
+ -- Class-wide precondition check not needed in interface thunks since
+ -- they are installed in the dispatching call that caused invoking the
+ -- thunk.
+
+ elsif Is_Thunk (Current_Scope) then
+ return;
+ end if;
+
+ Subp := Entity (Name (Call_Node));
+
+ -- No check needed for this subprogram call if no class-wide
+ -- preconditions apply (or if the unique available preconditions
+ -- are ignored preconditions).
+
+ Class_Subp := Class_Preconditions_Subprogram (Subp, Dynamic_Check);
+
+ if No (Class_Subp)
+ or else No (Class_Preconditions (Class_Subp))
+ then
+ return;
+ end if;
+
+ -- Build and install the check
+
+ if Dynamic_Check then
+ Cond := Build_Dynamic_Check_Helper_Call;
+ else
+ Cond := Build_Static_Check_Helper_Call;
+ end if;
+
+ if Exception_Locations_Suppressed then
+ Insert_Action (Call_Node,
+ Make_If_Statement (Loc,
+ Condition => Make_Op_Not (Loc, Cond),
+ Then_Statements => New_List (
+ Make_Raise_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Assert_Failure), Loc)))));
+
+ -- Failed check with message indicating the failed precondition and the
+ -- call that caused it.
+
+ else
+ Insert_Action (Call_Node,
+ Make_If_Statement (Loc,
+ Condition => Make_Op_Not (Loc, Cond),
+ Then_Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Raise_Assert_Failure), Loc),
+ Parameter_Associations =>
+ New_List (Build_Error_Message (Subp))))));
+ end if;
+ end Install_Class_Preconditions_Check;
+
-----------------------------------
-- Is_Build_In_Place_Result_Type --
-----------------------------------
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 76cec4d..196f7e6 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -121,6 +121,9 @@ package Exp_Ch6 is
-- The returned node is the root of the procedure body which will replace
-- the original function body, which is not needed for the C program.
+ procedure Install_Class_Preconditions_Check (Call_Node : Node_Id);
+ -- Install check of class-wide preconditions on the caller.
+
function Is_Build_In_Place_Entity (E : Entity_Id) return Boolean;
-- Ada 2005 (AI-318-02): Returns True if E is a BIP entity.
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f7807ac..71cad98 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -486,11 +486,11 @@ package body Exp_Ch7 is
function Make_Deep_Proc
(Prim : Final_Primitives;
Typ : Entity_Id;
- Stmts : List_Id) return Node_Id;
+ Stmts : List_Id) return Entity_Id;
-- This function generates the tree for Deep_Initialize, Deep_Adjust or
- -- Deep_Finalize procedures according to the first parameter, these
- -- procedures operate on the type Typ. The Stmts parameter gives the body
- -- of the procedure.
+ -- Deep_Finalize procedures according to the first parameter. These
+ -- procedures operate on the type Typ. The Stmts parameter gives the
+ -- body of the procedure.
function Make_Deep_Array_Body
(Prim : Final_Primitives;
@@ -5918,12 +5918,7 @@ package body Exp_Ch7 is
Build_Static_Dispatch_Tables (N);
end if;
- -- If procedures marked with CUDA_Global have been defined within N,
- -- we need to register them with the CUDA runtime at program startup.
- -- This requires multiple declarations and function calls which need
- -- to be appended to N's declarations.
-
- Build_And_Insert_CUDA_Initialization (N);
+ Expand_CUDA_Package (N);
Build_Task_Activation_Call (N);
@@ -6072,7 +6067,7 @@ package body Exp_Ch7 is
Pop_Scope;
end if;
- -- Build dispatch tables of library level tagged types
+ -- Build dispatch tables of library-level tagged types
if Tagged_Type_Expansion
and then (Is_Compilation_Unit (Id)
@@ -9560,8 +9555,11 @@ package body Exp_Ch7 is
-- If initialization procedure for an array of controlled objects is
-- trivial, do not generate a useless call to it.
+ -- The initialization procedure may be missing altogether in the case
+ -- of a derived container whose components have trivial initialization.
- if (Is_Array_Type (Utyp) and then Is_Trivial_Subprogram (Proc))
+ if No (Proc)
+ or else (Is_Array_Type (Utyp) and then Is_Trivial_Subprogram (Proc))
or else
(not Comes_From_Source (Proc)
and then Present (Alias (Proc))
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 427b430..694cf90 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -145,7 +145,7 @@ package body Exp_Ch9 is
function Build_Corresponding_Record
(N : Node_Id;
- Ctyp : Node_Id;
+ Ctyp : Entity_Id;
Loc : Source_Ptr) return Node_Id;
-- Common to tasks and protected types. Copy discriminant specifications,
-- build record declaration. N is the type declaration, Ctyp is the
@@ -1583,9 +1583,9 @@ package body Exp_Ch9 is
--------------------------------
function Build_Corresponding_Record
- (N : Node_Id;
- Ctyp : Entity_Id;
- Loc : Source_Ptr) return Node_Id
+ (N : Node_Id;
+ Ctyp : Entity_Id;
+ Loc : Source_Ptr) return Node_Id
is
Rec_Ent : constant Entity_Id :=
Make_Defining_Identifier
@@ -13796,14 +13796,15 @@ package body Exp_Ch9 is
Comp : Node_Id;
Comp_Id : Entity_Id;
Decl_Id : Entity_Id;
+ Nam : Name_Id;
begin
Comp := First (Private_Declarations (Def));
while Present (Comp) loop
if Nkind (Comp) = N_Component_Declaration then
Comp_Id := Defining_Identifier (Comp);
- Decl_Id :=
- Make_Defining_Identifier (Loc, Chars (Comp_Id));
+ Nam := Chars (Comp_Id);
+ Decl_Id := Make_Defining_Identifier (Sloc (Comp_Id), Nam);
-- Minimal decoration
@@ -13818,6 +13819,14 @@ package body Exp_Ch9 is
Set_Is_Aliased (Decl_Id, Is_Aliased (Comp_Id));
Set_Is_Independent (Decl_Id, Is_Independent (Comp_Id));
+ -- Copy the Comes_From_Source flag of the component, as
+ -- the renaming may be the only entity directly seen by
+ -- the user in the context, but do not warn for it.
+
+ Set_Comes_From_Source
+ (Decl_Id, Comes_From_Source (Comp_Id));
+ Set_Warnings_Off (Decl_Id);
+
-- Generate:
-- comp_name : comp_typ renames _object.comp_name;
@@ -13828,10 +13837,8 @@ package body Exp_Ch9 is
New_Occurrence_Of (Etype (Comp_Id), Loc),
Name =>
Make_Selected_Component (Loc,
- Prefix =>
- New_Occurrence_Of (Obj_Ent, Loc),
- Selector_Name =>
- Make_Identifier (Loc, Chars (Comp_Id))));
+ Prefix => New_Occurrence_Of (Obj_Ent, Loc),
+ Selector_Name => Make_Identifier (Loc, Nam)));
Add (Decl);
end if;
@@ -14867,7 +14874,7 @@ package body Exp_Ch9 is
Actuals : List_Id;
Formals : List_Id;
Decls : List_Id;
- Stmts : List_Id) return Node_Id
+ Stmts : List_Id) return Entity_Id
is
Actual : Entity_Id;
Expr : Node_Id := Empty;
diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb
index bfc3b33..96d78cc 100644
--- a/gcc/ada/exp_dbug.adb
+++ b/gcc/ada/exp_dbug.adb
@@ -409,7 +409,9 @@ package body Exp_Dbug is
when N_Expanded_Name
| N_Identifier
=>
- if not Present (Renamed_Object (Entity (Ren))) then
+ if No (Entity (Ren))
+ or else not Present (Renamed_Object (Entity (Ren)))
+ then
exit;
end if;
@@ -438,7 +440,7 @@ package body Exp_Dbug is
Enable
or else Is_Packed
(Underlying_Type (Etype (Prefix (Ren))))
- or else (First_Bit /= No_Uint
+ or else (Present (First_Bit)
and then First_Bit /= Uint_0);
end;
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index e9d6e74..6ade54b 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -63,7 +63,6 @@ with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
-with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
with Stringt; use Stringt;
@@ -93,10 +92,6 @@ package body Exp_Disp is
-- Duplicate_Subexpr with an explicit dereference when From is an access
-- parameter.
- function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean;
- -- Check if the type has a private view or if the public view appears in
- -- the visible part of a package spec.
-
function Prim_Op_Kind
(Prim : Entity_Id;
Typ : Entity_Id) return Node_Id;
@@ -352,7 +347,7 @@ package body Exp_Disp is
-- Build_Static_Dispatch_Tables --
----------------------------------
- procedure Build_Static_Dispatch_Tables (N : Entity_Id) is
+ procedure Build_Static_Dispatch_Tables (N : Node_Id) is
Target_List : List_Id;
procedure Build_Dispatch_Tables (List : List_Id);
@@ -581,7 +576,7 @@ package body Exp_Disp is
-- If number of primitives already set in the tag component, use it
if Present (Tag_Comp)
- and then DT_Entry_Count (Tag_Comp) /= No_Uint
+ and then Present (DT_Entry_Count (Tag_Comp))
then
return UI_To_Int (DT_Entry_Count (Tag_Comp));
@@ -701,233 +696,11 @@ package body Exp_Disp is
Eq_Prim_Op : Entity_Id := Empty;
Controlling_Tag : Node_Id;
- procedure Build_Class_Wide_Check (E : Entity_Id);
- -- If the denoted subprogram has a class-wide precondition, generate a
- -- check using that precondition before the dispatching call, because
- -- this is the only class-wide precondition that applies to the call;
- -- otherwise climb to the ancestors searching for the enclosing
- -- overridden primitive of E that has a class-wide precondition (and
- -- use it to generate the check).
-
function New_Value (From : Node_Id) return Node_Id;
-- From is the original Expression. New_Value is equivalent to a call
-- to Duplicate_Subexpr with an explicit dereference when From is an
-- access parameter.
- ----------------------------
- -- Build_Class_Wide_Check --
- ----------------------------
-
- procedure Build_Class_Wide_Check (E : Entity_Id) is
- Subp : Entity_Id := E;
-
- function Has_Class_Wide_Precondition
- (Subp : Entity_Id) return Boolean;
- -- Evaluates if the dispatching subprogram Subp has a class-wide
- -- precondition.
-
- function Replace_Formals (N : Node_Id) return Traverse_Result;
- -- Replace occurrences of the formals of the subprogram by the
- -- corresponding actuals in the call, given that this check is
- -- performed outside of the body of the subprogram.
-
- -- If the dispatching call appears in the same scope as the
- -- declaration of the dispatching subprogram (for example in
- -- the expression of a local expression function), the spec
- -- has not been analyzed yet, in which case we use the Chars
- -- field to recognize intended occurrences of the formals.
-
- ---------------------------------
- -- Has_Class_Wide_Precondition --
- ---------------------------------
-
- function Has_Class_Wide_Precondition
- (Subp : Entity_Id) return Boolean
- is
- Prec : Node_Id := Empty;
-
- begin
- if Present (Contract (Subp))
- and then Present (Pre_Post_Conditions (Contract (Subp)))
- then
- Prec := Pre_Post_Conditions (Contract (Subp));
-
- while Present (Prec) loop
- exit when Pragma_Name (Prec) = Name_Precondition
- and then Class_Present (Prec);
- Prec := Next_Pragma (Prec);
- end loop;
- end if;
-
- return Present (Prec)
- and then not Is_Ignored (Prec);
- end Has_Class_Wide_Precondition;
-
- ---------------------
- -- Replace_Formals --
- ---------------------
-
- function Replace_Formals (N : Node_Id) return Traverse_Result is
- A : Node_Id;
- F : Entity_Id;
- begin
- if Is_Entity_Name (N) then
- F := First_Formal (Subp);
- A := First_Actual (Call_Node);
-
- if Present (Entity (N)) and then Is_Formal (Entity (N)) then
- while Present (F) loop
- if F = Entity (N) then
- if not Is_Controlling_Actual (N) then
- Rewrite (N, New_Copy_Tree (A));
-
- -- If the formal is class-wide, and thus not a
- -- controlling argument, preserve its type because
- -- it may appear in a nested call with a class-wide
- -- parameter.
-
- if Is_Class_Wide_Type (Etype (F)) then
- Set_Etype (N, Etype (F));
-
- -- Conversely, if this is a controlling argument
- -- (in a dispatching call in the condition) that
- -- is a dereference, the source is an access-to-
- -- -class-wide type, so preserve the dispatching
- -- nature of the call in the rewritten condition.
-
- elsif Nkind (Parent (N)) = N_Explicit_Dereference
- and then Is_Controlling_Actual (Parent (N))
- then
- Set_Controlling_Argument (Parent (Parent (N)),
- Parent (N));
- end if;
-
- -- Ensure that the type of the controlling actual
- -- matches the type of the controlling formal of the
- -- parent primitive Subp defining the class-wide
- -- precondition.
-
- elsif Is_Class_Wide_Type (Etype (A)) then
- Rewrite (N,
- Convert_To
- (Class_Wide_Type (Etype (F)),
- New_Copy_Tree (A)));
-
- else
- Rewrite (N,
- Convert_To
- (Etype (F),
- New_Copy_Tree (A)));
- end if;
-
- exit;
- end if;
-
- Next_Formal (F);
- Next_Actual (A);
- end loop;
-
- -- If the node is not analyzed, recognize occurrences of a
- -- formal by name, as would be done when resolving the aspect
- -- expression in the context of the subprogram.
-
- elsif not Analyzed (N)
- and then Nkind (N) = N_Identifier
- and then No (Entity (N))
- then
- while Present (F) loop
- if Chars (N) = Chars (F) then
- Rewrite (N, New_Copy_Tree (A));
- return Skip;
- end if;
-
- Next_Formal (F);
- Next_Actual (A);
- end loop;
- end if;
- end if;
-
- return OK;
- end Replace_Formals;
-
- procedure Update is new Traverse_Proc (Replace_Formals);
-
- -- Local variables
-
- Str_Loc : constant String := Build_Location_String (Loc);
-
- A : Node_Id;
- Cond : Node_Id;
- Msg : Node_Id;
- Prec : Node_Id;
-
- -- Start of processing for Build_Class_Wide_Check
-
- begin
- -- Climb searching for the enclosing class-wide precondition
-
- while not Has_Class_Wide_Precondition (Subp)
- and then Present (Overridden_Operation (Subp))
- loop
- Subp := Overridden_Operation (Subp);
- end loop;
-
- -- Locate class-wide precondition, if any
-
- if Present (Contract (Subp))
- and then Present (Pre_Post_Conditions (Contract (Subp)))
- then
- Prec := Pre_Post_Conditions (Contract (Subp));
-
- while Present (Prec) loop
- exit when Pragma_Name (Prec) = Name_Precondition
- and then Class_Present (Prec);
- Prec := Next_Pragma (Prec);
- end loop;
-
- if No (Prec) or else Is_Ignored (Prec) then
- return;
- end if;
-
- -- Ensure that the evaluation of the actuals will not produce side
- -- effects (since the check will use a copy of the actuals).
-
- A := First_Actual (Call_Node);
- while Present (A) loop
- Remove_Side_Effects (A);
- Next_Actual (A);
- end loop;
-
- -- The expression for the precondition is analyzed within the
- -- generated pragma. The message text is the last parameter of
- -- the generated pragma, indicating source of precondition.
-
- Cond :=
- New_Copy_Tree
- (Expression (First (Pragma_Argument_Associations (Prec))));
- Update (Cond);
-
- -- Build message indicating the failed precondition and the
- -- dispatching call that caused it.
-
- Msg := Expression (Last (Pragma_Argument_Associations (Prec)));
- Name_Len := 0;
- Append (Global_Name_Buffer, Strval (Msg));
- Append (Global_Name_Buffer, " in dispatching call at ");
- Append (Global_Name_Buffer, Str_Loc);
- Msg := Make_String_Literal (Loc, Name_Buffer (1 .. Name_Len));
-
- Insert_Action (Call_Node,
- Make_If_Statement (Loc,
- Condition => Make_Op_Not (Loc, Cond),
- Then_Statements => New_List (
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Raise_Assert_Failure), Loc),
- Parameter_Associations => New_List (Msg)))));
- end if;
- end Build_Class_Wide_Check;
-
---------------
-- New_Value --
---------------
@@ -988,8 +761,6 @@ package body Exp_Disp is
Subp := Alias (Subp);
end if;
- Build_Class_Wide_Check (Subp);
-
-- Definition of the class-wide type and the tagged type
-- If the controlling argument is itself a tag rather than a tagged
@@ -1020,6 +791,10 @@ package body Exp_Disp is
Typ := Find_Specific_Type (CW_Typ);
+ -- The tagged type of a dispatching call must be frozen at this stage
+
+ pragma Assert (Is_Frozen (Typ));
+
if not Is_Limited_Type (Typ) then
Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
end if;
@@ -4716,7 +4491,7 @@ package body Exp_Disp is
Exname : Entity_Id;
HT_Link : Entity_Id;
ITable : Node_Id;
- I_Depth : Nat := 0;
+ I_Depth : Nat;
Iface_Table_Node : Node_Id;
Name_ITable : Name_Id;
Nb_Prim : Nat := 0;
@@ -5928,6 +5703,11 @@ package body Exp_Disp is
Set_Is_True_Constant (TSD, Building_Static_DT (Typ));
+ -- The debugging information for type Ada.Tags.Type_Specific_Data is
+ -- needed by the debugger in order to display values of tagged types.
+
+ Set_Needs_Debug_Info (TSD, Needs_Debug_Info (Typ));
+
-- Initialize or declare the dispatch table object
if not Has_DT (Typ) then
@@ -6614,7 +6394,6 @@ package body Exp_Disp is
Append_Elmt (DT, DT_Decl);
Analyze_List (Result, Suppress => All_Checks);
- Set_Has_Dispatch_Table (Typ);
-- Mark entities containing dispatch tables. Required by the backend to
-- handle them properly.
@@ -6647,6 +6426,8 @@ package body Exp_Disp is
<<Leave_SCIL>>
+ Set_Has_Dispatch_Table (Typ);
+
-- Register the tagged type in the call graph nodes table
Register_CG_Node (Typ);
@@ -7394,31 +7175,6 @@ package body Exp_Disp is
end if;
end New_Value;
- -----------------------------------
- -- Original_View_In_Visible_Part --
- -----------------------------------
-
- function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean is
- Scop : constant Entity_Id := Scope (Typ);
-
- begin
- -- The scope must be a package
-
- if not Is_Package_Or_Generic_Package (Scop) then
- return False;
- end if;
-
- -- A type with a private declaration has a private view declared in
- -- the visible part.
-
- if Has_Private_Declaration (Typ) then
- return True;
- end if;
-
- return List_Containing (Parent (Typ)) =
- Visible_Declarations (Package_Specification (Scop));
- end Original_View_In_Visible_Part;
-
------------------
-- Prim_Op_Kind --
------------------
@@ -8036,14 +7792,14 @@ package body Exp_Disp is
(Find_Dispatching_Type (Interface_Alias (Prim)), Typ,
Use_Full_View => True)
then
- pragma Assert (DT_Position (Prim) = No_Uint
- and then Present (DTC_Entity (Interface_Alias (Prim))));
+ pragma Assert (No (DT_Position (Prim)));
+ pragma Assert (Present (DTC_Entity (Interface_Alias (Prim))));
E := Interface_Alias (Prim);
Set_DT_Position_Value (Prim, DT_Position (E));
pragma Assert
- (DT_Position (Alias (Prim)) = No_Uint
+ (No (DT_Position (Alias (Prim)))
or else DT_Position (Alias (Prim)) = DT_Position (E));
Set_DT_Position_Value (Alias (Prim), DT_Position (E));
Set_Fixed_Prim (UI_To_Int (DT_Position (Prim)));
@@ -8094,7 +7850,7 @@ package body Exp_Disp is
-- Skip primitives previously set entries
- if DT_Position (Prim) /= No_Uint then
+ if Present (DT_Position (Prim)) then
null;
-- Primitives covering interface primitives are handled later
@@ -8127,7 +7883,7 @@ package body Exp_Disp is
while Present (Prim_Elmt) loop
Prim := Node (Prim_Elmt);
- if DT_Position (Prim) = No_Uint
+ if No (DT_Position (Prim))
and then Present (Interface_Alias (Prim))
then
pragma Assert (Present (Alias (Prim))
@@ -8139,14 +7895,14 @@ package body Exp_Disp is
(Find_Dispatching_Type (Interface_Alias (Prim)), Typ,
Use_Full_View => True)
then
- pragma Assert (DT_Position (Alias (Prim)) /= No_Uint);
+ pragma Assert (Present (DT_Position (Alias (Prim))));
Set_DT_Position_Value (Prim, DT_Position (Alias (Prim)));
-- Otherwise it will be placed in the secondary DT
else
pragma Assert
- (DT_Position (Interface_Alias (Prim)) /= No_Uint);
+ (Present (DT_Position (Interface_Alias (Prim))));
Set_DT_Position_Value (Prim,
DT_Position (Interface_Alias (Prim)));
end if;
@@ -8175,7 +7931,7 @@ package body Exp_Disp is
-- At this point all the primitives MUST have a position in the
-- dispatch table.
- if DT_Position (Prim) = No_Uint then
+ if No (DT_Position (Prim)) then
raise Program_Error;
end if;
@@ -8795,7 +8551,7 @@ package body Exp_Disp is
-- (primary or secondary) dispatch table.
if Present (DTC_Entity (Prim))
- and then DT_Position (Prim) /= No_Uint
+ and then Present (DT_Position (Prim))
then
Write_Str (" at #");
Write_Int (UI_To_Int (DT_Position (Prim)));
diff --git a/gcc/ada/exp_dist.adb b/gcc/ada/exp_dist.adb
index 5cb8fb5..41c0aea 100644
--- a/gcc/ada/exp_dist.adb
+++ b/gcc/ada/exp_dist.adb
@@ -300,12 +300,9 @@ package body Exp_Dist is
NVList : Entity_Id;
Parameter : Entity_Id;
Constrained : Boolean;
- RACW_Ctrl : Boolean := False;
Any : Entity_Id) return Node_Id;
-- Return a call to Add_Item to add the Any corresponding to the designated
-- formal Parameter (with the indicated Constrained status) to NVList.
- -- RACW_Ctrl must be set to True for controlling formals of distributed
- -- object primitive operations.
--------------------
-- Stub_Structure --
@@ -1089,7 +1086,6 @@ package body Exp_Dist is
NVList : Entity_Id;
Parameter : Entity_Id;
Constrained : Boolean;
- RACW_Ctrl : Boolean := False;
Any : Entity_Id) return Node_Id
is
Parameter_Name_String : String_Id;
@@ -1146,7 +1142,7 @@ package body Exp_Dist is
Parameter_Name_String := String_From_Name_Buffer;
- if RACW_Ctrl or else Nkind (Parameter) = N_Defining_Identifier then
+ if Nkind (Parameter) = N_Defining_Identifier then
-- When the parameter passed to Add_Parameter_To_NVList is an
-- Extra_Constrained parameter, Parameter is an N_Defining_
diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
index 8d7624f..94a61df 100644
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -190,6 +190,15 @@ package body Exp_Fixd is
-- The expression returned is neither analyzed nor resolved. The Etype
-- of the result is properly set (to Universal_Real).
+ function Get_Size_For_Value (V : Uint) return Pos;
+ -- Given a non-negative universal integer value, return the size of a small
+ -- signed integer type covering -V .. V, or Pos'Max if no such type exists.
+
+ function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id;
+ -- Return the smallest signed integer type containing at least Siz bits.
+ -- If no such type exists, return Empty if Force is False or the largest
+ -- signed integer type if Force is True.
+
function Integer_Literal
(N : Node_Id;
V : Uint;
@@ -324,7 +333,6 @@ package body Exp_Fixd is
Right_Type : constant Entity_Id := Base_Type (Etype (R));
Left_Size : Int;
Right_Size : Int;
- Rsize : Int;
Result_Type : Entity_Id;
Rnode : Node_Id;
@@ -354,20 +362,17 @@ 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 in signed 8/16/32 bits.
+ -- operand to get a size if it would fit in a small signed integer.
Left_Size := UI_To_Int (RM_Size (Left_Type));
if Compile_Time_Known_Value (L) then
declare
- Val : constant Uint := Expr_Value (L);
+ Siz : constant Int :=
+ Get_Size_For_Value (UI_Abs (Expr_Value (L)));
begin
- if Val < Uint_2 ** 7 then
- Left_Size := 8;
- elsif Val < Uint_2 ** 15 then
- Left_Size := 16;
- elsif Val < Uint_2 ** 31 then
- Left_Size := 32;
+ if Siz < Left_Size then
+ Left_Size := Siz;
end if;
end;
end if;
@@ -376,35 +381,19 @@ package body Exp_Fixd is
if Compile_Time_Known_Value (R) then
declare
- Val : constant Uint := Expr_Value (R);
+ Siz : constant Int :=
+ Get_Size_For_Value (UI_Abs (Expr_Value (R)));
begin
- if Val <= Int'(2 ** 7) then
- Right_Size := 8;
- elsif Val <= Int'(2 ** 15) then
- Right_Size := 16;
+ if Siz < Right_Size then
+ Right_Size := Siz;
end if;
end;
end if;
-- Do the operation using the longer of the two sizes
- Rsize := Int'Max (Left_Size, Right_Size);
-
- if Rsize <= 8 then
- Result_Type := Standard_Integer_8;
-
- elsif Rsize <= 16 then
- Result_Type := Standard_Integer_16;
-
- elsif Rsize <= 32 then
- Result_Type := Standard_Integer_32;
-
- elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
- Result_Type := Standard_Integer_64;
-
- else
- Result_Type := Standard_Integer_128;
- end if;
+ Result_Type :=
+ Get_Type_For_Size (Int'Max (Left_Size, Right_Size), Force => True);
Rnode :=
Make_Op_Divide (Loc,
@@ -664,7 +653,6 @@ package body Exp_Fixd is
Right_Type : constant Entity_Id := Etype (R);
Left_Size : Int;
Right_Size : Int;
- Rsize : Int;
Result_Type : Entity_Id;
Rnode : Node_Id;
@@ -697,20 +685,17 @@ 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 in signed 8/16/32 bits.
+ -- operand to get a size if it would fit in a small signed integer.
Left_Size := UI_To_Int (RM_Size (Left_Type));
if Compile_Time_Known_Value (L) then
declare
- Val : constant Uint := Expr_Value (L);
+ Siz : constant Int :=
+ Get_Size_For_Value (UI_Abs (Expr_Value (L)));
begin
- if Val < Uint_2 ** 7 then
- Left_Size := 8;
- elsif Val < Uint_2 ** 15 then
- Left_Size := 16;
- elsif Val < Uint_2 ** 31 then
- Left_Size := 32;
+ if Siz < Left_Size then
+ Left_Size := Siz;
end if;
end;
end if;
@@ -719,12 +704,11 @@ package body Exp_Fixd is
if Compile_Time_Known_Value (R) then
declare
- Val : constant Uint := Expr_Value (R);
+ Siz : constant Int :=
+ Get_Size_For_Value (UI_Abs (Expr_Value (R)));
begin
- if Val <= Int'(2 ** 7) then
- Right_Size := 8;
- elsif Val <= Int'(2 ** 15) then
- Right_Size := 16;
+ if Siz < Right_Size then
+ Right_Size := Siz;
end if;
end;
end if;
@@ -732,23 +716,8 @@ package body Exp_Fixd is
-- Now the result size must be at least the sum of the two sizes,
-- to accommodate all possible results.
- Rsize := Left_Size + Right_Size;
-
- if Rsize <= 8 then
- Result_Type := Standard_Integer_8;
-
- elsif Rsize <= 16 then
- Result_Type := Standard_Integer_16;
-
- elsif Rsize <= 32 then
- Result_Type := Standard_Integer_32;
-
- elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
- Result_Type := Standard_Integer_64;
-
- else
- Result_Type := Standard_Integer_128;
- end if;
+ Result_Type :=
+ Get_Type_For_Size (Left_Size + Right_Size, Force => True);
Rnode :=
Make_Op_Multiply (Loc,
@@ -1542,7 +1511,7 @@ package body Exp_Fixd is
else
Lit_Int := Integer_Literal (N, Frac_Den, UR_Is_Negative (Frac));
- Lit_K := Integer_Literal (N, Frac_Num);
+ Lit_K := Integer_Literal (N, Frac_Num, False);
if Present (Lit_Int) and then Present (Lit_K) then
Set_Result (N, Build_Scaled_Divide (N, Left, Lit_K, Lit_Int));
@@ -2422,6 +2391,64 @@ package body Exp_Fixd is
return Build_Conversion (N, Universal_Real, N);
end Fpt_Value;
+ ------------------------
+ -- Get_Size_For_Value --
+ ------------------------
+
+ function Get_Size_For_Value (V : Uint) return Pos is
+ begin
+ pragma Assert (V >= Uint_0);
+
+ if V < Uint_2 ** 7 then
+ return 8;
+
+ elsif V < Uint_2 ** 15 then
+ return 16;
+
+ elsif V < Uint_2 ** 31 then
+ return 32;
+
+ elsif V < Uint_2 ** 63 then
+ return 64;
+
+ elsif V < Uint_2 ** 127 then
+ return 128;
+
+ else
+ return Pos'Last;
+ end if;
+ end Get_Size_For_Value;
+
+ -----------------------
+ -- Get_Type_For_Size --
+ -----------------------
+
+ function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id is
+ begin
+ if Siz <= 8 then
+ return Standard_Integer_8;
+
+ elsif Siz <= 16 then
+ return Standard_Integer_16;
+
+ elsif Siz <= 32 then
+ return Standard_Integer_32;
+
+ elsif Siz <= 64
+ or else (Force and then System_Max_Integer_Size < 128)
+ then
+ return Standard_Integer_64;
+
+ elsif (Siz <= 128 and then System_Max_Integer_Size = 128)
+ or else Force
+ then
+ return Standard_Integer_128;
+
+ else
+ return Empty;
+ end if;
+ end Get_Type_For_Size;
+
---------------------
-- Integer_Literal --
---------------------
@@ -2435,22 +2462,8 @@ package body Exp_Fixd is
L : Node_Id;
begin
- if V < Uint_2 ** 7 then
- T := Standard_Integer_8;
-
- elsif V < Uint_2 ** 15 then
- T := Standard_Integer_16;
-
- elsif V < Uint_2 ** 31 then
- T := Standard_Integer_32;
-
- 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
+ T := Get_Type_For_Size (Get_Size_For_Value (V), Force => False);
+ if No (T) then
return Empty;
end if;
diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb
index 45de0fb..86cb702 100644
--- a/gcc/ada/exp_intr.adb
+++ b/gcc/ada/exp_intr.adb
@@ -1151,7 +1151,7 @@ package body Exp_Intr is
else
Set_Procedure_To_Call
- (Free_Nod, Find_Prim_Op (Etype (Pool), Name_Deallocate));
+ (Free_Nod, Find_Storage_Op (Etype (Pool), Name_Deallocate));
end if;
end if;
diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb
index 88f86f4..779dbb3 100644
--- a/gcc/ada/exp_pakd.adb
+++ b/gcc/ada/exp_pakd.adb
@@ -493,7 +493,7 @@ package body Exp_Pakd is
Ancest : Entity_Id;
PB_Type : Entity_Id;
- PASize : Uint;
+ PASize : Uint := No_Uint;
Decl : Node_Id;
PAT : Entity_Id;
Len_Expr : Node_Id;
@@ -563,19 +563,21 @@ package body Exp_Pakd is
-- Do not reset RM_Size if already set, as happens in the case of
-- a modular type.
- if not Known_Esize (PAT) then
- Set_Esize (PAT, PASize);
- end if;
+ if Present (PASize) then
+ if not Known_Esize (PAT) then
+ Set_Esize (PAT, PASize);
+ end if;
- if not Known_RM_Size (PAT) then
- Set_RM_Size (PAT, PASize);
+ if not Known_RM_Size (PAT) then
+ Set_RM_Size (PAT, PASize);
+ end if;
end if;
Adjust_Esize_Alignment (PAT);
-- Set remaining fields of packed array type
- Init_Alignment (PAT);
+ Reinit_Alignment (PAT);
Set_Parent (PAT, Empty);
Set_Associated_Node_For_Itype (PAT, Typ);
Set_Original_Array_Type (PAT, Typ);
@@ -680,7 +682,9 @@ package body Exp_Pakd is
-- type, since this size clearly belongs to the packed array type. The
-- size of the conceptual unpacked type is always set to unknown.
- PASize := RM_Size (Typ);
+ if Known_RM_Size (Typ) then
+ PASize := RM_Size (Typ);
+ end if;
-- Case of an array where at least one index is of an enumeration
-- type with a non-standard representation, but the component size
@@ -943,7 +947,7 @@ package body Exp_Pakd is
Make_Integer_Literal (Loc, 0),
High_Bound => Lit))));
- if PASize = Uint_0 then
+ if Present (PASize) then
PASize := Len_Bits;
end if;
@@ -1973,6 +1977,7 @@ package body Exp_Pakd is
Rtyp : Entity_Id;
PAT : Entity_Id;
Lit : Node_Id;
+ Size : Unat;
begin
Convert_To_Actual_Subtype (Opnd);
@@ -1994,9 +1999,15 @@ package body Exp_Pakd is
-- where PAT is the packed array type, Mask is a mask of all 1 bits of
-- length equal to the size of this packed type, and Rtyp is the actual
- -- actual subtype of the operand.
+ -- actual subtype of the operand. Preserve old behavior in case size is
+ -- not set.
- Lit := Make_Integer_Literal (Loc, 2 ** RM_Size (PAT) - 1);
+ if Known_RM_Size (PAT) then
+ Size := RM_Size (PAT);
+ else
+ Size := Uint_0;
+ end if;
+ Lit := Make_Integer_Literal (Loc, 2 ** Size - 1);
Set_Print_In_Hex (Lit);
if not Is_Array_Type (PAT) then
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 43ecdcd..27b4e7d 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -752,10 +752,10 @@ package body Exp_Prag is
-- value of which is Init_Val if present or null if not.
function Build_Simple_Declaration_With_Default
- (Decl_Id : Entity_Id;
- Init_Val : Entity_Id;
- Typ : Entity_Id;
- Default_Val : Entity_Id) return Node_Id;
+ (Decl_Id : Entity_Id;
+ Init_Val : Node_Id;
+ Typ : Node_Id;
+ Default_Val : Node_Id) return Node_Id;
-- Build a declaration the Defining_Identifier of which is Decl_Id, the
-- Object_Definition of which is Typ, the value of which is Init_Val if
-- present or Default otherwise.
@@ -983,7 +983,7 @@ package body Exp_Prag is
function Build_Simple_Declaration_With_Default
(Decl_Id : Entity_Id;
Init_Val : Node_Id;
- Typ : Entity_Id;
+ Typ : Node_Id;
Default_Val : Node_Id) return Node_Id
is
Value : Node_Id := Init_Val;
@@ -1525,9 +1525,7 @@ package body Exp_Prag is
begin
-- Attribute 'Old
- if Nkind (N) = N_Attribute_Reference
- and then Attribute_Name (N) = Name_Old
- then
+ if Is_Attribute_Old (N) then
Pref := Prefix (N);
Indirect := Indirect_Temp_Needed (Etype (Pref));
@@ -2862,7 +2860,7 @@ package body Exp_Prag is
procedure Expand_Pragma_Subprogram_Variant
(Prag : Node_Id;
- Subp_Id : Node_Id;
+ Subp_Id : Entity_Id;
Body_Decls : List_Id)
is
Curr_Decls : List_Id;
diff --git a/gcc/ada/exp_smem.adb b/gcc/ada/exp_smem.adb
index 45db487..216065f5 100644
--- a/gcc/ada/exp_smem.adb
+++ b/gcc/ada/exp_smem.adb
@@ -86,7 +86,7 @@ package body Exp_Smem is
function Build_Shared_Var_Proc_Call
(Loc : Source_Ptr;
- E : Node_Id;
+ E : Entity_Id;
N : Name_Id) return Node_Id;
-- Build a call to support procedure N for shared object E (provided by the
-- instance of System.Shared_Storage.Shared_Var_Procs associated to E).
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 2584041..0a6837c 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -1270,11 +1270,10 @@ package body Exp_Util is
---------------------------------
procedure Build_Class_Wide_Expression
- (Prag : Node_Id;
- Subp : Entity_Id;
- Par_Subp : Entity_Id;
- Adjust_Sloc : Boolean;
- Needs_Wrapper : out Boolean)
+ (Pragma_Or_Expr : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Adjust_Sloc : Boolean)
is
function Replace_Entity (N : Node_Id) return Traverse_Result;
-- Replace reference to formal of inherited operation or to primitive
@@ -1294,7 +1293,7 @@ package body Exp_Util is
Adjust_Inherited_Pragma_Sloc (N);
end if;
- if Nkind (N) = N_Identifier
+ if Nkind (N) in N_Identifier | N_Expanded_Name | N_Operator_Symbol
and then Present (Entity (N))
and then
(Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
@@ -1319,84 +1318,6 @@ package body Exp_Util is
if Present (New_E) then
Rewrite (N, New_Occurrence_Of (New_E, Sloc (N)));
-
- -- AI12-0166: a precondition for a protected operation
- -- cannot include an internal call to a protected function
- -- of the type. In the case of an inherited condition for an
- -- overriding operation, both the operation and the function
- -- are given by primitive wrappers.
- -- Move this check to sem???
-
- if Ekind (New_E) = E_Function
- and then Is_Primitive_Wrapper (New_E)
- and then Is_Primitive_Wrapper (Subp)
- and then Scope (Subp) = Scope (New_E)
- and then Chars (Pragma_Identifier (Prag)) = Name_Precondition
- then
- Error_Msg_Node_2 := Wrapped_Entity (Subp);
- Error_Msg_NE
- ("internal call to& cannot appear in inherited "
- & "precondition of protected operation&",
- N, Wrapped_Entity (New_E));
- end if;
-
- -- If the entity is an overridden primitive and we are not
- -- in GNATprove mode, we must build a wrapper for the current
- -- inherited operation. If the reference is the prefix of an
- -- attribute such as 'Result (or others ???) there is no need
- -- for a wrapper: the condition is just rewritten in terms of
- -- the inherited subprogram.
-
- if Is_Subprogram (New_E)
- and then Nkind (Parent (N)) /= N_Attribute_Reference
- and then not GNATprove_Mode
- then
- Needs_Wrapper := True;
- end if;
- end if;
-
- -- Check that there are no calls left to abstract operations if
- -- the current subprogram is not abstract.
- -- Move this check to sem???
-
- if Nkind (Parent (N)) = N_Function_Call
- and then N = Name (Parent (N))
- then
- if not Is_Abstract_Subprogram (Subp)
- and then Is_Abstract_Subprogram (Entity (N))
- then
- Error_Msg_Sloc := Sloc (Current_Scope);
- Error_Msg_Node_2 := Subp;
- if Comes_From_Source (Subp) then
- Error_Msg_NE
- ("cannot call abstract subprogram & in inherited "
- & "condition for&#", Subp, Entity (N));
- else
- Error_Msg_NE
- ("cannot call abstract subprogram & in inherited "
- & "condition for inherited&#", Subp, Entity (N));
- end if;
-
- -- In SPARK mode, reject an inherited condition for an
- -- inherited operation if it contains a call to an overriding
- -- operation, because this implies that the pre/postconditions
- -- of the inherited operation have changed silently.
-
- elsif SPARK_Mode = On
- and then Warn_On_Suspicious_Contract
- and then Present (Alias (Subp))
- and then Present (New_E)
- and then Comes_From_Source (New_E)
- then
- Error_Msg_N
- ("cannot modify inherited condition (SPARK RM 6.1.1(1))",
- Parent (Subp));
- Error_Msg_Sloc := Sloc (New_E);
- Error_Msg_Node_2 := Subp;
- Error_Msg_NE
- ("\overriding of&# forces overriding of&",
- Parent (Subp), New_E);
- end if;
end if;
-- Update type of function call node, which should be the same as
@@ -1422,26 +1343,17 @@ package body Exp_Util is
-- Local variables
- Par_Formal : Entity_Id;
- Subp_Formal : Entity_Id;
+ Par_Typ : constant Entity_Id := Find_Dispatching_Type (Par_Subp);
+ Subp_Typ : constant Entity_Id := Find_Dispatching_Type (Subp);
-- Start of processing for Build_Class_Wide_Expression
begin
- Needs_Wrapper := False;
-
- -- Add mapping from old formals to new formals
-
- Par_Formal := First_Formal (Par_Subp);
- Subp_Formal := First_Formal (Subp);
-
- while Present (Par_Formal) and then Present (Subp_Formal) loop
- Type_Map.Set (Par_Formal, Subp_Formal);
- Next_Formal (Par_Formal);
- Next_Formal (Subp_Formal);
- end loop;
+ pragma Assert (Par_Typ /= Subp_Typ);
- Replace_Condition_Entities (Prag);
+ Update_Primitives_Mapping (Par_Subp, Subp);
+ Map_Formals (Par_Subp, Subp);
+ Replace_Condition_Entities (Pragma_Or_Expr);
end Build_Class_Wide_Expression;
--------------------
@@ -1895,7 +1807,33 @@ package body Exp_Util is
Priv_Typ : Entity_Id;
-- The partial view of Par_Typ
+ Op_Node : Elmt_Id;
+ Par_Prim : Entity_Id;
+ Prim : Entity_Id;
+
begin
+ -- Map the overridden primitive to the overriding one; required by
+ -- Replace_References (called by Add_Inherited_DICs) to handle calls
+ -- to parent primitives.
+
+ Op_Node := First_Elmt (Primitive_Operations (T));
+ while Present (Op_Node) loop
+ Prim := Node (Op_Node);
+
+ if Present (Overridden_Operation (Prim))
+ and then Comes_From_Source (Prim)
+ then
+ Par_Prim := Overridden_Operation (Prim);
+
+ -- Create a mapping of the form:
+ -- parent type primitive -> derived type primitive
+
+ Type_Map.Set (Par_Prim, Prim);
+ end if;
+
+ Next_Elmt (Op_Node);
+ end loop;
+
-- Climb the parent type chain
Curr_Typ := T;
@@ -2097,14 +2035,11 @@ package body Exp_Util is
Stmts => Stmts);
end if;
- -- 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.
+ -- Otherwise, the "full" DIC procedure verifies the DICs inherited from
+ -- parent types, as well as indirectly verifying the DICs of the partial
+ -- view by calling the "partial" DIC procedure.
else
- pragma Assert (Present (Full_Typ));
-
-- Check the DIC of the partial view by calling the "partial" DIC
-- procedure, unless the partial DIC body is empty. Generate:
@@ -2118,44 +2053,6 @@ package body Exp_Util is
New_Occurrence_Of (Obj_Id, Loc))));
end if;
- -- 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;
-
-- Process inherited Default_Initial_Conditions for all parent types
Add_Parent_DICs (Work_Typ, Obj_Id, Stmts);
@@ -4892,6 +4789,9 @@ package body Exp_Util is
then
return False;
+ elsif not Known_Normalized_First_Bit (Comp) then
+ return True;
+
-- Otherwise if the component is not byte aligned, we know we have the
-- nasty unaligned case.
@@ -4911,7 +4811,7 @@ package body Exp_Util is
-- Convert_To_Actual_Subtype --
-------------------------------
- procedure Convert_To_Actual_Subtype (Exp : Entity_Id) is
+ procedure Convert_To_Actual_Subtype (Exp : Node_Id) is
Act_ST : Entity_Id;
begin
@@ -6356,6 +6256,32 @@ package body Exp_Util is
raise Program_Error;
end Find_Protection_Type;
+ function Find_Storage_Op
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id
+ is
+ use Sem_Util.Storage_Model_Support;
+
+ begin
+ if Has_Storage_Model_Type_Aspect (Typ) then
+ declare
+ SMT_Op : constant Entity_Id :=
+ Get_Storage_Model_Type_Entity (Typ, Nam);
+ begin
+ if not Present (SMT_Op) then
+ raise Program_Error;
+ else
+ return SMT_Op;
+ end if;
+ end;
+
+ -- Otherwise we assume that Typ is a descendant of Root_Storage_Pool
+
+ else
+ return Find_Prim_Op (Typ, Nam);
+ end if;
+ end Find_Storage_Op;
+
-----------------------
-- Find_Hook_Context --
-----------------------
@@ -6589,6 +6515,7 @@ package body Exp_Util is
Related_Id : Entity_Id := Empty;
Is_Low_Bound : Boolean := False;
Is_High_Bound : Boolean := False;
+ Discr_Number : Int := 0;
Mode : Force_Evaluation_Mode := Relaxed)
is
begin
@@ -6600,6 +6527,7 @@ package body Exp_Util is
Related_Id => Related_Id,
Is_Low_Bound => Is_Low_Bound,
Is_High_Bound => Is_High_Bound,
+ Discr_Number => Discr_Number,
Check_Side_Effects =>
Is_Static_Expression (Exp)
or else Mode = Relaxed);
@@ -7043,7 +6971,7 @@ package body Exp_Util is
-- Get_Index_Subtype --
-----------------------
- function Get_Index_Subtype (N : Node_Id) return Node_Id is
+ function Get_Index_Subtype (N : Node_Id) return Entity_Id is
P_Type : Entity_Id := Etype (Prefix (N));
Indx : Node_Id;
J : Int;
@@ -7068,6 +6996,15 @@ package body Exp_Util is
return Etype (Indx);
end Get_Index_Subtype;
+ -----------------------
+ -- Get_Mapped_Entity --
+ -----------------------
+
+ function Get_Mapped_Entity (E : Entity_Id) return Entity_Id is
+ begin
+ return Type_Map.Get (E);
+ end Get_Mapped_Entity;
+
---------------------
-- Get_Stream_Size --
---------------------
@@ -7682,8 +7619,18 @@ package body Exp_Util is
| N_Iterated_Component_Association
| N_Iterated_Element_Association
=>
- if Nkind (Parent (P)) = N_Aggregate
- and then Present (Loop_Actions (P))
+ if Nkind (Parent (P)) in N_Aggregate | N_Delta_Aggregate
+
+ -- We must not climb up out of an N_Iterated_xxx_Association
+ -- because the actions might contain references to the loop
+ -- parameter. But it turns out that setting the Loop_Actions
+ -- attribute in the case of an N_Component_Association
+ -- when the attribute was not already set can lead to
+ -- (as yet not understood) bugboxes (gcc failures that are
+ -- presumably due to malformed trees). So we don't do that.
+
+ and then (Nkind (P) /= N_Component_Association
+ or else Present (Loop_Actions (P)))
then
if Is_Empty_List (Loop_Actions (P)) then
Set_Loop_Actions (P, Ins_Actions);
@@ -8057,10 +8004,8 @@ package body Exp_Util is
----------------------
function Inside_Init_Proc return Boolean is
- Proc : constant Entity_Id := Enclosing_Init_Proc;
-
begin
- return Proc /= Empty;
+ return Present (Enclosing_Init_Proc);
end Inside_Init_Proc;
----------------------
@@ -10345,6 +10290,36 @@ package body Exp_Util is
end if;
end Make_Variant_Comparison;
+ -----------------
+ -- Map_Formals --
+ -----------------
+
+ procedure Map_Formals
+ (Parent_Subp : Entity_Id;
+ Derived_Subp : Entity_Id;
+ Force_Update : Boolean := False)
+ is
+ Par_Formal : Entity_Id := First_Formal (Parent_Subp);
+ Subp_Formal : Entity_Id := First_Formal (Derived_Subp);
+
+ begin
+ if Force_Update then
+ Type_Map.Set (Parent_Subp, Derived_Subp);
+ end if;
+
+ -- At this stage either we are under regular processing and the caller
+ -- has previously ensured that these primitives are already mapped (by
+ -- means of calling previously to Update_Primitives_Mapping), or we are
+ -- processing a late-overriding primitive and Force_Update updated above
+ -- the mapping of these primitives.
+
+ while Present (Par_Formal) and then Present (Subp_Formal) loop
+ Type_Map.Set (Par_Formal, Subp_Formal);
+ Next_Formal (Par_Formal);
+ Next_Formal (Subp_Formal);
+ end loop;
+ end Map_Formals;
+
---------------
-- Map_Types --
---------------
@@ -10640,7 +10615,7 @@ package body Exp_Util is
end if;
-- Otherwise the constraint denotes a reference to some name
- -- which results in a Girder discriminant:
+ -- which results in a Stored discriminant:
-- vvvv
-- Name : ...;
@@ -10661,7 +10636,7 @@ package body Exp_Util is
return Find_Constraint_Value (Entity (Constr));
-- Otherwise the current constraint is an expression which yields
- -- a Girder discriminant:
+ -- a Stored discriminant:
-- type Typ (D1 : ...; DN : ...) is
-- new Anc (Discr => <expression>) with ...
@@ -10736,7 +10711,7 @@ package body Exp_Util is
-- that D_2 constrains D_1, therefore if the algorithm finds the
-- value of D_2, then this would also be the value for D_1.
- -- 2.2) The constraint is a name (aka Girder):
+ -- 2.2) The constraint is a name (aka Stored):
-- Name : ...
-- type Ancestor_1 (D_1 : ...) is tagged ...
@@ -10745,7 +10720,7 @@ package body Exp_Util is
-- In this case the name is the final value of D_1 because the
-- discriminant cannot be further constrained.
- -- 2.3) The constraint is an expression (aka Girder):
+ -- 2.3) The constraint is an expression (aka Stored):
-- type Ancestor_1 (D_1 : ...) is tagged ...
-- type Ancestor_2 is new Ancestor_1 (D_1 => 1 + 2) ...
@@ -10856,7 +10831,7 @@ package body Exp_Util is
-- they relate to the primitives of the parent type. If there is a
-- meaningful relation, create a mapping of the form:
- -- parent type primitive -> perived type primitive
+ -- parent type primitive -> derived type primitive
if Present (Direct_Primitive_Operations (Deriv_Typ)) then
Prim_Elmt := First_Elmt (Direct_Primitive_Operations (Deriv_Typ));
@@ -10992,26 +10967,25 @@ package body Exp_Util is
-- At the current time, the only types that we return False for (i.e. where
-- we decide we know they cannot generate large temps) are ones where we
-- know the size is 256 bits or less at compile time, and we are still not
- -- doing a thorough job on arrays and records ???
+ -- doing a thorough job on arrays and records.
function May_Generate_Large_Temp (Typ : Entity_Id) return Boolean is
begin
if not Size_Known_At_Compile_Time (Typ) then
return False;
+ end if;
- elsif Esize (Typ) /= 0 and then Esize (Typ) <= 256 then
+ if Known_Esize (Typ) and then Esize (Typ) <= 256 then
return False;
+ end if;
- elsif Is_Array_Type (Typ)
+ if Is_Array_Type (Typ)
and then Present (Packed_Array_Impl_Type (Typ))
then
return May_Generate_Large_Temp (Packed_Array_Impl_Type (Typ));
-
- -- We could do more here to find other small types ???
-
- else
- return True;
end if;
+
+ return True;
end May_Generate_Large_Temp;
--------------------------------------------
@@ -11623,6 +11597,7 @@ package body Exp_Util is
Related_Id : Entity_Id := Empty;
Is_Low_Bound : Boolean := False;
Is_High_Bound : Boolean := False;
+ Discr_Number : Int := 0;
Check_Side_Effects : Boolean := True)
is
function Build_Temporary
@@ -11651,19 +11626,45 @@ package body Exp_Util is
is
Temp_Id : Entity_Id;
Temp_Nam : Name_Id;
+ Should_Set_Related_Expression : Boolean := False;
begin
- -- The context requires an external symbol
+ -- The context requires an external symbol : expression is
+ -- the bound of an array, or a discriminant value. We create
+ -- a unique string using the related entity and an appropriate
+ -- suffix, rather than a numeric serial number (used for internal
+ -- entities) that may vary depending on compilation options, in
+ -- particular on the Assertions_Enabled mode. This avoids spurious
+ -- link errors.
if Present (Related_Id) then
if Is_Low_Bound then
Temp_Nam := New_External_Name (Chars (Related_Id), "_FIRST");
- else pragma Assert (Is_High_Bound);
+
+ elsif Is_High_Bound then
Temp_Nam := New_External_Name (Chars (Related_Id), "_LAST");
+
+ else
+ pragma Assert (Discr_Number > 0);
+
+ -- We don't have any intelligible way of printing T_DISCR in
+ -- CodePeer. Thus, set a related expression in this case.
+
+ Should_Set_Related_Expression := True;
+
+ -- Use fully qualified name to avoid ambiguities.
+
+ Temp_Nam :=
+ New_External_Name
+ (Get_Qualified_Name (Related_Id), "_DISCR", Discr_Number);
end if;
Temp_Id := Make_Defining_Identifier (Loc, Temp_Nam);
+ if Should_Set_Related_Expression then
+ Set_Related_Expression (Temp_Id, Related_Nod);
+ end if;
+
-- Otherwise generate an internal temporary
else
@@ -11770,10 +11771,15 @@ package body Exp_Util is
-- case and it is better not to make an additional one for the attribute
-- itself, because the return type of many of them is universal integer,
-- which is a very large type for a temporary.
+ -- The prefix of an attribute reference Reduce may be syntactically an
+ -- aggregate, but will be expanded into a loop, so no need to remove
+ -- side-effects.
if Nkind (Exp) = N_Attribute_Reference
and then Side_Effect_Free_Attribute (Attribute_Name (Exp))
and then Side_Effect_Free (Expressions (Exp), Name_Req, Variable_Ref)
+ and then (Attribute_Name (Exp) /= Name_Reduce
+ or else Nkind (Prefix (Exp)) /= N_Aggregate)
and then not Is_Name_Reference (Prefix (Exp))
then
Remove_Side_Effects (Prefix (Exp), Name_Req, Variable_Ref);
@@ -13111,11 +13117,11 @@ package body Exp_Util is
(Component_Type (Ityp))));
end if;
- if Ialign /= No_Uint and then Ialign > Maximum_Alignment then
+ if Present (Ialign) and then Ialign > Maximum_Alignment then
return True;
- elsif Ialign /= No_Uint
- and then Oalign /= No_Uint
+ elsif Present (Ialign)
+ and then Present (Oalign)
and then Ialign <= Oalign
then
return True;
@@ -14092,10 +14098,12 @@ package body Exp_Util is
(Inher_Id : Entity_Id;
Subp_Id : Entity_Id)
is
+ Parent_Type : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
+ Derived_Type : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
begin
- Map_Types
- (Parent_Type => Find_Dispatching_Type (Inher_Id),
- Derived_Type => Find_Dispatching_Type (Subp_Id));
+ pragma Assert (Parent_Type /= Derived_Type);
+ Map_Types (Parent_Type, Derived_Type);
end Update_Primitives_Mapping;
----------------------------------
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 5c931c9..2b61132 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -270,28 +270,16 @@ package Exp_Util is
-- not install a call to Abort_Defer.
procedure Build_Class_Wide_Expression
- (Prag : Node_Id;
- Subp : Entity_Id;
- Par_Subp : Entity_Id;
- Adjust_Sloc : Boolean;
- Needs_Wrapper : out Boolean);
- -- Build the expression for an inherited class-wide condition. Prag is
- -- the pragma constructed from the corresponding aspect of the parent
- -- subprogram, and Subp is the overriding operation, and Par_Subp is
- -- the overridden operation that has the condition. Adjust_Sloc is True
- -- when the sloc of nodes traversed should be adjusted for the inherited
- -- pragma. The routine is also called to check whether an inherited
- -- operation that is not overridden but has inherited conditions needs
- -- a wrapper, because the inherited condition includes calls to other
- -- primitives that have been overridden. In that case the first argument
- -- is the expression of the original class-wide aspect. In SPARK_Mode, such
- -- operation which are just inherited but have modified pre/postconditions
- -- are illegal.
- -- If there are calls to overridden operations in the condition, and the
- -- pragma applies to an inherited operation, a wrapper must be built for
- -- it to capture the new inherited condition. The flag Needs_Wrapper is
- -- set in that case so that the wrapper can be built, when the controlling
- -- type is frozen.
+ (Pragma_Or_Expr : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id;
+ Adjust_Sloc : Boolean);
+ -- Build the expression for an inherited class-wide condition. Pragma_Or_
+ -- _Expr is either the pragma constructed from the corresponding aspect of
+ -- the parent subprogram or the class-wide pre/postcondition built from the
+ -- parent, Subp is the overriding operation, and Par_Subp is the overridden
+ -- operation that has the condition. Adjust_Sloc is True when the sloc of
+ -- nodes traversed should be adjusted for the inherited pragma.
function Build_DIC_Call
(Loc : Source_Ptr;
@@ -612,7 +600,7 @@ package Exp_Util is
function Find_Prim_Op (T : Entity_Id; Name : Name_Id) return Entity_Id;
-- Find the first primitive operation of a tagged type T with name Name.
-- This function allows the use of a primitive operation which is not
- -- directly visible. If T is a class wide type, then the reference is to an
+ -- directly visible. If T is a class-wide type, then the reference is to an
-- operation of the corresponding root type. It is an error if no primitive
-- operation with the given name is found.
@@ -640,6 +628,16 @@ package Exp_Util is
-- Given a protected type or its corresponding record, find the type of
-- field _object.
+ function Find_Storage_Op
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id;
+ -- Given type Typ that's either a descendant of Root_Storage_Pool or else
+ -- specifies aspect Storage_Model_Type, returns the Entity_Id of the
+ -- subprogram associated with Nam, which must either be a primitive op of
+ -- the type in the case of a storage pool, or the operation corresponding
+ -- to Nam as specified in the aspect Storage_Model_Type. It is an error if
+ -- no operation corresponding to the given name is found.
+
function Find_Hook_Context (N : Node_Id) return Node_Id;
-- Determine a suitable node on which to attach actions related to N that
-- need to be elaborated unconditionally. In general this is the topmost
@@ -668,6 +666,7 @@ package Exp_Util is
Related_Id : Entity_Id := Empty;
Is_Low_Bound : Boolean := False;
Is_High_Bound : Boolean := False;
+ Discr_Number : Int := 0;
Mode : Force_Evaluation_Mode := Relaxed);
-- Force the evaluation of the expression right away. Similar behavior
-- to Remove_Side_Effects when Variable_Ref is set to TRUE. That is to
@@ -688,6 +687,12 @@ package Exp_Util is
-- of the Is_xxx_Bound flags must be set. For use of these parameters see
-- the warning in the body of Sem_Ch3.Process_Range_Expr_In_Decl.
+ -- Discr_Number is positive when the expression is a discriminant value
+ -- in an object or component declaration. In that case Discr_Number is
+ -- the position of the corresponding discriminant in the corresponding
+ -- type declaration, and the name for the evaluated expression is built
+ -- out of the Related_Id and the Discr_Number.
+
function Fully_Qualified_Name_String
(E : Entity_Id;
Append_NUL : Boolean := True) return String_Id;
@@ -732,6 +737,10 @@ package Exp_Util is
-- Used for First, Last, and Length, when the prefix is an array type.
-- Obtains the corresponding index subtype.
+ function Get_Mapped_Entity (E : Entity_Id) return Entity_Id;
+ -- Return the mapped entity of E; used to check inherited class-wide
+ -- pre/postconditions.
+
function Get_Stream_Size (E : Entity_Id) return Uint;
-- Return the stream size value of the subtype E
@@ -911,6 +920,15 @@ package Exp_Util is
-- Subprogram_Variant. Generate a comparison between Curr_Val and Old_Val
-- depending on the variant mode (Increases / Decreases).
+ procedure Map_Formals
+ (Parent_Subp : Entity_Id;
+ Derived_Subp : Entity_Id;
+ Force_Update : Boolean := False);
+ -- Establish the mapping from the formals of Parent_Subp to the formals
+ -- of Derived_Subp; if Force_Update is True then mapping of Parent_Subp to
+ -- Derived_Subp is also updated; used to update mapping of late-overriding
+ -- primitives of a tagged type.
+
procedure Map_Types (Parent_Type : Entity_Id; Derived_Type : Entity_Id);
-- Establish the following mapping between the attributes of tagged parent
-- type Parent_Type and tagged derived type Derived_Type.
@@ -1004,6 +1022,7 @@ package Exp_Util is
Related_Id : Entity_Id := Empty;
Is_Low_Bound : Boolean := False;
Is_High_Bound : Boolean := False;
+ Discr_Number : Int := 0;
Check_Side_Effects : Boolean := True);
-- Given the node for a subexpression, this function replaces the node if
-- necessary by an equivalent subexpression that is guaranteed to be side
@@ -1028,6 +1047,9 @@ package Exp_Util is
-- of the Is_xxx_Bound flags must be set. For use of these parameters see
-- the warning in the body of Sem_Ch3.Process_Range_Expr_In_Decl.
--
+ -- If Discr_Number is positive, the expression denotes a discrimant value
+ -- in a constraint, the suffix DISCR is used to create the external name.
+
-- The side effects are captured using one of the following methods:
--
-- 1) a constant initialized with the value of the subexpression
@@ -1194,5 +1216,6 @@ package Exp_Util is
private
pragma Inline (Duplicate_Subexpr);
pragma Inline (Force_Evaluation);
+ pragma Inline (Get_Mapped_Entity);
pragma Inline (Is_Library_Level_Tagged_Type);
end Exp_Util;
diff --git a/gcc/ada/expander.adb b/gcc/ada/expander.adb
index e0483b7..75c0edb 100644
--- a/gcc/ada/expander.adb
+++ b/gcc/ada/expander.adb
@@ -49,6 +49,7 @@ with Sem_Ch8; use Sem_Ch8;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
+with Stand; use Stand;
with Table;
package body Expander is
@@ -152,7 +153,19 @@ package body Expander is
-- not take place. This prevents cascaded errors due to stack mismatch.
elsif not Expander_Active then
- Set_Analyzed (N, Full_Analysis);
+
+ -- Do not clear the Analyzed flag if it has been set on purpose
+ -- during preanalysis in Fold_Ureal. In that case, the Etype field
+ -- in N_Real_Literal will be set to something different than
+ -- Universal_Real.
+
+ if Full_Analysis
+ or else not (Nkind (N) = N_Real_Literal
+ and then Present (Etype (N))
+ and then Etype (N) /= Universal_Real)
+ then
+ Set_Analyzed (N, Full_Analysis);
+ end if;
if Serious_Errors_Detected > 0 and then Scope_Is_Transient then
Scope_Stack.Table
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 4517c59..67cc218 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -61,14 +61,25 @@ extern void Compiler_Abort (String_Pointer, String_Pointer, Boolean) ATTRIBUTE_N
#define Debug_Flag_Dot_KK debug__debug_flag_dot_kk
#define Debug_Flag_Dot_R debug__debug_flag_dot_r
+#define Debug_Flag_Dot_8 debug__debug_flag_dot_8
#define Debug_Flag_NN debug__debug_flag_nn
extern Boolean Debug_Flag_Dot_KK;
extern Boolean Debug_Flag_Dot_R;
+extern Boolean Debug_Flag_Dot_8;
extern Boolean Debug_Flag_NN;
/* einfo: */
+/* Valid_Uint is used to preserve the old behavior of Esize and
+ friends, where Uint_0 was the default. All calls to this
+ are questionable. */
+INLINE Valid_Uint
+No_Uint_To_0 (Uint X)
+{
+ return X == No_Uint ? Uint_0 : X;
+}
+
#define Set_Alignment einfo__entities__set_alignment
#define Set_Component_Bit_Offset einfo__entities__set_component_bit_offset
#define Set_Component_Size einfo__entities__set_component_size
@@ -249,6 +260,8 @@ extern Boolean Back_End_Exceptions (void);
restrict__check_no_implicit_task_alloc
#define No_Exception_Handlers_Set \
restrict__no_exception_handlers_set
+#define No_Exception_Propagation_Active \
+ restrict__no_exception_propagation_active
extern void Check_Elaboration_Code_Allowed (Node_Id);
extern void Check_Implicit_Dynamic_Code_Allowed (Node_Id);
@@ -256,6 +269,7 @@ extern void Check_No_Implicit_Heap_Alloc (Node_Id);
extern void Check_No_Implicit_Protected_Alloc (Node_Id);
extern void Check_No_Implicit_Task_Alloc (Node_Id);
extern Boolean No_Exception_Handlers_Set (void);
+extern Boolean No_Exception_Propagation_Active (void);
/* sem_aggr: */
@@ -615,30 +629,15 @@ B Known_Normalized_Position_Max (Entity_Id E);
#define Known_RM_Size einfo__utils__known_rm_size
B Known_RM_Size (Entity_Id E);
-#define Known_Static_Component_Bit_Offset einfo__utils__known_static_component_bit_offset
-B Known_Static_Component_Bit_Offset (Entity_Id E);
-
-#define Known_Static_Component_Size einfo__utils__known_static_component_size
-B Known_Static_Component_Size (Entity_Id E);
-
-#define Known_Static_Esize einfo__utils__known_static_esize
-B Known_Static_Esize (Entity_Id E);
-
-#define Known_Static_Normalized_First_Bit einfo__utils__known_static_normalized_first_bit
-B Known_Static_Normalized_First_Bit (Entity_Id E);
-
-#define Known_Static_Normalized_Position einfo__utils__known_static_normalized_position
-B Known_Static_Normalized_Position (Entity_Id E);
-
-#define Known_Static_Normalized_Position_Max einfo__utils__known_static_normalized_position_max
-B Known_Static_Normalized_Position_Max (Entity_Id E);
-
-#define Known_Static_RM_Size einfo__utils__known_static_rm_size
-B Known_Static_RM_Size (Entity_Id E);
-
#define Copy_Alignment einfo__utils__copy_alignment
B Copy_Alignment(Entity_Id To, Entity_Id From);
+#define Copy_Esize einfo__utils__copy_esize
+B Copy_Esize(Entity_Id To, Entity_Id From);
+
+#define Copy_RM_Size einfo__utils__copy_rm_size
+B Copy_RM_Size(Entity_Id To, Entity_Id From);
+
#define Is_Discrete_Or_Fixed_Point_Type einfo__utils__is_discrete_or_fixed_point_type
B Is_Discrete_Or_Fixed_Point_Type (E Id);
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 84502d8..5f81d9e 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -35,6 +35,7 @@ with Elists; use Elists;
with Errout; use Errout;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch7; use Exp_Ch7;
+with Exp_Disp; use Exp_Disp;
with Exp_Pakd; use Exp_Pakd;
with Exp_Util; use Exp_Util;
with Exp_Tss; use Exp_Tss;
@@ -56,6 +57,7 @@ with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
with Sem_Ch13; use Sem_Ch13;
+with Sem_Disp; use Sem_Disp;
with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
with Sem_Prag; use Sem_Prag;
@@ -132,11 +134,6 @@ package body Freeze is
-- Attribute references to outer types are freeze points for those types;
-- this routine generates the required freeze nodes for them.
- procedure Check_Inherited_Conditions (R : Entity_Id);
- -- For a tagged derived type, create wrappers for inherited operations
- -- that have a class-wide condition, so it can be properly rewritten if
- -- it involves calls to other overriding primitives.
-
procedure Check_Strict_Alignment (E : Entity_Id);
-- E is a base type. If E is tagged or has a component that is aliased
-- or tagged or contains something this is aliased or tagged, set
@@ -160,7 +157,7 @@ package body Freeze is
procedure Freeze_Enumeration_Type (Typ : Entity_Id);
-- Freeze enumeration type. The Esize field is set as processing
-- proceeds (i.e. set by default when the type is declared and then
- -- adjusted by rep clauses. What this procedure does is to make sure
+ -- adjusted by rep clauses). What this procedure does is to make sure
-- that if a foreign convention is specified, and no specific size
-- is given, then the size must be at least Integer'Size.
@@ -284,11 +281,11 @@ package body Freeze is
-- Full_View or Corresponding_Record_Type.
procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Node_Id);
- -- Expr is the expression for an address clause for entity Nam whose type
- -- is Typ. If Typ has a default initialization, and there is no explicit
- -- initialization in the source declaration, check whether the address
- -- clause might cause overlaying of an entity, and emit a warning on the
- -- side effect that the initialization will cause.
+ -- Expr is the expression for an address clause for the entity denoted by
+ -- Nam whose type is Typ. If Typ has a default initialization, and there is
+ -- no explicit initialization in the source declaration, check whether the
+ -- address clause might cause overlaying of an entity, and emit a warning
+ -- on the side effect that the initialization will cause.
-------------------------------
-- Adjust_Esize_For_Alignment --
@@ -636,13 +633,26 @@ package body Freeze is
Next (Param_Spec);
end loop;
- Body_Node :=
- Make_Subprogram_Body (Loc,
- Specification => Spec,
- Declarations => New_List,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Call_Node)));
+ -- In GNATprove, prefer to generate an expression function whenever
+ -- possible, to benefit from the more precise analysis in that case
+ -- (as if an implicit postcondition had been generated).
+
+ if GNATprove_Mode
+ and then Nkind (Call_Node) = N_Simple_Return_Statement
+ then
+ Body_Node :=
+ Make_Expression_Function (Loc,
+ Specification => Spec,
+ Expression => Expression (Call_Node));
+ else
+ Body_Node :=
+ Make_Subprogram_Body (Loc,
+ Specification => Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call_Node)));
+ end if;
if Nkind (Decl) /= N_Subprogram_Declaration then
Rewrite (N,
@@ -1268,9 +1278,13 @@ package body Freeze is
if Present (Component_Clause (Comp)) then
Comp_Byte_Aligned :=
- (Normalized_First_Bit (Comp) mod System_Storage_Unit = 0)
+ Known_Normalized_First_Bit (Comp)
and then
- (Esize (Comp) mod System_Storage_Unit = 0);
+ Known_Esize (Comp)
+ and then
+ Normalized_First_Bit (Comp) mod System_Storage_Unit = 0
+ and then
+ Esize (Comp) mod System_Storage_Unit = 0;
else
Comp_Byte_Aligned := not Is_Packed (Encl_Type);
end if;
@@ -1348,9 +1362,15 @@ package body Freeze is
elsif Is_Record_Type (Encl_Base)
and then not Comp_Byte_Aligned
then
- Error_Msg_N
- ("type of non-byte-aligned component must have same scalar "
- & "storage order as enclosing composite", Err_Node);
+ if Present (Component_Clause (Comp)) then
+ Error_Msg_N
+ ("type of non-byte-aligned component must have same scalar"
+ & " storage order as enclosing record", Err_Node);
+ else
+ Error_Msg_N
+ ("type of packed component must have same scalar"
+ & " storage order as enclosing record", Err_Node);
+ end if;
-- Warn if specified only for the outer composite
@@ -1460,90 +1480,322 @@ package body Freeze is
-- Check_Inherited_Conditions --
--------------------------------
- procedure Check_Inherited_Conditions (R : Entity_Id) is
- Prim_Ops : constant Elist_Id := Primitive_Operations (R);
- Decls : List_Id;
- Needs_Wrapper : Boolean;
- Op_Node : Elmt_Id;
- Par_Prim : Entity_Id;
- Prim : Entity_Id;
-
- procedure Build_Inherited_Condition_Pragmas (Subp : Entity_Id);
+ procedure Check_Inherited_Conditions
+ (R : Entity_Id;
+ Late_Overriding : Boolean := False)
+ is
+ Prim_Ops : constant Elist_Id := Primitive_Operations (R);
+ Decls : List_Id;
+ Op_Node : Elmt_Id;
+ Par_Prim : Entity_Id;
+ Prim : Entity_Id;
+ Wrapper_Needed : Boolean;
+
+ function Build_DTW_Body
+ (Loc : Source_Ptr;
+ DTW_Spec : Node_Id;
+ DTW_Decls : List_Id;
+ Par_Prim : Entity_Id;
+ Wrapped_Subp : Entity_Id) return Node_Id;
+ -- Build the body of the dispatch table wrapper containing the given
+ -- spec and declarations; the call to the wrapped subprogram includes
+ -- the proper type conversion.
+
+ function Build_DTW_Spec (Par_Prim : Entity_Id) return Node_Id;
+ -- Build the spec of the dispatch table wrapper
+
+ procedure Build_Inherited_Condition_Pragmas
+ (Subp : Entity_Id;
+ Wrapper_Needed : out Boolean);
-- Build corresponding pragmas for an operation whose ancestor has
- -- class-wide pre/postconditions. If the operation is inherited, the
- -- pragmas force the creation of a wrapper for the inherited operation.
- -- If the ancestor is being overridden, the pragmas are constructed only
- -- to verify their legality, in case they contain calls to other
- -- primitives that may have been overridden.
+ -- class-wide pre/postconditions. If the operation is inherited then
+ -- Wrapper_Needed is returned True to force the creation of a wrapper
+ -- for the inherited operation. If the ancestor is being overridden,
+ -- the pragmas are constructed only to verify their legality, in case
+ -- they contain calls to other primitives that may have been overridden.
+
+ function Needs_Wrapper
+ (Class_Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id) return Boolean;
+ -- Checks whether the dispatch-table wrapper (DTW) for Subp must be
+ -- built to evaluate the given class-wide condition.
+
+ --------------------
+ -- Build_DTW_Body --
+ --------------------
+
+ function Build_DTW_Body
+ (Loc : Source_Ptr;
+ DTW_Spec : Node_Id;
+ DTW_Decls : List_Id;
+ Par_Prim : Entity_Id;
+ Wrapped_Subp : Entity_Id) return Node_Id
+ is
+ Par_Typ : constant Entity_Id := Find_Dispatching_Type (Par_Prim);
+ Actuals : constant List_Id := Empty_List;
+ Call : Node_Id;
+ Formal : Entity_Id := First_Formal (Par_Prim);
+ New_F_Spec : Entity_Id := First (Parameter_Specifications (DTW_Spec));
+ New_Formal : Entity_Id;
+
+ begin
+ -- Build parameter association for call to wrapped subprogram
+
+ while Present (Formal) loop
+ New_Formal := Defining_Identifier (New_F_Spec);
+
+ -- If the controlling argument is inherited, add conversion to
+ -- parent type for the call.
+
+ if Etype (Formal) = Par_Typ
+ and then Is_Controlling_Formal (Formal)
+ then
+ Append_To (Actuals,
+ Make_Type_Conversion (Loc,
+ New_Occurrence_Of (Par_Typ, Loc),
+ New_Occurrence_Of (New_Formal, Loc)));
+ else
+ Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
+ end if;
+
+ Next_Formal (Formal);
+ Next (New_F_Spec);
+ end loop;
+
+ if Ekind (Wrapped_Subp) = E_Procedure then
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Wrapped_Subp, Loc),
+ Parameter_Associations => Actuals);
+ else
+ Call :=
+ Make_Simple_Return_Statement (Loc,
+ Expression =>
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Wrapped_Subp, Loc),
+ Parameter_Associations => Actuals));
+ end if;
+
+ return
+ Make_Subprogram_Body (Loc,
+ Specification => Copy_Subprogram_Spec (DTW_Spec),
+ Declarations => DTW_Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call),
+ End_Label => Make_Identifier (Loc,
+ Chars (Defining_Entity (DTW_Spec)))));
+ end Build_DTW_Body;
+
+ --------------------
+ -- Build_DTW_Spec --
+ --------------------
+
+ function Build_DTW_Spec (Par_Prim : Entity_Id) return Node_Id is
+ DTW_Id : Entity_Id;
+ DTW_Spec : Node_Id;
+
+ begin
+ DTW_Spec := Build_Overriding_Spec (Par_Prim, R);
+ DTW_Id := Defining_Entity (DTW_Spec);
+
+ -- Add minimal decoration of fields
+
+ Mutate_Ekind (DTW_Id, Ekind (Par_Prim));
+ Set_LSP_Subprogram (DTW_Id, Par_Prim);
+ Set_Is_Dispatch_Table_Wrapper (DTW_Id);
+ Set_Is_Wrapper (DTW_Id);
+
+ -- The DTW wrapper is never a null procedure
+
+ if Nkind (DTW_Spec) = N_Procedure_Specification then
+ Set_Null_Present (DTW_Spec, False);
+ end if;
+
+ return DTW_Spec;
+ end Build_DTW_Spec;
---------------------------------------
-- Build_Inherited_Condition_Pragmas --
---------------------------------------
- procedure Build_Inherited_Condition_Pragmas (Subp : Entity_Id) is
- A_Post : Node_Id;
- A_Pre : Node_Id;
- New_Prag : Node_Id;
+ procedure Build_Inherited_Condition_Pragmas
+ (Subp : Entity_Id;
+ Wrapper_Needed : out Boolean)
+ is
+ Class_Pre : constant Node_Id :=
+ Class_Preconditions (Ultimate_Alias (Subp));
+ Class_Post : Node_Id := Class_Postconditions (Par_Prim);
+ A_Post : Node_Id;
+ New_Prag : Node_Id;
begin
- A_Pre := Get_Class_Wide_Pragma (Par_Prim, Pragma_Precondition);
+ Wrapper_Needed := False;
- if Present (A_Pre) then
- New_Prag := New_Copy_Tree (A_Pre);
- Build_Class_Wide_Expression
- (Prag => New_Prag,
- Subp => Prim,
- Par_Subp => Par_Prim,
- Adjust_Sloc => False,
- Needs_Wrapper => Needs_Wrapper);
-
- if Needs_Wrapper
- and then not Comes_From_Source (Subp)
- and then Expander_Active
- then
- Append (New_Prag, Decls);
- end if;
+ if No (Class_Pre) and then No (Class_Post) then
+ return;
end if;
- A_Post := Get_Class_Wide_Pragma (Par_Prim, Pragma_Postcondition);
+ -- For class-wide preconditions we just evaluate whether the wrapper
+ -- is needed; there is no need to build the pragma since the check
+ -- is performed on the caller side.
- if Present (A_Post) then
- New_Prag := New_Copy_Tree (A_Post);
+ if Present (Class_Pre)
+ and then Needs_Wrapper (Class_Pre, Subp, Par_Prim)
+ then
+ Wrapper_Needed := True;
+ end if;
+
+ -- For class-wide postconditions we evaluate whether the wrapper is
+ -- needed and we build the class-wide postcondition pragma to install
+ -- it in the wrapper.
+
+ if Present (Class_Post)
+ and then Needs_Wrapper (Class_Post, Subp, Par_Prim)
+ then
+ Wrapper_Needed := True;
+
+ -- Update the class-wide postcondition
+
+ Class_Post := New_Copy_Tree (Class_Post);
Build_Class_Wide_Expression
- (Prag => New_Prag,
- Subp => Prim,
+ (Pragma_Or_Expr => Class_Post,
+ Subp => Subp,
Par_Subp => Par_Prim,
- Adjust_Sloc => False,
- Needs_Wrapper => Needs_Wrapper);
+ Adjust_Sloc => False);
- if Needs_Wrapper
- and then not Comes_From_Source (Subp)
- and then Expander_Active
- then
- Append (New_Prag, Decls);
+ -- Install the updated class-wide postcondition in a copy of the
+ -- pragma postcondition defined for the nearest ancestor.
+
+ A_Post := Get_Class_Wide_Pragma (Par_Prim,
+ Pragma_Postcondition);
+
+ if No (A_Post) then
+ declare
+ Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp);
+ begin
+ for Index in Subps'Range loop
+ A_Post := Get_Class_Wide_Pragma (Subps (Index),
+ Pragma_Postcondition);
+ exit when Present (A_Post);
+ end loop;
+ end;
end if;
+
+ New_Prag := New_Copy_Tree (A_Post);
+ Rewrite
+ (Expression (First (Pragma_Argument_Associations (New_Prag))),
+ Class_Post);
+ Append (New_Prag, Decls);
end if;
end Build_Inherited_Condition_Pragmas;
+ -------------------
+ -- Needs_Wrapper --
+ -------------------
+
+ function Needs_Wrapper
+ (Class_Cond : Node_Id;
+ Subp : Entity_Id;
+ Par_Subp : Entity_Id) return Boolean
+ is
+ Result : Boolean := False;
+
+ function Check_Entity (N : Node_Id) return Traverse_Result;
+ -- Check calls to overridden primitives
+
+ --------------------
+ -- Replace_Entity --
+ --------------------
+
+ function Check_Entity (N : Node_Id) return Traverse_Result is
+ New_E : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then
+ (Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
+ and then
+ (Nkind (Parent (N)) /= N_Attribute_Reference
+ or else Attribute_Name (Parent (N)) /= Name_Class)
+ then
+ -- The check does not apply to dispatching calls within the
+ -- condition, but only to calls whose static tag is that of
+ -- the parent type.
+
+ if Is_Subprogram (Entity (N))
+ and then Nkind (Parent (N)) = N_Function_Call
+ and then Present (Controlling_Argument (Parent (N)))
+ then
+ return OK;
+ end if;
+
+ -- Determine whether entity has a renaming
+
+ New_E := Get_Mapped_Entity (Entity (N));
+
+ -- If the entity is an overridden primitive and we are not
+ -- in GNATprove mode, we must build a wrapper for the current
+ -- inherited operation. If the reference is the prefix of an
+ -- attribute such as 'Result (or others ???) there is no need
+ -- for a wrapper: the condition is just rewritten in terms of
+ -- the inherited subprogram.
+
+ if Present (New_E)
+ and then Comes_From_Source (New_E)
+ and then Is_Subprogram (New_E)
+ and then Nkind (Parent (N)) /= N_Attribute_Reference
+ and then not GNATprove_Mode
+ then
+ Result := True;
+ return Abandon;
+ end if;
+ end if;
+
+ return OK;
+ end Check_Entity;
+
+ procedure Check_Condition_Entities is
+ new Traverse_Proc (Check_Entity);
+
+ -- Start of processing for Needs_Wrapper
+
+ begin
+ Update_Primitives_Mapping (Par_Subp, Subp);
+
+ Map_Formals (Par_Subp, Subp);
+ Check_Condition_Entities (Class_Cond);
+
+ return Result;
+ end Needs_Wrapper;
+
-- Start of processing for Check_Inherited_Conditions
begin
- Op_Node := First_Elmt (Prim_Ops);
- while Present (Op_Node) loop
- Prim := Node (Op_Node);
+ if Late_Overriding then
+ Op_Node := First_Elmt (Prim_Ops);
+ while Present (Op_Node) loop
+ Prim := Node (Op_Node);
- -- Map the overridden primitive to the overriding one. This takes
- -- care of all overridings and is done only once.
+ -- Map the overridden primitive to the overriding one
- if Present (Overridden_Operation (Prim))
- and then Comes_From_Source (Prim)
- then
- Par_Prim := Overridden_Operation (Prim);
- Update_Primitives_Mapping (Par_Prim, Prim);
- end if;
+ if Present (Overridden_Operation (Prim))
+ and then Comes_From_Source (Prim)
+ then
+ Par_Prim := Overridden_Operation (Prim);
+ Update_Primitives_Mapping (Par_Prim, Prim);
- Next_Elmt (Op_Node);
- end loop;
+ -- Force discarding previous mappings of its formals
+
+ Map_Formals (Par_Prim, Prim, Force_Update => True);
+ end if;
+
+ Next_Elmt (Op_Node);
+ end loop;
+ end if;
-- Perform validity checks on the inherited conditions of overriding
-- operations, for conformance with LSP, and apply SPARK-specific
@@ -1579,12 +1831,6 @@ package body Freeze is
if GNATprove_Mode then
Collect_Inherited_Class_Wide_Conditions (Prim);
-
- -- Otherwise build the corresponding pragmas to check for legality
- -- of the inherited condition.
-
- else
- Build_Inherited_Condition_Pragmas (Prim);
end if;
end if;
@@ -1598,12 +1844,17 @@ package body Freeze is
Op_Node := First_Elmt (Prim_Ops);
while Present (Op_Node) loop
- Decls := Empty_List;
- Prim := Node (Op_Node);
- Needs_Wrapper := False;
+ Decls := Empty_List;
+ Prim := Node (Op_Node);
+ Wrapper_Needed := False;
- if not Comes_From_Source (Prim) and then Present (Alias (Prim)) then
- Par_Prim := Alias (Prim);
+ -- Skip internal entities built for mapping interface primitives
+
+ if not Comes_From_Source (Prim)
+ and then Present (Alias (Prim))
+ and then No (Interface_Alias (Prim))
+ then
+ Par_Prim := Ultimate_Alias (Prim);
-- When the primitive is an LSP wrapper we climb to the parent
-- primitive that has the inherited contract.
@@ -1621,39 +1872,39 @@ package body Freeze is
-- in the loop above.
Analyze_Entry_Or_Subprogram_Contract (Par_Prim);
- Build_Inherited_Condition_Pragmas (Prim);
+ Build_Inherited_Condition_Pragmas (Prim, Wrapper_Needed);
end if;
- if Needs_Wrapper
+ if Wrapper_Needed
and then not Is_Abstract_Subprogram (Par_Prim)
and then Expander_Active
then
- -- We need to build a new primitive that overrides the inherited
- -- one, and whose inherited expression has been updated above.
- -- These expressions are the arguments of pragmas that are part
- -- of the declarations of the wrapper. The wrapper holds a single
- -- statement that is a call to the class-wide clone, where the
- -- controlling actuals are conversions to the corresponding type
- -- in the parent primitive:
-
- -- procedure New_Prim (F1 : T1; ...);
- -- procedure New_Prim (F1 : T1; ...) is
- -- pragma Check (Precondition, Expr);
- -- begin
- -- Par_Prim_Clone (Par_Type (F1), ...);
- -- end;
-
- -- If the primitive is a function the statement is a return
- -- statement with a call.
+ -- Build the dispatch-table wrapper (DTW). The support for
+ -- AI12-0195 relies on two kind of wrappers: one for indirect
+ -- calls (also used for AI12-0220), and one for putting in the
+ -- dispatch table:
+ --
+ -- 1) "indirect-call wrapper" (ICW) is needed anytime there are
+ -- class-wide preconditions. Prim'Access will point directly
+ -- at the ICW if any, or at the "pristine" body if Prim has
+ -- no class-wide preconditions.
+ --
+ -- 2) "dispatch-table wrapper" (DTW) is needed anytime the class
+ -- wide preconditions *or* the class-wide postconditions are
+ -- affected by overriding.
+ --
+ -- The DTW holds a single statement that is a single call where
+ -- the controlling actuals are conversions to the corresponding
+ -- type in the parent primitive. If the primitive is a function
+ -- the statement is a return statement with a call.
declare
Alias_Id : constant Entity_Id := Ultimate_Alias (Prim);
Loc : constant Source_Ptr := Sloc (R);
- Par_R : constant Node_Id := Parent (R);
- New_Body : Node_Id;
- New_Decl : Node_Id;
- New_Id : Entity_Id;
- New_Spec : Node_Id;
+ DTW_Body : Node_Id;
+ DTW_Decl : Node_Id;
+ DTW_Id : Entity_Id;
+ DTW_Spec : Node_Id;
begin
-- The wrapper must be analyzed in the scope of its wrapped
@@ -1661,47 +1912,130 @@ package body Freeze is
Push_Scope (Scope (Prim));
- New_Spec := Build_Overriding_Spec (Par_Prim, R);
- New_Id := Defining_Entity (New_Spec);
- New_Decl :=
- Make_Subprogram_Declaration (Loc,
- Specification => New_Spec);
-
- -- Insert the declaration and the body of the wrapper after
- -- type declaration that generates inherited operation. For
- -- a null procedure, the declaration implies a null body.
+ DTW_Spec := Build_DTW_Spec (Par_Prim);
+ DTW_Id := Defining_Entity (DTW_Spec);
+ DTW_Decl := Make_Subprogram_Declaration (Loc,
+ Specification => DTW_Spec);
+
+ -- For inherited class-wide preconditions the DTW wrapper
+ -- reuses the ICW of the parent (which checks the parent
+ -- interpretation of the class-wide preconditions); the
+ -- interpretation of the class-wide preconditions for the
+ -- inherited subprogram is checked at the caller side.
+
+ -- When the subprogram inherits class-wide postconditions
+ -- the DTW also checks the interpretation of the class-wide
+ -- postconditions for the inherited subprogram, and the body
+ -- of the parent checks its interpretation of the parent for
+ -- the class-wide postconditions.
+
+ -- procedure Prim (F1 : T1; ...) is
+ -- [ pragma Check (Postcondition, Expr); ]
+ -- begin
+ -- Par_Prim_ICW (Par_Type (F1), ...);
+ -- end;
+
+ if Present (Indirect_Call_Wrapper (Par_Prim)) then
+ DTW_Body :=
+ Build_DTW_Body (Loc,
+ DTW_Spec => DTW_Spec,
+ DTW_Decls => Decls,
+ Par_Prim => Par_Prim,
+ Wrapped_Subp => Indirect_Call_Wrapper (Par_Prim));
+
+ -- For subprograms that only inherit class-wide postconditions
+ -- the DTW wrapper calls the parent primitive (which on its
+ -- body checks the interpretation of the class-wide post-
+ -- conditions for the parent subprogram), and the DTW checks
+ -- the interpretation of the class-wide postconditions for the
+ -- inherited subprogram.
+
+ -- procedure Prim (F1 : T1; ...) is
+ -- pragma Check (Postcondition, Expr);
+ -- begin
+ -- Par_Prim (Par_Type (F1), ...);
+ -- end;
- -- Before insertion, do some minimal decoration of fields
+ else
+ DTW_Body :=
+ Build_DTW_Body (Loc,
+ DTW_Spec => DTW_Spec,
+ DTW_Decls => Decls,
+ Par_Prim => Par_Prim,
+ Wrapped_Subp => Par_Prim);
+ end if;
- Mutate_Ekind (New_Id, Ekind (Par_Prim));
- Set_LSP_Subprogram (New_Id, Par_Prim);
- Set_Is_Wrapper (New_Id);
+ -- Insert the declaration of the wrapper before the freezing
+ -- node of the record type declaration to ensure that it will
+ -- override the internal primitive built by Derive_Subprogram.
- if Nkind (New_Spec) = N_Procedure_Specification
- and then Null_Present (New_Spec)
- then
- Insert_After_And_Analyze (Par_R, New_Decl);
+ Ensure_Freeze_Node (R);
+ if Late_Overriding then
+ Insert_Before_And_Analyze (Freeze_Node (R), DTW_Decl);
else
- -- Build body as wrapper to a call to the already built
- -- class-wide clone.
+ Append_Freeze_Action (R, DTW_Decl);
+ end if;
+
+ Analyze (DTW_Decl);
+
+ -- Insert the body of the wrapper in the freeze actions of
+ -- its record type declaration to ensure that it is placed
+ -- in the scope of its declaration but not too early to cause
+ -- premature freezing of other entities.
+
+ Append_Freeze_Action (R, DTW_Body);
+ Analyze (DTW_Body);
+
+ -- Ensure correct decoration
+
+ pragma Assert (Is_Dispatching_Operation (DTW_Id));
+ pragma Assert (Present (Overridden_Operation (DTW_Id)));
+ pragma Assert (Overridden_Operation (DTW_Id) = Alias_Id);
- New_Body :=
- Build_Class_Wide_Clone_Call
- (Loc, Decls, Par_Prim, New_Spec);
+ -- Inherit dispatch table slot
- Insert_List_After_And_Analyze
- (Par_R, New_List (New_Decl, New_Body));
+ Set_DTC_Entity_Value (R, DTW_Id);
+ Set_DT_Position (DTW_Id, DT_Position (Alias_Id));
- -- Ensure correct decoration
+ -- Register the wrapper in the dispatch table
- pragma Assert (Present (Alias (Prim)));
- pragma Assert (Present (Overridden_Operation (New_Id)));
- pragma Assert (Overridden_Operation (New_Id) = Alias_Id);
+ if Late_Overriding
+ and then not Building_Static_DT (R)
+ then
+ Insert_List_After_And_Analyze (Freeze_Node (R),
+ Register_Primitive (Loc, DTW_Id));
end if;
- pragma Assert (Is_Dispatching_Operation (Prim));
- pragma Assert (Is_Dispatching_Operation (New_Id));
+ -- Build the helper and ICW for the DTW
+
+ if Present (Indirect_Call_Wrapper (Par_Prim)) then
+ declare
+ CW_Subp : Entity_Id;
+ Decl_N : Node_Id;
+ Body_N : Node_Id;
+
+ begin
+ Merge_Class_Conditions (DTW_Id);
+ Make_Class_Precondition_Subps (DTW_Id,
+ Late_Overriding => Late_Overriding);
+
+ CW_Subp := Static_Call_Helper (DTW_Id);
+ Decl_N := Unit_Declaration_Node (CW_Subp);
+ Analyze (Decl_N);
+
+ -- If the DTW was built for a late-overriding primitive
+ -- its body must be analyzed now (since the tagged type
+ -- is already frozen).
+
+ if Late_Overriding then
+ Body_N :=
+ Unit_Declaration_Node
+ (Corresponding_Body (Decl_N));
+ Analyze (Body_N);
+ end if;
+ end;
+ end if;
Pop_Scope;
end;
@@ -3640,8 +3974,8 @@ package body Freeze is
(No (Ancestor_Subtype (Arr))
or else not Has_Size_Clause (Ancestor_Subtype (Arr)))
then
- Set_Esize (Arr, Esize (Packed_Array_Impl_Type (Arr)));
- Set_RM_Size (Arr, RM_Size (Packed_Array_Impl_Type (Arr)));
+ Copy_Esize (To => Arr, From => Packed_Array_Impl_Type (Arr));
+ Copy_RM_Size (To => Arr, From => Packed_Array_Impl_Type (Arr));
end if;
if not Has_Alignment_Clause (Arr) then
@@ -4173,6 +4507,7 @@ package body Freeze is
-- active.
if Is_Access_Type (F_Type)
+ and then Known_Esize (F_Type)
and then Esize (F_Type) > Ttypes.System_Address_Size
and then (not Unnest_Subprogram_Mode
or else not Is_Access_Subprogram_Type (F_Type))
@@ -4313,6 +4648,7 @@ package body Freeze is
-- Check suspicious return of fat C pointer
if Is_Access_Type (R_Type)
+ and then Known_Esize (R_Type)
and then Esize (R_Type) > Ttypes.System_Address_Size
and then not Has_Warnings_Off (E)
and then not Has_Warnings_Off (R_Type)
@@ -6249,7 +6585,8 @@ package body Freeze is
if Is_Array_Type (E) then
declare
Ctyp : constant Entity_Id := Component_Type (E);
- Rsiz : constant Uint := RM_Size (Ctyp);
+ Rsiz : constant Uint :=
+ (if Known_RM_Size (Ctyp) then RM_Size (Ctyp) else Uint_0);
SZ : constant Node_Id := Size_Clause (E);
Btyp : constant Entity_Id := Base_Type (E);
@@ -6695,7 +7032,7 @@ package body Freeze is
if Is_Type (Full_View (E)) then
Set_Size_Info (E, Full_View (E));
- Set_RM_Size (E, RM_Size (Full_View (E)));
+ Copy_RM_Size (To => E, From => Full_View (E));
end if;
goto Leave;
@@ -7391,7 +7728,7 @@ package body Freeze is
if Is_Type (E) then
Freeze_And_Append (First_Subtype (E), N, Result);
- -- If we just froze a tagged non-class wide record, then freeze the
+ -- If we just froze a tagged non-class-wide record, then freeze the
-- corresponding class-wide type. This must be done after the tagged
-- type itself is frozen, because the class-wide type refers to the
-- tagged type which generates the class.
@@ -7467,7 +7804,7 @@ package body Freeze is
and then not Target_Short_Enums
then
- Init_Esize (Typ, Standard_Integer_Size);
+ Set_Esize (Typ, UI_From_Int (Standard_Integer_Size));
Set_Alignment (Typ, Alignment (Standard_Integer));
-- Normal Ada case or size clause present or not Long_C_Enums on target
@@ -8579,10 +8916,10 @@ package body Freeze is
Orig_Hi : Ureal;
-- Save original bounds (for shaving tests)
- Actual_Size : Nat;
+ Actual_Size : Int;
-- Actual size chosen
- function Fsize (Lov, Hiv : Ureal) return Nat;
+ function Fsize (Lov, Hiv : Ureal) return Int;
-- Returns size of type with given bounds. Also leaves these
-- bounds set as the current bounds of the Typ.
@@ -8596,7 +8933,7 @@ package body Freeze is
-- Fsize --
-----------
- function Fsize (Lov, Hiv : Ureal) return Nat is
+ function Fsize (Lov, Hiv : Ureal) return Int is
begin
Set_Realval (Lo, Lov);
Set_Realval (Hi, Hiv);
@@ -8642,7 +8979,7 @@ package body Freeze is
if Present (Atype) then
Set_Esize (Typ, Esize (Atype));
else
- Set_Esize (Typ, Esize (Btyp));
+ Copy_Esize (To => Typ, From => Btyp);
end if;
end if;
@@ -8705,8 +9042,8 @@ package body Freeze is
Loval_Excl_EP : Ureal;
Hival_Excl_EP : Ureal;
- Size_Incl_EP : Nat;
- Size_Excl_EP : Nat;
+ Size_Incl_EP : Int;
+ Size_Excl_EP : Int;
Model_Num : Ureal;
First_Subt : Entity_Id;
@@ -9076,7 +9413,7 @@ package body Freeze is
Actual_Size := 128;
end if;
- Init_Esize (Typ, Actual_Size);
+ Set_Esize (Typ, UI_From_Int (Actual_Size));
Adjust_Esize_For_Alignment (Typ);
end if;
@@ -9132,7 +9469,7 @@ package body Freeze is
-- Set Esize to calculated size if not set already
if not Known_Esize (Typ) then
- Init_Esize (Typ, Actual_Size);
+ Set_Esize (Typ, UI_From_Int (Actual_Size));
end if;
-- Set RM_Size if not already set. If already set, check value
@@ -9141,7 +9478,9 @@ package body Freeze is
Minsiz : constant Uint := UI_From_Int (Minimum_Size (Typ));
begin
- if RM_Size (Typ) /= Uint_0 then
+ if Known_RM_Size (Typ)
+ and then RM_Size (Typ) /= Uint_0
+ then
if RM_Size (Typ) < Minsiz then
Error_Msg_Uint_1 := RM_Size (Typ);
Error_Msg_Uint_2 := Minsiz;
@@ -10053,7 +10392,7 @@ package body Freeze is
-- Warn_Overlay --
------------------
- procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Entity_Id) is
+ procedure Warn_Overlay (Expr : Node_Id; Typ : Entity_Id; Nam : Node_Id) is
Ent : constant Entity_Id := Entity (Nam);
-- The object to which the address clause applies
diff --git a/gcc/ada/freeze.ads b/gcc/ada/freeze.ads
index 6f4feca..0174756 100644
--- a/gcc/ada/freeze.ads
+++ b/gcc/ada/freeze.ads
@@ -174,6 +174,15 @@ package Freeze is
-- do not allow a size clause if the size would not otherwise be known at
-- compile time in any case.
+ procedure Check_Inherited_Conditions
+ (R : Entity_Id;
+ Late_Overriding : Boolean := False);
+ -- For a tagged derived type R, create wrappers for inherited operations
+ -- that have class-wide conditions, so it can be properly rewritten if
+ -- it involves calls to other overriding primitives. Late_Overriding is
+ -- True when we are processing the body of a primitive with no previous
+ -- spec defined after R is frozen (see Check_Dispatching_Operation).
+
function Is_Full_Access_Aggregate (N : Node_Id) return Boolean;
-- If a full access object is initialized with an aggregate or is assigned
-- an aggregate, we have to prevent a piecemeal access or assignment to the
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 765654f..61a627f 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -298,6 +298,7 @@ GNAT_ADA_OBJS = \
ada/alloc.o \
ada/aspects.o \
ada/atree.o \
+ ada/backend_utils.o \
ada/butil.o \
ada/casing.o \
ada/checks.o \
@@ -516,7 +517,6 @@ GNAT_ADA_OBJS+= \
ada/libgnat/s-excmac.o \
ada/libgnat/s-exctab.o \
ada/libgnat/s-htable.o \
- ada/libgnat/s-imenne.o \
ada/libgnat/s-imgint.o \
ada/libgnat/s-mastop.o \
ada/libgnat/s-memory.o \
@@ -683,7 +683,6 @@ GNATBIND_OBJS += \
ada/libgnat/s-excmac.o \
ada/libgnat/s-exctab.o \
ada/libgnat/s-htable.o \
- ada/libgnat/s-imenne.o \
ada/libgnat/s-imgint.o \
ada/libgnat/s-mastop.o \
ada/libgnat/s-memory.o \
diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c
index 6ac82d7..abf8d46 100644
--- a/gcc/ada/gcc-interface/cuintp.c
+++ b/gcc/ada/gcc-interface/cuintp.c
@@ -39,6 +39,7 @@
#include "ada.h"
#include "types.h"
#include "uintp.h"
+#include "sinfo.h"
#include "ada-tree.h"
#include "gigi.h"
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 5cedb74..639cf06 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -28,6 +28,7 @@
#include "coretypes.h"
#include "target.h"
#include "tree.h"
+#include "gimple-expr.h"
#include "stringpool.h"
#include "diagnostic-core.h"
#include "alias.h"
@@ -238,8 +239,10 @@ static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool,
const char *, const char *);
static void set_rm_size (Uint, tree, Entity_Id);
static unsigned int validate_alignment (Uint, Entity_Id, unsigned int);
-static unsigned int promote_object_alignment (tree, Entity_Id);
+static unsigned int promote_object_alignment (tree, tree, Entity_Id);
static void check_ok_for_atomic_type (tree, Entity_Id, bool);
+static bool type_for_atomic_builtin_p (tree);
+static tree resolve_atomic_builtin (enum built_in_function, tree);
static tree create_field_decl_from (tree, tree, tree, tree, tree,
vec<subst_pair>);
static tree create_rep_part (tree, tree, tree);
@@ -261,7 +264,7 @@ typedef struct {
tree btin_fntype; /* The GCC builtin function type node. */
} intrin_binding_t;
-static bool intrin_profiles_compatible_p (intrin_binding_t *);
+static bool intrin_profiles_compatible_p (const 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)
@@ -556,7 +559,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If the entity is an inherited component (in the case of extended
tagged record types), just return the original entity, which must
be a FIELD_DECL. Likewise for discriminants. If the entity is a
- non-girder discriminant (in the case of derived untagged record
+ non-stored discriminant (in the case of derived untagged record
types), return the stored discriminant it renames. */
if (Present (Original_Record_Component (gnat_entity))
&& Original_Record_Component (gnat_entity) != gnat_entity)
@@ -896,7 +899,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
or a reference to another object, and the size of its type is a
constant, set the alignment to the smallest one which is not
smaller than the size, with an appropriate cap. */
- if (!gnu_size && align == 0
+ if (!Known_Esize (gnat_entity)
+ && !Known_Alignment (gnat_entity)
&& (Is_Full_Access (gnat_entity)
|| (!Optimize_Alignment_Space (gnat_entity)
&& kind != E_Exception
@@ -907,8 +911,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
&& !imported_p
&& No (gnat_renamed_obj)
&& No (Address_Clause (gnat_entity))))
- && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST)
- align = promote_object_alignment (gnu_type, gnat_entity);
+ && (TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST || gnu_size))
+ align = promote_object_alignment (gnu_type, gnu_size, gnat_entity);
/* If the object is set to have atomic components, find the component
type and validate it.
@@ -4279,6 +4283,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
handling alignment and possible padding. */
if (is_type && (!gnu_decl || this_made_decl))
{
+ const bool is_by_ref = Is_By_Reference_Type (gnat_entity);
+
gcc_assert (!TYPE_IS_DUMMY_P (gnu_type));
/* Process the attributes, if not already done. Note that the type is
@@ -4293,15 +4299,22 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
non-constant). */
if (!gnu_size && kind != E_String_Literal_Subtype)
{
+ const char *size_s = "size for %s too small{, minimum allowed is ^}";
+ const char *type_s = is_by_ref ? "by-reference type &" : "&";
+
if (Known_Esize (gnat_entity))
gnu_size
= validate_size (Esize (gnat_entity), gnu_type, gnat_entity,
- VAR_DECL, false, false, NULL, NULL);
- else
+ VAR_DECL, false, false, size_s, type_s);
+
+ /* ??? The test on Has_Size_Clause must be removed when "unknown" is
+ no longer represented as Uint_0 (i.e. Use_New_Unknown_Rep). */
+ else if (Known_RM_Size (gnat_entity)
+ || Has_Size_Clause (gnat_entity))
gnu_size
= validate_size (RM_Size (gnat_entity), gnu_type, gnat_entity,
TYPE_DECL, false, Has_Size_Clause (gnat_entity),
- NULL, NULL);
+ size_s, type_s);
}
/* If a size was specified, see if we can make a new type of that size
@@ -4380,7 +4393,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Now set the RM size of the type. We cannot do it before padding
because we need to accept arbitrary RM sizes on integral types. */
- set_rm_size (RM_Size (gnat_entity), gnu_type, gnat_entity);
+ if (Known_RM_Size (gnat_entity))
+ set_rm_size (RM_Size (gnat_entity), gnu_type, gnat_entity);
/* Back-annotate the alignment of the type if not already set. */
if (!Known_Alignment (gnat_entity))
@@ -4411,16 +4425,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Likewise for the size, if any. */
if (!Known_Esize (gnat_entity) && TYPE_SIZE (gnu_type))
{
- tree gnu_size = TYPE_SIZE (gnu_type);
+ tree size = TYPE_SIZE (gnu_type);
/* If the size is self-referential, annotate the maximum value
after saturating it, if need be, to avoid a No_Uint value. */
- if (CONTAINS_PLACEHOLDER_P (gnu_size))
+ if (CONTAINS_PLACEHOLDER_P (size))
{
const unsigned int align
= UI_To_Int (Alignment (gnat_entity)) * BITS_PER_UNIT;
- gnu_size
- = maybe_saturate_size (max_size (gnu_size, true), align);
+ size = maybe_saturate_size (max_size (size, true), align);
}
/* If we are just annotating types and the type is tagged, the tag
@@ -4458,12 +4471,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
if (TYPE_FIELDS (gnu_type))
offset
= round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
- gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
+ size = size_binop (PLUS_EXPR, size, offset);
}
- gnu_size
- = maybe_saturate_size (round_up (gnu_size, align), align);
- Set_Esize (gnat_entity, annotate_value (gnu_size));
+ size = maybe_saturate_size (round_up (size, align), align);
+ Set_Esize (gnat_entity, annotate_value (size));
/* Tagged types are Strict_Alignment so RM_Size = Esize. */
if (!Known_RM_Size (gnat_entity))
@@ -4472,12 +4484,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Otherwise no adjustment is needed. */
else
- Set_Esize (gnat_entity, annotate_value (gnu_size));
+ Set_Esize (gnat_entity, No_Uint_To_0 (annotate_value (size)));
}
/* Likewise for the RM size, if any. */
if (!Known_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type))
- Set_RM_Size (gnat_entity, annotate_value (rm_size (gnu_type)));
+ Set_RM_Size (gnat_entity,
+ No_Uint_To_0 (annotate_value (rm_size (gnu_type))));
/* If we are at global level, GCC applied variable_size to the size but
this has done nothing. So, if it's not constant or self-referential,
@@ -4614,7 +4627,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
TYPE_ALIGN_OK (gnu_type) = 1;
/* Record whether the type is passed by reference. */
- if (Is_By_Reference_Type (gnat_entity) && !VOID_TYPE_P (gnu_type))
+ if (is_by_ref && !VOID_TYPE_P (gnu_type))
TYPE_BY_REFERENCE_P (gnu_type) = 1;
/* Record whether an alignment clause was specified. */
@@ -4734,6 +4747,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
else
gnu_decl = create_type_decl (gnu_entity_name, gnu_type, artificial_p,
debug_info_p, gnat_entity);
+
+ /* For vector types, make the representative array the debug type. */
+ if (VECTOR_TYPE_P (gnu_type))
+ {
+ tree rep = TYPE_REPRESENTATIVE_ARRAY (gnu_type);
+ TYPE_NAME (rep) = DECL_NAME (gnu_decl);
+ SET_TYPE_DEBUG_TYPE (gnu_type, rep);
+ }
}
/* Otherwise, for a type reusing an existing DECL, back-annotate values. */
@@ -4744,9 +4765,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
if (!Known_Alignment (gnat_entity))
Copy_Alignment (gnat_entity, gnat_annotate_type);
if (!Known_Esize (gnat_entity))
- Set_Esize (gnat_entity, Esize (gnat_annotate_type));
+ Copy_Esize (gnat_entity, gnat_annotate_type);
if (!Known_RM_Size (gnat_entity))
- Set_RM_Size (gnat_entity, RM_Size (gnat_annotate_type));
+ Copy_RM_Size (gnat_entity, gnat_annotate_type);
}
/* If we haven't already, associate the ..._DECL node that we just made with
@@ -5385,19 +5406,21 @@ gnat_to_gnu_param (Entity_Id gnat_param, tree gnu_param_type, bool first,
mech = Default;
}
- /* If this is either a foreign function or if the underlying type won't
- be passed by reference and is as aligned as the original type, strip
- off possible padding type. */
+ /* Either for foreign conventions, or if the underlying type is not passed
+ by reference and is as large and aligned as the original type, strip off
+ a possible padding type. */
if (TYPE_IS_PADDING_P (gnu_param_type))
{
- tree unpadded_type = TREE_TYPE (TYPE_FIELDS (gnu_param_type));
+ tree inner_type = TREE_TYPE (TYPE_FIELDS (gnu_param_type));
if (foreign
|| (mech != By_Reference
- && !must_pass_by_ref (unpadded_type)
- && (mech == By_Copy || !default_pass_by_ref (unpadded_type))
- && TYPE_ALIGN (unpadded_type) >= TYPE_ALIGN (gnu_param_type)))
- gnu_param_type = unpadded_type;
+ && !must_pass_by_ref (inner_type)
+ && (mech == By_Copy || !default_pass_by_ref (inner_type))
+ && ((TYPE_SIZE (inner_type) == TYPE_SIZE (gnu_param_type)
+ && TYPE_ALIGN (inner_type) >= TYPE_ALIGN (gnu_param_type))
+ || Is_Init_Proc (gnat_subprog))))
+ gnu_param_type = inner_type;
}
/* For foreign conventions, pass arrays as pointers to the element type.
@@ -6291,15 +6314,106 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
the checker is expected to post diagnostics in this case. */
if (gnu_builtin_decl)
{
- intrin_binding_t inb
- = { gnat_subprog, gnu_type, TREE_TYPE (gnu_builtin_decl) };
+ if (fndecl_built_in_p (gnu_builtin_decl, BUILT_IN_NORMAL))
+ {
+ const enum built_in_function fncode
+ = DECL_FUNCTION_CODE (gnu_builtin_decl);
- if (!intrin_profiles_compatible_p (&inb))
- post_error
- ("??profile of& doesn''t match the builtin it binds!",
- gnat_subprog);
+ switch (fncode)
+ {
+ case BUILT_IN_SYNC_FETCH_AND_ADD_N:
+ case BUILT_IN_SYNC_FETCH_AND_SUB_N:
+ case BUILT_IN_SYNC_FETCH_AND_OR_N:
+ case BUILT_IN_SYNC_FETCH_AND_AND_N:
+ case BUILT_IN_SYNC_FETCH_AND_XOR_N:
+ case BUILT_IN_SYNC_FETCH_AND_NAND_N:
+ case BUILT_IN_SYNC_ADD_AND_FETCH_N:
+ case BUILT_IN_SYNC_SUB_AND_FETCH_N:
+ case BUILT_IN_SYNC_OR_AND_FETCH_N:
+ case BUILT_IN_SYNC_AND_AND_FETCH_N:
+ case BUILT_IN_SYNC_XOR_AND_FETCH_N:
+ case BUILT_IN_SYNC_NAND_AND_FETCH_N:
+ case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_SYNC_LOCK_TEST_AND_SET_N:
+ case BUILT_IN_ATOMIC_EXCHANGE_N:
+ case BUILT_IN_ATOMIC_LOAD_N:
+ case BUILT_IN_ATOMIC_ADD_FETCH_N:
+ case BUILT_IN_ATOMIC_SUB_FETCH_N:
+ case BUILT_IN_ATOMIC_AND_FETCH_N:
+ case BUILT_IN_ATOMIC_NAND_FETCH_N:
+ case BUILT_IN_ATOMIC_XOR_FETCH_N:
+ case BUILT_IN_ATOMIC_OR_FETCH_N:
+ case BUILT_IN_ATOMIC_FETCH_ADD_N:
+ case BUILT_IN_ATOMIC_FETCH_SUB_N:
+ case BUILT_IN_ATOMIC_FETCH_AND_N:
+ case BUILT_IN_ATOMIC_FETCH_NAND_N:
+ case BUILT_IN_ATOMIC_FETCH_XOR_N:
+ case BUILT_IN_ATOMIC_FETCH_OR_N:
+ /* This is a generic builtin overloaded on its return
+ type, so do type resolution based on it. */
+ if (!VOID_TYPE_P (gnu_return_type)
+ && type_for_atomic_builtin_p (gnu_return_type))
+ gnu_builtin_decl
+ = resolve_atomic_builtin (fncode, gnu_return_type);
+ else
+ {
+ post_error
+ ("??cannot import type-generic 'G'C'C builtin!",
+ gnat_subprog);
+ post_error
+ ("\\?use a supported result type",
+ gnat_subprog);
+ gnu_builtin_decl = NULL_TREE;
+ }
+ break;
+
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N:
+ /* This is a generic builtin overloaded on its third
+ parameter type, so do type resolution based on it. */
+ if (list_length (gnu_param_type_list) >= 4
+ && type_for_atomic_builtin_p
+ (list_third (gnu_param_type_list)))
+ gnu_builtin_decl
+ = resolve_atomic_builtin
+ (fncode, list_third (gnu_param_type_list));
+ else
+ {
+ post_error
+ ("??cannot import type-generic 'G'C'C builtin!",
+ gnat_subprog);
+ post_error
+ ("\\?use a supported third parameter type",
+ gnat_subprog);
+ gnu_builtin_decl = NULL_TREE;
+ }
+ break;
+
+ case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_SYNC_LOCK_RELEASE_N:
+ case BUILT_IN_ATOMIC_STORE_N:
+ post_error
+ ("??unsupported type-generic 'G'C'C builtin!",
+ gnat_subprog);
+ gnu_builtin_decl = NULL_TREE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (gnu_builtin_decl)
+ {
+ const intrin_binding_t inb
+ = { gnat_subprog, gnu_type, TREE_TYPE (gnu_builtin_decl) };
+
+ if (!intrin_profiles_compatible_p (&inb))
+ post_error
+ ("??profile of& doesn''t match the builtin it binds!",
+ gnat_subprog);
- return gnu_builtin_decl;
+ return gnu_builtin_decl;
+ }
}
/* Inability to find the builtin DECL most often indicates a genuine
@@ -6309,7 +6423,7 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
on demand without risking false positives with common default sets
of options. */
if (warn_shadow)
- post_error ("??gcc intrinsic not found for&!", gnat_subprog);
+ post_error ("'G'C'C builtin not found for&!??", gnat_subprog);
}
}
@@ -6486,7 +6600,8 @@ range_cannot_be_superflat (Node_Id gnat_range)
Node_Id gnat_scalar_range;
tree gnu_lb, gnu_hb, gnu_lb_minus_one;
- /* If the low bound is not constant, try to find an upper bound. */
+ /* If the low bound is not constant, take the worst case by finding an upper
+ bound for its type, repeatedly if need be. */
while (Nkind (gnat_lb) != N_Integer_Literal
&& (Ekind (Etype (gnat_lb)) == E_Signed_Integer_Subtype
|| Ekind (Etype (gnat_lb)) == E_Modular_Integer_Subtype)
@@ -6495,7 +6610,8 @@ range_cannot_be_superflat (Node_Id gnat_range)
|| Nkind (gnat_scalar_range) == N_Range))
gnat_lb = High_Bound (gnat_scalar_range);
- /* If the high bound is not constant, try to find a lower bound. */
+ /* If the high bound is not constant, take the worst case by finding a lower
+ bound for its type, repeatedly if need be. */
while (Nkind (gnat_hb) != N_Integer_Literal
&& (Ekind (Etype (gnat_hb)) == E_Signed_Integer_Subtype
|| Ekind (Etype (gnat_hb)) == E_Modular_Integer_Subtype)
@@ -7301,7 +7417,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
if (Is_Full_Access (gnat_field))
{
const unsigned int align
- = promote_object_alignment (gnu_field_type, gnat_field);
+ = promote_object_alignment (gnu_field_type, NULL_TREE, gnat_field);
if (align > 0)
gnu_field_type
= maybe_pad_type (gnu_field_type, NULL_TREE, align, gnat_field,
@@ -8761,7 +8877,7 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref)
size = TYPE_SIZE (gnu_type);
if (size)
- Set_Esize (gnat_entity, annotate_value (size));
+ Set_Esize (gnat_entity, No_Uint_To_0 (annotate_value (size)));
}
if (!Known_Alignment (gnat_entity))
@@ -8867,8 +8983,9 @@ annotate_rep (Entity_Id gnat_entity, tree gnu_type)
(gnat_field,
annotate_value (bit_from_pos (offset, bit_offset)));
- Set_Esize (gnat_field,
- annotate_value (DECL_SIZE (TREE_PURPOSE (t))));
+ Set_Esize
+ (gnat_field,
+ No_Uint_To_0 (annotate_value (DECL_SIZE (TREE_PURPOSE (t)))));
}
else if (is_extension)
{
@@ -9178,13 +9295,12 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
/* Issue an error either if the default size of the object isn't a constant
or if the new size is smaller than it. */
if (TREE_CODE (old_size) != INTEGER_CST
- || TREE_OVERFLOW (old_size)
- || tree_int_cst_lt (size, old_size))
+ || (!TREE_OVERFLOW (old_size) && tree_int_cst_lt (size, old_size)))
{
char buf[128];
const char *s;
- if (kind == FIELD_DECL)
+ if (s1 && s2)
{
snprintf (buf, sizeof (buf), s1, s2);
s = buf;
@@ -9193,6 +9309,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
s = "component size for& too small{, minimum allowed is ^}";
else
s = "size for& too small{, minimum allowed is ^}";
+
post_error_ne_tree (s, gnat_error_node, gnat_object, old_size);
return NULL_TREE;
@@ -9371,11 +9488,11 @@ 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. */
+/* Promote the alignment of GNU_TYPE for an object with GNU_SIZE corresponding
+ to GNAT_ENTITY. Return a positive value on success or zero on failure. */
static unsigned int
-promote_object_alignment (tree gnu_type, Entity_Id gnat_entity)
+promote_object_alignment (tree gnu_type, tree gnu_size, Entity_Id gnat_entity)
{
unsigned int align, size_cap, align_cap;
@@ -9396,14 +9513,17 @@ promote_object_alignment (tree gnu_type, Entity_Id gnat_entity)
align_cap = get_mode_alignment (ptr_mode);
}
+ if (!gnu_size)
+ gnu_size = TYPE_SIZE (gnu_type);
+
/* Do the promotion within the above limits. */
- if (!tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
- || compare_tree_int (TYPE_SIZE (gnu_type), size_cap) > 0)
+ if (!tree_fits_uhwi_p (gnu_size)
+ || compare_tree_int (gnu_size, size_cap) > 0)
align = 0;
- else if (compare_tree_int (TYPE_SIZE (gnu_type), align_cap) > 0)
+ else if (compare_tree_int (gnu_size, align_cap) > 0)
align = align_cap;
else
- align = ceil_pow2 (tree_to_uhwi (TYPE_SIZE (gnu_type)));
+ align = ceil_pow2 (tree_to_uhwi (gnu_size));
/* But make sure not to under-align the object. */
if (align <= TYPE_ALIGN (gnu_type))
@@ -9486,51 +9606,38 @@ check_ok_for_atomic_type (tree type, Entity_Id gnat_entity, bool component_p)
gnat_error_point, gnat_entity);
}
-
-/* Helper for the intrin compatibility checks family. Evaluate whether
- two types are definitely incompatible. */
+/* Return true if TYPE is suitable for a type-generic atomic builtin. */
static bool
-intrin_types_incompatible_p (tree t1, tree t2)
+type_for_atomic_builtin_p (tree type)
{
- enum tree_code code;
-
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return false;
-
- if (TYPE_MODE (t1) != TYPE_MODE (t2))
+ const enum machine_mode mode = TYPE_MODE (type);
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
return true;
- if (TREE_CODE (t1) != TREE_CODE (t2))
+ scalar_int_mode imode;
+ if (is_a <scalar_int_mode> (mode, &imode) && GET_MODE_SIZE (imode) <= 16)
return true;
- code = TREE_CODE (t1);
-
- switch (code)
- {
- case INTEGER_TYPE:
- case REAL_TYPE:
- return TYPE_PRECISION (t1) != TYPE_PRECISION (t2);
+ return false;
+}
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- /* Assume designated types are ok. We'd need to account for char * and
- void * variants to do better, which could rapidly get messy and isn't
- clearly worth the effort. */
- return false;
+/* Return the GCC atomic builtin based on CODE and sized for TYPE. */
- default:
- break;
- }
+static tree
+resolve_atomic_builtin (enum built_in_function code, tree type)
+{
+ const unsigned int size = resolve_atomic_size (type);
+ code = (enum built_in_function) ((int) code + exact_log2 (size) + 1);
- return false;
+ return builtin_decl_implicit (code);
}
/* Helper for intrin_profiles_compatible_p, to perform compatibility checks
on the Ada/builtin argument lists for the INB binding. */
static bool
-intrin_arglists_compatible_p (intrin_binding_t * inb)
+intrin_arglists_compatible_p (const intrin_binding_t *inb)
{
function_args_iterator ada_iter, btin_iter;
@@ -9555,27 +9662,32 @@ intrin_arglists_compatible_p (intrin_binding_t * inb)
/* If we're done with the Ada args and not with the internal builtin
args, or the other way around, complain. */
- if (ada_type == void_type_node
- && btin_type != void_type_node)
+ if (ada_type == void_type_node && btin_type != void_type_node)
{
- post_error ("??Ada arguments list too short!", inb->gnat_entity);
+ post_error ("??Ada parameter list too short!", inb->gnat_entity);
return false;
}
- if (btin_type == void_type_node
- && ada_type != void_type_node)
+ if (btin_type == void_type_node && ada_type != void_type_node)
{
- post_error_ne_num ("??Ada arguments list too long ('> ^)!",
+ post_error_ne_num ("??Ada parameter list too long ('> ^)!",
inb->gnat_entity, inb->gnat_entity, argpos);
return false;
}
/* Otherwise, check that types match for the current argument. */
- argpos ++;
- if (intrin_types_incompatible_p (ada_type, btin_type))
+ argpos++;
+ if (!types_compatible_p (ada_type, btin_type))
{
- post_error_ne_num ("??intrinsic binding type mismatch on argument ^!",
- inb->gnat_entity, inb->gnat_entity, argpos);
+ /* For vector builtins, issue an error to avoid an ICE. */
+ if (VECTOR_TYPE_P (btin_type))
+ post_error_ne_num
+ ("intrinsic binding type mismatch on parameter ^",
+ inb->gnat_entity, inb->gnat_entity, argpos);
+ else
+ post_error_ne_num
+ ("??intrinsic binding type mismatch on parameter ^!",
+ inb->gnat_entity, inb->gnat_entity, argpos);
return false;
}
@@ -9591,22 +9703,26 @@ intrin_arglists_compatible_p (intrin_binding_t * inb)
on the Ada/builtin return values for the INB binding. */
static bool
-intrin_return_compatible_p (intrin_binding_t * inb)
+intrin_return_compatible_p (const intrin_binding_t *inb)
{
tree ada_return_type = TREE_TYPE (inb->ada_fntype);
tree btin_return_type = TREE_TYPE (inb->btin_fntype);
/* Accept function imported as procedure, common and convenient. */
- if (VOID_TYPE_P (ada_return_type)
- && !VOID_TYPE_P (btin_return_type))
+ if (VOID_TYPE_P (ada_return_type) && !VOID_TYPE_P (btin_return_type))
return true;
/* Check return types compatibility otherwise. Note that this
handles void/void as well. */
- if (intrin_types_incompatible_p (btin_return_type, ada_return_type))
+ if (!types_compatible_p (btin_return_type, ada_return_type))
{
- post_error ("??intrinsic binding type mismatch on return value!",
- inb->gnat_entity);
+ /* For vector builtins, issue an error to avoid an ICE. */
+ if (VECTOR_TYPE_P (btin_return_type))
+ post_error ("intrinsic binding type mismatch on result",
+ inb->gnat_entity);
+ else
+ post_error ("??intrinsic binding type mismatch on result",
+ inb->gnat_entity);
return false;
}
@@ -9622,7 +9738,7 @@ intrin_return_compatible_p (intrin_binding_t * inb)
especially when binding straight to a compiler internal. */
static bool
-intrin_profiles_compatible_p (intrin_binding_t * inb)
+intrin_profiles_compatible_p (const intrin_binding_t *inb)
{
/* Check compatibility on return values and argument lists, each responsible
for posting warnings as appropriate. Ensure use of the proper sloc for
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 49b85a4..1b55ec5 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -234,7 +234,7 @@ extern "C" {
extern void gigi (Node_Id gnat_root,
int max_gnat_node,
int number_name,
- Field_Offset *node_offsets_ptr,
+ Node_Header *node_offsets_ptr,
any_slot *slots_ptr,
Node_Id *next_node_ptr,
Node_Id *prev_node_ptr,
@@ -1026,6 +1026,9 @@ extern Entity_Id get_debug_scope (Node_Id gnat_node, bool *is_subprogram);
should be synchronized with Exp_Dbug.Debug_Renaming_Declaration. */
extern bool can_materialize_object_renaming_p (Node_Id expr);
+/* Return the size of TYPE, which must be a positive power of 2. */
+extern unsigned int resolve_atomic_size (tree type);
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -1223,3 +1226,11 @@ operand_type (tree expr)
{
return TREE_TYPE (TREE_OPERAND (expr, 0));
}
+
+/* Return the third value of a list. */
+
+static inline tree
+list_third (tree list)
+{
+ return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (list)));
+}
diff --git a/gcc/ada/gcc-interface/lang-specs.h b/gcc/ada/gcc-interface/lang-specs.h
index f5a7496..d26cc8d 100644
--- a/gcc/ada/gcc-interface/lang-specs.h
+++ b/gcc/ada/gcc-interface/lang-specs.h
@@ -36,7 +36,7 @@
"\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{!S:%{!c:%e-c or -S required for Ada}}\
- gnat1 %{I*} %{k8:-gnatk8} %{Wall:-gnatwa} %{w:-gnatws} %{!Q:-quiet}\
+ gnat1 %{I*} %{k8:-gnatk8} %{!Q:-quiet}\
%{nostdinc*} %{nostdlib*}\
%{fcompare-debug-second:-gnatd_A} \
%{O*} %{W*} %{w} %{p} %{pg:-p} " ADA_DUMPS_OPTIONS " \
@@ -44,8 +44,9 @@
#if defined(TARGET_VXWORKS_RTP)
"%{fRTS=rtp|fRTS=rtp-smp|fRTS=ravenscar-cert-rtp:-mrtp} "
#endif
- "%{gnatea:-gnatez} %{g*&m*&f*} "
- "%1 %{!S:%{o*:%w%*-gnatO}} \
+ "%{Wall:-gnatwa} %{Werror:-gnatwe} %{w:-gnatws} \
+ %{gnatea:-gnatez} %{g*&m*&f*} \
+ %1 %{!S:%{o*:%w%*-gnatO}} \
%i %{S:%W{o*}%{!o*:-o %w%b.s}} \
%{gnatc*|gnats*: -o %j} %{-param*} \
%{!gnatc*:%{!gnats*:%(invoke_as)}}", 0, 0, 0},
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 186367a..2caa83f 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -256,6 +256,9 @@ gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
/* Excess precision other than "fast" requires front-end support. */
if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
sorry ("%<-fexcess-precision=standard%> for Ada");
+ else if (flag_excess_precision == EXCESS_PRECISION_FLOAT16)
+ sorry ("%<-fexcess-precision=16%> for Ada");
+
flag_excess_precision = EXCESS_PRECISION_FAST;
/* No psABI change warnings for Ada. */
@@ -268,15 +271,9 @@ gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
warn_stringop_overflow = 0;
/* No caret by default for Ada. */
- if (!global_options_set.x_flag_diagnostics_show_caret)
+ if (!OPTION_SET_P (flag_diagnostics_show_caret))
global_dc->show_caret = false;
- /* Warn only if STABS is not the default: we don't want to emit a warning if
- the user did not use a -gstabs option. */
- if (PREFERRED_DEBUGGING_TYPE != DBX_DEBUG && write_symbols == DBX_DEBUG)
- warning (0, "STABS debugging information for Ada is obsolete and not "
- "supported anymore");
-
/* Copy global settings to local versions. */
gnat_encodings = global_options.x_gnat_encodings;
optimize = global_options.x_optimize;
@@ -419,12 +416,12 @@ gnat_init_gcc_eh (void)
flag_delete_dead_exceptions = 1;
if (Suppress_Checks)
{
- if (!global_options_set.x_flag_non_call_exceptions)
+ if (!OPTION_SET_P (flag_non_call_exceptions))
flag_non_call_exceptions = Machine_Overflows_On_Target && GNAT_Mode;
}
else
{
- if (!global_options_set.x_flag_non_call_exceptions)
+ if (!OPTION_SET_P (flag_non_call_exceptions))
flag_non_call_exceptions = 1;
flag_aggressive_loop_optimizations = 0;
warn_aggressive_loop_optimizations = 0;
@@ -442,14 +439,14 @@ gnat_init_gcc_fp (void)
S'Signed_Zeros is true, but don't override the user if not. */
if (Signed_Zeros_On_Target)
flag_signed_zeros = 1;
- else if (!global_options_set.x_flag_signed_zeros)
+ else if (!OPTION_SET_P (flag_signed_zeros))
flag_signed_zeros = 0;
/* Assume that FP operations can trap if S'Machine_Overflow is true,
but don't override the user if not. */
if (Machine_Overflows_On_Target)
flag_trapping_math = 1;
- else if (!global_options_set.x_flag_trapping_math)
+ else if (!OPTION_SET_P (flag_trapping_math))
flag_trapping_math = 0;
}
diff --git a/gcc/ada/gcc-interface/targtyps.c b/gcc/ada/gcc-interface/targtyps.c
index 704172d..fb103a1 100644
--- a/gcc/ada/gcc-interface/targtyps.c
+++ b/gcc/ada/gcc-interface/targtyps.c
@@ -34,6 +34,7 @@
#include "ada.h"
#include "types.h"
+#include "sinfo.h"
#include "ada-tree.h"
#include "gigi.h"
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 3df56aa..8a192c7 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -75,7 +75,7 @@
#define ALLOCA_THRESHOLD 1000
/* Pointers to front-end tables accessed through macros. */
-Field_Offset *Node_Offsets_Ptr;
+Node_Header *Node_Offsets_Ptr;
any_slot *Slots_Ptr;
Node_Id *Next_Node_Ptr;
Node_Id *Prev_Node_Ptr;
@@ -279,7 +279,7 @@ void
gigi (Node_Id gnat_root,
int max_gnat_node,
int number_name ATTRIBUTE_UNUSED,
- Field_Offset *node_offsets_ptr,
+ Node_Header *node_offsets_ptr,
any_slot *slots_ptr,
Node_Id *next_node_ptr,
Node_Id *prev_node_ptr,
@@ -3893,7 +3893,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
/* If the body comes from an expression function, arrange it to be inlined
in almost all cases. */
- if (Was_Expression_Function (gnat_node))
+ if (Was_Expression_Function (gnat_node) && !Debug_Flag_Dot_8)
DECL_DISREGARD_INLINE_LIMITS (gnu_subprog_decl) = 1;
/* Try to create a bona-fide thunk and hand it over to the middle-end. */
@@ -7872,21 +7872,24 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Pop_Constraint_Error_Label:
gnat_temp = gnu_constraint_error_label_stack.pop ();
if (Present (gnat_temp)
- && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false)))
+ && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false))
+ && No_Exception_Propagation_Active ())
Warn_If_No_Local_Raise (gnat_temp);
break;
case N_Pop_Storage_Error_Label:
gnat_temp = gnu_storage_error_label_stack.pop ();
if (Present (gnat_temp)
- && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false)))
+ && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false))
+ && No_Exception_Propagation_Active ())
Warn_If_No_Local_Raise (gnat_temp);
break;
case N_Pop_Program_Error_Label:
gnat_temp = gnu_program_error_label_stack.pop ();
if (Present (gnat_temp)
- && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false)))
+ && !TREE_USED (gnat_to_gnu_entity (gnat_temp, NULL_TREE, false))
+ && No_Exception_Propagation_Active ())
Warn_If_No_Local_Raise (gnat_temp);
break;
@@ -8261,6 +8264,7 @@ gnat_to_gnu (Node_Id gnat_node)
|| kind == N_Selected_Component)
&& TREE_CODE (get_base_type (gnu_result_type)) == BOOLEAN_TYPE
&& Nkind (Parent (gnat_node)) != N_Attribute_Reference
+ && Nkind (Parent (gnat_node)) != N_Pragma_Argument_Association
&& Nkind (Parent (gnat_node)) != N_Variant_Part
&& !lvalue_required_p (gnat_node, gnu_result_type, false, false))
{
@@ -9279,10 +9283,10 @@ process_freeze_entity (Node_Id gnat_node)
Copy_Alignment (gnat_entity, full_view);
if (!Known_Esize (gnat_entity))
- Set_Esize (gnat_entity, Esize (full_view));
+ Copy_Esize (gnat_entity, full_view);
if (!Known_RM_Size (gnat_entity))
- Set_RM_Size (gnat_entity, RM_Size (full_view));
+ Copy_RM_Size (gnat_entity, full_view);
/* The above call may have defined this entity (the simplest example
of this is when we have a private enumeral type since the bounds
@@ -10507,10 +10511,15 @@ set_end_locus_from_node (tree gnu_node, Node_Id gnat_node)
case N_Package_Body:
case N_Subprogram_Body:
case N_Block_Statement:
- gnat_end_label = End_Label (Handled_Statement_Sequence (gnat_node));
+ if (Present (Handled_Statement_Sequence (gnat_node)))
+ gnat_end_label = End_Label (Handled_Statement_Sequence (gnat_node));
+ else
+ gnat_end_label = Empty;
+
break;
case N_Package_Declaration:
+ gcc_checking_assert (Present (Specification (gnat_node)));
gnat_end_label = End_Label (Specification (gnat_node));
break;
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 846d20a..ab5ca5b 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -38,6 +38,7 @@
#include "attribs.h"
#include "varasm.h"
#include "toplev.h"
+#include "opts.h"
#include "output.h"
#include "debug.h"
#include "convert.h"
@@ -93,6 +94,7 @@ static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_stack_protector_attribute (tree *, tree, tree, int, bool *);
+static tree handle_strub_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
@@ -109,6 +111,8 @@ static tree handle_target_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *);
+static tree handle_zero_call_used_regs_attribute (tree *, tree, tree, int,
+ bool *);
static const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
{
@@ -154,6 +158,8 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "no_stack_protector",0, 0, true, false, false, false,
handle_no_stack_protector_attribute,
attr_stack_protect_exclusions },
+ { "strub", 0, 1, false, true, false, true,
+ handle_strub_attribute, NULL },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute, NULL },
{ "noclone", 0, 0, true, false, false, false,
@@ -191,6 +197,9 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "may_alias", 0, 0, false, true, false, false,
NULL, NULL },
+ { "zero_call_used_regs", 1, 1, true, false, false, false,
+ handle_zero_call_used_regs_attribute, NULL },
+
/* ??? format and format_arg are heavy and not supported, which actually
prevents support for stdio builtins, which we however declare as part
of the common builtins.def contents. */
@@ -4329,6 +4338,7 @@ update_pointer_to (tree old_type, tree new_type)
TREE_TYPE (t) = new_type;
if (TYPE_NULL_BOUNDS (t))
TREE_TYPE (TREE_OPERAND (TYPE_NULL_BOUNDS (t), 0)) = new_type;
+ TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_POINTER_TO (new_type));
}
/* Chain REF and its variants at the end. */
@@ -4345,7 +4355,10 @@ update_pointer_to (tree old_type, tree new_type)
/* Now adjust them. */
for (; ref; ref = TYPE_NEXT_REF_TO (ref))
for (t = TYPE_MAIN_VARIANT (ref); t; t = TYPE_NEXT_VARIANT (t))
- TREE_TYPE (t) = new_type;
+ {
+ TREE_TYPE (t) = new_type;
+ TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_REFERENCE_TO (new_type));
+ }
TYPE_POINTER_TO (old_type) = NULL_TREE;
TYPE_REFERENCE_TO (old_type) = NULL_TREE;
@@ -5858,8 +5871,7 @@ can_materialize_object_renaming_p (Node_Id expr)
const Uint bitpos
= Normalized_First_Bit (Entity (Selector_Name (expr)));
- if (!UI_Is_In_Int_Range (bitpos)
- || (bitpos != UI_No_Uint && bitpos != UI_From_Int (0)))
+ if (bitpos != UI_No_Uint && bitpos != Uint_0)
return false;
expr = Prefix (expr);
@@ -6593,6 +6605,15 @@ handle_no_stack_protector_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
+/* Handle a "strub" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_strub_attribute (tree *, tree, tree, int, bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */
@@ -6984,6 +7005,59 @@ handle_vector_type_attribute (tree *node, tree name, tree ARG_UNUSED (args),
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;
+ }
+
+ /* pragma Machine_Attribute turns string arguments into identifiers.
+ Reverse it. */
+ if (TREE_CODE (id) == IDENTIFIER_NODE)
+ id = TREE_VALUE (args) = build_string
+ (IDENTIFIER_LENGTH (id), IDENTIFIER_POINTER (id));
+
+ 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;
+}
+
/* ----------------------------------------------------------------------- *
* BUILTIN FUNCTIONS *
* ----------------------------------------------------------------------- */
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index e8ed4b2..06d8203 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -663,7 +663,7 @@ nonbinary_modular_operation (enum tree_code op_code, tree type, tree lhs,
/* Return the size of TYPE, which must be a positive power of 2. */
-static unsigned int
+unsigned int
resolve_atomic_size (tree type)
{
unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 0a3046e..f3f3ca4 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -23,8 +23,6 @@
-- --
------------------------------------------------------------------------------
-with Gen_IL.Types;
-
package Gen_IL.Fields is
-- The following is "optional field enumeration" -- i.e. it is Field_Enum
@@ -36,8 +34,7 @@ package Gen_IL.Fields is
-- which might need to be kept in sync when modifying this.
-- Be sure to put new fields in the appropriate subrange (Field_Enum,
- -- Node_Header_Field, Node_Field, Entity_Field -- search for comments
- -- below).
+ -- Node_Field, Entity_Field -- search for comments below).
type Opt_Field_Enum is
(No_Field,
@@ -461,7 +458,9 @@ package Gen_IL.Fields is
Can_Never_Be_Null,
Can_Use_Internal_Rep,
Checks_May_Be_Suppressed,
- Class_Wide_Clone,
+ Class_Postconditions,
+ Class_Preconditions,
+ Class_Preconditions_Subprogram,
Class_Wide_Type,
Cloned_Subtype,
Component_Alignment,
@@ -509,6 +508,7 @@ package Gen_IL.Fields is
Discriminant_Default_Value,
Discriminant_Number,
Dispatch_Table_Wrappers,
+ Dynamic_Call_Helper,
DT_Entry_Count,
DT_Offset_To_Top_Func,
DT_Position,
@@ -649,9 +649,12 @@ package Gen_IL.Fields is
Hiding_Loop_Variable,
Hidden_In_Formal_Instance,
Homonym,
+ Ignored_Class_Postconditions,
+ Ignored_Class_Preconditions,
Ignore_SPARK_Mode_Pragmas,
Import_Pragma,
Incomplete_Actuals,
+ Indirect_Call_Wrapper,
In_Package_Body,
In_Private_Part,
In_Use,
@@ -677,6 +680,7 @@ package Gen_IL.Fields is
Is_Checked_Ghost_Entity,
Is_Child_Unit,
Is_Class_Wide_Equivalent_Type,
+ Is_Class_Wide_Wrapper,
Is_Compilation_Unit,
Is_Completely_Hidden,
Is_Concurrent_Record_Type,
@@ -693,6 +697,7 @@ package Gen_IL.Fields is
Is_Discrim_SO_Function,
Is_Discriminant_Check_Function,
Is_Dispatch_Table_Entity,
+ Is_Dispatch_Table_Wrapper,
Is_Dispatching_Operation,
Is_Elaboration_Checks_OK_Id,
Is_Elaboration_Warnings_OK_Id,
@@ -828,7 +833,6 @@ package Gen_IL.Fields is
Nonzero_Is_True,
Normalized_First_Bit,
Normalized_Position,
- Normalized_Position_Max,
OK_To_Rename,
Optimize_Alignment_Space,
Optimize_Alignment_Time,
@@ -893,6 +897,7 @@ package Gen_IL.Fields is
Spec_Entity,
SSO_Set_High_By_Default,
SSO_Set_Low_By_Default,
+ Static_Call_Helper,
Static_Discrete_Predicate,
Static_Elaboration_Desired,
Static_Initialization,
@@ -936,13 +941,4 @@ package Gen_IL.Fields is
-- Enumeration of fields -- Opt_Field_Enum without the special null value
-- No_Field.
- subtype Node_Header_Field is Field_Enum with Predicate =>
- Node_Header_Field in Nkind .. Link | Ekind;
-
- use Gen_IL.Types;
-
- subtype Node_Header_Type is Type_Enum range
- Node_Kind_Type .. Union_Id;
- -- Types of node header fields
-
end Gen_IL.Fields;
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index 41dd232..1fa7f0b 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -126,6 +126,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Is_Character_Type, Flag),
Sm (Is_Checked_Ghost_Entity, Flag),
Sm (Is_Child_Unit, Flag),
+ Sm (Is_Class_Wide_Wrapper, Flag),
Sm (Is_Class_Wide_Equivalent_Type, Flag),
Sm (Is_Compilation_Unit, Flag),
Sm (Is_Concurrent_Record_Type, Flag),
@@ -139,6 +140,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Is_Discrim_SO_Function, Flag),
Sm (Is_Discriminant_Check_Function, Flag),
Sm (Is_Dispatch_Table_Entity, Flag),
+ Sm (Is_Dispatch_Table_Wrapper, Flag),
Sm (Is_Dispatching_Operation, Flag),
Sm (Is_Eliminated, Flag),
Sm (Is_Entry_Formal, Flag),
@@ -316,7 +318,6 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Interface_Name, Node_Id),
Sm (Normalized_First_Bit, Uint),
Sm (Normalized_Position, Uint),
- Sm (Normalized_Position_Max, Uint),
Sm (Original_Record_Component, Node_Id)));
Cc (E_Component, Record_Field_Kind,
@@ -978,8 +979,11 @@ begin -- Gen_IL.Gen.Gen_Entities
Ab (Subprogram_Kind, Overloadable_Kind,
(Sm (Body_Needed_For_SAL, Flag),
- Sm (Class_Wide_Clone, Node_Id),
+ Sm (Class_Postconditions, Node_Id),
+ Sm (Class_Preconditions, Node_Id),
+ Sm (Class_Preconditions_Subprogram, Node_Id),
Sm (Contract, Node_Id),
+ Sm (Dynamic_Call_Helper, Node_Id),
Sm (Elaboration_Entity, Node_Id),
Sm (Elaboration_Entity_Required, Flag),
Sm (First_Entity, Node_Id),
@@ -987,8 +991,11 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Has_Nested_Subprogram, Flag),
Sm (Has_Out_Or_In_Out_Parameter, Flag),
Sm (Has_Recursive_Call, Flag),
+ Sm (Ignored_Class_Postconditions, Node_Id),
+ Sm (Ignored_Class_Preconditions, Node_Id),
Sm (Ignore_SPARK_Mode_Pragmas, Flag),
Sm (Import_Pragma, Node_Id),
+ Sm (Indirect_Call_Wrapper, Node_Id),
Sm (Interface_Alias, Node_Id),
Sm (Interface_Name, Node_Id),
Sm (Is_Elaboration_Checks_OK_Id, Flag),
@@ -999,6 +1006,7 @@ begin -- Gen_IL.Gen.Gen_Entities
Sm (Overridden_Operation, Node_Id),
Sm (Protected_Body_Subprogram, Node_Id),
Sm (Scope_Depth_Value, Uint),
+ Sm (Static_Call_Helper, Node_Id),
Sm (SPARK_Pragma, Node_Id),
Sm (SPARK_Pragma_Inherited, Flag),
Sm (Subps_Index, Uint)));
@@ -1384,6 +1392,23 @@ begin -- Gen_IL.Gen.Gen_Entities
(E_Entry,
E_Entry_Family));
+ Union (Evaluable_Kind,
+ Children =>
+ (Exception_Or_Object_Kind,
+ E_Enumeration_Literal,
+ E_Label,
+ Subprogram_Kind));
+ -- Kinds that represent values that can be evaluated
+
+ Union (Global_Name_Kind,
+ Children =>
+ (Constant_Or_Variable_Kind,
+ E_Exception,
+ E_Package,
+ Subprogram_Kind));
+ -- Kinds that can have an Interface_Name that corresponds to a global
+ -- (linker) name.
+
Union (Named_Access_Kind,
Children =>
(E_Access_Type,
@@ -1409,4 +1434,10 @@ begin -- Gen_IL.Gen.Gen_Entities
E_Record_Type_With_Private,
E_Record_Subtype_With_Private));
+ Union (Subprogram_Type_Or_Kind,
+ Children =>
+ (Subprogram_Kind,
+ E_Subprogram_Body,
+ E_Subprogram_Type));
+
end Gen_IL.Gen.Gen_Entities;
diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index 55ba71d..20d25ea 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -577,7 +577,8 @@ begin -- Gen_IL.Gen.Gen_Nodes
Ab (N_Declaration, Node_Kind);
-- Note: this includes all constructs normally thought of as declarations
- -- except those that are separately grouped in N_Later_Decl_Item.
+ -- except those that are separately grouped in N_Later_Decl_Item. But
+ -- Declaration_Node may return yet more node types; see N_Is_Decl below.
Cc (N_Component_Declaration, N_Declaration,
(Sy (Defining_Identifier, Node_Id),
@@ -1649,4 +1650,67 @@ begin -- Gen_IL.Gen.Gen_Nodes
N_Terminate_Alternative));
-- Nodes with condition fields (does not include N_Raise_xxx_Error)
+ Union (N_Has_Bounds,
+ Children =>
+ (N_Range,
+ N_Real_Range_Specification,
+ N_Signed_Integer_Type_Definition));
+ -- Nodes that have Low_Bound and High_Bound defined
+
+ Union (N_Is_Index,
+ Children =>
+ (N_Has_Bounds,
+ N_Has_Entity,
+ N_Subtype_Indication));
+ -- Nodes that can be an index of an array
+
+ Union (N_Entity_Name,
+ Children =>
+ (N_Expanded_Name,
+ N_Identifier,
+ N_Operator_Symbol));
+ -- Nodes that are definitely representing an entity.
+ -- Some N_Attribute_Reference nodes may also represent an entity. See
+ -- Is_Entity_Name.
+
+ Union (N_Is_Decl,
+ Children =>
+ (N_Declaration,
+ N_Discriminant_Specification,
+ N_Enumeration_Type_Definition,
+ N_Exception_Handler,
+ N_Later_Decl_Item,
+ N_Package_Specification,
+ N_Parameter_Specification,
+ N_Renaming_Declaration,
+ N_Subprogram_Specification));
+ -- Nodes that can be returned by Declaration_Node
+
+ Union (N_Is_Range,
+ Children =>
+ (N_Character_Literal,
+ N_Entity_Name,
+ N_Has_Bounds,
+ N_Integer_Literal,
+ N_Subtype_Indication));
+ -- Nodes that can be used to specify a range
+
+ Union (N_Is_Case_Choice,
+ Children =>
+ (N_Is_Range,
+ N_Others_Choice));
+ -- Nodes that can be in the choices of a case statement
+
+ Union (N_Is_Exception_Choice,
+ Children =>
+ (N_Entity_Name,
+ N_Others_Choice));
+ -- Nodes that can be in the choices of an exception handler
+
+ Union (N_Alternative,
+ Children =>
+ (N_Case_Statement_Alternative,
+ N_Variant));
+ -- Nodes that can be alternatives in case contructs
+
end Gen_IL.Gen.Gen_Nodes;
diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb
index a9c7bd7..e786251 100644
--- a/gcc/ada/gen_il-gen.adb
+++ b/gcc/ada/gen_il-gen.adb
@@ -28,6 +28,27 @@ with Ada.Text_IO;
package body Gen_IL.Gen is
+ Statistics_Enabled : constant Boolean := False;
+ -- Change to True or False to enable/disable statistics printed by
+ -- Atree. Should normally be False, for efficiency. Also compile with
+ -- -gnatd.A to get the statistics printed. Enabling these statistics
+ -- makes the compiler about 20% slower.
+
+ Num_Header_Slots : constant := 3;
+ -- Number of header slots; the first Num_Header_Slots slots are stored in
+ -- the header; the rest are dynamically allocated in the Slots table. We
+ -- need to subtract this off when accessing dynamic slots. The constant
+ -- Seinfo.N_Head will contain this value. Fields that are allocated in the
+ -- header slots are quicker to access.
+ --
+ -- This number can be adjusted for efficiency. We choose 3 because the
+ -- minimum node size is 3 slots, and because that causes the size of type
+ -- Node_Header to be a power of 2. We can't make it zero, however, because
+ -- C doesn't allow zero-length arrays.
+
+ N_Head : constant String := Image (Field_Offset'(Num_Header_Slots));
+ -- String form of the above
+
Enable_Assertions : constant Boolean := True;
-- True to enable predicates on the _Id types, and preconditions on getters
-- and setters.
@@ -37,6 +58,9 @@ package body Gen_IL.Gen is
-- which results in enormous nodes. For experimenting and debugging.
-- Should be True in normal operation, for efficiency.
+ SS : constant := 32; -- slot size in bits
+ SSS : constant String := Image (Bit_Offset'(SS));
+
Inline : constant String := "Inline";
-- For experimenting with Inline_Always
@@ -309,7 +333,7 @@ package body Gen_IL.Gen is
Pre => new String'(Pre),
Pre_Get => new String'(Pre_Get),
Pre_Set => new String'(Pre_Set),
- Offset => <>); -- filled in later
+ Offset => Unknown_Offset);
-- The Field_Table entry has already been created by the 'then' part
-- above. Now we're seeing the same field being "created" again in a
@@ -479,8 +503,6 @@ package body Gen_IL.Gen is
Min_Entity_Size : Field_Offset := Field_Offset'Last;
Max_Entity_Size : Field_Offset := 0;
- Average_Node_Size_In_Slots : Long_Float;
-
Node_Field_Types_Used, Entity_Field_Types_Used : Type_Set;
Setter_Needs_Parent : Field_Set :=
@@ -563,6 +585,8 @@ package body Gen_IL.Gen is
procedure Put_Setter_Spec (S : in out Sink; F : Field_Enum);
procedure Put_Getter_Decl (S : in out Sink; F : Field_Enum);
procedure Put_Setter_Decl (S : in out Sink; F : Field_Enum);
+ procedure Put_Getter_Setter_Locals
+ (S : in out Sink; F : Field_Enum; Get : Boolean);
procedure Put_Getter_Body (S : in out Sink; F : Field_Enum);
procedure Put_Setter_Body (S : in out Sink; F : Field_Enum);
-- Print out the specification, declaration, or body of a getter or
@@ -573,9 +597,9 @@ package body Gen_IL.Gen is
-- Print out the precondition, if any, for a getter or setter for the
-- given field.
- procedure Put_Low_Level_Accessor_Instantiations
+ procedure Put_Casts
(S : in out Sink; T : Type_Enum);
- -- Print out the low-level getter and setter for a given type
+ -- Print out the Cast functions for a given type
procedure Put_Traversed_Fields (S : in out Sink);
-- Called by Put_Nodes to print out the Traversed_Fields table in
@@ -616,22 +640,17 @@ package body Gen_IL.Gen is
-- corresponding to the Ada Node_Kind, Entity_Kind, and subtypes
-- thereof.
- procedure Put_Low_Level_C_Getter
- (S : in out Sink; T : Type_Enum);
- -- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out low-level
- -- getters.
-
- procedure Put_High_Level_C_Getters
+ procedure Put_C_Getters
(S : in out Sink; Root : Root_Type);
-- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out high-level
-- getters.
- procedure Put_High_Level_C_Getter
+ procedure Put_C_Getter
(S : in out Sink; F : Field_Enum);
- -- Used by Put_High_Level_C_Getters to print out one high-level getter.
+ -- Used by Put_C_Getters to print out one high-level getter.
procedure Put_Union_Membership
- (S : in out Sink; Root : Root_Type);
+ (S : in out Sink; Root : Root_Type; Only_Prototypes : Boolean);
-- Used by Put_Sinfo_Dot_H and Put_Einfo_Dot_H to print out functions to
-- test membership in a union type.
@@ -691,6 +710,8 @@ package body Gen_IL.Gen is
Type_Table (T).Last := T;
Add_Concrete_Descendant_To_Ancestors
(Type_Table (T).Parent, T);
+ -- Parent cannot be No_Type here, because T is a concrete
+ -- type, and therefore not a root type.
when Abstract_Type =>
declare
@@ -884,13 +905,13 @@ package body Gen_IL.Gen is
function To_Size_In_Slots (Size_In_Bits : Bit_Offset)
return Field_Offset is
- ((Field_Offset (Size_In_Bits) + 31) / 32);
+ ((Field_Offset (Size_In_Bits) + (SS - 1)) / SS);
function Type_Size_In_Slots (T : Concrete_Type) return Field_Offset is
(To_Size_In_Slots (Type_Bit_Size (T))); -- rounded up to slot boundary
function Type_Bit_Size_Aligned (T : Concrete_Type) return Bit_Offset is
- (Bit_Offset (Type_Size_In_Slots (T)) * 32); -- multiple of slot size
+ (Bit_Offset (Type_Size_In_Slots (T)) * SS); -- multiple of slot size
---------------------------
-- Compute_Field_Offsets --
@@ -924,8 +945,7 @@ package body Gen_IL.Gen is
(F : Field_Enum; Offset : Field_Offset);
-- Mark the offset as "in use"
- function Choose_Offset
- (F : Field_Enum) return Field_Offset;
+ procedure Choose_Offset (F : Field_Enum);
-- Choose an offset for this field
function Offset_OK
@@ -965,14 +985,14 @@ package body Gen_IL.Gen is
end loop;
end Set_Offset_In_Use;
- function Choose_Offset
- (F : Field_Enum) return Field_Offset is
+ procedure Choose_Offset (F : Field_Enum) is
begin
for Offset in Field_Offset loop
if Offset_OK (F, Offset) then
Set_Offset_In_Use (F, Offset);
- return Offset;
+ Field_Table (F).Offset := Offset;
+ return;
end if;
end loop;
@@ -981,16 +1001,16 @@ package body Gen_IL.Gen is
Image (Gen_IL.Internals.Bit_Offset'Last) & " is too small)";
end Choose_Offset;
- Num_Concrete_Have_Field : array (Field_Enum) of Type_Count :=
+ Weighted_Node_Frequency : array (Field_Enum) of Type_Count :=
(others => 0);
-- Number of concrete types that have each field
function More_Types_Have_Field (F1, F2 : Field_Enum) return Boolean is
- (Num_Concrete_Have_Field (F1) > Num_Concrete_Have_Field (F2));
+ (Weighted_Node_Frequency (F1) > Weighted_Node_Frequency (F2));
-- True if F1 appears in more concrete types than F2
function Sort_Less (F1, F2 : Field_Enum) return Boolean is
- (if Num_Concrete_Have_Field (F1) = Num_Concrete_Have_Field (F2) then
+ (if Weighted_Node_Frequency (F1) = Weighted_Node_Frequency (F2) then
F1 < F2
else More_Types_Have_Field (F1, F2));
@@ -999,15 +1019,18 @@ package body Gen_IL.Gen is
All_Fields : Field_Vector;
+ -- Start of processing for Compute_Field_Offsets
+
begin
- -- Compute the number of types that have each field
+ -- Compute the number of types that have each field, weighted by the
+ -- frequency of such nodes.
for T in Concrete_Type loop
for F in Field_Enum loop
if Fields_Per_Node (T) (F) then
- Num_Concrete_Have_Field (F) :=
- Num_Concrete_Have_Field (F) + 1;
+ Weighted_Node_Frequency (F) :=
+ Weighted_Node_Frequency (F) + Type_Frequency (T);
end if;
end loop;
end loop;
@@ -1038,8 +1061,33 @@ package body Gen_IL.Gen is
-- complication compared to standard graph coloring is that fields
-- are different sizes.
+ -- First choose offsets for some heavily-used fields, so they will
+ -- get low offsets, so they will wind up in the node header for
+ -- faster access.
+
+ Choose_Offset (Nkind);
+ pragma Assert (Field_Table (Nkind).Offset = 0);
+ Choose_Offset (Ekind);
+ pragma Assert (Field_Table (Ekind).Offset = 1);
+ Choose_Offset (Homonym);
+ pragma Assert (Field_Table (Homonym).Offset = 1);
+ Choose_Offset (Is_Immediately_Visible);
+ pragma Assert (Field_Table (Is_Immediately_Visible).Offset = 16);
+ Choose_Offset (From_Limited_With);
+ pragma Assert (Field_Table (From_Limited_With).Offset = 17);
+ Choose_Offset (Is_Potentially_Use_Visible);
+ pragma Assert (Field_Table (Is_Potentially_Use_Visible).Offset = 18);
+ Choose_Offset (Is_Generic_Instance);
+ pragma Assert (Field_Table (Is_Generic_Instance).Offset = 19);
+ Choose_Offset (Scope);
+ pragma Assert (Field_Table (Scope).Offset = 2);
+
+ -- Then loop through them all, skipping the ones we did above
+
for F of All_Fields loop
- Field_Table (F).Offset := Choose_Offset (F);
+ if Field_Table (F).Offset = Unknown_Offset then
+ Choose_Offset (F);
+ end if;
end loop;
end Compute_Field_Offsets;
@@ -1049,231 +1097,6 @@ package body Gen_IL.Gen is
------------------------
procedure Compute_Type_Sizes is
- -- Node_Counts is the number of nodes of each kind created during
- -- compilation of a large example. This is used purely to compute an
- -- estimate of the average node size. New node types can default to
- -- "others => 0". At some point we can instrument Atree to print out
- -- accurate size statistics, and remove this code.
-
- Node_Counts : constant array (Concrete_Node) of Natural :=
- (N_Identifier => 429298,
- N_Defining_Identifier => 231636,
- N_Integer_Literal => 90892,
- N_Parameter_Specification => 62811,
- N_Attribute_Reference => 47150,
- N_Expanded_Name => 37375,
- N_Selected_Component => 30699,
- N_Subprogram_Declaration => 20744,
- N_Freeze_Entity => 20314,
- N_Procedure_Specification => 18901,
- N_Object_Declaration => 18023,
- N_Function_Specification => 16570,
- N_Range => 16216,
- N_Explicit_Dereference => 12198,
- N_Component_Association => 11188,
- N_Unchecked_Type_Conversion => 11165,
- N_Subtype_Indication => 10727,
- N_Procedure_Call_Statement => 10056,
- N_Subtype_Declaration => 8141,
- N_Handled_Sequence_Of_Statements => 8078,
- N_Null => 7288,
- N_Aggregate => 7222,
- N_String_Literal => 7152,
- N_Function_Call => 6958,
- N_Simple_Return_Statement => 6911,
- N_And_Then => 6867,
- N_Op_Eq => 6845,
- N_Call_Marker => 6683,
- N_Pragma_Argument_Association => 6525,
- N_Component_Definition => 6487,
- N_Assignment_Statement => 6483,
- N_With_Clause => 6480,
- N_Null_Statement => 5917,
- N_Index_Or_Discriminant_Constraint => 5877,
- N_Generic_Association => 5667,
- N_Full_Type_Declaration => 5573,
- N_If_Statement => 5553,
- N_Subprogram_Body => 5455,
- N_Op_Add => 5443,
- N_Type_Conversion => 5260,
- N_Component_Declaration => 5059,
- N_Raise_Constraint_Error => 4840,
- N_Formal_Concrete_Subprogram_Declaration => 4602,
- N_Expression_With_Actions => 4598,
- N_Op_Ne => 3854,
- N_Indexed_Component => 3834,
- N_Op_Subtract => 3777,
- N_Package_Specification => 3490,
- N_Subprogram_Renaming_Declaration => 3445,
- N_Pragma => 3427,
- N_Case_Statement_Alternative => 3272,
- N_Block_Statement => 3239,
- N_Parameter_Association => 3213,
- N_Op_Lt => 3020,
- N_Op_Not => 2926,
- N_Character_Literal => 2914,
- N_Others_Choice => 2769,
- N_Or_Else => 2576,
- N_Itype_Reference => 2511,
- N_Defining_Operator_Symbol => 2487,
- N_Component_List => 2470,
- N_Formal_Object_Declaration => 2262,
- N_Generic_Subprogram_Declaration => 2227,
- N_Real_Literal => 2156,
- N_Op_Gt => 2156,
- N_Access_To_Object_Definition => 1984,
- N_Op_Le => 1975,
- N_Op_Ge => 1942,
- N_Package_Renaming_Declaration => 1811,
- N_Formal_Type_Declaration => 1756,
- N_Qualified_Expression => 1746,
- N_Package_Declaration => 1729,
- N_Record_Definition => 1651,
- N_Allocator => 1521,
- N_Op_Concat => 1377,
- N_Access_Definition => 1358,
- N_Case_Statement => 1322,
- N_Number_Declaration => 1316,
- N_Generic_Package_Declaration => 1311,
- N_Slice => 1078,
- N_Constrained_Array_Definition => 1068,
- N_Exception_Renaming_Declaration => 1011,
- N_Implicit_Label_Declaration => 978,
- N_Exception_Handler => 966,
- N_Private_Type_Declaration => 898,
- N_Operator_Symbol => 872,
- N_Formal_Private_Type_Definition => 867,
- N_Range_Constraint => 849,
- N_Aspect_Specification => 837,
- N_Variant => 834,
- N_Discriminant_Specification => 746,
- N_Loop_Statement => 744,
- N_Derived_Type_Definition => 731,
- N_Freeze_Generic_Entity => 702,
- N_Iteration_Scheme => 686,
- N_Package_Instantiation => 658,
- N_Loop_Parameter_Specification => 632,
- N_Attribute_Definition_Clause => 608,
- N_Compilation_Unit_Aux => 599,
- N_Compilation_Unit => 599,
- N_Label => 572,
- N_Goto_Statement => 572,
- N_In => 564,
- N_Enumeration_Type_Definition => 523,
- N_Object_Renaming_Declaration => 482,
- N_If_Expression => 476,
- N_Exception_Declaration => 472,
- N_Reference => 455,
- N_Incomplete_Type_Declaration => 438,
- N_Use_Package_Clause => 401,
- N_Unconstrained_Array_Definition => 360,
- N_Variant_Part => 340,
- N_Defining_Program_Unit_Name => 336,
- N_Op_And => 334,
- N_Raise_Program_Error => 329,
- N_Formal_Discrete_Type_Definition => 319,
- N_Contract => 311,
- N_Not_In => 305,
- N_Designator => 285,
- N_Component_Clause => 247,
- N_Formal_Signed_Integer_Type_Definition => 244,
- N_Raise_Statement => 214,
- N_Op_Expon => 205,
- N_Op_Minus => 202,
- N_Op_Multiply => 158,
- N_Exit_Statement => 130,
- N_Function_Instantiation => 129,
- N_Discriminant_Association => 123,
- N_Private_Extension_Declaration => 119,
- N_Extended_Return_Statement => 117,
- N_Op_Divide => 107,
- N_Op_Or => 103,
- N_Signed_Integer_Type_Definition => 101,
- N_Record_Representation_Clause => 76,
- N_Unchecked_Expression => 70,
- N_Op_Abs => 63,
- N_Elsif_Part => 62,
- N_Formal_Floating_Point_Definition => 59,
- N_Formal_Package_Declaration => 58,
- N_Modular_Type_Definition => 55,
- N_Abstract_Subprogram_Declaration => 52,
- N_Validate_Unchecked_Conversion => 49,
- N_Defining_Character_Literal => 36,
- N_Raise_Storage_Error => 33,
- N_Compound_Statement => 29,
- N_Procedure_Instantiation => 28,
- N_Access_Procedure_Definition => 25,
- N_Floating_Point_Definition => 20,
- N_Use_Type_Clause => 19,
- N_Op_Plus => 14,
- N_Package_Body => 13,
- N_Op_Rem => 13,
- N_Enumeration_Representation_Clause => 13,
- N_Access_Function_Definition => 11,
- N_Extension_Aggregate => 11,
- N_Formal_Ordinary_Fixed_Point_Definition => 10,
- N_Op_Mod => 10,
- N_Expression_Function => 9,
- N_Delay_Relative_Statement => 9,
- N_Quantified_Expression => 7,
- N_Formal_Derived_Type_Definition => 7,
- N_Free_Statement => 7,
- N_Iterator_Specification => 5,
- N_Op_Shift_Left => 5,
- N_Formal_Modular_Type_Definition => 4,
- N_Generic_Package_Renaming_Declaration => 1,
- N_Empty => 1,
- N_Real_Range_Specification => 1,
- N_Ordinary_Fixed_Point_Definition => 1,
- N_Op_Shift_Right => 1,
- N_Error => 1,
- N_Mod_Clause => 1,
- others => 0);
-
- Total_Node_Count : constant Long_Float := 1370676.0;
-
- type Node_Frequency_Table is array (Concrete_Node) of Long_Float;
-
- function Init_Node_Frequency return Node_Frequency_Table;
- -- Compute the value of the Node_Frequency table
-
- function Average_Type_Size_In_Slots return Long_Float;
- -- Compute the average over all concrete node types of the size,
- -- weighted by the frequency of that node type.
-
- function Init_Node_Frequency return Node_Frequency_Table is
- Result : Node_Frequency_Table := (others => 0.0);
-
- begin
- for T in Concrete_Node loop
- Result (T) := Long_Float (Node_Counts (T)) / Total_Node_Count;
- end loop;
-
- return Result;
- end Init_Node_Frequency;
-
- Node_Frequency : constant Node_Frequency_Table := Init_Node_Frequency;
- -- Table mapping concrete node types to the relative frequency of
- -- that node, in our large example. The sum of these values should
- -- add up to approximately 1.0. For example, if Node_Frequency(K) =
- -- 0.02, then that means that approximately 2% of all nodes are K
- -- nodes.
-
- function Average_Type_Size_In_Slots return Long_Float is
- -- We don't have data on entities, so we leave those out
-
- Result : Long_Float := 0.0;
- begin
- for T in Concrete_Node loop
- Result := Result +
- Node_Frequency (T) * Long_Float (Type_Size_In_Slots (T));
- end loop;
-
- return Result;
- end Average_Type_Size_In_Slots;
-
- -- Start of processing for Compute_Type_Sizes
-
begin
for T in Concrete_Type loop
declare
@@ -1289,7 +1112,10 @@ package body Gen_IL.Gen is
end if;
end loop;
- Type_Bit_Size (T) := Max_Offset + 1;
+ -- No type can be smaller than the header slots
+
+ Type_Bit_Size (T) :=
+ Bit_Offset'Max (Max_Offset + 1, SS * Num_Header_Slots);
end;
end loop;
@@ -1311,8 +1137,6 @@ package body Gen_IL.Gen is
Max_Node_Size := To_Size_In_Slots (Max_Node_Bit_Size);
Min_Entity_Size := To_Size_In_Slots (Min_Entity_Bit_Size);
Max_Entity_Size := To_Size_In_Slots (Max_Entity_Bit_Size);
-
- Average_Node_Size_In_Slots := Average_Type_Size_In_Slots;
end Compute_Type_Sizes;
----------------------------------------
@@ -1405,6 +1229,10 @@ package body Gen_IL.Gen is
-- Print out a subtype (of type Node_Id or Entity_Id) for a given
-- nonroot abstract type.
+ procedure Put_Opt_Subtype (T : Node_Or_Entity_Type);
+ -- Print out an "optional" subtype; that is, one that allows
+ -- Empty. Their names start with "Opt_".
+
procedure Put_Enum_Type is
procedure Put_Enum_Lit (T : Node_Or_Entity_Type);
-- Print out one enumeration literal in the declaration of
@@ -1496,6 +1324,29 @@ package body Gen_IL.Gen is
end if;
end Put_Id_Subtype;
+ procedure Put_Opt_Subtype (T : Node_Or_Entity_Type) is
+ begin
+ if Type_Table (T).Parent /= No_Type then
+ Put (S, "subtype Opt_" & Id_Image (T) & " is" & LF);
+ Increase_Indent (S, 2);
+ Put (S, Id_Image (Root));
+
+ -- Assert that the Opt_XXX subtype is empty or in the XXX
+ -- subtype.
+
+ if Enable_Assertions then
+ Put (S, " with Predicate =>" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "Opt_" & Id_Image (T) & " = Empty or else" & LF);
+ Put (S, "Opt_" & Id_Image (T) & " in " & Id_Image (T));
+ Decrease_Indent (S, 2);
+ end if;
+
+ Put (S, ";" & LF);
+ Decrease_Indent (S, 2);
+ end if;
+ end Put_Opt_Subtype;
+
begin -- Put_Type_And_Subtypes
Put_Enum_Type;
@@ -1506,7 +1357,7 @@ package body Gen_IL.Gen is
case Root is
when Node_Kind =>
Put_Getter_Decl (S, Nkind);
- Put (S, "function K (N : Node_Id) return Node_Kind renames Nkind;" & LF);
+ Put (S, "function K (N : Node_Id) return Node_Kind renames " & Image (Nkind) & ";" & LF);
Put (S, "-- Shorthand for use in predicates and preconditions below" & LF);
Put (S, "-- There is no procedure Set_Nkind." & LF);
Put (S, "-- See Init_Nkind and Mutate_Nkind in Atree." & LF & LF);
@@ -1544,69 +1395,42 @@ package body Gen_IL.Gen is
end if;
end loop;
- Put (S, "subtype Flag is Boolean;" & LF & LF);
- end Put_Type_And_Subtypes;
+ Put (S, LF & "-- Optional subtypes of " & Id_Image (Root) & "." &
+ " These allow Empty." & LF & LF);
+
+ Iterate_Types (Root, Pre => Put_Opt_Subtype'Access);
+
+ Put (S, LF & "-- Optional union types:" & LF & LF);
- function Low_Level_Getter_Name (T : Type_Enum) return String is
- ("Get_" & Image (T));
- function Low_Level_Setter_Name (T : Type_Enum) return String is
- ("Set_" & Image (T));
- function Low_Level_Setter_Name (F : Field_Enum) return String is
- (Low_Level_Setter_Name (Field_Table (F).Field_Type) &
- (if Setter_Needs_Parent (F) then "_With_Parent" else ""));
+ for T in First_Abstract (Root) .. Last_Abstract (Root) loop
+ if Type_Table (T) /= null and then Type_Table (T).Is_Union then
+ Put_Opt_Subtype (T);
+ end if;
+ end loop;
+
+ Put (S, LF & "subtype Flag is Boolean;" & LF & LF);
+ end Put_Type_And_Subtypes;
-------------------------------------------
- -- Put_Low_Level_Accessor_Instantiations --
+ -- Put_Casts --
-------------------------------------------
- procedure Put_Low_Level_Accessor_Instantiations
+ procedure Put_Casts
(S : in out Sink; T : Type_Enum)
is
+ Pre : constant String :=
+ "function Cast is new Unchecked_Conversion (";
+ Lo_Type : constant String := "Field_Size_" & Image (Field_Size (T)) & "_Bit";
+ Hi_Type : constant String := Get_Set_Id_Image (T);
begin
- -- Special case for subtypes of Uint that have predicates. Use
- -- Get_Valid_32_Bit_Field in that case.
-
- if T in Uint_Subtype then
- pragma Assert (Field_Size (T) = 32);
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_Valid_32_Bit_Field (" &
- Get_Set_Id_Image (T) &
- ") with " & Inline & ";" & LF);
-
- -- Special case for types that have special defaults; instantiate
- -- Get_32_Bit_Field_With_Default and pass in the Default_Val.
-
- elsif Field_Has_Special_Default (T) then
- pragma Assert (Field_Size (T) = 32);
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_32_Bit_Field_With_Default (" &
- Get_Set_Id_Image (T) & ", " & Special_Default (T) &
- ") with " & Inline & ";" & LF);
-
- -- Otherwise, instantiate the normal getter for the right size in
- -- bits.
-
- else
- Put (S, LF & "function " & Low_Level_Getter_Name (T) &
- " is new Get_" & Image (Field_Size (T)) & "_Bit_Field (" &
- Get_Set_Id_Image (T) & ") with " & Inline & ";" & LF);
- end if;
-
- if T in Node_Kind_Type | Entity_Kind_Type then
- Put (S, "pragma Warnings (Off);" & LF);
- -- Set_Node_Kind_Type and Set_Entity_Kind_Type might not be called
- end if;
-
- -- No special cases for the setter
-
- Put (S, "procedure " & Low_Level_Setter_Name (T) & " is new Set_" &
- Image (Field_Size (T)) & "_Bit_Field (" & Get_Set_Id_Image (T) &
- ") with " & Inline & ";" & LF);
+ if T not in Uint_Subtype then
+ if T not in Node_Kind_Type | Entity_Kind_Type then
+ Put (S, Pre & Hi_Type & ", " & Lo_Type & ");" & LF);
+ end if;
- if T in Node_Kind_Type | Entity_Kind_Type then
- Put (S, "pragma Warnings (On);" & LF);
+ Put (S, Pre & Lo_Type & ", " & Hi_Type & ");" & LF);
end if;
- end Put_Low_Level_Accessor_Instantiations;
+ end Put_Casts;
----------------------
-- Put_Precondition --
@@ -1673,6 +1497,25 @@ package body Gen_IL.Gen is
-- Node_Id or Entity_Id, and the getter and setter will have
-- preconditions.
+ procedure Put_Get_Set_Incr
+ (S : in out Sink; F : Field_Enum; Get_Or_Set : String)
+ with Pre => Get_Or_Set in "Get" | "Set";
+ -- If statistics are enabled, put the appropriate increment statement
+
+ ----------------------
+ -- Put_Get_Set_Incr --
+ ----------------------
+
+ procedure Put_Get_Set_Incr
+ (S : in out Sink; F : Field_Enum; Get_Or_Set : String) is
+ begin
+ if Statistics_Enabled then
+ Put (S, "Atree." & Get_Or_Set & "_Count (" & F_Image (F) &
+ ") := Atree." & Get_Or_Set & "_Count (" &
+ F_Image (F) & ") + 1;" & LF);
+ end if;
+ end Put_Get_Set_Incr;
+
------------------------
-- Node_To_Fetch_From --
------------------------
@@ -1708,17 +1551,68 @@ package body Gen_IL.Gen is
Put (S, " with " & Inline);
Increase_Indent (S, 2);
Put_Precondition (S, F);
-
Decrease_Indent (S, 2);
Put (S, ";" & LF);
end Put_Getter_Decl;
+ ------------------------------
+ -- Put_Getter_Setter_Locals --
+ ------------------------------
+
+ procedure Put_Getter_Setter_Locals
+ (S : in out Sink; F : Field_Enum; Get : Boolean)
+ is
+ Rec : Field_Info renames Field_Table (F).all;
+
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ Off : constant Field_Offset := Rec.Offset;
+ F_Per_Slot : constant Field_Offset :=
+ SS / Field_Offset (Field_Size (Rec.Field_Type));
+ Slot_Off : constant Field_Offset := Off / F_Per_Slot;
+ In_NH : constant Boolean := Slot_Off < Num_Header_Slots;
+
+ N : constant String :=
+ (if Get then Node_To_Fetch_From (F) else "N");
+
+ begin
+ Put (S, " is" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "-- " & Image (F_Per_Slot) & " " & Image (F_Size) &
+ "-bit fields per " & SSS & "-bit slot." & LF);
+ Put (S, "-- Offset " & Image (Off) & " = " &
+ Image (Slot_Off) & " slots + " & Image (Off mod F_Per_Slot) &
+ " fields in slot." & LF & LF);
+
+ Put (S, "Off : constant := " & Image (Off) & ";" & LF);
+ Put (S, "F_Size : constant := " & Image (F_Size) & ";" & LF);
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "Mask : constant := 2**F_Size - 1;" & LF);
+ end if;
+
+ Put (S, "F_Per_Slot : constant Field_Offset := Slot_Size / F_Size;" & LF);
+ Put (S, "Slot_Off : constant Field_Offset := Off / F_Per_Slot;" & LF);
+
+ if In_NH then
+ Put (S, "S : Slot renames Node_Offsets.Table (" & N & ").Slots (Slot_Off);" & LF);
+ else
+ Put (S, "S : Slot renames Slots.Table (Node_Offsets.Table (" & N & ").Offset + Slot_Off);" & LF);
+ end if;
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "V : constant Natural := Natural ((Off mod F_Per_Slot) * F_Size);" & LF);
+ Put (S, LF);
+ end if;
+ end Put_Getter_Setter_Locals;
+
---------------------
-- Put_Getter_Body --
---------------------
procedure Put_Getter_Body (S : in out Sink; F : Field_Enum) is
Rec : Field_Info renames Field_Table (F).all;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ T : constant String := Get_Set_Id_Image (Rec.Field_Type);
begin
-- Note that we store the result in a local constant below, so that
-- the "Pre => ..." can refer to it. The constant is called Val so
@@ -1727,16 +1621,44 @@ package body Gen_IL.Gen is
-- and setter.
Put_Getter_Spec (S, F);
- Put (S, " is" & LF);
- Increase_Indent (S, 3);
- Put (S, "Val : constant " & Get_Set_Id_Image (Rec.Field_Type) &
- " := " & Low_Level_Getter_Name (Rec.Field_Type) &
- " (" & Node_To_Fetch_From (F) & ", " &
- Image (Rec.Offset) & ");" & LF);
+ Put_Getter_Setter_Locals (S, F, Get => True);
+
+ Put (S, "Raw : constant Field_Size_" & Image (F_Size) & "_Bit :=" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "Field_Size_" & Image (F_Size) & "_Bit (");
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "Shift_Right (S, V) and Mask);" & LF);
+ else
+ Put (S, "S);" & LF);
+ end if;
+
+ Decrease_Indent (S, 2);
+
+ Put (S, "Val : constant " & T & " :=");
+
+ if Field_Has_Special_Default (Rec.Field_Type) then
+ pragma Assert (Field_Size (Rec.Field_Type) = 32);
+ Put (S, LF);
+ Increase_Indent (S, 2);
+ Put (S, "(if Raw = 0 then " & Special_Default (Rec.Field_Type) &
+ " else " & "Cast (Raw));");
+ Decrease_Indent (S, 2);
+
+ else
+ Put (S, " Cast (Raw);");
+ end if;
+
+ Put (S, LF);
+
Decrease_Indent (S, 3);
Put (S, "begin" & LF);
Increase_Indent (S, 3);
+ Put (S, "-- pragma Debug (Validate_Node_And_Offset (NN, Slot_Off));" & LF);
+ -- Comment out the validation, because it's too slow, and because the
+ -- relevant routines in Atree are not visible.
+
if Rec.Pre.all /= "" then
Put (S, "pragma Assert (" & Rec.Pre.all & ");" & LF);
end if;
@@ -1745,6 +1667,7 @@ package body Gen_IL.Gen is
Put (S, "pragma Assert (" & Rec.Pre_Get.all & ");" & LF);
end if;
+ Put_Get_Set_Incr (S, F, "Get");
Put (S, "return Val;" & LF);
Decrease_Indent (S, 3);
Put (S, "end " & Image (F) & ";" & LF & LF);
@@ -1784,6 +1707,7 @@ package body Gen_IL.Gen is
procedure Put_Setter_Body (S : in out Sink; F : Field_Enum) is
Rec : Field_Info renames Field_Table (F).all;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
-- If Type_Only was specified in the call to Create_Semantic_Field,
-- then we assert that the node is a base type. We cannot assert that
@@ -1796,10 +1720,18 @@ package body Gen_IL.Gen is
"Is_Base_Type (N)");
begin
Put_Setter_Spec (S, F);
- Put (S, " is" & LF);
+ Put_Getter_Setter_Locals (S, F, Get => False);
+
+ Put (S, "Raw : constant Field_Size_" & Image (F_Size) & "_Bit := Cast (Val);" & LF);
+
+ Decrease_Indent (S, 3);
Put (S, "begin" & LF);
Increase_Indent (S, 3);
+ Put (S, "-- pragma Debug (Validate_Node_And_Offset_Write (N, Slot_Off));" & LF);
+ -- Comment out the validation, because it's too slow, and because the
+ -- relevant routines in Atree are not visible.
+
if Rec.Pre.all /= "" then
Put (S, "pragma Assert (" & Rec.Pre.all & ");" & LF);
end if;
@@ -1812,8 +1744,29 @@ package body Gen_IL.Gen is
Put (S, "pragma Assert (" & Type_Only_Assertion & ");" & LF);
end if;
- Put (S, Low_Level_Setter_Name (F) & " (N, " & Image (Rec.Offset)
- & ", Val);" & LF);
+ if Setter_Needs_Parent (F) then
+ declare
+ Err : constant String :=
+ (if Rec.Field_Type = List_Id then "Error_List" else "Error");
+ begin
+ Put (S, "if Present (Val) and then Val /= " & Err & " then" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "pragma Warnings (Off, ""actuals for this call may be in wrong order"");" & LF);
+ Put (S, "Set_Parent (Val, N);" & LF);
+ Put (S, "pragma Warnings (On, ""actuals for this call may be in wrong order"");" & LF);
+ Decrease_Indent (S, 3);
+ Put (S, "end if;" & LF & LF);
+ end;
+ end if;
+
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "S := (S and not Shift_Left (Mask, V)) or Shift_Left (Slot (Raw), V);" & LF);
+
+ else
+ Put (S, "S := Slot (Raw);" & LF);
+ end if;
+
+ Put_Get_Set_Incr (S, F, "Set");
Decrease_Indent (S, 3);
Put (S, "end Set_" & Image (F) & ";" & LF & LF);
end Put_Setter_Body;
@@ -2036,7 +1989,7 @@ package body Gen_IL.Gen is
when others => "Entity_Field"); -- Entity_Kind
begin
- Put (S, "-- Table of sizes in 32-bit slots for given " &
+ Put (S, "-- Table of sizes in " & SSS & "-bit slots for given " &
Image (Root) & ", for use by Atree:" & LF);
case Root is
@@ -2045,8 +1998,7 @@ package body Gen_IL.Gen is
Image (Min_Node_Size) & ";" & LF);
Put (S, "Max_Node_Size : constant Field_Offset := " &
Image (Max_Node_Size) & ";" & LF & LF);
- Put (S, "Average_Node_Size_In_Slots : constant := " &
- Average_Node_Size_In_Slots'Img & ";" & LF & LF);
+
when Entity_Kind =>
Put (S, LF & "Min_Entity_Size : constant Field_Offset := " &
Image (Min_Entity_Size) & ";" & LF);
@@ -2067,34 +2019,48 @@ package body Gen_IL.Gen is
Put (S, "); -- Size" & LF);
Decrease_Indent (S, 2);
- declare
- type Dummy is array
- (First_Field (Root) .. Last_Field (Root)) of Boolean;
- Num_Fields : constant Root_Int := Dummy'Length;
- First_Time : Boolean := True;
- begin
- Put (S, LF & "-- Enumeration of all " & Image (Num_Fields)
- & " fields:" & LF & LF);
+ if Root = Node_Kind then
+ declare
+ type Node_Dummy is array (Node_Field) of Boolean;
+ type Entity_Dummy is array (Entity_Field) of Boolean;
+ Num_Fields : constant Root_Int :=
+ Node_Dummy'Length + Entity_Dummy'Length;
+ First_Time : Boolean := True;
+ begin
+ Put (S, LF & "-- Enumeration of all " & Image (Num_Fields)
+ & " fields:" & LF & LF);
- Put (S, "type " & Field_Enum_Type_Name & " is" & LF);
- Increase_Indent (S, 2);
- Put (S, "(");
- Increase_Indent (S, 1);
+ Put (S, "type Node_Or_Entity_Field is" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "(");
+ Increase_Indent (S, 1);
- for F in First_Field (Root) .. Last_Field (Root) loop
- if First_Time then
- First_Time := False;
- else
+ for F in Node_Field loop
+ if First_Time then
+ First_Time := False;
+ else
+ Put (S, "," & LF);
+ end if;
+
+ Put (S, F_Image (F));
+ end loop;
+
+ for F in Entity_Field loop
Put (S, "," & LF);
- end if;
+ Put (S, F_Image (F));
+ end loop;
- Put (S, F_Image (F));
- end loop;
+ Decrease_Indent (S, 1);
+ Put (S, "); -- Node_Or_Entity_Field" & LF);
+ Decrease_Indent (S, 2);
+ end;
+ end if;
- Decrease_Indent (S, 1);
- Put (S, "); -- " & Field_Enum_Type_Name & LF);
- Decrease_Indent (S, 2);
- end;
+ Put (S, LF & "subtype " & Field_Enum_Type_Name & " is" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "Node_Or_Entity_Field range " & F_Image (First_Field (Root)) &
+ " .. " & F_Image (Last_Field (Root)) & ";" & LF);
+ Decrease_Indent (S, 2);
Put (S, LF & "type " & Field_Enum_Type_Name & "_Index is new Pos;" & LF);
Put (S, "type " & Field_Enum_Type_Name & "_Array is array (" &
@@ -2153,34 +2119,67 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 2);
end;
- declare
- First_Time : Boolean := True;
- begin
- Put (S, LF & "-- Table mapping fields to kind and offset:" & LF & LF);
+ if Root = Node_Kind then
+ declare
+ First_Time : Boolean := True;
+ FS, FB, LB : Bit_Offset;
+ -- Field size in bits, first bit, and last bit for the previous
+ -- time around the loop. Used to print a comment after ",".
- Put (S, Field_Enum_Type_Name & "_Descriptors : constant array (" &
- Field_Enum_Type_Name & ") of Field_Descriptor :=" & LF);
+ procedure One_Comp (F : Field_Enum);
- Increase_Indent (S, 2);
- Put (S, "(");
- Increase_Indent (S, 1);
+ procedure One_Comp (F : Field_Enum) is
+ pragma Annotate (Codepeer, Modified, Field_Table);
+ Offset : constant Field_Offset := Field_Table (F).Offset;
+ begin
+ if First_Time then
+ First_Time := False;
+ else
+ Put (S, ",");
- for F in First_Field (Root) .. Last_Field (Root) loop
- if First_Time then
- First_Time := False;
- else
- Put (S, "," & LF);
- end if;
+ -- Print comment showing field's bits, except for 1-bit
+ -- fields.
- Put (S, F_Image (F) & " => (" &
- Image (Field_Table (F).Field_Type) & "_Field, " &
- Image (Field_Table (F).Offset) & ")");
- end loop;
+ if FS /= 1 then
+ Put (S, " -- *" & Image (FS) & " = bits " &
+ Image (FB) & ".." & Image (LB));
+ end if;
- Decrease_Indent (S, 1);
- Put (S, "); -- Field_Descriptors" & LF);
- Decrease_Indent (S, 2);
- end;
+ Put (S, LF);
+ end if;
+
+ Put (S, F_Image (F) & " => (" &
+ Image (Field_Table (F).Field_Type) & "_Field, " &
+ Image (Offset) & ")");
+
+ FS := Field_Size (F);
+ FB := First_Bit (F, Offset);
+ LB := Last_Bit (F, Offset);
+ end One_Comp;
+
+ begin
+ Put (S, LF & "-- Table mapping fields to kind and offset:" & LF & LF);
+
+ Put (S, "Field_Descriptors : constant array (" &
+ "Node_Or_Entity_Field) of Field_Descriptor :=" & LF);
+
+ Increase_Indent (S, 2);
+ Put (S, "(");
+ Increase_Indent (S, 1);
+
+ for F in Node_Field loop
+ One_Comp (F);
+ end loop;
+
+ for F in Entity_Field loop
+ One_Comp (F);
+ end loop;
+
+ Decrease_Indent (S, 1);
+ Put (S, "); -- Field_Descriptors" & LF);
+ Decrease_Indent (S, 2);
+ end;
+ end if;
end Put_Tables;
@@ -2251,7 +2250,16 @@ package body Gen_IL.Gen is
Put (S, "Kind : Field_Kind;" & LF);
Put (S, "Offset : Field_Offset;" & LF);
Decrease_Indent (S, 3);
- Put (S, "end record;" & LF);
+ Put (S, "end record;" & LF & LF);
+
+ -- Print out the node header types. Note that the Offset field is of
+ -- the base type, because we are using zero-origin addressing in
+ -- Atree.
+
+ Put (S, "N_Head : constant Field_Offset := " & N_Head & ";" & LF & LF);
+
+ Put (S, "Atree_Statistics_Enabled : constant Boolean := " &
+ Capitalize (Boolean'Image (Statistics_Enabled)) & ";" & LF);
Decrease_Indent (S, 3);
Put (S, LF & "end Seinfo;" & LF);
@@ -2265,39 +2273,6 @@ package body Gen_IL.Gen is
S : Sink;
B : Sink;
- procedure Put_Setter_With_Parent (Kind : String);
- -- Put the low-level ..._With_Parent setter. Kind is either "Node" or
- -- "List".
-
- procedure Put_Setter_With_Parent (Kind : String) is
- Error : constant String := (if Kind = "Node" then "" else "_" & Kind);
- begin
- Put (B, LF & "procedure Set_" & Kind & "_Id_With_Parent" & LF);
- Increase_Indent (B, 2);
- Put (B, "(N : Node_Id; Offset : Field_Offset; Val : " & Kind & "_Id);" & LF & LF);
- Decrease_Indent (B, 2);
-
- Put (B, "procedure Set_" & Kind & "_Id_With_Parent" & LF);
- Increase_Indent (B, 2);
- Put (B, "(N : Node_Id; Offset : Field_Offset; Val : " & Kind & "_Id) is" & LF);
- Decrease_Indent (B, 2);
- Put (B, "begin" & LF);
- Increase_Indent (B, 3);
- Put (B, "if Present (Val) and then Val /= Error" & Error & " then" & LF);
- Increase_Indent (B, 3);
- Put (B, "pragma Warnings (Off, ""actuals for this call may be in wrong order"");" & LF);
- Put (B, "Set_Parent (Val, N);" & LF);
- Put (B, "pragma Warnings (On, ""actuals for this call may be in wrong order"");" & LF);
- Decrease_Indent (B, 3);
- Put (B, "end if;" & LF & LF);
-
- Put (B, "Set_" & Kind & "_Id (N, Offset, Val);" & LF);
- Decrease_Indent (B, 3);
- Put (B, "end Set_" & Kind & "_Id_With_Parent;" & LF);
- end Put_Setter_With_Parent;
-
- -- Start of processing for Put_Nodes
-
begin
Create_File (S, "sinfo-nodes.ads");
Create_File (B, "sinfo-nodes.adb");
@@ -2329,6 +2304,7 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 3);
Put (S, LF & "end Sinfo.Nodes;" & LF);
+ Put (B, "with Unchecked_Conversion;" & LF);
Put (B, "with Atree; use Atree; use Atree.Atree_Private_Part;" & LF);
Put (B, "with Nlists; use Nlists;" & LF);
Put (B, "pragma Warnings (Off);" & LF);
@@ -2341,19 +2317,14 @@ package body Gen_IL.Gen is
Put (B, "-- This package is automatically generated." & LF & LF);
- Put (B, "-- Instantiations of low-level getters and setters that take offsets" & LF);
- Put (B, "-- in units of the size of the field." & LF);
-
Put (B, "pragma Style_Checks (""M200"");" & LF);
+
for T in Special_Type loop
if Node_Field_Types_Used (T) then
- Put_Low_Level_Accessor_Instantiations (B, T);
+ Put_Casts (B, T);
end if;
end loop;
- Put_Setter_With_Parent ("Node");
- Put_Setter_With_Parent ("List");
-
Put_Subp_Bodies (B, Node_Kind);
Decrease_Indent (B, 3);
@@ -2371,7 +2342,6 @@ package body Gen_IL.Gen is
begin
Create_File (S, "einfo-entities.ads");
Create_File (B, "einfo-entities.adb");
- Put (S, "with Seinfo; use Seinfo;" & LF);
Put (S, "with Sinfo.Nodes; use Sinfo.Nodes;" & LF);
Put (S, LF & "package Einfo.Entities is" & LF & LF);
@@ -2390,6 +2360,7 @@ package body Gen_IL.Gen is
Decrease_Indent (S, 3);
Put (S, LF & "end Einfo.Entities;" & LF);
+ Put (B, "with Unchecked_Conversion;" & LF);
Put (B, "with Atree; use Atree; use Atree.Atree_Private_Part;" & LF);
Put (B, "with Einfo.Utils; use Einfo.Utils;" & LF);
-- This forms a cycle between packages (via bodies, which is OK)
@@ -2399,13 +2370,11 @@ package body Gen_IL.Gen is
Put (B, "-- This package is automatically generated." & LF & LF);
- Put (B, "-- Instantiations of low-level getters and setters that take offsets" & LF);
- Put (B, "-- in units of the size of the field." & LF);
-
Put (B, "pragma Style_Checks (""M200"");" & LF);
+
for T in Special_Type loop
if Entity_Field_Types_Used (T) then
- Put_Low_Level_Accessor_Instantiations (B, T);
+ Put_Casts (B, T);
end if;
end loop;
@@ -2454,7 +2423,8 @@ package body Gen_IL.Gen is
end if;
end loop;
- Put (S, ")" & LF & "return " & Node_Or_Entity (Root) & "_Id");
+ Put (S, ")" & LF);
+ Put (S, "return " & Node_Or_Entity (Root) & "_Id");
Decrease_Indent (S, 2);
Decrease_Indent (S, 1);
end Put_Make_Spec;
@@ -2674,11 +2644,11 @@ package body Gen_IL.Gen is
return Result : Bit_Offset do
if F = No_Field then
-- We don't have a field size for No_Field, so just look at
- -- the bits up to the next word boundary.
+ -- the bits up to the next slot boundary.
Result := First_Bit;
- while (Result + 1) mod 32 /= 0
+ while (Result + 1) mod SS /= 0
and then Type_Layout (T) (Result + 1) = No_Field
loop
Result := Result + 1;
@@ -2691,19 +2661,19 @@ package body Gen_IL.Gen is
end Get_Last_Bit;
function First_Bit_Image (First_Bit : Bit_Offset) return String is
- W : constant Bit_Offset := First_Bit / 32;
- B : constant Bit_Offset := First_Bit mod 32;
- pragma Assert (W * 32 + B = First_Bit);
+ W : constant Bit_Offset := First_Bit / SS;
+ B : constant Bit_Offset := First_Bit mod SS;
+ pragma Assert (W * SS + B = First_Bit);
begin
return
- Image (W) & "*32" & (if B = 0 then "" else " + " & Image (B));
+ Image (W) & "*" & SSS & (if B = 0 then "" else " + " & Image (B));
end First_Bit_Image;
function Last_Bit_Image (Last_Bit : Bit_Offset) return String is
- W : constant Bit_Offset := (Last_Bit + 1) / 32;
+ W : constant Bit_Offset := (Last_Bit + 1) / SS;
begin
- if W * 32 - 1 = Last_Bit then
- return Image (W) & "*32 - 1";
+ if W * SS - 1 = Last_Bit then
+ return Image (W) & "*" & SSS & " - 1";
else
return First_Bit_Image (Last_Bit);
end if;
@@ -2817,6 +2787,7 @@ package body Gen_IL.Gen is
declare
First_Time : Boolean := True;
+
begin
for T in Concrete_Type loop
if First_Time then
@@ -2838,40 +2809,45 @@ package body Gen_IL.Gen is
declare
First_Time : Boolean := True;
First_Bit : Bit_Offset := 0;
+ F : Opt_Field_Enum;
+
+ function Node_Field_Of_Entity return String is
+ (if T in Entity_Type and then F in Node_Field then
+ " -- N" else "");
+ -- A comment to put out for fields of entities that are
+ -- shared with nodes, such as Chars.
+
begin
while First_Bit < Type_Bit_Size_Aligned (T) loop
if First_Time then
First_Time := False;
else
- Put (B, "," & LF);
+ Put (B, "," & Node_Field_Of_Entity & LF);
end if;
+ F := Type_Layout (T) (First_Bit);
+
declare
- F : constant Opt_Field_Enum :=
- Type_Layout (T) (First_Bit);
+ Last_Bit : constant Bit_Offset :=
+ Get_Last_Bit (T, F, First_Bit);
begin
- declare
- Last_Bit : constant Bit_Offset :=
- Get_Last_Bit (T, F, First_Bit);
- begin
+ pragma Assert
+ (Type_Layout (T) (First_Bit .. Last_Bit) =
+ (First_Bit .. Last_Bit => F));
+
+ if Last_Bit = First_Bit then
+ Put (B, First_Bit_Image (First_Bit) & " => " &
+ Image_Or_Waste (F));
+ else
pragma Assert
- (Type_Layout (T) (First_Bit .. Last_Bit) =
- (First_Bit .. Last_Bit => F));
-
- if Last_Bit = First_Bit then
- Put (B, First_Bit_Image (First_Bit) & " => " &
- Image_Or_Waste (F));
- else
- pragma Assert
- (if F /= No_Field then
- First_Bit mod Field_Size (F) = 0);
- Put (B, First_Bit_Image (First_Bit) & " .. " &
- Last_Bit_Image (Last_Bit) & " => " &
- Image_Or_Waste (F));
- end if;
-
- First_Bit := Last_Bit + 1;
- end;
+ (if F /= No_Field then
+ First_Bit mod Field_Size (F) = 0);
+ Put (B, First_Bit_Image (First_Bit) & " .. " &
+ Last_Bit_Image (Last_Bit) & " => " &
+ Image_Or_Waste (F));
+ end if;
+
+ First_Bit := Last_Bit + 1;
end;
end loop;
end;
@@ -2977,6 +2953,8 @@ package body Gen_IL.Gen is
end Put_Kind_Subtype;
begin
+ Put_Union_Membership (S, Root, Only_Prototypes => True);
+
Iterate_Types (Root, Pre => Put_Enum_Lit'Access);
Put (S, "#define Number_" & Node_Or_Entity (Root) & "_Kinds " &
@@ -2984,86 +2962,94 @@ package body Gen_IL.Gen is
Iterate_Types (Root, Pre => Put_Kind_Subtype'Access);
- Put_Union_Membership (S, Root);
+ Put_Union_Membership (S, Root, Only_Prototypes => False);
end Put_C_Type_And_Subtypes;
- ----------------------------
- -- Put_Low_Level_C_Getter --
- ----------------------------
+ ------------------
+ -- Put_C_Getter --
+ ------------------
- procedure Put_Low_Level_C_Getter
- (S : in out Sink; T : Type_Enum)
+ procedure Put_C_Getter
+ (S : in out Sink; F : Field_Enum)
is
- T_Image : constant String := Get_Set_Id_Image (T);
+ Rec : Field_Info renames Field_Table (F).all;
+
+ Off : constant Field_Offset := Rec.Offset;
+ F_Size : constant Bit_Offset := Field_Size (Rec.Field_Type);
+ F_Per_Slot : constant Field_Offset :=
+ SS / Field_Offset (Field_Size (Rec.Field_Type));
+ Slot_Off : constant Field_Offset := Off / F_Per_Slot;
+ In_NH : constant Boolean := Slot_Off < Num_Header_Slots;
+ N : constant String := Node_To_Fetch_From (F);
begin
- Put (S, "INLINE " & T_Image & "" & LF);
- Put (S, "Get_" & Image (T) & " (Node_Id N, Field_Offset Offset)" & LF);
+ Put (S, "INLINE " & Get_Set_Id_Image (Rec.Field_Type) &
+ " " & Image (F) & " (Node_Id N)" & LF);
+ Put (S, "{" & LF);
Increase_Indent (S, 3);
+ Put (S, "const Field_Offset Off = " & Image (Rec.Offset) & ";" & LF);
+ Put (S, "const Field_Offset F_Size = " & Image (F_Size) & ";" & LF);
- -- Same special cases for getters as in
- -- Put_Low_Level_Accessor_Instantiations.
-
- if T in Uint_Subtype then
- pragma Assert (Field_Size (T) = 32);
- Put (S, "{ return (" & T_Image &
- ") Get_Valid_32_Bit_Field(N, Offset); }" & LF & LF);
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "const any_slot Mask = (1 << F_Size) - 1;" & LF);
+ end if;
- elsif Field_Has_Special_Default (T) then
- pragma Assert (Field_Size (T) = 32);
- Put (S, "{ return (" & T_Image &
- ") Get_32_Bit_Field_With_Default(N, Offset, " &
- Special_Default (T) & "); }" & LF & LF);
+ Put (S, "const Field_Offset F_Per_Slot = Slot_Size / F_Size;" & LF);
+ Put (S, "const Field_Offset Slot_Off = Off / F_Per_Slot;" & LF);
+ Put (S, LF);
+ if In_NH then
+ Put (S, "any_slot slot = Node_Offsets_Ptr[" & N & "].Slots[Slot_Off];" & LF);
+ else
+ Put (S, "any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[" & N &
+ "].Offset + Slot_Off);" & LF);
+ end if;
+ if Field_Size (Rec.Field_Type) /= SS then
+ Put (S, "unsigned int Raw = (slot >> (Off % F_Per_Slot) * F_Size) & Mask;" & LF);
else
- Put (S, "{ return (" & T_Image & ") Get_" &
- Image (Field_Size (T)) & "_Bit_Field(N, Offset); }" & LF & LF);
+ Put (S, "unsigned int Raw = slot;" & LF);
end if;
- Decrease_Indent (S, 3);
- end Put_Low_Level_C_Getter;
+ Put (S, Get_Set_Id_Image (Rec.Field_Type) & " val = ");
- -----------------------------
- -- Put_High_Level_C_Getter --
- -----------------------------
+ if Field_Has_Special_Default (Rec.Field_Type) then
+ Increase_Indent (S, 2);
+ Put (S, "(Raw? Raw : " & Special_Default (Rec.Field_Type) & ")");
+ Decrease_Indent (S, 2);
- procedure Put_High_Level_C_Getter
- (S : in out Sink; F : Field_Enum)
- is
- begin
- Put (S, "INLINE " & Get_Set_Id_Image (Field_Table (F).Field_Type) &
- " " & Image (F) & " (Node_Id N)" & LF);
+ else
+ Put (S, "Raw");
+ end if;
- Increase_Indent (S, 3);
- Put (S, "{ return " &
- Low_Level_Getter_Name (Field_Table (F).Field_Type) &
- "(" & Node_To_Fetch_From (F) & ", " &
- Image (Field_Table (F).Offset) & "); }" & LF & LF);
+ Put (S, ";" & LF);
+
+ Put (S, "return val;" & LF);
Decrease_Indent (S, 3);
- end Put_High_Level_C_Getter;
+ Put (S, "}" & LF & LF);
+ end Put_C_Getter;
- ------------------------------
- -- Put_High_Level_C_Getters --
- ------------------------------
+ -------------------
+ -- Put_C_Getters --
+ -------------------
- procedure Put_High_Level_C_Getters
+ procedure Put_C_Getters
(S : in out Sink; Root : Root_Type)
is
begin
Put (S, "// Getters for fields" & LF & LF);
for F in First_Field (Root) .. Last_Field (Root) loop
- Put_High_Level_C_Getter (S, F);
+ Put_C_Getter (S, F);
end loop;
- end Put_High_Level_C_Getters;
+ end Put_C_Getters;
--------------------------
-- Put_Union_Membership --
--------------------------
procedure Put_Union_Membership
- (S : in out Sink; Root : Root_Type) is
+ (S : in out Sink; Root : Root_Type; Only_Prototypes : Boolean) is
procedure Put_Ors (T : Abstract_Type);
-- Print the "or" (i.e. "||") of tests whether kind is in each child
@@ -3097,22 +3083,27 @@ package body Gen_IL.Gen is
end Put_Ors;
begin
- Put (S, LF & "// Membership tests for union types" & LF & LF);
+ if not Only_Prototypes then
+ Put (S, LF & "// Membership tests for union types" & LF & LF);
+ end if;
for T in First_Abstract (Root) .. Last_Abstract (Root) loop
if Type_Table (T) /= null and then Type_Table (T).Is_Union then
Put (S, "INLINE Boolean" & LF);
Put (S, "Is_In_" & Image (T) & " (" &
- Node_Or_Entity (Root) & "_Kind kind)" & LF);
+ Node_Or_Entity (Root) & "_Kind kind)" &
+ (if Only_Prototypes then ";" else "") & LF);
- Put (S, "{" & LF);
- Increase_Indent (S, 3);
- Put (S, "return" & LF);
- Increase_Indent (S, 3);
- Put_Ors (T);
- Decrease_Indent (S, 3);
- Decrease_Indent (S, 3);
- Put (S, ";" & LF & "}" & LF);
+ if not Only_Prototypes then
+ Put (S, "{" & LF);
+ Increase_Indent (S, 3);
+ Put (S, "return" & LF);
+ Increase_Indent (S, 3);
+ Put_Ors (T);
+ Decrease_Indent (S, 3);
+ Decrease_Indent (S, 3);
+ Put (S, ";" & LF & "}" & LF);
+ end if;
Put (S, "" & LF);
end if;
@@ -3134,16 +3125,24 @@ package body Gen_IL.Gen is
Put (S, "typedef Boolean Flag;" & LF & LF);
+ Put (S, "#define N_Head " & N_Head & LF);
+ Put (S, "" & LF);
+ Put (S, "typedef struct Node_Header {" & LF);
+ Increase_Indent (S, 2);
+ Put (S, "any_slot Slots[N_Head];" & LF);
+ Put (S, "Field_Offset Offset;" & LF);
+ Decrease_Indent (S, 2);
+ Put (S, "} Node_Header;" & LF & LF);
+
+ Put (S, "extern Node_Header *Node_Offsets_Ptr;" & LF);
+ Put (S, "extern any_slot *Slots_Ptr;" & LF & LF);
+
Put_C_Type_And_Subtypes (S, Node_Kind);
Put (S, "// Getters corresponding to instantiations of Atree.Get_n_Bit_Field"
& LF & LF);
- for T in Special_Type loop
- Put_Low_Level_C_Getter (S, T);
- end loop;
-
- Put_High_Level_C_Getters (S, Node_Kind);
+ Put_C_Getters (S, Node_Kind);
Put (S, "#ifdef __cplusplus" & LF);
Put (S, "}" & LF);
@@ -3198,11 +3197,7 @@ package body Gen_IL.Gen is
Put_C_Type_And_Subtypes (S, Entity_Kind);
- -- Note that we do not call Put_Low_Level_C_Getter here. Those are in
- -- sinfo.h, so every file that #includes einfo.h must #include
- -- sinfo.h first.
-
- Put_High_Level_C_Getters (S, Entity_Kind);
+ Put_C_Getters (S, Entity_Kind);
Put (S, "// Abstract type queries" & LF & LF);
diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb
index d77fe7a..fe1af78 100644
--- a/gcc/ada/gen_il-internals.adb
+++ b/gcc/ada/gen_il-internals.adb
@@ -255,7 +255,7 @@ package body Gen_IL.Internals is
begin
case F is
-- Special cases for the same reason as in the above Image
- -- function.
+ -- function for Opt_Type_Enum.
when Alloc_For_BIP_Return =>
return "Alloc_For_BIP_Return";
diff --git a/gcc/ada/gen_il-internals.ads b/gcc/ada/gen_il-internals.ads
index ae448de..a811e0b4 100644
--- a/gcc/ada/gen_il-internals.ads
+++ b/gcc/ada/gen_il-internals.ads
@@ -147,6 +147,9 @@ package Gen_IL.Internals is
-- The default is No_Type_Only, indicating the field is not one of
-- these special "[... only]" ones.
+ Unknown_Offset : constant := -1;
+ -- Initial value of Offset, so we can tell whether it has been set
+
type Field_Info is record
Have_This_Field : Type_Vector;
-- Types that have this field
@@ -162,7 +165,7 @@ package Gen_IL.Internals is
-- Above record the information in the calls to Create_...Field.
-- See Gen_IL.Gen for details.
- Offset : Field_Offset;
+ Offset : Field_Offset'Base range Unknown_Offset .. Field_Offset'Last;
-- Offset of the field from the start of the node, in units of the field
-- size. So if a field is 4 bits in size, it starts at bit number
-- Offset*4 from the start of the node.
@@ -190,11 +193,6 @@ package Gen_IL.Internals is
(Field_Type : Type_Enum) return String is
(if Field_Type = Elist_Id then "No_Elist" else "Uint_0");
- function Invalid_Val
- (Field_Type : Uint_Subtype) return String is
- ("No_Uint");
- -- We could generalize this to other than Uint at some point
-
----------------
subtype Node_Field is
@@ -279,4 +277,344 @@ package Gen_IL.Internals is
-- Return "Node" or "Entity" depending on whether Root = Node_Kind or
-- Entity_Kind.
+ pragma Style_Checks (Off);
+ -- We don't want warnings about wrong casing in the Type_Frequency table;
+ -- this table is not intended to be particularly readable.
+
+ -- The Type_Frequency table shows the frequency of nodes and entity kinds
+ -- printed by -gnatd.A for a large example. It is used in the field offset
+ -- computations for efficiency. Note that N_Defining_Identifier,
+ -- N_Defining_Operator_Symbol, and N_Defining_Character_Literal are set to
+ -- zero, because the Ekind is what matters for those.
+
+ Type_Frequency : constant array (Concrete_Type) of Type_Count :=
+ (N_Identifier => 3496964, -- (0.354) 7 slots
+ N_Defining_Identifier => 0, -- 1468484, -- (0.149) 8 slots
+ N_Integer_Literal => 455415, -- (0.046) 6 slots
+ E_In_Parameter => 391008, -- (0.040) 42 slots
+ N_Attribute_Reference => 330825, -- (0.033) 9 slots
+ N_Expanded_Name => 329509, -- (0.033) 8 slots
+ N_Selected_Component => 328862, -- (0.033) 8 slots
+ N_Parameter_Specification => 321313, -- (0.033) 7 slots
+ E_Void => 173019, -- (0.018) 59 slots
+ N_Explicit_Dereference => 155113, -- (0.016) 8 slots
+ N_Procedure_Call_Statement => 125403, -- (0.013) 8 slots
+ N_Object_Declaration => 115610, -- (0.012) 8 slots
+ E_Component => 108208, -- (0.011) 49 slots
+ N_Procedure_Specification => 106277, -- (0.011) 7 slots
+ E_Procedure => 104063, -- (0.011) 62 slots
+ N_Unchecked_Type_Conversion => 94477, -- (0.010) 7 slots
+ N_Range => 91413, -- (0.009) 6 slots
+ E_Function => 90035, -- (0.009) 62 slots
+ N_Handled_Sequence_Of_Statements => 87930, -- (0.009) 8 slots
+ N_Subprogram_Declaration => 85248, -- (0.009) 7 slots
+ N_Parameter_Association => 81464, -- (0.008) 8 slots
+ N_Indexed_Component => 80049, -- (0.008) 7 slots
+ N_Freeze_Entity => 79904, -- (0.008) 8 slots
+ N_Call_Marker => 79521, -- (0.008) 4 slots
+ N_Assignment_Statement => 76554, -- (0.008) 8 slots
+ N_Function_Specification => 76052, -- (0.008) 7 slots
+ N_Function_Call => 75028, -- (0.008) 9 slots
+ N_Op_Eq => 74874, -- (0.008) 8 slots
+ E_Constant => 66667, -- (0.007) 47 slots
+ N_If_Statement => 60066, -- (0.006) 8 slots
+ N_Component_Association => 54642, -- (0.006) 7 slots
+ N_Subprogram_Body => 53805, -- (0.005) 10 slots
+ N_Type_Conversion => 53383, -- (0.005) 7 slots
+ E_In_Out_Parameter => 52936, -- (0.005) 38 slots
+ N_Simple_Return_Statement => 52436, -- (0.005) 7 slots
+ N_Subtype_Indication => 49535, -- (0.005) 6 slots
+ N_Raise_Constraint_Error => 49069, -- (0.005) 6 slots
+ N_Null => 46850, -- (0.005) 5 slots
+ N_Itype_Reference => 45422, -- (0.005) 4 slots
+ E_Anonymous_Access_Type => 45149, -- (0.005) 44 slots
+ N_And_Then => 44721, -- (0.005) 8 slots
+ N_Block_Statement => 44328, -- (0.004) 10 slots
+ N_Subtype_Declaration => 43149, -- (0.004) 6 slots
+ N_Op_Not => 40531, -- (0.004) 7 slots
+ E_Array_Subtype => 40051, -- (0.004) 50 slots
+ N_Expression_With_Actions => 36726, -- (0.004) 7 slots
+ E_Access_Subprogram_Type => 36700, -- (0.004) 45 slots
+ E_Signed_Integer_Subtype => 36659, -- (0.004) 43 slots
+ N_String_Literal => 34815, -- (0.004) 7 slots
+ N_Aggregate => 33899, -- (0.003) 8 slots
+ N_Index_Or_Discriminant_Constraint => 33546, -- (0.003) 4 slots
+ E_Variable => 33102, -- (0.003) 55 slots
+ E_Block => 32829, -- (0.003) 58 slots
+ N_Op_Ne => 32127, -- (0.003) 8 slots
+ N_Pragma_Argument_Association => 31504, -- (0.003) 7 slots
+ N_Null_Statement => 30816, -- (0.003) 5 slots
+ N_Aspect_Specification => 29667, -- (0.003) 9 slots
+ N_Pragma => 28317, -- (0.003) 9 slots
+ N_Generic_Association => 26297, -- (0.003) 8 slots
+ N_Formal_Concrete_Subprogram_Declaration => 25843, -- (0.003) 6 slots
+ N_Op_Lt => 25328, -- (0.003) 8 slots
+ E_String_Literal_Subtype => 25272, -- (0.003) 48 slots
+ N_Full_Type_Declaration => 25258, -- (0.003) 7 slots
+ N_With_Clause => 24370, -- (0.002) 9 slots
+ N_Op_Add => 23839, -- (0.002) 8 slots
+ E_Subprogram_Body => 23790, -- (0.002) 42 slots
+ E_Return_Statement => 23098, -- (0.002) 51 slots
+ N_Or_Else => 22858, -- (0.002) 8 slots
+ N_Implicit_Label_Declaration => 21687, -- (0.002) 5 slots
+ N_Others_Choice => 21579, -- (0.002) 4 slots
+ E_Out_Parameter => 21513, -- (0.002) 38 slots
+ N_Op_Subtract => 21441, -- (0.002) 8 slots
+ N_Op_Ge => 21116, -- (0.002) 8 slots
+ N_Component_Definition => 21075, -- (0.002) 7 slots
+ N_Case_Statement_Alternative => 19664, -- (0.002) 8 slots
+ N_Loop_Statement => 19507, -- (0.002) 9 slots
+ E_Package => 19029, -- (0.002) 53 slots
+ N_Op_Gt => 18619, -- (0.002) 8 slots
+ N_Op_Le => 16564, -- (0.002) 8 slots
+ N_Formal_Object_Declaration => 16219, -- (0.002) 7 slots
+ E_Discriminant => 16091, -- (0.002) 56 slots
+ N_Component_Declaration => 15858, -- (0.002) 7 slots
+ N_Iteration_Scheme => 15719, -- (0.002) 8 slots
+ N_Access_To_Object_Definition => 14875, -- (0.002) 5 slots
+ E_Record_Subtype => 14569, -- (0.001) 52 slots
+ N_Generic_Subprogram_Declaration => 14320, -- (0.001) 7 slots
+ N_Package_Specification => 13323, -- (0.001) 8 slots
+ N_Exception_Handler => 12841, -- (0.001) 8 slots
+ E_Enumeration_Literal => 11608, -- (0.001) 42 slots
+ N_Subprogram_Renaming_Declaration => 10991, -- (0.001) 9 slots
+ N_In => 10794, -- (0.001) 8 slots
+ E_Allocator_Type => 10751, -- (0.001) 44 slots
+ E_General_Access_Type => 10451, -- (0.001) 44 slots
+ E_Generic_Procedure => 9837, -- (0.001) 41 slots
+ N_Package_Renaming_Declaration => 9395, -- (0.001) 8 slots
+ N_Access_Definition => 9388, -- (0.001) 6 slots
+ N_Qualified_Expression => 9012, -- (0.001) 7 slots
+ E_Enumeration_Subtype => 8560, -- (0.001) 46 slots
+ N_Allocator => 8474, -- (0.001) 8 slots
+ N_Package_Declaration => 8099, -- (0.001) 10 slots
+ N_Formal_Type_Declaration => 7964, -- (0.001) 7 slots
+ N_Exit_Statement => 7960, -- (0.001) 8 slots
+ N_Component_List => 7829, -- (0.001) 5 slots
+ N_Defining_Operator_Symbol => 0, -- 7525, -- (0.001) 8 slots
+ N_Case_Statement => 7271, -- (0.001) 7 slots
+ N_Expression_Function => 7242, -- (0.001) 9 slots
+ N_Loop_Parameter_Specification => 7042, -- (0.001) 7 slots
+ N_Character_Literal => 6842, -- (0.001) 7 slots
+ N_Op_Concat => 6565, -- (0.001) 8 slots
+ N_Not_In => 6341, -- (0.001) 8 slots
+ N_Label => 6133, -- (0.001) 9 slots
+ N_Goto_Statement => 6133, -- (0.001) 8 slots
+ E_Label => 6133, -- (0.001) 57 slots
+ E_Loop => 6008, -- (0.001) 41 slots
+ N_Generic_Package_Declaration => 5808, -- (0.001) 10 slots
+ N_If_Expression => 5800, -- (0.001) 7 slots
+ N_Record_Definition => 5628, -- (0.001) 7 slots
+ N_Slice => 5461, -- (0.001) 7 slots
+ N_Reference => 5332, -- (0.001) 7 slots
+ E_Generic_Package => 5268, -- (0.001) 59 slots
+ E_Record_Type => 4838, -- (0.000) 51 slots
+ N_Raise_Program_Error => 4675, -- (0.000) 6 slots
+ N_Raise_Statement => 4628, -- (0.000) 8 slots
+ N_Use_Type_Clause => 4487, -- (0.000) 9 slots
+ E_Array_Type => 4325, -- (0.000) 48 slots
+ E_Operator => 4308, -- (0.000) 55 slots
+ N_Freeze_Generic_Entity => 4249, -- (0.000) 4 slots
+ N_Constrained_Array_Definition => 4244, -- (0.000) 5 slots
+ N_Object_Renaming_Declaration => 4067, -- (0.000) 8 slots
+ N_Formal_Private_Type_Definition => 4018, -- (0.000) 8 slots
+ E_Loop_Parameter => 3870, -- (0.000) 38 slots
+ N_Real_Literal => 3759, -- (0.000) 7 slots
+ N_Attribute_Definition_Clause => 3724, -- (0.000) 8 slots
+ N_Exception_Renaming_Declaration => 3697, -- (0.000) 8 slots
+ E_Class_Wide_Type => 3674, -- (0.000) 48 slots
+ E_Exception => 3632, -- (0.000) 24 slots
+ N_Range_Constraint => 3506, -- (0.000) 4 slots
+ E_Access_Type => 3487, -- (0.000) 44 slots
+ E_Subprogram_Type => 3248, -- (0.000) 47 slots
+ N_Package_Instantiation => 3005, -- (0.000) 8 slots
+ E_Access_Attribute_Type => 2959, -- (0.000) 44 slots
+ N_Op_And => 2957, -- (0.000) 8 slots
+ E_Generic_In_Parameter => 2704, -- (0.000) 31 slots
+ N_Derived_Type_Definition => 2688, -- (0.000) 7 slots
+ N_Variant => 2535, -- (0.000) 8 slots
+ E_Record_Subtype_With_Private => 2327, -- (0.000) 50 slots
+ N_Private_Type_Declaration => 2287, -- (0.000) 6 slots
+ E_Private_Type => 1890, -- (0.000) 48 slots
+ N_Discriminant_Specification => 1864, -- (0.000) 7 slots
+ N_Procedure_Instantiation => 1659, -- (0.000) 8 slots
+ N_Op_Multiply => 1634, -- (0.000) 8 slots
+ E_Access_Subtype => 1606, -- (0.000) 44 slots
+ N_Defining_Program_Unit_Name => 1463, -- (0.000) 8 slots
+ N_Number_Declaration => 1461, -- (0.000) 7 slots
+ E_Named_Integer => 1430, -- (0.000) 19 slots
+ N_Use_Package_Clause => 1369, -- (0.000) 9 slots
+ N_Compilation_Unit_Aux => 1341, -- (0.000) 8 slots
+ N_Compilation_Unit => 1341, -- (0.000) 8 slots
+ N_Elsif_Part => 1331, -- (0.000) 7 slots
+ N_Operator_Symbol => 1305, -- (0.000) 7 slots
+ E_Limited_Private_Type => 1299, -- (0.000) 48 slots
+ E_Generic_Function => 1292, -- (0.000) 41 slots
+ E_Enumeration_Type => 1186, -- (0.000) 47 slots
+ N_Enumeration_Type_Definition => 1169, -- (0.000) 6 slots
+ N_Unchecked_Expression => 1112, -- (0.000) 7 slots
+ N_Op_Or => 1107, -- (0.000) 8 slots
+ N_Designator => 1100, -- (0.000) 9 slots
+ N_Formal_Discrete_Type_Definition => 1086, -- (0.000) 4 slots
+ N_Variant_Part => 1072, -- (0.000) 8 slots
+ N_Formal_Package_Declaration => 1047, -- (0.000) 8 slots
+ N_Quantified_Expression => 1033, -- (0.000) 8 slots
+ E_Record_Type_With_Private => 1017, -- (0.000) 51 slots
+ N_Package_Body => 999, -- (0.000) 9 slots
+ N_Unconstrained_Array_Definition => 973, -- (0.000) 5 slots
+ E_Private_Subtype => 971, -- (0.000) 48 slots
+ N_Incomplete_Type_Declaration => 863, -- (0.000) 6 slots
+ E_Incomplete_Type => 863, -- (0.000) 48 slots
+ N_Contract => 859, -- (0.000) 6 slots
+ E_Package_Body => 852, -- (0.000) 46 slots
+ N_Extended_Return_Statement => 801, -- (0.000) 8 slots
+ N_Op_Divide => 724, -- (0.000) 8 slots
+ N_Extension_Aggregate => 718, -- (0.000) 8 slots
+ N_Function_Instantiation => 642, -- (0.000) 8 slots
+ N_Exception_Declaration => 594, -- (0.000) 7 slots
+ N_Discriminant_Association => 552, -- (0.000) 7 slots
+ N_Iterator_Specification => 543, -- (0.000) 8 slots
+ N_Private_Extension_Declaration => 540, -- (0.000) 8 slots
+ N_Formal_Signed_Integer_Type_Definition => 512, -- (0.000) 4 slots
+ E_Modular_Integer_Subtype => 490, -- (0.000) 44 slots
+ N_Component_Clause => 468, -- (0.000) 7 slots
+ E_Signed_Integer_Type => 399, -- (0.000) 43 slots
+ N_Op_Minus => 356, -- (0.000) 7 slots
+ N_Raise_Expression => 337, -- (0.000) 8 slots
+ N_Case_Expression_Alternative => 336, -- (0.000) 8 slots
+ N_Op_Expon => 280, -- (0.000) 8 slots
+ N_Abstract_Subprogram_Declaration => 250, -- (0.000) 6 slots
+ E_Modular_Integer_Type => 232, -- (0.000) 44 slots
+ N_Modular_Type_Definition => 214, -- (0.000) 7 slots
+ N_Compound_Statement => 212, -- (0.000) 6 slots
+ N_Free_Statement => 209, -- (0.000) 8 slots
+ N_Record_Representation_Clause => 197, -- (0.000) 9 slots
+ N_Access_Procedure_Definition => 195, -- (0.000) 6 slots
+ E_Limited_Private_Subtype => 178, -- (0.000) 48 slots
+ N_Access_Function_Definition => 172, -- (0.000) 7 slots
+ N_Op_Mod => 163, -- (0.000) 8 slots
+ N_Validate_Unchecked_Conversion => 156, -- (0.000) 5 slots
+ E_Anonymous_Access_Subprogram_Type => 155, -- (0.000) 44 slots
+ N_Op_Rem => 147, -- (0.000) 8 slots
+ N_Formal_Incomplete_Type_Definition => 140, -- (0.000) 4 slots
+ N_Signed_Integer_Type_Definition => 137, -- (0.000) 6 slots
+ N_Case_Expression => 132, -- (0.000) 7 slots
+ N_Op_Plus => 129, -- (0.000) 7 slots
+ E_Incomplete_Subtype => 129, -- (0.000) 48 slots
+ N_Op_Abs => 119, -- (0.000) 7 slots
+ N_Op_Shift_Right => 109, -- (0.000) 8 slots
+ E_Floating_Point_Subtype => 94, -- (0.000) 43 slots
+ N_Op_Shift_Left => 72, -- (0.000) 8 slots
+ E_Floating_Point_Type => 59, -- (0.000) 43 slots
+ N_Formal_Derived_Type_Definition => 53, -- (0.000) 7 slots
+ N_Formal_Floating_Point_Definition => 40, -- (0.000) 4 slots
+ N_Defining_Character_Literal => 0, -- 36, -- (0.000) 8 slots
+ N_Formal_Modular_Type_Definition => 27, -- (0.000) 4 slots
+ E_Ordinary_Fixed_Point_Subtype => 23, -- (0.000) 44 slots
+ E_Abstract_State => 22, -- (0.000) 48 slots
+ E_Named_Real => 20, -- (0.000) 19 slots
+ N_Floating_Point_Definition => 19, -- (0.000) 6 slots
+ N_Subunit => 17, -- (0.000) 8 slots
+ N_Enumeration_Representation_Clause => 17, -- (0.000) 9 slots
+ N_Entry_Declaration => 17, -- (0.000) 7 slots
+ N_Subprogram_Body_Stub => 16, -- (0.000) 8 slots
+ N_Unused_At_Start => 15, -- (0.000) 4 slots
+ E_Entry => 14, -- (0.000) 42 slots
+ N_Formal_Ordinary_Fixed_Point_Definition => 12, -- (0.000) 4 slots
+ E_Class_Wide_Subtype => 9, -- (0.000) 52 slots
+ E_Protected_Subtype => 8, -- (0.000) 48 slots
+ E_Ordinary_Fixed_Point_Type => 8, -- (0.000) 44 slots
+ N_Op_Xor => 7, -- (0.000) 8 slots
+ E_Generic_In_Out_Parameter => 7, -- (0.000) 31 slots
+ N_Protected_Type_Declaration => 6, -- (0.000) 8 slots
+ N_Protected_Definition => 6, -- (0.000) 8 slots
+ N_Task_Type_Declaration => 4, -- (0.000) 8 slots
+ N_Task_Definition => 4, -- (0.000) 8 slots
+ N_Protected_Body => 4, -- (0.000) 9 slots
+ E_Task_Subtype => 4, -- (0.000) 50 slots
+ E_Protected_Type => 4, -- (0.000) 49 slots
+ E_Access_Protected_Subprogram_Type => 4, -- (0.000) 45 slots
+ N_Entry_Call_Statement => 3, -- (0.000) 8 slots
+ E_Task_Type => 3, -- (0.000) 50 slots
+ N_Raise_Storage_Error => 2, -- (0.000) 6 slots
+ N_Package_Body_Stub => 2, -- (0.000) 8 slots
+ N_Generic_Procedure_Renaming_Declaration => 2, -- (0.000) 8 slots
+ N_Task_Body => 1, -- (0.000) 10 slots
+ N_Single_Protected_Declaration => 1, -- (0.000) 8 slots
+ N_Real_Range_Specification => 1, -- (0.000) 6 slots
+ N_Ordinary_Fixed_Point_Definition => 1, -- (0.000) 6 slots
+ N_Error => 1, -- (0.000) 6 slots
+ N_Entry_Body_Formal_Part => 1, -- (0.000) 6 slots
+ N_Entry_Body => 1, -- (0.000) 10 slots
+ N_Empty => 1, -- (0.000) 6 slots
+ N_Delay_Relative_Statement => 1, -- (0.000) 7 slots
+ E_Protected_Body => 1, -- (0.000) 35 slots
+
+ Between_Concrete_Node_And_Concrete_Entity_Types => 0,
+
+ -- The rest had frequency 0 (i.e. no such nodes were created in the
+ -- example), but we set them to 1, so we won't lose information when
+ -- multiplying. We use "others", so that if new node types are added,
+ -- we don't have to modify the table; new node types are unlikely to
+ -- be very common.
+
+ others => 1
+ -- N_Variable_Reference_Marker => 0, (0.000) 4 slots
+ -- N_Unused_At_End => 0, (0.000) 4 slots
+ -- N_Triggering_Alternative => 0, (0.000) 6 slots
+ -- N_Timed_Entry_Call => 0, (0.000) 5 slots
+ -- N_Terminate_Alternative => 0, (0.000) 6 slots
+ -- N_Task_Body_Stub => 0, (0.000) 8 slots
+ -- N_Target_Name => 0, (0.000) 5 slots
+ -- N_Single_Task_Declaration => 0, (0.000) 8 slots
+ -- N_Selective_Accept => 0, (0.000) 5 slots
+ -- N_Scil_Membership_Test => 0, (0.000) 5 slots
+ -- N_Scil_Dispatch_Table_Tag_Init => 0, (0.000) 4 slots
+ -- N_Scil_Dispatching_Call => 0, (0.000) 6 slots
+ -- N_Return_When_Statement => 0, (0.000) 7 slots
+ -- N_Requeue_Statement => 0, (0.000) 8 slots
+ -- N_Raise_When_Statement => 0, (0.000) 8 slots
+ -- N_Push_Storage_Error_Label => 0, (0.000) 4 slots
+ -- N_Push_Program_Error_Label => 0, (0.000) 4 slots
+ -- N_Push_Constraint_Error_Label => 0, (0.000) 4 slots
+ -- N_Protected_Body_Stub => 0, (0.000) 8 slots
+ -- N_Pop_Storage_Error_Label => 0, (0.000) 4 slots
+ -- N_Pop_Program_Error_Label => 0, (0.000) 4 slots
+ -- N_Pop_Constraint_Error_Label => 0, (0.000) 4 slots
+ -- N_Op_Shift_Right_Arithmetic => 0, (0.000) 8 slots
+ -- N_Op_Rotate_Right => 0, (0.000) 8 slots
+ -- N_Op_Rotate_Left => 0, (0.000) 8 slots
+ -- N_Mod_Clause => 0, (0.000) 7 slots
+ -- N_Iterated_Element_Association => 0, (0.000) 8 slots
+ -- N_Iterated_Component_Association => 0, (0.000) 8 slots
+ -- N_Goto_When_Statement => 0, (0.000) 8 slots
+ -- N_Generic_Package_Renaming_Declaration => 0, (0.000) 8 slots
+ -- N_Generic_Function_Renaming_Declaration => 0, (0.000) 8 slots
+ -- N_Formal_Decimal_Fixed_Point_Definition => 0, (0.000) 4 slots
+ -- N_Formal_Abstract_Subprogram_Declaration => 0, (0.000) 6 slots
+ -- N_Entry_Index_Specification => 0, (0.000) 7 slots
+ -- N_Entry_Call_Alternative => 0, (0.000) 6 slots
+ -- N_Digits_Constraint => 0, (0.000) 6 slots
+ -- N_Delta_Constraint => 0, (0.000) 6 slots
+ -- N_Delta_Aggregate => 0, (0.000) 8 slots
+ -- N_Delay_Until_Statement => 0, (0.000) 7 slots
+ -- N_Delay_Alternative => 0, (0.000) 7 slots
+ -- N_Decimal_Fixed_Point_Definition => 0, (0.000) 6 slots
+ -- N_Conditional_Entry_Call => 0, (0.000) 5 slots
+ -- N_Code_Statement => 0, (0.000) 7 slots
+ -- N_At_Clause => 0, (0.000) 9 slots
+ -- N_Asynchronous_Select => 0, (0.000) 5 slots
+ -- N_Accept_Statement => 0, (0.000) 8 slots
+ -- N_Accept_Alternative => 0, (0.000) 8 slots
+ -- N_Abort_Statement => 0, (0.000) 4 slots
+ -- N_Abortable_Part => 0, (0.000) 5 slots
+ -- E_Task_Body => 0, (0.000) 39 slots
+ -- E_Exception_Type => 0, (0.000) 45 slots
+ -- E_Entry_Index_Parameter => 0, (0.000) 19 slots
+ -- E_Entry_Family => 0, (0.000) 42 slots
+ -- E_Decimal_Fixed_Point_Type => 0, (0.000) 52 slots
+ -- E_Decimal_Fixed_Point_Subtype => 0, (0.000) 52 slots
+ -- E_Anonymous_Access_Protected_Subprogram_Type => 0, (0.000) 45 slots
+ ); -- Type_Frequency
+
end Gen_IL.Internals;
diff --git a/gcc/ada/gen_il-types.ads b/gcc/ada/gen_il-types.ads
index 321eec6..97b9dd2 100644
--- a/gcc/ada/gen_il-types.ads
+++ b/gcc/ada/gen_il-types.ads
@@ -77,6 +77,7 @@ package Gen_IL.Types is
Node_Kind, -- root of node type hierarchy
N_Access_To_Subprogram_Definition,
+ N_Alternative,
N_Array_Type_Definition,
N_Binary_Op,
N_Body_Stub,
@@ -84,13 +85,21 @@ package Gen_IL.Types is
N_Delay_Statement,
N_Direct_Name,
N_Entity,
+ N_Entity_Name,
N_Formal_Subprogram_Declaration,
N_Generic_Declaration,
N_Generic_Instantiation,
N_Generic_Renaming_Declaration,
+ N_Has_Bounds,
N_Has_Chars,
+ N_Has_Condition,
N_Has_Entity,
N_Has_Etype,
+ N_Is_Case_Choice,
+ N_Is_Decl,
+ N_Is_Exception_Choice,
+ N_Is_Index,
+ N_Is_Range,
N_Multiplying_Operator,
N_Later_Decl_Item,
N_Membership_Test,
@@ -111,7 +120,6 @@ package Gen_IL.Types is
N_Statement_Other_Than_Procedure_Call,
N_Subprogram_Call,
N_Subprogram_Instantiation,
- N_Has_Condition,
N_Subexpr,
N_Subprogram_Specification,
N_Unary_Op,
@@ -144,6 +152,7 @@ package Gen_IL.Types is
Elementary_Kind,
Enumeration_Kind,
Entry_Kind,
+ Evaluable_Kind,
Exception_Or_Object_Kind,
Fixed_Point_Kind,
Float_Kind,
@@ -151,6 +160,7 @@ package Gen_IL.Types is
Formal_Object_Kind,
Generic_Subprogram_Kind,
Generic_Unit_Kind,
+ Global_Name_Kind,
Incomplete_Kind,
Incomplete_Or_Private_Kind,
Integer_Kind,
@@ -167,8 +177,9 @@ package Gen_IL.Types is
Record_Kind,
Record_Field_Kind,
Scalar_Kind,
- Subprogram_Kind,
Signed_Integer_Kind,
+ Subprogram_Type_Or_Kind,
+ Subprogram_Kind,
Task_Kind,
Type_Kind,
Void_Or_Type_Kind,
diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb
index 42ea0f5..1720fe0 100644
--- a/gcc/ada/ghost.adb
+++ b/gcc/ada/ghost.adb
@@ -584,6 +584,15 @@ package body Ghost is
-- Start of processing for Check_Ghost_Context
begin
+ -- Class-wide pre/postconditions of ignored pragmas are preanalyzed
+ -- to report errors on wrong conditions; however, ignored pragmas may
+ -- also have references to ghost entities and we must disable checking
+ -- their context to avoid reporting spurious errors.
+
+ if Inside_Class_Condition_Preanalysis then
+ return;
+ end if;
+
-- Once it has been established that the reference to the Ghost entity
-- is within a suitable context, ensure that the policy at the point of
-- declaration and at the point of use match.
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index 6f65d74..55f9efa 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -1616,7 +1616,14 @@ begin
Errout.Finalize (Last_Call => True);
Errout.Output_Messages;
- Repinfo.List_Rep_Info (Ttypes.Bytes_Big_Endian);
+
+ -- Back annotation of representation info is not done in CodePeer and
+ -- SPARK modes.
+
+ if not (Generate_SCIL or GNATprove_Mode) then
+ Repinfo.List_Rep_Info (Ttypes.Bytes_Big_Endian);
+ end if;
+
Inline.List_Inlining_Info;
-- Only write the library if the backend did not generate any error
@@ -1688,6 +1695,10 @@ begin
<<End_Of_Program>>
+ if Debug_Flag_Dot_AA then
+ Atree.Print_Statistics;
+ end if;
+
-- The outer exception handler handles an unrecoverable error
exception
diff --git a/gcc/ada/gnat_cuda.adb b/gcc/ada/gnat_cuda.adb
index b7ce953..a1739be 100644
--- a/gcc/ada/gnat_cuda.adb
+++ b/gcc/ada/gnat_cuda.adb
@@ -25,20 +25,25 @@
-- This package defines CUDA-specific datastructures and functions.
+with Atree; use Atree;
with Debug; use Debug;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
with Elists; use Elists;
+with Errout; use Errout;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Rtsfind; use Rtsfind;
-with Sinfo; use Sinfo;
+with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Util; use Sem_Util;
with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo; use Sinfo;
+with Snames; use Snames;
with Stringt; use Stringt;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
-with Sem; use Sem;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
with GNAT.HTable;
@@ -54,6 +59,18 @@ package body GNAT_CUDA is
function Hash (F : Entity_Id) return Hash_Range;
-- Hash function for hash table
+ package CUDA_Device_Entities_Table is new
+ GNAT.HTable.Simple_HTable
+ (Header_Num => Hash_Range,
+ Element => Elist_Id,
+ No_Element => No_Elist,
+ Key => Entity_Id,
+ Hash => Hash,
+ Equal => "=");
+ -- The keys of this table are package entities whose bodies contain at
+ -- least one procedure marked with aspect CUDA_Device. The values are
+ -- Elists of the marked entities.
+
package CUDA_Kernels_Table is new
GNAT.HTable.Simple_HTable
(Header_Num => Hash_Range,
@@ -66,17 +83,79 @@ package body GNAT_CUDA is
-- least one procedure marked with aspect CUDA_Global. The values are
-- Elists of the marked procedures.
+ procedure Build_And_Insert_CUDA_Initialization (N : Node_Id);
+ -- Builds declarations necessary for CUDA initialization and inserts them
+ -- in N, the package body that contains CUDA_Global nodes. These
+ -- declarations are:
+ --
+ -- * A symbol to hold the pointer P to the CUDA fat binary.
+ --
+ -- * A type definition T for a wrapper that contains the pointer to the
+ -- CUDA fat binary.
+ --
+ -- * An object of the aforementioned type to hold the aforementioned
+ -- pointer.
+ --
+ -- * For each CUDA_Global procedure in the package, a declaration of a C
+ -- string containing the function's name.
+ --
+ -- * A procedure that takes care of calling CUDA functions that register
+ -- CUDA_Global procedures with the runtime.
+
+ procedure Empty_CUDA_Global_Subprograms (Pack_Id : Entity_Id);
+ -- For all subprograms marked CUDA_Global in Pack_Id, remove declarations
+ -- and replace statements with a single null statement.
+ -- This is required because CUDA_Global subprograms could be referring to
+ -- device-only symbols, which would result in unknown symbols at link time
+ -- if kept around.
+ -- We choose to empty CUDA_Global subprograms rather than completely
+ -- removing them from the package because registering CUDA_Global
+ -- subprograms with the CUDA runtime on the host requires knowing the
+ -- subprogram's host-side address.
+
+ function Get_CUDA_Device_Entities (Pack_Id : Entity_Id) return Elist_Id;
+ -- Returns an Elist of all entities marked with pragma CUDA_Device that
+ -- are declared within package body Pack_Body. Returns No_Elist if Pack_Id
+ -- does not contain such entities.
+
function Get_CUDA_Kernels (Pack_Id : Entity_Id) return Elist_Id;
-- Returns an Elist of all procedures marked with pragma CUDA_Global that
-- are declared within package body Pack_Body. Returns No_Elist if Pack_Id
-- does not contain such procedures.
+ procedure Remove_CUDA_Device_Entities (Pack_Id : Entity_Id);
+ -- Removes all entities marked with the CUDA_Device pragma from package
+ -- Pack_Id. Must only be called when compiling for the host.
+
+ procedure Set_CUDA_Device_Entities
+ (Pack_Id : Entity_Id;
+ E : Elist_Id);
+ -- Stores E as the list of CUDA_Device entities belonging to the package
+ -- entity Pack_Id. Pack_Id must not have a list of device entities.
+
procedure Set_CUDA_Kernels
(Pack_Id : Entity_Id;
Kernels : Elist_Id);
-- Stores Kernels as the list of kernels belonging to the package entity
-- Pack_Id. Pack_Id must not have a list of kernels.
+ ----------------------------
+ -- Add_CUDA_Device_Entity --
+ ----------------------------
+
+ procedure Add_CUDA_Device_Entity
+ (Pack_Id : Entity_Id;
+ E : Entity_Id)
+ is
+ Device_Entities : Elist_Id := Get_CUDA_Device_Entities (Pack_Id);
+ begin
+ if Device_Entities = No_Elist then
+ Device_Entities := New_Elmt_List;
+ Set_CUDA_Device_Entities (Pack_Id, Device_Entities);
+ end if;
+ Append_Elmt (E, Device_Entities);
+ end Add_CUDA_Device_Entity;
+
---------------------
-- Add_CUDA_Kernel --
---------------------
@@ -94,6 +173,81 @@ package body GNAT_CUDA is
Append_Elmt (Kernel, Kernels);
end Add_CUDA_Kernel;
+ -----------------------------------
+ -- Empty_CUDA_Global_Subprograms --
+ -----------------------------------
+
+ procedure Empty_CUDA_Global_Subprograms (Pack_Id : Entity_Id) is
+ Spec_Id : constant Node_Id := Corresponding_Spec (Pack_Id);
+ Kernels : constant Elist_Id := Get_CUDA_Kernels (Spec_Id);
+ Kernel_Elm : Elmt_Id;
+ Kernel : Entity_Id;
+ Kernel_Body : Node_Id;
+ Null_Body : Entity_Id;
+ Loc : Source_Ptr;
+ begin
+ -- It is an error to empty CUDA_Global subprograms when not compiling
+ -- for the host.
+ pragma Assert (Debug_Flag_Underscore_C);
+
+ if No (Kernels) then
+ return;
+ end if;
+
+ Kernel_Elm := First_Elmt (Kernels);
+ while Present (Kernel_Elm) loop
+ Kernel := Node (Kernel_Elm);
+ Kernel_Body := Subprogram_Body (Kernel);
+ Loc := Sloc (Kernel_Body);
+
+ Null_Body := Make_Subprogram_Body (Loc,
+ Specification => Subprogram_Specification (Kernel),
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Make_Null_Statement (Loc))));
+
+ Rewrite (Kernel_Body, Null_Body);
+
+ Next_Elmt (Kernel_Elm);
+ end loop;
+ end Empty_CUDA_Global_Subprograms;
+
+ -------------------------
+ -- Expand_CUDA_Package --
+ -------------------------
+
+ procedure Expand_CUDA_Package (N : Node_Id) is
+ begin
+
+ -- If not compiling for the host, do not do anything.
+
+ if not Debug_Flag_Underscore_C then
+ return;
+ end if;
+
+ -- Remove the content (both declarations and statements) of CUDA_Global
+ -- procedures. This is required because CUDA_Global functions could be
+ -- referencing entities available only on the device, which would result
+ -- in unknown symbol errors at link time.
+
+ Empty_CUDA_Global_Subprograms (N);
+
+ -- Remove CUDA_Device entities (except if they are also CUDA_Host), as
+ -- they can only be referenced from the device and might reference
+ -- device-only symbols.
+
+ Remove_CUDA_Device_Entities
+ (Package_Specification (Corresponding_Spec (N)));
+
+ -- If procedures marked with CUDA_Global have been defined within N,
+ -- we need to register them with the CUDA runtime at program startup.
+ -- This requires multiple declarations and function calls which need
+ -- to be appended to N's declarations.
+
+ Build_And_Insert_CUDA_Initialization (N);
+ end Expand_CUDA_Package;
+
----------
-- Hash --
----------
@@ -103,6 +257,15 @@ package body GNAT_CUDA is
return Hash_Range (F mod 511);
end Hash;
+ ------------------------------
+ -- Get_CUDA_Device_Entities --
+ ------------------------------
+
+ function Get_CUDA_Device_Entities (Pack_Id : Entity_Id) return Elist_Id is
+ begin
+ return CUDA_Device_Entities_Table.Get (Pack_Id);
+ end Get_CUDA_Device_Entities;
+
----------------------
-- Get_CUDA_Kernels --
----------------------
@@ -524,7 +687,7 @@ package body GNAT_CUDA is
-- Start of processing for Build_And_Insert_CUDA_Initialization
begin
- if CUDA_Node_List = No_Elist or not Debug_Flag_Underscore_C then
+ if CUDA_Node_List = No_Elist then
return;
end if;
@@ -569,9 +732,70 @@ package body GNAT_CUDA is
Analyze (New_Stmt);
end Build_And_Insert_CUDA_Initialization;
- --------------------
- -- Set_CUDA_Nodes --
- --------------------
+ ---------------------------------
+ -- Remove_CUDA_Device_Entities --
+ ---------------------------------
+
+ procedure Remove_CUDA_Device_Entities (Pack_Id : Entity_Id) is
+ Device_Entities : constant Elist_Id :=
+ Get_CUDA_Device_Entities (Pack_Id);
+ Device_Elmt : Elmt_Id;
+ Device_Entity : Entity_Id;
+ Bod : Node_Id;
+ begin
+ pragma Assert (Debug_Flag_Underscore_C);
+
+ if Device_Entities = No_Elist then
+ return;
+ end if;
+
+ Device_Elmt := First_Elmt (Device_Entities);
+ while Present (Device_Elmt) loop
+ Device_Entity := Node (Device_Elmt);
+ Next_Elmt (Device_Elmt);
+
+ case Ekind (Device_Entity) is
+ when E_Function | E_Procedure =>
+ Bod := Subprogram_Body (Device_Entity);
+
+ if Nkind (Parent (Bod)) = N_Subunit
+ and then Present (Corresponding_Stub (Parent (Bod)))
+ then
+ Error_Msg_N
+ ("Cuda_Device not suported on separate subprograms",
+ Corresponding_Stub (Parent (Bod)));
+ else
+ Remove (Bod);
+ Remove (Subprogram_Spec (Device_Entity));
+ end if;
+
+ when E_Variable | E_Constant =>
+ Remove (Declaration_Node (Device_Entity));
+
+ when others =>
+ pragma Assert (False);
+ end case;
+
+ Remove_Entity_And_Homonym (Device_Entity);
+ end loop;
+ end Remove_CUDA_Device_Entities;
+
+ ------------------------------
+ -- Set_CUDA_Device_Entities --
+ ------------------------------
+
+ procedure Set_CUDA_Device_Entities
+ (Pack_Id : Entity_Id;
+ E : Elist_Id)
+ is
+ begin
+ pragma Assert (Get_CUDA_Device_Entities (Pack_Id) = No_Elist);
+ CUDA_Device_Entities_Table.Set (Pack_Id, E);
+ end Set_CUDA_Device_Entities;
+
+ ----------------------
+ -- Set_CUDA_Kernels --
+ ----------------------
procedure Set_CUDA_Kernels
(Pack_Id : Entity_Id;
diff --git a/gcc/ada/gnat_cuda.ads b/gcc/ada/gnat_cuda.ads
index 200aeeb..390f5de 100644
--- a/gcc/ada/gnat_cuda.ads
+++ b/gcc/ada/gnat_cuda.ads
@@ -77,31 +77,19 @@ with Types; use Types;
package GNAT_CUDA is
+ procedure Add_CUDA_Device_Entity (Pack_Id : Entity_Id; E : Entity_Id);
+ -- And E to the list of CUDA_Device entities that belong to Pack_Id
+
procedure Add_CUDA_Kernel (Pack_Id : Entity_Id; Kernel : Entity_Id);
-- Add Kernel to the list of CUDA_Global nodes that belong to Pack_Id.
-- Kernel is a procedure entity marked with CUDA_Global, Pack_Id is the
-- entity of its parent package body.
- procedure Build_And_Insert_CUDA_Initialization (N : Node_Id);
- -- Builds declarations necessary for CUDA initialization and inserts them
- -- in N, the package body that contains CUDA_Global nodes. These
- -- declarations are:
- --
- -- * A symbol to hold the pointer to the CUDA fat binary
- --
- -- * A type definition for a wrapper that contains the pointer to the
- -- CUDA fat binary
- --
- -- * An object of the aforementioned type to hold the aforementioned
- -- pointer.
- --
- -- * For each CUDA_Global procedure in the package, a declaration of a C
- -- string containing the function's name.
- --
- -- * A function that takes care of calling CUDA functions that register
- -- CUDA_Global procedures with the runtime.
- --
- -- * A boolean that holds the result of the call to the aforementioned
- -- function.
+ procedure Expand_CUDA_Package (N : Node_Id);
+ -- When compiling for the host:
+ -- - Generate code to register kernels with the CUDA runtime and
+ -- post-process kernels.
+ -- - Empty content of CUDA_Global procedures.
+ -- - Remove declarations of CUDA_Device entities.
end GNAT_CUDA;
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 349586e..0a962ee 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT Reference Manual , Jun 23, 2021
+GNAT Reference Manual , Sep 28, 2021
AdaCore
@@ -79,6 +79,7 @@ included in the section entitled @ref{1,,GNU Free Documentation License}.
* Specialized Needs Annexes::
* Implementation of Specific Ada Features::
* Implementation of Ada 2012 Features::
+* Security Hardening Features::
* Obsolescent Features::
* Compatibility and Porting Guide::
* GNU Free Documentation License::
@@ -224,7 +225,6 @@ Implementation Defined Pragmas
* Pragma Post::
* Pragma Postcondition::
* Pragma Post_Class::
-* Pragma Rename_Pragma::
* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
@@ -247,6 +247,7 @@ Implementation Defined Pragmas
* Pragma Refined_State::
* Pragma Relative_Deadline::
* Pragma Remote_Access_Type::
+* Pragma Rename_Pragma::
* Pragma Restricted_Run_Time::
* Pragma Restriction_Warnings::
* Pragma Reviewable::
@@ -529,6 +530,7 @@ Partition-Wide Restrictions
Program Unit Level Restrictions
* No_Elaboration_Code::
+* No_Dynamic_Accessibility_Checks::
* No_Dynamic_Sized_Objects::
* No_Entry_Queue::
* No_Implementation_Aspect_Specifications::
@@ -877,6 +879,11 @@ Code Generation for Array Aggregates
* Aggregates with nonstatic bounds::
* Aggregates in assignment statements::
+Security Hardening Features
+
+* Register Scrubbing::
+* Stack Scrubbing::
+
Obsolescent Features
* pragma No_Run_Time::
@@ -1033,13 +1040,17 @@ other features.
GNAT implementation of the Ada 2012 language standard.
@item
-@ref{15,,Obsolescent Features} documents implementation dependent features,
+@ref{15,,Security Hardening Features} documents GNAT extensions aimed
+at security hardening.
+
+@item
+@ref{16,,Obsolescent Features} documents implementation dependent features,
including pragmas and attributes, which are considered obsolescent, since
there are other preferred ways of achieving the same results. These
obsolescent forms are retained for backwards compatibility.
@item
-@ref{16,,Compatibility and Porting Guide} presents some guidelines for
+@ref{17,,Compatibility and Porting Guide} presents some guidelines for
developing portable Ada code, describes the compatibility issues that
may arise between GNAT and other Ada compilation systems (including those
for Ada 83), and shows how GNAT can expedite porting applications
@@ -1062,7 +1073,7 @@ All three reference manuals are included in the GNAT documentation
package.
@node Conventions,Related Information,What This Reference Manual Contains,About This Guide
-@anchor{gnat_rm/about_this_guide conventions}@anchor{17}
+@anchor{gnat_rm/about_this_guide conventions}@anchor{18}
@section Conventions
@@ -1109,7 +1120,7 @@ comprising the @code{$} character followed by a space.
@end itemize
@node Related Information,,Conventions,About This Guide
-@anchor{gnat_rm/about_this_guide related-information}@anchor{18}
+@anchor{gnat_rm/about_this_guide related-information}@anchor{19}
@section Related Information
@@ -1155,7 +1166,7 @@ compiler system.
@end itemize
@node Implementation Defined Pragmas,Implementation Defined Aspects,About This Guide,Top
-@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{19}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1a}@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7}
+@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{1a}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1b}@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7}
@chapter Implementation Defined Pragmas
@@ -1304,7 +1315,6 @@ consideration, the use of these pragmas should be minimized.
* Pragma Post::
* Pragma Postcondition::
* Pragma Post_Class::
-* Pragma Rename_Pragma::
* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
@@ -1327,6 +1337,7 @@ consideration, the use of these pragmas should be minimized.
* Pragma Refined_State::
* Pragma Relative_Deadline::
* Pragma Remote_Access_Type::
+* Pragma Rename_Pragma::
* Pragma Restricted_Run_Time::
* Pragma Restriction_Warnings::
* Pragma Reviewable::
@@ -1380,7 +1391,7 @@ consideration, the use of these pragmas should be minimized.
@end menu
@node Pragma Abort_Defer,Pragma Abstract_State,,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-abort-defer}@anchor{1b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-abort-defer}@anchor{1c}
@section Pragma Abort_Defer
@@ -1413,7 +1424,7 @@ end;
@end example
@node Pragma Abstract_State,Pragma Ada_83,Pragma Abort_Defer,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1c}@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1d}
+@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1d}@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1e}
@section Pragma Abstract_State
@@ -1463,7 +1474,7 @@ For the semantics of this pragma, see the entry for aspect @code{Abstract_State}
the SPARK 2014 Reference Manual, section 7.1.4.
@node Pragma Ada_83,Pragma Ada_95,Pragma Abstract_State,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-83}@anchor{1e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-83}@anchor{1f}
@section Pragma Ada_83
@@ -1492,7 +1503,7 @@ by GNAT in Ada 83 mode will in fact compile and execute with an Ada
required by Ada 83.
@node Pragma Ada_95,Pragma Ada_05,Pragma Ada_83,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-95}@anchor{1f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-95}@anchor{20}
@section Pragma Ada_95
@@ -1511,7 +1522,7 @@ itself uses Ada 95 features, but which is intended to be usable from
either Ada 83 or Ada 95 programs.
@node Pragma Ada_05,Pragma Ada_2005,Pragma Ada_95,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-05}@anchor{20}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-05}@anchor{21}
@section Pragma Ada_05
@@ -1540,7 +1551,7 @@ otherwise legal pre-Ada_2005 programs. The one argument form is
intended for exclusive use in the GNAT run-time library.
@node Pragma Ada_2005,Pragma Ada_12,Pragma Ada_05,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2005}@anchor{21}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2005}@anchor{22}
@section Pragma Ada_2005
@@ -1554,7 +1565,7 @@ This configuration pragma is a synonym for pragma Ada_05 and has the
same syntax and effect.
@node Pragma Ada_12,Pragma Ada_2012,Pragma Ada_2005,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-12}@anchor{22}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-12}@anchor{23}
@section Pragma Ada_12
@@ -1585,7 +1596,7 @@ otherwise legal pre-Ada_2012 programs. The one argument form is
intended for exclusive use in the GNAT run-time library.
@node Pragma Ada_2012,Pragma Aggregate_Individually_Assign,Pragma Ada_12,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2012}@anchor{23}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ada-2012}@anchor{24}
@section Pragma Ada_2012
@@ -1599,7 +1610,7 @@ This configuration pragma is a synonym for pragma Ada_12 and has the
same syntax and effect.
@node Pragma Aggregate_Individually_Assign,Pragma Allow_Integer_Address,Pragma Ada_2012,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-aggregate-individually-assign}@anchor{24}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-aggregate-individually-assign}@anchor{25}
@section Pragma Aggregate_Individually_Assign
@@ -1615,7 +1626,7 @@ this behavior so that record aggregates are instead always converted into
individual assignment statements.
@node Pragma Allow_Integer_Address,Pragma Annotate,Pragma Aggregate_Individually_Assign,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-allow-integer-address}@anchor{25}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-allow-integer-address}@anchor{26}
@section Pragma Allow_Integer_Address
@@ -1665,7 +1676,7 @@ rather than rejected to allow common sets of sources to be used
in the two situations.
@node Pragma Annotate,Pragma Assert,Pragma Allow_Integer_Address,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{26}@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{27}
+@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{27}@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{28}
@section Pragma Annotate
@@ -1700,7 +1711,7 @@ affect the compilation process in any way. This pragma may be used as
a configuration pragma.
@node Pragma Assert,Pragma Assert_And_Cut,Pragma Annotate,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assert}@anchor{28}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assert}@anchor{29}
@section Pragma Assert
@@ -1766,7 +1777,7 @@ of Ada, and the DISABLE policy is an implementation-defined
addition.
@node Pragma Assert_And_Cut,Pragma Assertion_Policy,Pragma Assert,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assert-and-cut}@anchor{29}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assert-and-cut}@anchor{2a}
@section Pragma Assert_And_Cut
@@ -1793,7 +1804,7 @@ formal verification. The pragma also serves as useful
documentation.
@node Pragma Assertion_Policy,Pragma Assume,Pragma Assert_And_Cut,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assertion-policy}@anchor{2a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assertion-policy}@anchor{2b}
@section Pragma Assertion_Policy
@@ -1880,7 +1891,7 @@ applies to @code{Assert}, @code{Assert_And_Cut},
@code{Assume}, @code{Loop_Invariant}, and @code{Loop_Variant}.
@node Pragma Assume,Pragma Assume_No_Invalid_Values,Pragma Assertion_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assume}@anchor{2b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assume}@anchor{2c}
@section Pragma Assume
@@ -1914,7 +1925,7 @@ is met, and documents the need to ensure that it is met by
reference to information outside the program.
@node Pragma Assume_No_Invalid_Values,Pragma Async_Readers,Pragma Assume,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-assume-no-invalid-values}@anchor{2c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-assume-no-invalid-values}@anchor{2d}
@section Pragma Assume_No_Invalid_Values
@@ -1967,7 +1978,7 @@ is erroneous so there are no guarantees that this will always be the
case, and it is recommended that these two options not be used together.
@node Pragma Async_Readers,Pragma Async_Writers,Pragma Assume_No_Invalid_Values,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2d}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2e}
+@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2e}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2f}
@section Pragma Async_Readers
@@ -1981,7 +1992,7 @@ For the semantics of this pragma, see the entry for aspect @code{Async_Readers}
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Async_Writers,Pragma Attribute_Definition,Pragma Async_Readers,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id5}@anchor{2f}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-writers}@anchor{30}
+@anchor{gnat_rm/implementation_defined_pragmas id5}@anchor{30}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-writers}@anchor{31}
@section Pragma Async_Writers
@@ -1995,7 +2006,7 @@ For the semantics of this pragma, see the entry for aspect @code{Async_Writers}
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Attribute_Definition,Pragma C_Pass_By_Copy,Pragma Async_Writers,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-attribute-definition}@anchor{31}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-attribute-definition}@anchor{32}
@section Pragma Attribute_Definition
@@ -2021,7 +2032,7 @@ code to be written that takes advantage of some new attribute, while remaining
compilable with earlier compilers.
@node Pragma C_Pass_By_Copy,Pragma Check,Pragma Attribute_Definition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-c-pass-by-copy}@anchor{32}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-c-pass-by-copy}@anchor{33}
@section Pragma C_Pass_By_Copy
@@ -2065,7 +2076,7 @@ You can also pass records by copy by specifying the convention
passing mechanisms on a parameter by parameter basis.
@node Pragma Check,Pragma Check_Float_Overflow,Pragma C_Pass_By_Copy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check}@anchor{33}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check}@anchor{34}
@section Pragma Check
@@ -2104,7 +2115,7 @@ of these identifiers in @code{Assertion_Policy} and @code{Check_Policy}
pragmas, where they are used to refer to sets of assertions.
@node Pragma Check_Float_Overflow,Pragma Check_Name,Pragma Check,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-float-overflow}@anchor{34}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-float-overflow}@anchor{35}
@section Pragma Check_Float_Overflow
@@ -2160,7 +2171,7 @@ This mode can also be set by use of the compiler
switch @emph{-gnateF}.
@node Pragma Check_Name,Pragma Check_Policy,Pragma Check_Float_Overflow,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-name}@anchor{35}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-name}@anchor{36}
@section Pragma Check_Name
@@ -2196,7 +2207,7 @@ Check names introduced by this pragma are subject to control by compiler
switches (in particular -gnatp) in the usual manner.
@node Pragma Check_Policy,Pragma Comment,Pragma Check_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-check-policy}@anchor{36}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-check-policy}@anchor{37}
@section Pragma Check_Policy
@@ -2276,7 +2287,7 @@ policy setting @code{DISABLE} causes the second argument of a corresponding
@code{Check} pragma to be completely ignored and not analyzed.
@node Pragma Comment,Pragma Common_Object,Pragma Check_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-comment}@anchor{37}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-comment}@anchor{38}
@section Pragma Comment
@@ -2295,7 +2306,7 @@ anywhere in the main source unit), and if more than one pragma
is used, all comments are retained.
@node Pragma Common_Object,Pragma Compile_Time_Error,Pragma Comment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-common-object}@anchor{38}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-common-object}@anchor{39}
@section Pragma Common_Object
@@ -2327,7 +2338,7 @@ indicating that the necessary attribute for implementation of this
pragma is not available.
@node Pragma Compile_Time_Error,Pragma Compile_Time_Warning,Pragma Common_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{39}@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{3a}
+@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{3a}@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{3b}
@section Pragma Compile_Time_Error
@@ -2354,7 +2365,7 @@ the value given as the second argument. This string value may contain
embedded ASCII.LF characters to break the message into multiple lines.
@node Pragma Compile_Time_Warning,Pragma Compiler_Unit,Pragma Compile_Time_Error,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-warning}@anchor{3b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-warning}@anchor{3c}
@section Pragma Compile_Time_Warning
@@ -2381,11 +2392,11 @@ for example that it is not fully implemented.
In previous versions of the compiler, combining @emph{-gnatwe} with
Compile_Time_Warning resulted in a fatal error. Now the compiler always emits
-a warning. You can use @ref{39,,Pragma Compile_Time_Error} to force the generation of
+a warning. You can use @ref{3a,,Pragma Compile_Time_Error} to force the generation of
an error.
@node Pragma Compiler_Unit,Pragma Compiler_Unit_Warning,Pragma Compile_Time_Warning,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit}@anchor{3c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit}@anchor{3d}
@section Pragma Compiler_Unit
@@ -2400,7 +2411,7 @@ retained so that old versions of the GNAT run-time that use this pragma can
be compiled with newer versions of the compiler.
@node Pragma Compiler_Unit_Warning,Pragma Complete_Representation,Pragma Compiler_Unit,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit-warning}@anchor{3d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-compiler-unit-warning}@anchor{3e}
@section Pragma Compiler_Unit_Warning
@@ -2418,7 +2429,7 @@ version of GNAT. For the exact list of restrictions, see the compiler sources
and references to Check_Compiler_Unit.
@node Pragma Complete_Representation,Pragma Complex_Representation,Pragma Compiler_Unit_Warning,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-complete-representation}@anchor{3e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-complete-representation}@anchor{3f}
@section Pragma Complete_Representation
@@ -2437,7 +2448,7 @@ complete, and that this invariant is maintained if fields are
added to the record in the future.
@node Pragma Complex_Representation,Pragma Component_Alignment,Pragma Complete_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-complex-representation}@anchor{3f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-complex-representation}@anchor{40}
@section Pragma Complex_Representation
@@ -2459,7 +2470,7 @@ records by pointer, and the use of this pragma may result in passing
this type in floating-point registers.
@node Pragma Component_Alignment,Pragma Constant_After_Elaboration,Pragma Complex_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-component-alignment}@anchor{40}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-component-alignment}@anchor{41}
@section Pragma Component_Alignment
@@ -2550,7 +2561,7 @@ pragma @code{Pack}, pragma @code{Component_Alignment}, or a record rep
clause), the GNAT uses the default alignment as described previously.
@node Pragma Constant_After_Elaboration,Pragma Contract_Cases,Pragma Component_Alignment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id6}@anchor{41}@anchor{gnat_rm/implementation_defined_pragmas pragma-constant-after-elaboration}@anchor{42}
+@anchor{gnat_rm/implementation_defined_pragmas id6}@anchor{42}@anchor{gnat_rm/implementation_defined_pragmas pragma-constant-after-elaboration}@anchor{43}
@section Pragma Constant_After_Elaboration
@@ -2564,7 +2575,7 @@ For the semantics of this pragma, see the entry for aspect
@code{Constant_After_Elaboration} in the SPARK 2014 Reference Manual, section 3.3.1.
@node Pragma Contract_Cases,Pragma Convention_Identifier,Pragma Constant_After_Elaboration,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id7}@anchor{43}@anchor{gnat_rm/implementation_defined_pragmas pragma-contract-cases}@anchor{44}
+@anchor{gnat_rm/implementation_defined_pragmas id7}@anchor{44}@anchor{gnat_rm/implementation_defined_pragmas pragma-contract-cases}@anchor{45}
@section Pragma Contract_Cases
@@ -2649,7 +2660,7 @@ and that the consequence for this case should hold when the subprogram
returns.
@node Pragma Convention_Identifier,Pragma CPP_Class,Pragma Contract_Cases,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-convention-identifier}@anchor{45}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-convention-identifier}@anchor{46}
@section Pragma Convention_Identifier
@@ -2685,7 +2696,7 @@ define a convention identifier @code{Library} and use a single
would be used system-wide.
@node Pragma CPP_Class,Pragma CPP_Constructor,Pragma Convention_Identifier,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-class}@anchor{46}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-class}@anchor{47}
@section Pragma CPP_Class
@@ -2710,14 +2721,14 @@ functions (see pragma @code{CPP_Constructor}). Such types are implicitly
limited if not explicitly declared as limited or derived from a limited
type, and an error is issued in that case.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
Note: Pragma @code{CPP_Class} is currently obsolete. It is supported
for backward compatibility but its functionality is available
using pragma @code{Import} with @code{Convention} = @code{CPP}.
@node Pragma CPP_Constructor,Pragma CPP_Virtual,Pragma CPP_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-constructor}@anchor{48}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-constructor}@anchor{49}
@section Pragma CPP_Constructor
@@ -2768,7 +2779,7 @@ on the Ada side and the type is implicitly declared abstract.
Pragma @code{CPP_Constructor} is intended primarily for automatic generation
using an automatic binding generator tool (such as the @code{-fdump-ada-spec}
GCC switch).
-See @ref{47,,Interfacing to C++} for more related information.
+See @ref{48,,Interfacing to C++} for more related information.
Note: The use of functions returning class-wide types for constructors is
currently obsolete. They are supported for backward compatibility. The
@@ -2777,7 +2788,7 @@ because the imported C++ constructors always return an object of type T;
that is, they never return an object whose type is a descendant of type T.
@node Pragma CPP_Virtual,Pragma CPP_Vtable,Pragma CPP_Constructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-virtual}@anchor{49}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-virtual}@anchor{4a}
@section Pragma CPP_Virtual
@@ -2790,10 +2801,10 @@ purposes. It used to be required to ensure compoatibility with C++, but
is no longer required for that purpose because GNAT generates
the same object layout as the G++ compiler by default.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
@node Pragma CPP_Vtable,Pragma CPU,Pragma CPP_Virtual,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-vtable}@anchor{4a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpp-vtable}@anchor{4b}
@section Pragma CPP_Vtable
@@ -2805,10 +2816,10 @@ It used to be required to ensure compatibility with C++, but
is no longer required for that purpose because GNAT generates
the same object layout as the G++ compiler by default.
-See @ref{47,,Interfacing to C++} for related information.
+See @ref{48,,Interfacing to C++} for related information.
@node Pragma CPU,Pragma Deadline_Floor,Pragma CPP_Vtable,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-cpu}@anchor{4b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-cpu}@anchor{4c}
@section Pragma CPU
@@ -2823,7 +2834,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Deadline_Floor,Pragma Default_Initial_Condition,Pragma CPU,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-deadline-floor}@anchor{4c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-deadline-floor}@anchor{4d}
@section Pragma Deadline_Floor
@@ -2838,7 +2849,7 @@ deadline inherited by a task when the task enters a protected object.
It is effective only when the EDF scheduling policy is used.
@node Pragma Default_Initial_Condition,Pragma Debug,Pragma Deadline_Floor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id8}@anchor{4d}@anchor{gnat_rm/implementation_defined_pragmas pragma-default-initial-condition}@anchor{4e}
+@anchor{gnat_rm/implementation_defined_pragmas id8}@anchor{4e}@anchor{gnat_rm/implementation_defined_pragmas pragma-default-initial-condition}@anchor{4f}
@section Pragma Default_Initial_Condition
@@ -2852,7 +2863,7 @@ For the semantics of this pragma, see the entry for aspect
@code{Default_Initial_Condition} in the SPARK 2014 Reference Manual, section 7.3.3.
@node Pragma Debug,Pragma Debug_Policy,Pragma Default_Initial_Condition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-debug}@anchor{4f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-debug}@anchor{50}
@section Pragma Debug
@@ -2880,7 +2891,7 @@ or by use of the pragma @code{Check_Policy} with a first argument of
@code{Debug}.
@node Pragma Debug_Policy,Pragma Default_Scalar_Storage_Order,Pragma Debug,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-debug-policy}@anchor{50}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-debug-policy}@anchor{51}
@section Pragma Debug_Policy
@@ -2895,7 +2906,7 @@ with a first argument of @code{Debug}. It is retained for historical
compatibility reasons.
@node Pragma Default_Scalar_Storage_Order,Pragma Default_Storage_Pool,Pragma Debug_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-default-scalar-storage-order}@anchor{51}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-default-scalar-storage-order}@anchor{52}
@section Pragma Default_Scalar_Storage_Order
@@ -2968,7 +2979,7 @@ it may significantly degrade the run-time performance of the software, instead
the default scalar storage order ought to be changed only on a local basis.
@node Pragma Default_Storage_Pool,Pragma Depends,Pragma Default_Scalar_Storage_Order,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-default-storage-pool}@anchor{52}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-default-storage-pool}@anchor{53}
@section Pragma Default_Storage_Pool
@@ -2985,7 +2996,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Depends,Pragma Detect_Blocking,Pragma Default_Storage_Pool,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{53}@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{54}
+@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{54}@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{55}
@section Pragma Depends
@@ -3018,7 +3029,7 @@ For the semantics of this pragma, see the entry for aspect @code{Depends} in the
SPARK 2014 Reference Manual, section 6.1.5.
@node Pragma Detect_Blocking,Pragma Disable_Atomic_Synchronization,Pragma Depends,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-detect-blocking}@anchor{55}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-detect-blocking}@anchor{56}
@section Pragma Detect_Blocking
@@ -3036,7 +3047,7 @@ blocking operations within a protected operation, and to raise Program_Error
if that happens.
@node Pragma Disable_Atomic_Synchronization,Pragma Dispatching_Domain,Pragma Detect_Blocking,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-disable-atomic-synchronization}@anchor{56}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-disable-atomic-synchronization}@anchor{57}
@section Pragma Disable_Atomic_Synchronization
@@ -3062,7 +3073,7 @@ till the end of the scope. If an @code{Entity} argument is present,
the action applies only to that entity.
@node Pragma Dispatching_Domain,Pragma Effective_Reads,Pragma Disable_Atomic_Synchronization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-dispatching-domain}@anchor{57}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-dispatching-domain}@anchor{58}
@section Pragma Dispatching_Domain
@@ -3077,7 +3088,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Effective_Reads,Pragma Effective_Writes,Pragma Dispatching_Domain,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id10}@anchor{58}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-reads}@anchor{59}
+@anchor{gnat_rm/implementation_defined_pragmas id10}@anchor{59}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-reads}@anchor{5a}
@section Pragma Effective_Reads
@@ -3091,7 +3102,7 @@ For the semantics of this pragma, see the entry for aspect @code{Effective_Reads
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Effective_Writes,Pragma Elaboration_Checks,Pragma Effective_Reads,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id11}@anchor{5a}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-writes}@anchor{5b}
+@anchor{gnat_rm/implementation_defined_pragmas id11}@anchor{5b}@anchor{gnat_rm/implementation_defined_pragmas pragma-effective-writes}@anchor{5c}
@section Pragma Effective_Writes
@@ -3105,7 +3116,7 @@ For the semantics of this pragma, see the entry for aspect @code{Effective_Write
in the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Elaboration_Checks,Pragma Eliminate,Pragma Effective_Writes,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-elaboration-checks}@anchor{5c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-elaboration-checks}@anchor{5d}
@section Pragma Elaboration_Checks
@@ -3142,7 +3153,7 @@ effect. If the pragma argument is @code{Static}, then the static elaboration mod
is in effect.
@node Pragma Eliminate,Pragma Enable_Atomic_Synchronization,Pragma Elaboration_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-eliminate}@anchor{5d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-eliminate}@anchor{5e}
@section Pragma Eliminate
@@ -3302,7 +3313,7 @@ pragma Eliminate (Q, Proc,
@end quotation
@node Pragma Enable_Atomic_Synchronization,Pragma Export_Function,Pragma Eliminate,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-enable-atomic-synchronization}@anchor{5e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-enable-atomic-synchronization}@anchor{5f}
@section Pragma Enable_Atomic_Synchronization
@@ -3330,7 +3341,7 @@ till the end of the scope. If an @code{Entity} argument is present,
the action applies only to that entity.
@node Pragma Export_Function,Pragma Export_Object,Pragma Enable_Atomic_Synchronization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-function}@anchor{5f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-function}@anchor{60}
@section Pragma Export_Function
@@ -3402,7 +3413,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Export_Object,Pragma Export_Procedure,Pragma Export_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-object}@anchor{60}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-object}@anchor{61}
@section Pragma Export_Object
@@ -3427,7 +3438,7 @@ of portability), but it is not required. @code{Size} is syntax checked,
but otherwise ignored by GNAT.
@node Pragma Export_Procedure,Pragma Export_Valued_Procedure,Pragma Export_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-procedure}@anchor{61}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-procedure}@anchor{62}
@section Pragma Export_Procedure
@@ -3480,7 +3491,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Export_Valued_Procedure,Pragma Extend_System,Pragma Export_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-export-valued-procedure}@anchor{62}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-export-valued-procedure}@anchor{63}
@section Pragma Export_Valued_Procedure
@@ -3538,7 +3549,7 @@ string. In this case, no external name is generated. This form
still allows the specification of parameter mechanisms.
@node Pragma Extend_System,Pragma Extensions_Allowed,Pragma Export_Valued_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-extend-system}@anchor{63}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-extend-system}@anchor{64}
@section Pragma Extend_System
@@ -3589,7 +3600,7 @@ for compiling System units, as explained in the
GNAT User’s Guide.
@node Pragma Extensions_Allowed,Pragma Extensions_Visible,Pragma Extend_System,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-allowed}@anchor{64}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-allowed}@anchor{65}
@section Pragma Extensions_Allowed
@@ -3698,8 +3709,15 @@ will not be executed if the earlier alternative “matches”). All possible
values of the composite type shall be covered. The composite type of the
selector shall be a nonlimited untagged (but possibly discriminated)
record type, all of whose subcomponent subtypes are either static discrete
-subtypes or record types that meet the same restrictions. Support for arrays
-is planned, but not yet implemented.
+subtypes or record types that meet the same restrictions.
+
+Support for casing on arrays (and on records that contain arrays) is
+currently subject to some restrictions. Non-positional
+array aggregates are not supported as (or within) case choices. Likewise
+for array type and subtype names. The current implementation exceeds
+compile-time capacity limits in some annoyingly common scenarios; the
+message generated in such cases is usually “Capacity exceeded in compiling
+case statement with composite selector type”.
In addition, pattern bindings are supported. This is a mechanism
for binding a name to a component of a matching value for use within
@@ -3708,7 +3726,8 @@ that occurs within a case choice, the expression may be followed by
“is <identifier>”. In the special case of a “box” component association,
the identifier may instead be provided within the box. Either of these
indicates that the given identifer denotes (a constant view of) the matching
-subcomponent of the case selector.
+subcomponent of the case selector. Binding is not yet supported for arrays
+or subcomponents thereof.
Consider this example (which uses type Rec from the previous example):
@@ -3813,7 +3832,7 @@ name, preference is given to the component in a selected_component
@end itemize
@node Pragma Extensions_Visible,Pragma External,Pragma Extensions_Allowed,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id12}@anchor{65}@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-visible}@anchor{66}
+@anchor{gnat_rm/implementation_defined_pragmas id12}@anchor{66}@anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-visible}@anchor{67}
@section Pragma Extensions_Visible
@@ -3827,7 +3846,7 @@ For the semantics of this pragma, see the entry for aspect @code{Extensions_Visi
in the SPARK 2014 Reference Manual, section 6.1.7.
@node Pragma External,Pragma External_Name_Casing,Pragma Extensions_Visible,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-external}@anchor{67}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-external}@anchor{68}
@section Pragma External
@@ -3848,7 +3867,7 @@ used this pragma for exactly the same purposes as pragma
@code{Export} before the latter was standardized.
@node Pragma External_Name_Casing,Pragma Fast_Math,Pragma External,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-external-name-casing}@anchor{68}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-external-name-casing}@anchor{69}
@section Pragma External_Name_Casing
@@ -3937,7 +3956,7 @@ pragma External_Name_Casing (Uppercase, Uppercase);
to enforce the upper casing of all external symbols.
@node Pragma Fast_Math,Pragma Favor_Top_Level,Pragma External_Name_Casing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-fast-math}@anchor{69}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-fast-math}@anchor{6a}
@section Pragma Fast_Math
@@ -3966,7 +3985,7 @@ under control of the pragma, rather than use the preinstantiated versions.
@end table
@node Pragma Favor_Top_Level,Pragma Finalize_Storage_Only,Pragma Fast_Math,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id13}@anchor{6a}@anchor{gnat_rm/implementation_defined_pragmas pragma-favor-top-level}@anchor{6b}
+@anchor{gnat_rm/implementation_defined_pragmas id13}@anchor{6b}@anchor{gnat_rm/implementation_defined_pragmas pragma-favor-top-level}@anchor{6c}
@section Pragma Favor_Top_Level
@@ -3985,7 +4004,7 @@ When this pragma is used, dynamically generated trampolines may be used on some
targets for nested subprograms. See restriction @code{No_Implicit_Dynamic_Code}.
@node Pragma Finalize_Storage_Only,Pragma Float_Representation,Pragma Favor_Top_Level,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-finalize-storage-only}@anchor{6c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-finalize-storage-only}@anchor{6d}
@section Pragma Finalize_Storage_Only
@@ -4005,7 +4024,7 @@ name. Note that this pragma does not suppress Finalize calls for library-level
heap-allocated objects (see pragma @code{No_Heap_Finalization}).
@node Pragma Float_Representation,Pragma Ghost,Pragma Finalize_Storage_Only,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-float-representation}@anchor{6d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-float-representation}@anchor{6e}
@section Pragma Float_Representation
@@ -4040,7 +4059,7 @@ No other value of digits is permitted.
@end itemize
@node Pragma Ghost,Pragma Global,Pragma Float_Representation,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6e}@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{6f}
+@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6f}@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{70}
@section Pragma Ghost
@@ -4054,7 +4073,7 @@ For the semantics of this pragma, see the entry for aspect @code{Ghost} in the S
2014 Reference Manual, section 6.9.
@node Pragma Global,Pragma Ident,Pragma Ghost,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{70}@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{71}
+@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{71}@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{72}
@section Pragma Global
@@ -4079,7 +4098,7 @@ For the semantics of this pragma, see the entry for aspect @code{Global} in the
SPARK 2014 Reference Manual, section 6.1.4.
@node Pragma Ident,Pragma Ignore_Pragma,Pragma Global,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ident}@anchor{72}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ident}@anchor{73}
@section Pragma Ident
@@ -4093,7 +4112,7 @@ This pragma is identical in effect to pragma @code{Comment}. It is provided
for compatibility with other Ada compilers providing this pragma.
@node Pragma Ignore_Pragma,Pragma Implementation_Defined,Pragma Ident,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ignore-pragma}@anchor{73}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ignore-pragma}@anchor{74}
@section Pragma Ignore_Pragma
@@ -4113,7 +4132,7 @@ pragma allows such pragmas to be ignored, which may be useful in CodePeer
mode, or during porting of legacy code.
@node Pragma Implementation_Defined,Pragma Implemented,Pragma Ignore_Pragma,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implementation-defined}@anchor{74}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implementation-defined}@anchor{75}
@section Pragma Implementation_Defined
@@ -4140,7 +4159,7 @@ for the purpose of implementing the No_Implementation_Identifiers
restriction.
@node Pragma Implemented,Pragma Implicit_Packing,Pragma Implementation_Defined,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implemented}@anchor{75}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implemented}@anchor{76}
@section Pragma Implemented
@@ -4186,7 +4205,7 @@ By_Any shares the behavior of By_Entry and By_Protected_Procedure depending on
the target’s overriding subprogram kind.
@node Pragma Implicit_Packing,Pragma Import_Function,Pragma Implemented,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-implicit-packing}@anchor{76}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-implicit-packing}@anchor{77}
@section Pragma Implicit_Packing
@@ -4240,7 +4259,7 @@ sufficient. The use of pragma Implicit_Packing allows this record
declaration to compile without an explicit pragma Pack.
@node Pragma Import_Function,Pragma Import_Object,Pragma Implicit_Packing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-function}@anchor{77}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-function}@anchor{78}
@section Pragma Import_Function
@@ -4305,7 +4324,7 @@ notation. If the mechanism is not specified, the default mechanism
is used.
@node Pragma Import_Object,Pragma Import_Procedure,Pragma Import_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-object}@anchor{78}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-object}@anchor{79}
@section Pragma Import_Object
@@ -4331,7 +4350,7 @@ point of view). @code{size} is syntax checked, but otherwise ignored by
GNAT.
@node Pragma Import_Procedure,Pragma Import_Valued_Procedure,Pragma Import_Object,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-procedure}@anchor{79}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-procedure}@anchor{7a}
@section Pragma Import_Procedure
@@ -4371,7 +4390,7 @@ applies to a procedure rather than a function and the parameters
@code{Result_Type} and @code{Result_Mechanism} are not permitted.
@node Pragma Import_Valued_Procedure,Pragma Independent,Pragma Import_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-import-valued-procedure}@anchor{7a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-import-valued-procedure}@anchor{7b}
@section Pragma Import_Valued_Procedure
@@ -4424,7 +4443,7 @@ pragma Import that specifies the desired convention, since otherwise the
default convention is Ada, which is almost certainly not what is required.
@node Pragma Independent,Pragma Independent_Components,Pragma Import_Valued_Procedure,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-independent}@anchor{7b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-independent}@anchor{7c}
@section Pragma Independent
@@ -4446,7 +4465,7 @@ constraints on the representation of the object (for instance prohibiting
tight packing).
@node Pragma Independent_Components,Pragma Initial_Condition,Pragma Independent,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-independent-components}@anchor{7c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-independent-components}@anchor{7d}
@section Pragma Independent_Components
@@ -4467,7 +4486,7 @@ constraints on the representation of the object (for instance prohibiting
tight packing).
@node Pragma Initial_Condition,Pragma Initialize_Scalars,Pragma Independent_Components,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id16}@anchor{7d}@anchor{gnat_rm/implementation_defined_pragmas pragma-initial-condition}@anchor{7e}
+@anchor{gnat_rm/implementation_defined_pragmas id16}@anchor{7e}@anchor{gnat_rm/implementation_defined_pragmas pragma-initial-condition}@anchor{7f}
@section Pragma Initial_Condition
@@ -4481,7 +4500,7 @@ For the semantics of this pragma, see the entry for aspect @code{Initial_Conditi
in the SPARK 2014 Reference Manual, section 7.1.6.
@node Pragma Initialize_Scalars,Pragma Initializes,Pragma Initial_Condition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-initialize-scalars}@anchor{7f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-initialize-scalars}@anchor{80}
@section Pragma Initialize_Scalars
@@ -4590,7 +4609,7 @@ good idea to turn on stack checking (see description of stack checking in the
GNAT User’s Guide) when using this pragma.
@node Pragma Initializes,Pragma Inline_Always,Pragma Initialize_Scalars,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{80}@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{81}
+@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{81}@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{82}
@section Pragma Initializes
@@ -4617,7 +4636,7 @@ For the semantics of this pragma, see the entry for aspect @code{Initializes} in
SPARK 2014 Reference Manual, section 7.1.5.
@node Pragma Inline_Always,Pragma Inline_Generic,Pragma Initializes,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id18}@anchor{82}@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-always}@anchor{83}
+@anchor{gnat_rm/implementation_defined_pragmas id18}@anchor{83}@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-always}@anchor{84}
@section Pragma Inline_Always
@@ -4636,7 +4655,7 @@ apply this pragma to a primitive operation of a tagged type. Thanks to such
restrictions, the compiler is allowed to remove the out-of-line body of @code{NAME}.
@node Pragma Inline_Generic,Pragma Interface,Pragma Inline_Always,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-generic}@anchor{84}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-inline-generic}@anchor{85}
@section Pragma Inline_Generic
@@ -4654,7 +4673,7 @@ than to check that the given names are all names of generic units or
generic instances.
@node Pragma Interface,Pragma Interface_Name,Pragma Inline_Generic,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interface}@anchor{85}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interface}@anchor{86}
@section Pragma Interface
@@ -4681,7 +4700,7 @@ maintaining Ada 83/Ada 95 compatibility and is compatible with other
Ada 83 compilers.
@node Pragma Interface_Name,Pragma Interrupt_Handler,Pragma Interface,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interface-name}@anchor{86}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interface-name}@anchor{87}
@section Pragma Interface_Name
@@ -4700,7 +4719,7 @@ for an interfaced subprogram, and is provided for compatibility with Ada
least one of @code{External_Name} or @code{Link_Name}.
@node Pragma Interrupt_Handler,Pragma Interrupt_State,Pragma Interface_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-handler}@anchor{87}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-handler}@anchor{88}
@section Pragma Interrupt_Handler
@@ -4714,7 +4733,7 @@ This program unit pragma is supported for parameterless protected procedures
as described in Annex C of the Ada Reference Manual.
@node Pragma Interrupt_State,Pragma Invariant,Pragma Interrupt_Handler,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-state}@anchor{88}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-interrupt-state}@anchor{89}
@section Pragma Interrupt_State
@@ -4800,7 +4819,7 @@ with an application’s runtime behavior in the cases of the synchronous signals
and in the case of the signal used to implement the @code{abort} statement.
@node Pragma Invariant,Pragma Keep_Names,Pragma Interrupt_State,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id19}@anchor{89}@anchor{gnat_rm/implementation_defined_pragmas pragma-invariant}@anchor{8a}
+@anchor{gnat_rm/implementation_defined_pragmas id19}@anchor{8a}@anchor{gnat_rm/implementation_defined_pragmas pragma-invariant}@anchor{8b}
@section Pragma Invariant
@@ -4839,7 +4858,7 @@ For further details on the use of this pragma, see the Ada 2012 documentation
of the Type_Invariant aspect.
@node Pragma Keep_Names,Pragma License,Pragma Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-keep-names}@anchor{8b}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-keep-names}@anchor{8c}
@section Pragma Keep_Names
@@ -4859,7 +4878,7 @@ use a @code{Discard_Names} pragma in the @code{gnat.adc} file, but you
want to retain the names for specific enumeration types.
@node Pragma License,Pragma Link_With,Pragma Keep_Names,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-license}@anchor{8c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-license}@anchor{8d}
@section Pragma License
@@ -4954,7 +4973,7 @@ GPL, but no warning for @code{GNAT.Sockets} which is part of the GNAT
run time, and is therefore licensed under the modified GPL.
@node Pragma Link_With,Pragma Linker_Alias,Pragma License,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-link-with}@anchor{8d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-link-with}@anchor{8e}
@section Pragma Link_With
@@ -4978,7 +4997,7 @@ separate arguments to the linker. In addition pragma Link_With allows
multiple arguments, with the same effect as successive pragmas.
@node Pragma Linker_Alias,Pragma Linker_Constructor,Pragma Link_With,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-alias}@anchor{8e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-alias}@anchor{8f}
@section Pragma Linker_Alias
@@ -5019,7 +5038,7 @@ end p;
@end example
@node Pragma Linker_Constructor,Pragma Linker_Destructor,Pragma Linker_Alias,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-constructor}@anchor{8f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-constructor}@anchor{90}
@section Pragma Linker_Constructor
@@ -5049,7 +5068,7 @@ listed above. Where possible, the use of Stand Alone Libraries is preferable
to the use of this pragma.
@node Pragma Linker_Destructor,Pragma Linker_Section,Pragma Linker_Constructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-destructor}@anchor{90}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-destructor}@anchor{91}
@section Pragma Linker_Destructor
@@ -5072,7 +5091,7 @@ See @code{pragma Linker_Constructor} for the set of restrictions that apply
because of these specific contexts.
@node Pragma Linker_Section,Pragma Lock_Free,Pragma Linker_Destructor,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id20}@anchor{91}@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-section}@anchor{92}
+@anchor{gnat_rm/implementation_defined_pragmas id20}@anchor{92}@anchor{gnat_rm/implementation_defined_pragmas pragma-linker-section}@anchor{93}
@section Pragma Linker_Section
@@ -5146,7 +5165,7 @@ end IO_Card;
@end example
@node Pragma Lock_Free,Pragma Loop_Invariant,Pragma Linker_Section,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id21}@anchor{93}@anchor{gnat_rm/implementation_defined_pragmas pragma-lock-free}@anchor{94}
+@anchor{gnat_rm/implementation_defined_pragmas id21}@anchor{94}@anchor{gnat_rm/implementation_defined_pragmas pragma-lock-free}@anchor{95}
@section Pragma Lock_Free
@@ -5198,7 +5217,7 @@ Function calls and attribute references must be static
@end itemize
@node Pragma Loop_Invariant,Pragma Loop_Optimize,Pragma Lock_Free,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-invariant}@anchor{95}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-invariant}@anchor{96}
@section Pragma Loop_Invariant
@@ -5231,7 +5250,7 @@ attribute can only be used within the expression of a @code{Loop_Invariant}
pragma. For full details, see documentation of attribute @code{Loop_Entry}.
@node Pragma Loop_Optimize,Pragma Loop_Variant,Pragma Loop_Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-optimize}@anchor{96}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-optimize}@anchor{97}
@section Pragma Loop_Optimize
@@ -5293,7 +5312,7 @@ compiler in order to enable the relevant optimizations, that is to say
vectorization.
@node Pragma Loop_Variant,Pragma Machine_Attribute,Pragma Loop_Optimize,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-variant}@anchor{97}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-loop-variant}@anchor{98}
@section Pragma Loop_Variant
@@ -5340,7 +5359,7 @@ The @code{Loop_Entry} attribute may be used within the expressions of the
@code{Loop_Variant} pragma to refer to values on entry to the loop.
@node Pragma Machine_Attribute,Pragma Main,Pragma Loop_Variant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-machine-attribute}@anchor{98}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-machine-attribute}@anchor{99}
@section Pragma Machine_Attribute
@@ -5366,7 +5385,7 @@ which may make this pragma unusable for some attributes.
For further information see @cite{GNU Compiler Collection (GCC) Internals}.
@node Pragma Main,Pragma Main_Storage,Pragma Machine_Attribute,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-main}@anchor{99}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-main}@anchor{9a}
@section Pragma Main
@@ -5386,7 +5405,7 @@ This pragma is provided for compatibility with OpenVMS VAX Systems. It has
no effect in GNAT, other than being syntax checked.
@node Pragma Main_Storage,Pragma Max_Queue_Length,Pragma Main,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-main-storage}@anchor{9a}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-main-storage}@anchor{9b}
@section Pragma Main_Storage
@@ -5405,7 +5424,7 @@ This pragma is provided for compatibility with OpenVMS VAX Systems. It has
no effect in GNAT, other than being syntax checked.
@node Pragma Max_Queue_Length,Pragma No_Body,Pragma Main_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id22}@anchor{9b}@anchor{gnat_rm/implementation_defined_pragmas pragma-max-queue-length}@anchor{9c}
+@anchor{gnat_rm/implementation_defined_pragmas id22}@anchor{9c}@anchor{gnat_rm/implementation_defined_pragmas pragma-max-queue-length}@anchor{9d}
@section Pragma Max_Queue_Length
@@ -5423,7 +5442,7 @@ entry.
A value of -1 represents no additional restriction on queue length.
@node Pragma No_Body,Pragma No_Caching,Pragma Max_Queue_Length,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-body}@anchor{9d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-body}@anchor{9e}
@section Pragma No_Body
@@ -5446,7 +5465,7 @@ dummy body with a No_Body pragma ensures that there is no interference from
earlier versions of the package body.
@node Pragma No_Caching,Pragma No_Component_Reordering,Pragma No_Body,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9e}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{9f}
+@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9f}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{a0}
@section Pragma No_Caching
@@ -5460,7 +5479,7 @@ For the semantics of this pragma, see the entry for aspect @code{No_Caching} in
the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma No_Component_Reordering,Pragma No_Elaboration_Code_All,Pragma No_Caching,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-component-reordering}@anchor{a0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-component-reordering}@anchor{a1}
@section Pragma No_Component_Reordering
@@ -5479,7 +5498,7 @@ declared in units to which the pragma applies and there is a requirement
that this pragma be used consistently within a partition.
@node Pragma No_Elaboration_Code_All,Pragma No_Heap_Finalization,Pragma No_Component_Reordering,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id24}@anchor{a1}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-elaboration-code-all}@anchor{a2}
+@anchor{gnat_rm/implementation_defined_pragmas id24}@anchor{a2}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-elaboration-code-all}@anchor{a3}
@section Pragma No_Elaboration_Code_All
@@ -5498,7 +5517,7 @@ current unit, it must also have the No_Elaboration_Code_All aspect set.
It may be applied to package or subprogram specs or their generic versions.
@node Pragma No_Heap_Finalization,Pragma No_Inline,Pragma No_Elaboration_Code_All,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-heap-finalization}@anchor{a3}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-heap-finalization}@anchor{a4}
@section Pragma No_Heap_Finalization
@@ -5530,7 +5549,7 @@ lose its @code{No_Heap_Finalization} pragma when the corresponding instance does
appear at the library level.
@node Pragma No_Inline,Pragma No_Return,Pragma No_Heap_Finalization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id25}@anchor{a4}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-inline}@anchor{a5}
+@anchor{gnat_rm/implementation_defined_pragmas id25}@anchor{a5}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-inline}@anchor{a6}
@section Pragma No_Inline
@@ -5548,7 +5567,7 @@ in particular it is not subject to the use of option @emph{-gnatn} or
pragma @code{Inline_Always} for the same @code{NAME}.
@node Pragma No_Return,Pragma No_Strict_Aliasing,Pragma No_Inline,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-return}@anchor{a6}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-return}@anchor{a7}
@section Pragma No_Return
@@ -5575,7 +5594,7 @@ available in all earlier versions of Ada as an implementation-defined
pragma.
@node Pragma No_Strict_Aliasing,Pragma No_Tagged_Streams,Pragma No_Return,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-no-strict-aliasing}@anchor{a7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-no-strict-aliasing}@anchor{a8}
@section Pragma No_Strict_Aliasing
@@ -5597,7 +5616,7 @@ in the @cite{GNAT User’s Guide}.
This pragma currently has no effects on access to unconstrained array types.
@node Pragma No_Tagged_Streams,Pragma Normalize_Scalars,Pragma No_Strict_Aliasing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a8}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{a9}
+@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a9}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{aa}
@section Pragma No_Tagged_Streams
@@ -5636,7 +5655,7 @@ with empty strings. This is useful to avoid exposing entity names at binary
level but has a negative impact on the debuggability of tagged types.
@node Pragma Normalize_Scalars,Pragma Obsolescent,Pragma No_Tagged_Streams,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-normalize-scalars}@anchor{aa}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-normalize-scalars}@anchor{ab}
@section Pragma Normalize_Scalars
@@ -5718,7 +5737,7 @@ will always generate an invalid value if one exists.
@end table
@node Pragma Obsolescent,Pragma Optimize_Alignment,Pragma Normalize_Scalars,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ab}@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ac}
+@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ac}@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ad}
@section Pragma Obsolescent
@@ -5814,7 +5833,7 @@ So if you specify @code{Entity =>} for the @code{Entity} argument, and a @code{M
argument is present, it must be preceded by @code{Message =>}.
@node Pragma Optimize_Alignment,Pragma Ordered,Pragma Obsolescent,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-optimize-alignment}@anchor{ad}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-optimize-alignment}@anchor{ae}
@section Pragma Optimize_Alignment
@@ -5900,7 +5919,7 @@ latter are compiled by default in pragma Optimize_Alignment (Off) mode if no
pragma appears at the start of the file.
@node Pragma Ordered,Pragma Overflow_Mode,Pragma Optimize_Alignment,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-ordered}@anchor{ae}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-ordered}@anchor{af}
@section Pragma Ordered
@@ -5992,7 +6011,7 @@ For additional information please refer to the description of the
@emph{-gnatw.u} switch in the GNAT User’s Guide.
@node Pragma Overflow_Mode,Pragma Overriding_Renamings,Pragma Ordered,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{af}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{b0}
@section Pragma Overflow_Mode
@@ -6031,7 +6050,7 @@ The pragma @code{Unsuppress (Overflow_Check)} unsuppresses (enables)
overflow checking, but does not affect the overflow mode.
@node Pragma Overriding_Renamings,Pragma Partition_Elaboration_Policy,Pragma Overflow_Mode,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-overriding-renamings}@anchor{b0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-overriding-renamings}@anchor{b1}
@section Pragma Overriding_Renamings
@@ -6066,7 +6085,7 @@ RM 8.3 (15) stipulates that an overridden operation is not visible within the
declaration of the overriding operation.
@node Pragma Partition_Elaboration_Policy,Pragma Part_Of,Pragma Overriding_Renamings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-partition-elaboration-policy}@anchor{b1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-partition-elaboration-policy}@anchor{b2}
@section Pragma Partition_Elaboration_Policy
@@ -6083,7 +6102,7 @@ versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
@node Pragma Part_Of,Pragma Passive,Pragma Partition_Elaboration_Policy,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id28}@anchor{b2}@anchor{gnat_rm/implementation_defined_pragmas pragma-part-of}@anchor{b3}
+@anchor{gnat_rm/implementation_defined_pragmas id28}@anchor{b3}@anchor{gnat_rm/implementation_defined_pragmas pragma-part-of}@anchor{b4}
@section Pragma Part_Of
@@ -6099,7 +6118,7 @@ For the semantics of this pragma, see the entry for aspect @code{Part_Of} in the
SPARK 2014 Reference Manual, section 7.2.6.
@node Pragma Passive,Pragma Persistent_BSS,Pragma Part_Of,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-passive}@anchor{b4}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-passive}@anchor{b5}
@section Pragma Passive
@@ -6123,7 +6142,7 @@ For more information on the subject of passive tasks, see the section
‘Passive Task Optimization’ in the GNAT Users Guide.
@node Pragma Persistent_BSS,Pragma Post,Pragma Passive,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id29}@anchor{b5}@anchor{gnat_rm/implementation_defined_pragmas pragma-persistent-bss}@anchor{b6}
+@anchor{gnat_rm/implementation_defined_pragmas id29}@anchor{b6}@anchor{gnat_rm/implementation_defined_pragmas pragma-persistent-bss}@anchor{b7}
@section Pragma Persistent_BSS
@@ -6154,7 +6173,7 @@ If this pragma is used on a target where this feature is not supported,
then the pragma will be ignored. See also @code{pragma Linker_Section}.
@node Pragma Post,Pragma Postcondition,Pragma Persistent_BSS,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-post}@anchor{b7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-post}@anchor{b8}
@section Pragma Post
@@ -6179,7 +6198,7 @@ appear at the start of the declarations in a subprogram body
(preceded only by other pragmas).
@node Pragma Postcondition,Pragma Post_Class,Pragma Post,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-postcondition}@anchor{b8}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-postcondition}@anchor{b9}
@section Pragma Postcondition
@@ -6343,8 +6362,8 @@ use of the pragma identifier @code{Check}. Historically, pragma
Ada 2012, and has been retained in its original form for
compatibility purposes.
-@node Pragma Post_Class,Pragma Rename_Pragma,Pragma Postcondition,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-post-class}@anchor{b9}
+@node Pragma Post_Class,Pragma Pre,Pragma Postcondition,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-post-class}@anchor{ba}
@section Pragma Post_Class
@@ -6378,46 +6397,7 @@ aspects, but is prepared to ignore the pragmas. The assertion
policy that controls this pragma is @code{Post'Class}, not
@code{Post_Class}.
-@node Pragma Rename_Pragma,Pragma Pre,Pragma Post_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-rename-pragma}@anchor{ba}
-@section Pragma Rename_Pragma
-
-
-@geindex Pragmas
-@geindex synonyms
-
-Syntax:
-
-@example
-pragma Rename_Pragma (
- [New_Name =>] IDENTIFIER,
- [Renamed =>] pragma_IDENTIFIER);
-@end example
-
-This pragma provides a mechanism for supplying new names for existing
-pragmas. The @code{New_Name} identifier can subsequently be used as a synonym for
-the Renamed pragma. For example, suppose you have code that was originally
-developed on a compiler that supports Inline_Only as an implementation defined
-pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
-least very similar to) the GNAT implementation defined pragma
-Inline_Always. You could globally replace Inline_Only with Inline_Always.
-
-However, to avoid that source modification, you could instead add a
-configuration pragma:
-
-@example
-pragma Rename_Pragma (
- New_Name => Inline_Only,
- Renamed => Inline_Always);
-@end example
-
-Then GNAT will treat “pragma Inline_Only …” as if you had written
-“pragma Inline_Always …”.
-
-Pragma Inline_Only will not necessarily mean the same thing as the other Ada
-compiler; it’s up to you to make sure the semantics are close enough.
-
-@node Pragma Pre,Pragma Precondition,Pragma Rename_Pragma,Implementation Defined Pragmas
+@node Pragma Pre,Pragma Precondition,Pragma Post_Class,Implementation Defined Pragmas
@anchor{gnat_rm/implementation_defined_pragmas pragma-pre}@anchor{bb}
@section Pragma Pre
@@ -7246,7 +7226,7 @@ This pragma is standard in Ada 2005, but is available in all earlier
versions of Ada as an implementation-defined pragma.
See Ada 2012 Reference Manual for details.
-@node Pragma Remote_Access_Type,Pragma Restricted_Run_Time,Pragma Relative_Deadline,Implementation Defined Pragmas
+@node Pragma Remote_Access_Type,Pragma Rename_Pragma,Pragma Relative_Deadline,Implementation Defined Pragmas
@anchor{gnat_rm/implementation_defined_pragmas id36}@anchor{d6}@anchor{gnat_rm/implementation_defined_pragmas pragma-remote-access-type}@anchor{d7}
@section Pragma Remote_Access_Type
@@ -7272,8 +7252,47 @@ In the generic unit, the formal type is subject to all restrictions
pertaining to remote access to class-wide types. At instantiation, the
actual type must be a remote access to class-wide type.
-@node Pragma Restricted_Run_Time,Pragma Restriction_Warnings,Pragma Remote_Access_Type,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-restricted-run-time}@anchor{d8}
+@node Pragma Rename_Pragma,Pragma Restricted_Run_Time,Pragma Remote_Access_Type,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-rename-pragma}@anchor{d8}
+@section Pragma Rename_Pragma
+
+
+@geindex Pragmas
+@geindex synonyms
+
+Syntax:
+
+@example
+pragma Rename_Pragma (
+ [New_Name =>] IDENTIFIER,
+ [Renamed =>] pragma_IDENTIFIER);
+@end example
+
+This pragma provides a mechanism for supplying new names for existing
+pragmas. The @code{New_Name} identifier can subsequently be used as a synonym for
+the Renamed pragma. For example, suppose you have code that was originally
+developed on a compiler that supports Inline_Only as an implementation defined
+pragma. And suppose the semantics of pragma Inline_Only are identical to (or at
+least very similar to) the GNAT implementation defined pragma
+Inline_Always. You could globally replace Inline_Only with Inline_Always.
+
+However, to avoid that source modification, you could instead add a
+configuration pragma:
+
+@example
+pragma Rename_Pragma (
+ New_Name => Inline_Only,
+ Renamed => Inline_Always);
+@end example
+
+Then GNAT will treat “pragma Inline_Only …” as if you had written
+“pragma Inline_Always …”.
+
+Pragma Inline_Only will not necessarily mean the same thing as the other Ada
+compiler; it’s up to you to make sure the semantics are close enough.
+
+@node Pragma Restricted_Run_Time,Pragma Restriction_Warnings,Pragma Rename_Pragma,Implementation Defined Pragmas
+@anchor{gnat_rm/implementation_defined_pragmas pragma-restricted-run-time}@anchor{d9}
@section Pragma Restricted_Run_Time
@@ -7294,7 +7313,7 @@ which is the preferred method of setting the restricted run time
profile.
@node Pragma Restriction_Warnings,Pragma Reviewable,Pragma Restricted_Run_Time,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-restriction-warnings}@anchor{d9}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-restriction-warnings}@anchor{da}
@section Pragma Restriction_Warnings
@@ -7332,7 +7351,7 @@ generating a warning, but any other use of implementation
defined pragmas will cause a warning to be generated.
@node Pragma Reviewable,Pragma Secondary_Stack_Size,Pragma Restriction_Warnings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-reviewable}@anchor{da}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-reviewable}@anchor{db}
@section Pragma Reviewable
@@ -7436,7 +7455,7 @@ comprehensive messages identifying possible problems based on this
information.
@node Pragma Secondary_Stack_Size,Pragma Share_Generic,Pragma Reviewable,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id37}@anchor{db}@anchor{gnat_rm/implementation_defined_pragmas pragma-secondary-stack-size}@anchor{dc}
+@anchor{gnat_rm/implementation_defined_pragmas id37}@anchor{dc}@anchor{gnat_rm/implementation_defined_pragmas pragma-secondary-stack-size}@anchor{dd}
@section Pragma Secondary_Stack_Size
@@ -7472,7 +7491,7 @@ Note the pragma cannot appear when the restriction @code{No_Secondary_Stack}
is in effect.
@node Pragma Share_Generic,Pragma Shared,Pragma Secondary_Stack_Size,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-share-generic}@anchor{dd}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-share-generic}@anchor{de}
@section Pragma Share_Generic
@@ -7490,7 +7509,7 @@ than to check that the given names are all names of generic units or
generic instances.
@node Pragma Shared,Pragma Short_Circuit_And_Or,Pragma Share_Generic,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id38}@anchor{de}@anchor{gnat_rm/implementation_defined_pragmas pragma-shared}@anchor{df}
+@anchor{gnat_rm/implementation_defined_pragmas id38}@anchor{df}@anchor{gnat_rm/implementation_defined_pragmas pragma-shared}@anchor{e0}
@section Pragma Shared
@@ -7498,7 +7517,7 @@ This pragma is provided for compatibility with Ada 83. The syntax and
semantics are identical to pragma Atomic.
@node Pragma Short_Circuit_And_Or,Pragma Short_Descriptors,Pragma Shared,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-short-circuit-and-or}@anchor{e0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-short-circuit-and-or}@anchor{e1}
@section Pragma Short_Circuit_And_Or
@@ -7517,7 +7536,7 @@ within the file being compiled, it applies only to the file being compiled.
There is no requirement that all units in a partition use this option.
@node Pragma Short_Descriptors,Pragma Simple_Storage_Pool_Type,Pragma Short_Circuit_And_Or,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-short-descriptors}@anchor{e1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-short-descriptors}@anchor{e2}
@section Pragma Short_Descriptors
@@ -7531,7 +7550,7 @@ This pragma is provided for compatibility with other Ada implementations. It
is recognized but ignored by all current versions of GNAT.
@node Pragma Simple_Storage_Pool_Type,Pragma Source_File_Name,Pragma Short_Descriptors,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e2}@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e3}
+@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e3}@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e4}
@section Pragma Simple_Storage_Pool_Type
@@ -7585,7 +7604,7 @@ storage-management discipline).
An object of a simple storage pool type can be associated with an access
type by specifying the attribute
-@ref{e4,,Simple_Storage_Pool}. For example:
+@ref{e5,,Simple_Storage_Pool}. For example:
@example
My_Pool : My_Simple_Storage_Pool_Type;
@@ -7595,11 +7614,11 @@ type Acc is access My_Data_Type;
for Acc'Simple_Storage_Pool use My_Pool;
@end example
-See attribute @ref{e4,,Simple_Storage_Pool}
+See attribute @ref{e5,,Simple_Storage_Pool}
for further details.
@node Pragma Source_File_Name,Pragma Source_File_Name_Project,Pragma Simple_Storage_Pool_Type,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e5}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e6}
+@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e6}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e7}
@section Pragma Source_File_Name
@@ -7691,20 +7710,20 @@ aware of these pragmas, and so other tools that use the projet file would not
be aware of the intended naming conventions. If you are using project files,
file naming is controlled by Source_File_Name_Project pragmas, which are
usually supplied automatically by the project manager. A pragma
-Source_File_Name cannot appear after a @ref{e7,,Pragma Source_File_Name_Project}.
+Source_File_Name cannot appear after a @ref{e8,,Pragma Source_File_Name_Project}.
For more details on the use of the @code{Source_File_Name} pragma, see the
sections on @cite{Using Other File Names} and @cite{Alternative File Naming Schemes}
in the @cite{GNAT User’s Guide}.
@node Pragma Source_File_Name_Project,Pragma Source_Reference,Pragma Source_File_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e8}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e7}
+@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e9}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e8}
@section Pragma Source_File_Name_Project
This pragma has the same syntax and semantics as pragma Source_File_Name.
It is only allowed as a stand-alone configuration pragma.
-It cannot appear after a @ref{e6,,Pragma Source_File_Name}, and
+It cannot appear after a @ref{e7,,Pragma Source_File_Name}, and
most importantly, once pragma Source_File_Name_Project appears,
no further Source_File_Name pragmas are allowed.
@@ -7716,7 +7735,7 @@ Source_File_Name or Source_File_Name_Project pragmas (which would not be
known to the project manager).
@node Pragma Source_Reference,Pragma SPARK_Mode,Pragma Source_File_Name_Project,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-source-reference}@anchor{e9}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-source-reference}@anchor{ea}
@section Pragma Source_Reference
@@ -7740,7 +7759,7 @@ string expression other than a string literal. This is because its value
is needed for error messages issued by all phases of the compiler.
@node Pragma SPARK_Mode,Pragma Static_Elaboration_Desired,Pragma Source_Reference,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{ea}@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{eb}
+@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{eb}@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{ec}
@section Pragma SPARK_Mode
@@ -7822,7 +7841,7 @@ SPARK_Mode (@code{Off}), then that pragma will need to be repeated in
the package body.
@node Pragma Static_Elaboration_Desired,Pragma Stream_Convert,Pragma SPARK_Mode,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-static-elaboration-desired}@anchor{ec}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-static-elaboration-desired}@anchor{ed}
@section Pragma Static_Elaboration_Desired
@@ -7846,7 +7865,7 @@ construction of larger aggregates with static components that include an others
choice.)
@node Pragma Stream_Convert,Pragma Style_Checks,Pragma Static_Elaboration_Desired,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-stream-convert}@anchor{ed}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-stream-convert}@anchor{ee}
@section Pragma Stream_Convert
@@ -7923,7 +7942,7 @@ the pragma is silently ignored, and the default implementation of the stream
attributes is used instead.
@node Pragma Style_Checks,Pragma Subtitle,Pragma Stream_Convert,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-style-checks}@anchor{ee}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-style-checks}@anchor{ef}
@section Pragma Style_Checks
@@ -7996,7 +8015,7 @@ Rf2 : Integer := ARG; -- OK, no error
@end example
@node Pragma Subtitle,Pragma Suppress,Pragma Style_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-subtitle}@anchor{ef}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-subtitle}@anchor{f0}
@section Pragma Subtitle
@@ -8010,7 +8029,7 @@ This pragma is recognized for compatibility with other Ada compilers
but is ignored by GNAT.
@node Pragma Suppress,Pragma Suppress_All,Pragma Subtitle,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress}@anchor{f0}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress}@anchor{f1}
@section Pragma Suppress
@@ -8083,7 +8102,7 @@ Of course, run-time checks are omitted whenever the compiler can prove
that they will not fail, whether or not checks are suppressed.
@node Pragma Suppress_All,Pragma Suppress_Debug_Info,Pragma Suppress,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-all}@anchor{f1}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-all}@anchor{f2}
@section Pragma Suppress_All
@@ -8102,7 +8121,7 @@ The use of the standard Ada pragma @code{Suppress (All_Checks)}
as a normal configuration pragma is the preferred usage in GNAT.
@node Pragma Suppress_Debug_Info,Pragma Suppress_Exception_Locations,Pragma Suppress_All,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f2}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f3}
+@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f3}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f4}
@section Pragma Suppress_Debug_Info
@@ -8117,7 +8136,7 @@ for the specified entity. It is intended primarily for use in debugging
the debugger, and navigating around debugger problems.
@node Pragma Suppress_Exception_Locations,Pragma Suppress_Initialization,Pragma Suppress_Debug_Info,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-exception-locations}@anchor{f4}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-exception-locations}@anchor{f5}
@section Pragma Suppress_Exception_Locations
@@ -8140,7 +8159,7 @@ a partition, so it is fine to have some units within a partition compiled
with this pragma and others compiled in normal mode without it.
@node Pragma Suppress_Initialization,Pragma Task_Name,Pragma Suppress_Exception_Locations,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id44}@anchor{f5}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-initialization}@anchor{f6}
+@anchor{gnat_rm/implementation_defined_pragmas id44}@anchor{f6}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-initialization}@anchor{f7}
@section Pragma Suppress_Initialization
@@ -8185,7 +8204,7 @@ is suppressed, just as though its subtype had been given in a pragma
Suppress_Initialization, as described above.
@node Pragma Task_Name,Pragma Task_Storage,Pragma Suppress_Initialization,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-task-name}@anchor{f7}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-task-name}@anchor{f8}
@section Pragma Task_Name
@@ -8241,7 +8260,7 @@ end;
@end example
@node Pragma Task_Storage,Pragma Test_Case,Pragma Task_Name,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-task-storage}@anchor{f8}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-task-storage}@anchor{f9}
@section Pragma Task_Storage
@@ -8261,7 +8280,7 @@ created, depending on the target. This pragma can appear anywhere a
type.
@node Pragma Test_Case,Pragma Thread_Local_Storage,Pragma Task_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{f9}@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{fa}
+@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{fa}@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{fb}
@section Pragma Test_Case
@@ -8317,7 +8336,7 @@ postcondition. Mode @code{Robustness} indicates that the precondition and
postcondition of the subprogram should be ignored for this test case.
@node Pragma Thread_Local_Storage,Pragma Time_Slice,Pragma Test_Case,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fb}@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fc}
+@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fc}@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fd}
@section Pragma Thread_Local_Storage
@@ -8355,7 +8374,7 @@ If this pragma is used on a system where @code{TLS} is not supported,
then an error message will be generated and the program will be rejected.
@node Pragma Time_Slice,Pragma Title,Pragma Thread_Local_Storage,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-time-slice}@anchor{fd}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-time-slice}@anchor{fe}
@section Pragma Time_Slice
@@ -8371,7 +8390,7 @@ It is ignored if it is used in a system that does not allow this control,
or if it appears in other than the main program unit.
@node Pragma Title,Pragma Type_Invariant,Pragma Time_Slice,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-title}@anchor{fe}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-title}@anchor{ff}
@section Pragma Title
@@ -8396,7 +8415,7 @@ notation is used, and named and positional notation can be mixed
following the normal rules for procedure calls in Ada.
@node Pragma Type_Invariant,Pragma Type_Invariant_Class,Pragma Title,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant}@anchor{ff}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant}@anchor{100}
@section Pragma Type_Invariant
@@ -8417,7 +8436,7 @@ controlled by the assertion identifier @code{Type_Invariant}
rather than @code{Invariant}.
@node Pragma Type_Invariant_Class,Pragma Unchecked_Union,Pragma Type_Invariant,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id47}@anchor{100}@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant-class}@anchor{101}
+@anchor{gnat_rm/implementation_defined_pragmas id47}@anchor{101}@anchor{gnat_rm/implementation_defined_pragmas pragma-type-invariant-class}@anchor{102}
@section Pragma Type_Invariant_Class
@@ -8444,7 +8463,7 @@ policy that controls this pragma is @code{Type_Invariant'Class},
not @code{Type_Invariant_Class}.
@node Pragma Unchecked_Union,Pragma Unevaluated_Use_Of_Old,Pragma Type_Invariant_Class,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unchecked-union}@anchor{102}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unchecked-union}@anchor{103}
@section Pragma Unchecked_Union
@@ -8464,7 +8483,7 @@ version in all language modes (Ada 83, Ada 95, and Ada 2005). For full
details, consult the Ada 2012 Reference Manual, section B.3.3.
@node Pragma Unevaluated_Use_Of_Old,Pragma Unimplemented_Unit,Pragma Unchecked_Union,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unevaluated-use-of-old}@anchor{103}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unevaluated-use-of-old}@anchor{104}
@section Pragma Unevaluated_Use_Of_Old
@@ -8519,7 +8538,7 @@ uses up to the end of the corresponding statement sequence or
sequence of package declarations.
@node Pragma Unimplemented_Unit,Pragma Universal_Aliasing,Pragma Unevaluated_Use_Of_Old,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unimplemented-unit}@anchor{104}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unimplemented-unit}@anchor{105}
@section Pragma Unimplemented_Unit
@@ -8539,7 +8558,7 @@ The abort only happens if code is being generated. Thus you can use
specs of unimplemented packages in syntax or semantic checking mode.
@node Pragma Universal_Aliasing,Pragma Unmodified,Pragma Unimplemented_Unit,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{105}@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{106}
+@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{106}@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{107}
@section Pragma Universal_Aliasing
@@ -8558,7 +8577,7 @@ situations in which it must be suppressed, see the section on
@code{Optimization and Strict Aliasing} in the @cite{GNAT User’s Guide}.
@node Pragma Unmodified,Pragma Unreferenced,Pragma Universal_Aliasing,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{107}@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{108}
+@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{108}@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{109}
@section Pragma Unmodified
@@ -8592,7 +8611,7 @@ Thus it is never necessary to use @code{pragma Unmodified} for such
variables, though it is harmless to do so.
@node Pragma Unreferenced,Pragma Unreferenced_Objects,Pragma Unmodified,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{109}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{10a}
+@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{10a}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{10b}
@section Pragma Unreferenced
@@ -8636,7 +8655,7 @@ Note that if a warning is desired for all calls to a given subprogram,
regardless of whether they occur in the same unit as the subprogram
declaration, then this pragma should not be used (calls from another
unit would not be flagged); pragma Obsolescent can be used instead
-for this purpose, see @ref{ac,,Pragma Obsolescent}.
+for this purpose, see @ref{ad,,Pragma Obsolescent}.
The second form of pragma @code{Unreferenced} is used within a context
clause. In this case the arguments must be unit names of units previously
@@ -8652,7 +8671,7 @@ Thus it is never necessary to use @code{pragma Unreferenced} for such
variables, though it is harmless to do so.
@node Pragma Unreferenced_Objects,Pragma Unreserve_All_Interrupts,Pragma Unreferenced,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10b}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10c}
+@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10c}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10d}
@section Pragma Unreferenced_Objects
@@ -8677,7 +8696,7 @@ compiler will automatically suppress unwanted warnings about these variables
not being referenced.
@node Pragma Unreserve_All_Interrupts,Pragma Unsuppress,Pragma Unreferenced_Objects,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unreserve-all-interrupts}@anchor{10d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unreserve-all-interrupts}@anchor{10e}
@section Pragma Unreserve_All_Interrupts
@@ -8713,7 +8732,7 @@ handled, see pragma @code{Interrupt_State}, which subsumes the functionality
of the @code{Unreserve_All_Interrupts} pragma.
@node Pragma Unsuppress,Pragma Use_VADS_Size,Pragma Unreserve_All_Interrupts,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-unsuppress}@anchor{10e}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-unsuppress}@anchor{10f}
@section Pragma Unsuppress
@@ -8749,7 +8768,7 @@ number of implementation-defined check names. See the description of pragma
@code{Suppress} for full details.
@node Pragma Use_VADS_Size,Pragma Unused,Pragma Unsuppress,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-use-vads-size}@anchor{10f}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-use-vads-size}@anchor{110}
@section Pragma Use_VADS_Size
@@ -8773,7 +8792,7 @@ as implemented in the VADS compiler. See description of the VADS_Size
attribute for further details.
@node Pragma Unused,Pragma Validity_Checks,Pragma Use_VADS_Size,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{110}@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{111}
+@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{111}@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{112}
@section Pragma Unused
@@ -8807,7 +8826,7 @@ Thus it is never necessary to use @code{pragma Unmodified} for such
variables, though it is harmless to do so.
@node Pragma Validity_Checks,Pragma Volatile,Pragma Unused,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-validity-checks}@anchor{112}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-validity-checks}@anchor{113}
@section Pragma Validity_Checks
@@ -8863,7 +8882,7 @@ A := C; -- C will be validity checked
@end example
@node Pragma Volatile,Pragma Volatile_Full_Access,Pragma Validity_Checks,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{113}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{114}
+@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{114}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{115}
@section Pragma Volatile
@@ -8881,7 +8900,7 @@ implementation of pragma Volatile is upwards compatible with the
implementation in DEC Ada 83.
@node Pragma Volatile_Full_Access,Pragma Volatile_Function,Pragma Volatile,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id54}@anchor{115}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-full-access}@anchor{116}
+@anchor{gnat_rm/implementation_defined_pragmas id54}@anchor{116}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-full-access}@anchor{117}
@section Pragma Volatile_Full_Access
@@ -8907,7 +8926,7 @@ is not to the whole object; the compiler is allowed (and generally will)
access only part of the object in this case.
@node Pragma Volatile_Function,Pragma Warning_As_Error,Pragma Volatile_Full_Access,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id55}@anchor{117}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-function}@anchor{118}
+@anchor{gnat_rm/implementation_defined_pragmas id55}@anchor{118}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile-function}@anchor{119}
@section Pragma Volatile_Function
@@ -8921,7 +8940,7 @@ For the semantics of this pragma, see the entry for aspect @code{Volatile_Functi
in the SPARK 2014 Reference Manual, section 7.1.2.
@node Pragma Warning_As_Error,Pragma Warnings,Pragma Volatile_Function,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-warning-as-error}@anchor{119}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-warning-as-error}@anchor{11a}
@section Pragma Warning_As_Error
@@ -8961,7 +8980,7 @@ you can use multiple pragma Warning_As_Error.
The above use of patterns to match the message applies only to warning
messages generated by the front end. This pragma can also be applied to
-warnings provided by the back end and mentioned in @ref{11a,,Pragma Warnings}.
+warnings provided by the back end and mentioned in @ref{11b,,Pragma Warnings}.
By using a single full @emph{-Wxxx} switch in the pragma, such warnings
can also be treated as errors.
@@ -9011,7 +9030,7 @@ the tag is changed from “warning:” to “error:” and the string
“[warning-as-error]” is appended to the end of the message.
@node Pragma Warnings,Pragma Weak_External,Pragma Warning_As_Error,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas id56}@anchor{11b}@anchor{gnat_rm/implementation_defined_pragmas pragma-warnings}@anchor{11a}
+@anchor{gnat_rm/implementation_defined_pragmas id56}@anchor{11c}@anchor{gnat_rm/implementation_defined_pragmas pragma-warnings}@anchor{11b}
@section Pragma Warnings
@@ -9167,7 +9186,7 @@ selectively for each tool, and as a consequence to detect useless pragma
Warnings with switch @code{-gnatw.w}.
@node Pragma Weak_External,Pragma Wide_Character_Encoding,Pragma Warnings,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-weak-external}@anchor{11c}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-weak-external}@anchor{11d}
@section Pragma Weak_External
@@ -9218,7 +9237,7 @@ end External_Module;
@end example
@node Pragma Wide_Character_Encoding,,Pragma Weak_External,Implementation Defined Pragmas
-@anchor{gnat_rm/implementation_defined_pragmas pragma-wide-character-encoding}@anchor{11d}
+@anchor{gnat_rm/implementation_defined_pragmas pragma-wide-character-encoding}@anchor{11e}
@section Pragma Wide_Character_Encoding
@@ -9249,7 +9268,7 @@ encoding within that file, and does not affect withed units, specs,
or subunits.
@node Implementation Defined Aspects,Implementation Defined Attributes,Implementation Defined Pragmas,Top
-@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11e}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{120}
+@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{120}@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{121}
@chapter Implementation Defined Aspects
@@ -9369,16 +9388,16 @@ or attribute definition clause.
@end menu
@node Aspect Abstract_State,Aspect Annotate,,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-abstract-state}@anchor{121}
+@anchor{gnat_rm/implementation_defined_aspects aspect-abstract-state}@anchor{122}
@section Aspect Abstract_State
@geindex Abstract_State
-This aspect is equivalent to @ref{1d,,pragma Abstract_State}.
+This aspect is equivalent to @ref{1e,,pragma Abstract_State}.
@node Aspect Annotate,Aspect Async_Readers,Aspect Abstract_State,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-annotate}@anchor{122}
+@anchor{gnat_rm/implementation_defined_aspects aspect-annotate}@anchor{123}
@section Aspect Annotate
@@ -9386,7 +9405,7 @@ This aspect is equivalent to @ref{1d,,pragma Abstract_State}.
There are three forms of this aspect (where ID is an identifier,
and ARG is a general expression),
-corresponding to @ref{27,,pragma Annotate}.
+corresponding to @ref{28,,pragma Annotate}.
@table @asis
@@ -9405,63 +9424,63 @@ Equivalent to @code{pragma Annotate (ID, ID @{, ARG@}, Entity => Name);}
@end table
@node Aspect Async_Readers,Aspect Async_Writers,Aspect Annotate,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-async-readers}@anchor{123}
+@anchor{gnat_rm/implementation_defined_aspects aspect-async-readers}@anchor{124}
@section Aspect Async_Readers
@geindex Async_Readers
-This boolean aspect is equivalent to @ref{2e,,pragma Async_Readers}.
+This boolean aspect is equivalent to @ref{2f,,pragma Async_Readers}.
@node Aspect Async_Writers,Aspect Constant_After_Elaboration,Aspect Async_Readers,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-async-writers}@anchor{124}
+@anchor{gnat_rm/implementation_defined_aspects aspect-async-writers}@anchor{125}
@section Aspect Async_Writers
@geindex Async_Writers
-This boolean aspect is equivalent to @ref{30,,pragma Async_Writers}.
+This boolean aspect is equivalent to @ref{31,,pragma Async_Writers}.
@node Aspect Constant_After_Elaboration,Aspect Contract_Cases,Aspect Async_Writers,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-constant-after-elaboration}@anchor{125}
+@anchor{gnat_rm/implementation_defined_aspects aspect-constant-after-elaboration}@anchor{126}
@section Aspect Constant_After_Elaboration
@geindex Constant_After_Elaboration
-This aspect is equivalent to @ref{42,,pragma Constant_After_Elaboration}.
+This aspect is equivalent to @ref{43,,pragma Constant_After_Elaboration}.
@node Aspect Contract_Cases,Aspect Depends,Aspect Constant_After_Elaboration,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-contract-cases}@anchor{126}
+@anchor{gnat_rm/implementation_defined_aspects aspect-contract-cases}@anchor{127}
@section Aspect Contract_Cases
@geindex Contract_Cases
-This aspect is equivalent to @ref{44,,pragma Contract_Cases}, the sequence
+This aspect is equivalent to @ref{45,,pragma Contract_Cases}, the sequence
of clauses being enclosed in parentheses so that syntactically it is an
aggregate.
@node Aspect Depends,Aspect Default_Initial_Condition,Aspect Contract_Cases,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-depends}@anchor{127}
+@anchor{gnat_rm/implementation_defined_aspects aspect-depends}@anchor{128}
@section Aspect Depends
@geindex Depends
-This aspect is equivalent to @ref{54,,pragma Depends}.
+This aspect is equivalent to @ref{55,,pragma Depends}.
@node Aspect Default_Initial_Condition,Aspect Dimension,Aspect Depends,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-default-initial-condition}@anchor{128}
+@anchor{gnat_rm/implementation_defined_aspects aspect-default-initial-condition}@anchor{129}
@section Aspect Default_Initial_Condition
@geindex Default_Initial_Condition
-This aspect is equivalent to @ref{4e,,pragma Default_Initial_Condition}.
+This aspect is equivalent to @ref{4f,,pragma Default_Initial_Condition}.
@node Aspect Dimension,Aspect Dimension_System,Aspect Default_Initial_Condition,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-dimension}@anchor{129}
+@anchor{gnat_rm/implementation_defined_aspects aspect-dimension}@anchor{12a}
@section Aspect Dimension
@@ -9497,7 +9516,7 @@ Note that when the dimensioned type is an integer type, then any
dimension value must be an integer literal.
@node Aspect Dimension_System,Aspect Disable_Controlled,Aspect Dimension,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-dimension-system}@anchor{12a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-dimension-system}@anchor{12b}
@section Aspect Dimension_System
@@ -9557,7 +9576,7 @@ See section ‘Performing Dimensionality Analysis in GNAT’ in the GNAT Users
Guide for detailed examples of use of the dimension system.
@node Aspect Disable_Controlled,Aspect Effective_Reads,Aspect Dimension_System,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-disable-controlled}@anchor{12b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-disable-controlled}@anchor{12c}
@section Aspect Disable_Controlled
@@ -9570,110 +9589,110 @@ where for example you might want a record to be controlled or not depending on
whether some run-time check is enabled or suppressed.
@node Aspect Effective_Reads,Aspect Effective_Writes,Aspect Disable_Controlled,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-effective-reads}@anchor{12c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-effective-reads}@anchor{12d}
@section Aspect Effective_Reads
@geindex Effective_Reads
-This aspect is equivalent to @ref{59,,pragma Effective_Reads}.
+This aspect is equivalent to @ref{5a,,pragma Effective_Reads}.
@node Aspect Effective_Writes,Aspect Extensions_Visible,Aspect Effective_Reads,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-effective-writes}@anchor{12d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-effective-writes}@anchor{12e}
@section Aspect Effective_Writes
@geindex Effective_Writes
-This aspect is equivalent to @ref{5b,,pragma Effective_Writes}.
+This aspect is equivalent to @ref{5c,,pragma Effective_Writes}.
@node Aspect Extensions_Visible,Aspect Favor_Top_Level,Aspect Effective_Writes,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-extensions-visible}@anchor{12e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-extensions-visible}@anchor{12f}
@section Aspect Extensions_Visible
@geindex Extensions_Visible
-This aspect is equivalent to @ref{66,,pragma Extensions_Visible}.
+This aspect is equivalent to @ref{67,,pragma Extensions_Visible}.
@node Aspect Favor_Top_Level,Aspect Ghost,Aspect Extensions_Visible,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-favor-top-level}@anchor{12f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-favor-top-level}@anchor{130}
@section Aspect Favor_Top_Level
@geindex Favor_Top_Level
-This boolean aspect is equivalent to @ref{6b,,pragma Favor_Top_Level}.
+This boolean aspect is equivalent to @ref{6c,,pragma Favor_Top_Level}.
@node Aspect Ghost,Aspect Global,Aspect Favor_Top_Level,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-ghost}@anchor{130}
+@anchor{gnat_rm/implementation_defined_aspects aspect-ghost}@anchor{131}
@section Aspect Ghost
@geindex Ghost
-This aspect is equivalent to @ref{6f,,pragma Ghost}.
+This aspect is equivalent to @ref{70,,pragma Ghost}.
@node Aspect Global,Aspect Initial_Condition,Aspect Ghost,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-global}@anchor{131}
+@anchor{gnat_rm/implementation_defined_aspects aspect-global}@anchor{132}
@section Aspect Global
@geindex Global
-This aspect is equivalent to @ref{71,,pragma Global}.
+This aspect is equivalent to @ref{72,,pragma Global}.
@node Aspect Initial_Condition,Aspect Initializes,Aspect Global,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-initial-condition}@anchor{132}
+@anchor{gnat_rm/implementation_defined_aspects aspect-initial-condition}@anchor{133}
@section Aspect Initial_Condition
@geindex Initial_Condition
-This aspect is equivalent to @ref{7e,,pragma Initial_Condition}.
+This aspect is equivalent to @ref{7f,,pragma Initial_Condition}.
@node Aspect Initializes,Aspect Inline_Always,Aspect Initial_Condition,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-initializes}@anchor{133}
+@anchor{gnat_rm/implementation_defined_aspects aspect-initializes}@anchor{134}
@section Aspect Initializes
@geindex Initializes
-This aspect is equivalent to @ref{81,,pragma Initializes}.
+This aspect is equivalent to @ref{82,,pragma Initializes}.
@node Aspect Inline_Always,Aspect Invariant,Aspect Initializes,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-inline-always}@anchor{134}
+@anchor{gnat_rm/implementation_defined_aspects aspect-inline-always}@anchor{135}
@section Aspect Inline_Always
@geindex Inline_Always
-This boolean aspect is equivalent to @ref{83,,pragma Inline_Always}.
+This boolean aspect is equivalent to @ref{84,,pragma Inline_Always}.
@node Aspect Invariant,Aspect Invariant’Class,Aspect Inline_Always,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-invariant}@anchor{135}
+@anchor{gnat_rm/implementation_defined_aspects aspect-invariant}@anchor{136}
@section Aspect Invariant
@geindex Invariant
-This aspect is equivalent to @ref{8a,,pragma Invariant}. It is a
+This aspect is equivalent to @ref{8b,,pragma Invariant}. It is a
synonym for the language defined aspect @code{Type_Invariant} except
that it is separately controllable using pragma @code{Assertion_Policy}.
@node Aspect Invariant’Class,Aspect Iterable,Aspect Invariant,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-invariant-class}@anchor{136}
+@anchor{gnat_rm/implementation_defined_aspects aspect-invariant-class}@anchor{137}
@section Aspect Invariant’Class
@geindex Invariant'Class
-This aspect is equivalent to @ref{101,,pragma Type_Invariant_Class}. It is a
+This aspect is equivalent to @ref{102,,pragma Type_Invariant_Class}. It is a
synonym for the language defined aspect @code{Type_Invariant'Class} except
that it is separately controllable using pragma @code{Assertion_Policy}.
@node Aspect Iterable,Aspect Linker_Section,Aspect Invariant’Class,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-iterable}@anchor{137}
+@anchor{gnat_rm/implementation_defined_aspects aspect-iterable}@anchor{138}
@section Aspect Iterable
@@ -9753,73 +9772,73 @@ function Get_Element (Cont : Container; Position : Cursor) return Element_Type;
This aspect is used in the GNAT-defined formal container packages.
@node Aspect Linker_Section,Aspect Lock_Free,Aspect Iterable,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-linker-section}@anchor{138}
+@anchor{gnat_rm/implementation_defined_aspects aspect-linker-section}@anchor{139}
@section Aspect Linker_Section
@geindex Linker_Section
-This aspect is equivalent to @ref{92,,pragma Linker_Section}.
+This aspect is equivalent to @ref{93,,pragma Linker_Section}.
@node Aspect Lock_Free,Aspect Max_Queue_Length,Aspect Linker_Section,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-lock-free}@anchor{139}
+@anchor{gnat_rm/implementation_defined_aspects aspect-lock-free}@anchor{13a}
@section Aspect Lock_Free
@geindex Lock_Free
-This boolean aspect is equivalent to @ref{94,,pragma Lock_Free}.
+This boolean aspect is equivalent to @ref{95,,pragma Lock_Free}.
@node Aspect Max_Queue_Length,Aspect No_Caching,Aspect Lock_Free,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-max-queue-length}@anchor{13a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-max-queue-length}@anchor{13b}
@section Aspect Max_Queue_Length
@geindex Max_Queue_Length
-This aspect is equivalent to @ref{9c,,pragma Max_Queue_Length}.
+This aspect is equivalent to @ref{9d,,pragma Max_Queue_Length}.
@node Aspect No_Caching,Aspect No_Elaboration_Code_All,Aspect Max_Queue_Length,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-caching}@anchor{13b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-caching}@anchor{13c}
@section Aspect No_Caching
@geindex No_Caching
-This boolean aspect is equivalent to @ref{9f,,pragma No_Caching}.
+This boolean aspect is equivalent to @ref{a0,,pragma No_Caching}.
@node Aspect No_Elaboration_Code_All,Aspect No_Inline,Aspect No_Caching,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-elaboration-code-all}@anchor{13c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-elaboration-code-all}@anchor{13d}
@section Aspect No_Elaboration_Code_All
@geindex No_Elaboration_Code_All
-This aspect is equivalent to @ref{a2,,pragma No_Elaboration_Code_All}
+This aspect is equivalent to @ref{a3,,pragma No_Elaboration_Code_All}
for a program unit.
@node Aspect No_Inline,Aspect No_Tagged_Streams,Aspect No_Elaboration_Code_All,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-inline}@anchor{13d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-inline}@anchor{13e}
@section Aspect No_Inline
@geindex No_Inline
-This boolean aspect is equivalent to @ref{a5,,pragma No_Inline}.
+This boolean aspect is equivalent to @ref{a6,,pragma No_Inline}.
@node Aspect No_Tagged_Streams,Aspect No_Task_Parts,Aspect No_Inline,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-tagged-streams}@anchor{13e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-tagged-streams}@anchor{13f}
@section Aspect No_Tagged_Streams
@geindex No_Tagged_Streams
-This aspect is equivalent to @ref{a9,,pragma No_Tagged_Streams} with an
+This aspect is equivalent to @ref{aa,,pragma No_Tagged_Streams} with an
argument specifying a root tagged type (thus this aspect can only be
applied to such a type).
@node Aspect No_Task_Parts,Aspect Object_Size,Aspect No_Tagged_Streams,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-no-task-parts}@anchor{13f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-no-task-parts}@anchor{140}
@section Aspect No_Task_Parts
@@ -9835,45 +9854,45 @@ away certain tasking-related code that would otherwise be needed
for T’Class, because descendants of T might contain tasks.
@node Aspect Object_Size,Aspect Obsolescent,Aspect No_Task_Parts,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-object-size}@anchor{140}
+@anchor{gnat_rm/implementation_defined_aspects aspect-object-size}@anchor{141}
@section Aspect Object_Size
@geindex Object_Size
-This aspect is equivalent to @ref{141,,attribute Object_Size}.
+This aspect is equivalent to @ref{142,,attribute Object_Size}.
@node Aspect Obsolescent,Aspect Part_Of,Aspect Object_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-obsolescent}@anchor{142}
+@anchor{gnat_rm/implementation_defined_aspects aspect-obsolescent}@anchor{143}
@section Aspect Obsolescent
@geindex Obsolsecent
-This aspect is equivalent to @ref{ac,,pragma Obsolescent}. Note that the
+This aspect is equivalent to @ref{ad,,pragma Obsolescent}. Note that the
evaluation of this aspect happens at the point of occurrence, it is not
delayed until the freeze point.
@node Aspect Part_Of,Aspect Persistent_BSS,Aspect Obsolescent,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-part-of}@anchor{143}
+@anchor{gnat_rm/implementation_defined_aspects aspect-part-of}@anchor{144}
@section Aspect Part_Of
@geindex Part_Of
-This aspect is equivalent to @ref{b3,,pragma Part_Of}.
+This aspect is equivalent to @ref{b4,,pragma Part_Of}.
@node Aspect Persistent_BSS,Aspect Predicate,Aspect Part_Of,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-persistent-bss}@anchor{144}
+@anchor{gnat_rm/implementation_defined_aspects aspect-persistent-bss}@anchor{145}
@section Aspect Persistent_BSS
@geindex Persistent_BSS
-This boolean aspect is equivalent to @ref{b6,,pragma Persistent_BSS}.
+This boolean aspect is equivalent to @ref{b7,,pragma Persistent_BSS}.
@node Aspect Predicate,Aspect Pure_Function,Aspect Persistent_BSS,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-predicate}@anchor{145}
+@anchor{gnat_rm/implementation_defined_aspects aspect-predicate}@anchor{146}
@section Aspect Predicate
@@ -9887,7 +9906,7 @@ expression. It is also separately controllable using pragma
@code{Assertion_Policy}.
@node Aspect Pure_Function,Aspect Refined_Depends,Aspect Predicate,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-pure-function}@anchor{146}
+@anchor{gnat_rm/implementation_defined_aspects aspect-pure-function}@anchor{147}
@section Aspect Pure_Function
@@ -9896,7 +9915,7 @@ expression. It is also separately controllable using pragma
This boolean aspect is equivalent to @ref{ca,,pragma Pure_Function}.
@node Aspect Refined_Depends,Aspect Refined_Global,Aspect Pure_Function,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-depends}@anchor{147}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-depends}@anchor{148}
@section Aspect Refined_Depends
@@ -9905,7 +9924,7 @@ This boolean aspect is equivalent to @ref{ca,,pragma Pure_Function}.
This aspect is equivalent to @ref{ce,,pragma Refined_Depends}.
@node Aspect Refined_Global,Aspect Refined_Post,Aspect Refined_Depends,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-global}@anchor{148}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-global}@anchor{149}
@section Aspect Refined_Global
@@ -9914,7 +9933,7 @@ This aspect is equivalent to @ref{ce,,pragma Refined_Depends}.
This aspect is equivalent to @ref{d0,,pragma Refined_Global}.
@node Aspect Refined_Post,Aspect Refined_State,Aspect Refined_Global,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-post}@anchor{149}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-post}@anchor{14a}
@section Aspect Refined_Post
@@ -9923,7 +9942,7 @@ This aspect is equivalent to @ref{d0,,pragma Refined_Global}.
This aspect is equivalent to @ref{d2,,pragma Refined_Post}.
@node Aspect Refined_State,Aspect Relaxed_Initialization,Aspect Refined_Post,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-refined-state}@anchor{14a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-refined-state}@anchor{14b}
@section Aspect Refined_State
@@ -9932,7 +9951,7 @@ This aspect is equivalent to @ref{d2,,pragma Refined_Post}.
This aspect is equivalent to @ref{d4,,pragma Refined_State}.
@node Aspect Relaxed_Initialization,Aspect Remote_Access_Type,Aspect Refined_State,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-relaxed-initialization}@anchor{14b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-relaxed-initialization}@anchor{14c}
@section Aspect Relaxed_Initialization
@@ -9942,7 +9961,7 @@ For the syntax and semantics of this aspect, see the SPARK 2014 Reference
Manual, section 6.10.
@node Aspect Remote_Access_Type,Aspect Secondary_Stack_Size,Aspect Relaxed_Initialization,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-remote-access-type}@anchor{14c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-remote-access-type}@anchor{14d}
@section Aspect Remote_Access_Type
@@ -9951,178 +9970,178 @@ Manual, section 6.10.
This aspect is equivalent to @ref{d7,,pragma Remote_Access_Type}.
@node Aspect Secondary_Stack_Size,Aspect Scalar_Storage_Order,Aspect Remote_Access_Type,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-secondary-stack-size}@anchor{14d}
+@anchor{gnat_rm/implementation_defined_aspects aspect-secondary-stack-size}@anchor{14e}
@section Aspect Secondary_Stack_Size
@geindex Secondary_Stack_Size
-This aspect is equivalent to @ref{dc,,pragma Secondary_Stack_Size}.
+This aspect is equivalent to @ref{dd,,pragma Secondary_Stack_Size}.
@node Aspect Scalar_Storage_Order,Aspect Shared,Aspect Secondary_Stack_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-scalar-storage-order}@anchor{14e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-scalar-storage-order}@anchor{14f}
@section Aspect Scalar_Storage_Order
@geindex Scalar_Storage_Order
-This aspect is equivalent to a @ref{14f,,attribute Scalar_Storage_Order}.
+This aspect is equivalent to a @ref{150,,attribute Scalar_Storage_Order}.
@node Aspect Shared,Aspect Simple_Storage_Pool,Aspect Scalar_Storage_Order,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-shared}@anchor{150}
+@anchor{gnat_rm/implementation_defined_aspects aspect-shared}@anchor{151}
@section Aspect Shared
@geindex Shared
-This boolean aspect is equivalent to @ref{df,,pragma Shared}
+This boolean aspect is equivalent to @ref{e0,,pragma Shared}
and is thus a synonym for aspect @code{Atomic}.
@node Aspect Simple_Storage_Pool,Aspect Simple_Storage_Pool_Type,Aspect Shared,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool}@anchor{151}
+@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool}@anchor{152}
@section Aspect Simple_Storage_Pool
@geindex Simple_Storage_Pool
-This aspect is equivalent to @ref{e4,,attribute Simple_Storage_Pool}.
+This aspect is equivalent to @ref{e5,,attribute Simple_Storage_Pool}.
@node Aspect Simple_Storage_Pool_Type,Aspect SPARK_Mode,Aspect Simple_Storage_Pool,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool-type}@anchor{152}
+@anchor{gnat_rm/implementation_defined_aspects aspect-simple-storage-pool-type}@anchor{153}
@section Aspect Simple_Storage_Pool_Type
@geindex Simple_Storage_Pool_Type
-This boolean aspect is equivalent to @ref{e3,,pragma Simple_Storage_Pool_Type}.
+This boolean aspect is equivalent to @ref{e4,,pragma Simple_Storage_Pool_Type}.
@node Aspect SPARK_Mode,Aspect Suppress_Debug_Info,Aspect Simple_Storage_Pool_Type,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-spark-mode}@anchor{153}
+@anchor{gnat_rm/implementation_defined_aspects aspect-spark-mode}@anchor{154}
@section Aspect SPARK_Mode
@geindex SPARK_Mode
-This aspect is equivalent to @ref{eb,,pragma SPARK_Mode} and
+This aspect is equivalent to @ref{ec,,pragma SPARK_Mode} and
may be specified for either or both of the specification and body
of a subprogram or package.
@node Aspect Suppress_Debug_Info,Aspect Suppress_Initialization,Aspect SPARK_Mode,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-debug-info}@anchor{154}
+@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-debug-info}@anchor{155}
@section Aspect Suppress_Debug_Info
@geindex Suppress_Debug_Info
-This boolean aspect is equivalent to @ref{f3,,pragma Suppress_Debug_Info}.
+This boolean aspect is equivalent to @ref{f4,,pragma Suppress_Debug_Info}.
@node Aspect Suppress_Initialization,Aspect Test_Case,Aspect Suppress_Debug_Info,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-initialization}@anchor{155}
+@anchor{gnat_rm/implementation_defined_aspects aspect-suppress-initialization}@anchor{156}
@section Aspect Suppress_Initialization
@geindex Suppress_Initialization
-This boolean aspect is equivalent to @ref{f6,,pragma Suppress_Initialization}.
+This boolean aspect is equivalent to @ref{f7,,pragma Suppress_Initialization}.
@node Aspect Test_Case,Aspect Thread_Local_Storage,Aspect Suppress_Initialization,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-test-case}@anchor{156}
+@anchor{gnat_rm/implementation_defined_aspects aspect-test-case}@anchor{157}
@section Aspect Test_Case
@geindex Test_Case
-This aspect is equivalent to @ref{fa,,pragma Test_Case}.
+This aspect is equivalent to @ref{fb,,pragma Test_Case}.
@node Aspect Thread_Local_Storage,Aspect Universal_Aliasing,Aspect Test_Case,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-thread-local-storage}@anchor{157}
+@anchor{gnat_rm/implementation_defined_aspects aspect-thread-local-storage}@anchor{158}
@section Aspect Thread_Local_Storage
@geindex Thread_Local_Storage
-This boolean aspect is equivalent to @ref{fc,,pragma Thread_Local_Storage}.
+This boolean aspect is equivalent to @ref{fd,,pragma Thread_Local_Storage}.
@node Aspect Universal_Aliasing,Aspect Unmodified,Aspect Thread_Local_Storage,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-universal-aliasing}@anchor{158}
+@anchor{gnat_rm/implementation_defined_aspects aspect-universal-aliasing}@anchor{159}
@section Aspect Universal_Aliasing
@geindex Universal_Aliasing
-This boolean aspect is equivalent to @ref{106,,pragma Universal_Aliasing}.
+This boolean aspect is equivalent to @ref{107,,pragma Universal_Aliasing}.
@node Aspect Unmodified,Aspect Unreferenced,Aspect Universal_Aliasing,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unmodified}@anchor{159}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unmodified}@anchor{15a}
@section Aspect Unmodified
@geindex Unmodified
-This boolean aspect is equivalent to @ref{108,,pragma Unmodified}.
+This boolean aspect is equivalent to @ref{109,,pragma Unmodified}.
@node Aspect Unreferenced,Aspect Unreferenced_Objects,Aspect Unmodified,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced}@anchor{15a}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced}@anchor{15b}
@section Aspect Unreferenced
@geindex Unreferenced
-This boolean aspect is equivalent to @ref{10a,,pragma Unreferenced}.
+This boolean aspect is equivalent to @ref{10b,,pragma Unreferenced}.
When using the @code{-gnat2022} switch, this aspect is also supported on formal
parameters, which is in particular the only form possible for expression
functions.
@node Aspect Unreferenced_Objects,Aspect Value_Size,Aspect Unreferenced,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced-objects}@anchor{15b}
+@anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced-objects}@anchor{15c}
@section Aspect Unreferenced_Objects
@geindex Unreferenced_Objects
-This boolean aspect is equivalent to @ref{10c,,pragma Unreferenced_Objects}.
+This boolean aspect is equivalent to @ref{10d,,pragma Unreferenced_Objects}.
@node Aspect Value_Size,Aspect Volatile_Full_Access,Aspect Unreferenced_Objects,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-value-size}@anchor{15c}
+@anchor{gnat_rm/implementation_defined_aspects aspect-value-size}@anchor{15d}
@section Aspect Value_Size
@geindex Value_Size
-This aspect is equivalent to @ref{15d,,attribute Value_Size}.
+This aspect is equivalent to @ref{15e,,attribute Value_Size}.
@node Aspect Volatile_Full_Access,Aspect Volatile_Function,Aspect Value_Size,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-full-access}@anchor{15e}
+@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-full-access}@anchor{15f}
@section Aspect Volatile_Full_Access
@geindex Volatile_Full_Access
-This boolean aspect is equivalent to @ref{116,,pragma Volatile_Full_Access}.
+This boolean aspect is equivalent to @ref{117,,pragma Volatile_Full_Access}.
@node Aspect Volatile_Function,Aspect Warnings,Aspect Volatile_Full_Access,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-function}@anchor{15f}
+@anchor{gnat_rm/implementation_defined_aspects aspect-volatile-function}@anchor{160}
@section Aspect Volatile_Function
@geindex Volatile_Function
-This boolean aspect is equivalent to @ref{118,,pragma Volatile_Function}.
+This boolean aspect is equivalent to @ref{119,,pragma Volatile_Function}.
@node Aspect Warnings,,Aspect Volatile_Function,Implementation Defined Aspects
-@anchor{gnat_rm/implementation_defined_aspects aspect-warnings}@anchor{160}
+@anchor{gnat_rm/implementation_defined_aspects aspect-warnings}@anchor{161}
@section Aspect Warnings
@geindex Warnings
-This aspect is equivalent to the two argument form of @ref{11a,,pragma Warnings},
+This aspect is equivalent to the two argument form of @ref{11b,,pragma Warnings},
where the first argument is @code{ON} or @code{OFF} and the second argument
is the entity.
@node Implementation Defined Attributes,Standard and Implementation Defined Restrictions,Implementation Defined Aspects,Top
-@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{161}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{162}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8}
+@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{162}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{163}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8}
@chapter Implementation Defined Attributes
@@ -10229,7 +10248,7 @@ consideration, you should minimize the use of these attributes.
@end menu
@node Attribute Abort_Signal,Attribute Address_Size,,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-abort-signal}@anchor{163}
+@anchor{gnat_rm/implementation_defined_attributes attribute-abort-signal}@anchor{164}
@section Attribute Abort_Signal
@@ -10243,7 +10262,7 @@ completely outside the normal semantics of Ada, for a user program to
intercept the abort exception).
@node Attribute Address_Size,Attribute Asm_Input,Attribute Abort_Signal,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-address-size}@anchor{164}
+@anchor{gnat_rm/implementation_defined_attributes attribute-address-size}@anchor{165}
@section Attribute Address_Size
@@ -10259,7 +10278,7 @@ reference to System.Address’Size is nonstatic because Address
is a private type.
@node Attribute Asm_Input,Attribute Asm_Output,Attribute Address_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-asm-input}@anchor{165}
+@anchor{gnat_rm/implementation_defined_attributes attribute-asm-input}@anchor{166}
@section Attribute Asm_Input
@@ -10273,10 +10292,10 @@ to be a static expression, and is the constraint for the parameter,
value to be used as the input argument. The possible values for the
constant are the same as those used in the RTL, and are dependent on
the configuration file used to built the GCC back end.
-@ref{166,,Machine Code Insertions}
+@ref{167,,Machine Code Insertions}
@node Attribute Asm_Output,Attribute Atomic_Always_Lock_Free,Attribute Asm_Input,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-asm-output}@anchor{167}
+@anchor{gnat_rm/implementation_defined_attributes attribute-asm-output}@anchor{168}
@section Attribute Asm_Output
@@ -10292,10 +10311,10 @@ result. The possible values for constraint are the same as those used in
the RTL, and are dependent on the configuration file used to build the
GCC back end. If there are no output operands, then this argument may
either be omitted, or explicitly given as @code{No_Output_Operands}.
-@ref{166,,Machine Code Insertions}
+@ref{167,,Machine Code Insertions}
@node Attribute Atomic_Always_Lock_Free,Attribute Bit,Attribute Asm_Output,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-atomic-always-lock-free}@anchor{168}
+@anchor{gnat_rm/implementation_defined_attributes attribute-atomic-always-lock-free}@anchor{169}
@section Attribute Atomic_Always_Lock_Free
@@ -10307,7 +10326,7 @@ and False otherwise. The result indicate whether atomic operations are
supported by the target for the given type.
@node Attribute Bit,Attribute Bit_Position,Attribute Atomic_Always_Lock_Free,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-bit}@anchor{169}
+@anchor{gnat_rm/implementation_defined_attributes attribute-bit}@anchor{16a}
@section Attribute Bit
@@ -10338,7 +10357,7 @@ This attribute is designed to be compatible with the DEC Ada 83 definition
and implementation of the @code{Bit} attribute.
@node Attribute Bit_Position,Attribute Code_Address,Attribute Bit,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-bit-position}@anchor{16a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-bit-position}@anchor{16b}
@section Attribute Bit_Position
@@ -10353,7 +10372,7 @@ type @emph{universal_integer}. The value depends only on the field
the containing record @code{R}.
@node Attribute Code_Address,Attribute Compiler_Version,Attribute Bit_Position,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-code-address}@anchor{16b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-code-address}@anchor{16c}
@section Attribute Code_Address
@@ -10396,7 +10415,7 @@ the same value as is returned by the corresponding @code{'Address}
attribute.
@node Attribute Compiler_Version,Attribute Constrained,Attribute Code_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-compiler-version}@anchor{16c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-compiler-version}@anchor{16d}
@section Attribute Compiler_Version
@@ -10407,7 +10426,7 @@ prefix) yields a static string identifying the version of the compiler
being used to compile the unit containing the attribute reference.
@node Attribute Constrained,Attribute Default_Bit_Order,Attribute Compiler_Version,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-constrained}@anchor{16d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-constrained}@anchor{16e}
@section Attribute Constrained
@@ -10422,7 +10441,7 @@ record type without discriminants is always @code{True}. This usage is
compatible with older Ada compilers, including notably DEC Ada.
@node Attribute Default_Bit_Order,Attribute Default_Scalar_Storage_Order,Attribute Constrained,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-default-bit-order}@anchor{16e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-default-bit-order}@anchor{16f}
@section Attribute Default_Bit_Order
@@ -10439,7 +10458,7 @@ as a @code{Pos} value (0 for @code{High_Order_First}, 1 for
@code{Default_Bit_Order} in package @code{System}.
@node Attribute Default_Scalar_Storage_Order,Attribute Deref,Attribute Default_Bit_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-default-scalar-storage-order}@anchor{16f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-default-scalar-storage-order}@anchor{170}
@section Attribute Default_Scalar_Storage_Order
@@ -10456,7 +10475,7 @@ equal to @code{Default_Bit_Order} if unspecified) as a
@code{System.Bit_Order} value. This is a static attribute.
@node Attribute Deref,Attribute Descriptor_Size,Attribute Default_Scalar_Storage_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-deref}@anchor{170}
+@anchor{gnat_rm/implementation_defined_attributes attribute-deref}@anchor{171}
@section Attribute Deref
@@ -10469,7 +10488,7 @@ a named access-to-@cite{typ} type, except that it yields a variable, so it can b
used on the left side of an assignment.
@node Attribute Descriptor_Size,Attribute Elaborated,Attribute Deref,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-descriptor-size}@anchor{171}
+@anchor{gnat_rm/implementation_defined_attributes attribute-descriptor-size}@anchor{172}
@section Attribute Descriptor_Size
@@ -10498,7 +10517,7 @@ since @code{Positive} has an alignment of 4, the size of the descriptor is
which yields a size of 32 bits, i.e. including 16 bits of padding.
@node Attribute Elaborated,Attribute Elab_Body,Attribute Descriptor_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elaborated}@anchor{172}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elaborated}@anchor{173}
@section Attribute Elaborated
@@ -10513,7 +10532,7 @@ units has been completed. An exception is for units which need no
elaboration, the value is always False for such units.
@node Attribute Elab_Body,Attribute Elab_Spec,Attribute Elaborated,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-body}@anchor{173}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-body}@anchor{174}
@section Attribute Elab_Body
@@ -10529,7 +10548,7 @@ e.g., if it is necessary to do selective re-elaboration to fix some
error.
@node Attribute Elab_Spec,Attribute Elab_Subp_Body,Attribute Elab_Body,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-spec}@anchor{174}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-spec}@anchor{175}
@section Attribute Elab_Spec
@@ -10545,7 +10564,7 @@ Ada code, e.g., if it is necessary to do selective re-elaboration to fix
some error.
@node Attribute Elab_Subp_Body,Attribute Emax,Attribute Elab_Spec,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-elab-subp-body}@anchor{175}
+@anchor{gnat_rm/implementation_defined_attributes attribute-elab-subp-body}@anchor{176}
@section Attribute Elab_Subp_Body
@@ -10559,7 +10578,7 @@ elaboration procedure by the binder in CodePeer mode only and is unrecognized
otherwise.
@node Attribute Emax,Attribute Enabled,Attribute Elab_Subp_Body,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-emax}@anchor{176}
+@anchor{gnat_rm/implementation_defined_attributes attribute-emax}@anchor{177}
@section Attribute Emax
@@ -10572,7 +10591,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Enabled,Attribute Enum_Rep,Attribute Emax,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enabled}@anchor{177}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enabled}@anchor{178}
@section Attribute Enabled
@@ -10596,7 +10615,7 @@ a @code{pragma Suppress} or @code{pragma Unsuppress} before instantiating
the package or subprogram, controlling whether the check will be present.
@node Attribute Enum_Rep,Attribute Enum_Val,Attribute Enabled,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enum-rep}@anchor{178}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enum-rep}@anchor{179}
@section Attribute Enum_Rep
@@ -10636,7 +10655,7 @@ integer calculation is done at run time, then the call to @code{Enum_Rep}
may raise @code{Constraint_Error}.
@node Attribute Enum_Val,Attribute Epsilon,Attribute Enum_Rep,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-enum-val}@anchor{179}
+@anchor{gnat_rm/implementation_defined_attributes attribute-enum-val}@anchor{17a}
@section Attribute Enum_Val
@@ -10662,7 +10681,7 @@ absence of an enumeration representation clause. This is a static
attribute (i.e., the result is static if the argument is static).
@node Attribute Epsilon,Attribute Fast_Math,Attribute Enum_Val,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-epsilon}@anchor{17a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-epsilon}@anchor{17b}
@section Attribute Epsilon
@@ -10675,7 +10694,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Fast_Math,Attribute Finalization_Size,Attribute Epsilon,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-fast-math}@anchor{17b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-fast-math}@anchor{17c}
@section Attribute Fast_Math
@@ -10686,7 +10705,7 @@ prefix) yields a static Boolean value that is True if pragma
@code{Fast_Math} is active, and False otherwise.
@node Attribute Finalization_Size,Attribute Fixed_Value,Attribute Fast_Math,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-finalization-size}@anchor{17c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-finalization-size}@anchor{17d}
@section Attribute Finalization_Size
@@ -10704,7 +10723,7 @@ class-wide type whose tag denotes a type with no controlled parts.
Note that only heap-allocated objects contain finalization data.
@node Attribute Fixed_Value,Attribute From_Any,Attribute Finalization_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-fixed-value}@anchor{17d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-fixed-value}@anchor{17e}
@section Attribute Fixed_Value
@@ -10731,7 +10750,7 @@ This attribute is primarily intended for use in implementation of the
input-output functions for fixed-point values.
@node Attribute From_Any,Attribute Has_Access_Values,Attribute Fixed_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-from-any}@anchor{17e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-from-any}@anchor{17f}
@section Attribute From_Any
@@ -10741,7 +10760,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Has_Access_Values,Attribute Has_Discriminants,Attribute From_Any,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-access-values}@anchor{17f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-access-values}@anchor{180}
@section Attribute Has_Access_Values
@@ -10759,7 +10778,7 @@ 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 Has_Tagged_Values,Attribute Has_Access_Values,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-discriminants}@anchor{180}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-discriminants}@anchor{181}
@section Attribute Has_Discriminants
@@ -10775,7 +10794,7 @@ definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has discriminants.
@node Attribute Has_Tagged_Values,Attribute Img,Attribute Has_Discriminants,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-has-tagged-values}@anchor{181}
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-tagged-values}@anchor{182}
@section Attribute Has_Tagged_Values
@@ -10792,7 +10811,7 @@ 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{182}
+@anchor{gnat_rm/implementation_defined_attributes attribute-img}@anchor{183}
@section Attribute Img
@@ -10822,7 +10841,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{183}
+@anchor{gnat_rm/implementation_defined_attributes attribute-initialized}@anchor{184}
@section Attribute Initialized
@@ -10832,7 +10851,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{184}
+@anchor{gnat_rm/implementation_defined_attributes attribute-integer-value}@anchor{185}
@section Attribute Integer_Value
@@ -10860,7 +10879,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{185}
+@anchor{gnat_rm/implementation_defined_attributes attribute-invalid-value}@anchor{186}
@section Attribute Invalid_Value
@@ -10874,7 +10893,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{186}
+@anchor{gnat_rm/implementation_defined_attributes attribute-iterable}@anchor{187}
@section Attribute Iterable
@@ -10883,7 +10902,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{187}
+@anchor{gnat_rm/implementation_defined_attributes attribute-large}@anchor{188}
@section Attribute Large
@@ -10896,7 +10915,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{188}
+@anchor{gnat_rm/implementation_defined_attributes attribute-library-level}@anchor{189}
@section Attribute Library_Level
@@ -10922,7 +10941,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{189}
+@anchor{gnat_rm/implementation_defined_attributes attribute-lock-free}@anchor{18a}
@section Attribute Lock_Free
@@ -10932,7 +10951,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{18a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-loop-entry}@anchor{18b}
@section Attribute Loop_Entry
@@ -10962,7 +10981,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{18b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-machine-size}@anchor{18c}
@section Attribute Machine_Size
@@ -10972,7 +10991,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{18c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mantissa}@anchor{18d}
@section Attribute Mantissa
@@ -10985,7 +11004,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{18d}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{18e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-maximum-alignment}@anchor{18e}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{18f}
@section Attribute Maximum_Alignment
@@ -11001,7 +11020,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{18f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-max-integer-size}@anchor{190}
@section Attribute Max_Integer_Size
@@ -11012,7 +11031,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{190}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mechanism-code}@anchor{191}
@section Attribute Mechanism_Code
@@ -11043,7 +11062,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{191}
+@anchor{gnat_rm/implementation_defined_attributes attribute-null-parameter}@anchor{192}
@section Attribute Null_Parameter
@@ -11068,7 +11087,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{141}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{192}
+@anchor{gnat_rm/implementation_defined_attributes attribute-object-size}@anchor{142}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{193}
@section Attribute Object_Size
@@ -11138,7 +11157,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{193}
+@anchor{gnat_rm/implementation_defined_attributes attribute-old}@anchor{194}
@section Attribute Old
@@ -11153,7 +11172,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{194}
+@anchor{gnat_rm/implementation_defined_attributes attribute-passed-by-reference}@anchor{195}
@section Attribute Passed_By_Reference
@@ -11169,7 +11188,7 @@ 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{195}
+@anchor{gnat_rm/implementation_defined_attributes attribute-pool-address}@anchor{196}
@section Attribute Pool_Address
@@ -11191,7 +11210,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{196}
+@anchor{gnat_rm/implementation_defined_attributes attribute-range-length}@anchor{197}
@section Attribute Range_Length
@@ -11204,7 +11223,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{197}
+@anchor{gnat_rm/implementation_defined_attributes attribute-restriction-set}@anchor{198}
@section Attribute Restriction_Set
@@ -11274,7 +11293,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{198}
+@anchor{gnat_rm/implementation_defined_attributes attribute-result}@anchor{199}
@section Attribute Result
@@ -11287,7 +11306,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{199}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-emax}@anchor{19a}
@section Attribute Safe_Emax
@@ -11300,7 +11319,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{19a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-large}@anchor{19b}
@section Attribute Safe_Large
@@ -11313,7 +11332,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{19b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-small}@anchor{19c}
@section Attribute Safe_Small
@@ -11326,7 +11345,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 attribute-scalar-storage-order}@anchor{14f}@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{150}@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19d}
@section Attribute Scalar_Storage_Order
@@ -11489,7 +11508,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{e4}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e5}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19e}
@section Attribute Simple_Storage_Pool
@@ -11552,7 +11571,7 @@ 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 Small_Denominator,Attribute Simple_Storage_Pool,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{19e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{19f}
@section Attribute Small
@@ -11568,7 +11587,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute when applied to floating-point types.
@node Attribute Small_Denominator,Attribute Small_Numerator,Attribute Small,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small-denominator}@anchor{19f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-denominator}@anchor{1a0}
@section Attribute Small_Denominator
@@ -11581,7 +11600,7 @@ 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{1a0}
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-numerator}@anchor{1a1}
@section Attribute Small_Numerator
@@ -11594,7 +11613,7 @@ 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{1a1}
+@anchor{gnat_rm/implementation_defined_attributes attribute-storage-unit}@anchor{1a2}
@section Attribute Storage_Unit
@@ -11604,7 +11623,7 @@ with coprime factors (i.e. as an irreducible fraction).
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{1a3}
@section Attribute Stub_Type
@@ -11628,7 +11647,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{1a4}
@section Attribute System_Allocator_Alignment
@@ -11645,7 +11664,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{1a5}
@section Attribute Target_Name
@@ -11658,7 +11677,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{1a6}
@section Attribute To_Address
@@ -11681,7 +11700,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{1a7}
@section Attribute To_Any
@@ -11691,7 +11710,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{1a8}
@section Attribute Type_Class
@@ -11721,7 +11740,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{1a9}
@section Attribute Type_Key
@@ -11733,7 +11752,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{1aa}
@section Attribute TypeCode
@@ -11743,7 +11762,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{1ab}
@section Attribute Unconstrained_Array
@@ -11757,7 +11776,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{1ac}
@section Attribute Universal_Literal_String
@@ -11785,7 +11804,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{1ad}
@section Attribute Unrestricted_Access
@@ -11972,7 +11991,7 @@ In general this is a risky approach. It may appear to “work” but such uses o
of GNAT to another, so are best avoided if possible.
@node Attribute Update,Attribute Valid_Image,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{1ae}
@section Attribute Update
@@ -12053,7 +12072,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_Image,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1ae}
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1af}
@section Attribute Valid_Image
@@ -12065,7 +12084,7 @@ a String, and returns Boolean. @code{T'Valid_Image (S)} returns True
if and only if @code{T'Value (S)} would not raise Constraint_Error.
@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Image,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1af}
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1b0}
@section Attribute Valid_Scalars
@@ -12099,7 +12118,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{1b0}
+@anchor{gnat_rm/implementation_defined_attributes attribute-vads-size}@anchor{1b1}
@section Attribute VADS_Size
@@ -12119,7 +12138,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 attribute-value-size}@anchor{15d}@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b1}
+@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{15e}@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b2}
@section Attribute Value_Size
@@ -12133,7 +12152,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{1b2}
+@anchor{gnat_rm/implementation_defined_attributes attribute-wchar-t-size}@anchor{1b3}
@section Attribute Wchar_T_Size
@@ -12145,7 +12164,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{1b3}
+@anchor{gnat_rm/implementation_defined_attributes attribute-word-size}@anchor{1b4}
@section Attribute Word_Size
@@ -12156,7 +12175,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 doc}@anchor{1b4}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b5}@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{1b5}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}
@chapter Standard and Implementation Defined Restrictions
@@ -12185,7 +12204,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 id2}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b7}@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b8}
@section Partition-Wide Restrictions
@@ -12274,7 +12293,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{1b8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions immediate-reclamation}@anchor{1b9}
@subsection Immediate_Reclamation
@@ -12286,7 +12305,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{1b9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-asynchronous-select-nesting}@anchor{1ba}
@subsection Max_Asynchronous_Select_Nesting
@@ -12298,7 +12317,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{1ba}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-entry-queue-length}@anchor{1bb}
@subsection Max_Entry_Queue_Length
@@ -12319,7 +12338,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{1bb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-protected-entries}@anchor{1bc}
@subsection Max_Protected_Entries
@@ -12330,7 +12349,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{1bc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-select-alternatives}@anchor{1bd}
@subsection Max_Select_Alternatives
@@ -12339,7 +12358,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{1bd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-storage-at-blocking}@anchor{1be}
@subsection Max_Storage_At_Blocking
@@ -12350,7 +12369,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{1be}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-task-entries}@anchor{1bf}
@subsection Max_Task_Entries
@@ -12363,7 +12382,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{1bf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-tasks}@anchor{1c0}
@subsection Max_Tasks
@@ -12376,7 +12395,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{1c0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-abort-statements}@anchor{1c1}
@subsection No_Abort_Statements
@@ -12386,7 +12405,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{1c1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-parameter-allocators}@anchor{1c2}
@subsection No_Access_Parameter_Allocators
@@ -12397,7 +12416,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{1c2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-subprograms}@anchor{1c3}
@subsection No_Access_Subprograms
@@ -12407,7 +12426,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{1c3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-allocators}@anchor{1c4}
@subsection No_Allocators
@@ -12417,7 +12436,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{1c4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-anonymous-allocators}@anchor{1c5}
@subsection No_Anonymous_Allocators
@@ -12427,7 +12446,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{1c5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-asynchronous-control}@anchor{1c6}
@subsection No_Asynchronous_Control
@@ -12437,7 +12456,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{1c6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-calendar}@anchor{1c7}
@subsection No_Calendar
@@ -12447,7 +12466,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{1c7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-coextensions}@anchor{1c8}
@subsection No_Coextensions
@@ -12457,7 +12476,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{1c8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-default-initialization}@anchor{1c9}
@subsection No_Default_Initialization
@@ -12474,7 +12493,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{1c9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-delay}@anchor{1ca}
@subsection No_Delay
@@ -12484,7 +12503,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{1ca}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dependence}@anchor{1cb}
@subsection No_Dependence
@@ -12494,7 +12513,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{1cb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1cc}
@subsection No_Direct_Boolean_Operators
@@ -12507,7 +12526,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{1cc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatch}@anchor{1cd}
@subsection No_Dispatch
@@ -12517,7 +12536,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{1cd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatching-calls}@anchor{1ce}
@subsection No_Dispatching_Calls
@@ -12578,7 +12597,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{1ce}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-attachment}@anchor{1cf}
@subsection No_Dynamic_Attachment
@@ -12597,7 +12616,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{1cf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-priorities}@anchor{1d0}
@subsection No_Dynamic_Priorities
@@ -12606,7 +12625,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{1d0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-calls-in-elaboration-code}@anchor{1d1}
@subsection No_Entry_Calls_In_Elaboration_Code
@@ -12618,7 +12637,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{1d1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-enumeration-maps}@anchor{1d2}
@subsection No_Enumeration_Maps
@@ -12629,7 +12648,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{1d2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-handlers}@anchor{1d3}
@subsection No_Exception_Handlers
@@ -12654,7 +12673,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{1d3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-propagation}@anchor{1d4}
@subsection No_Exception_Propagation
@@ -12671,7 +12690,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{1d4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-registration}@anchor{1d5}
@subsection No_Exception_Registration
@@ -12685,7 +12704,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{1d5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exceptions}@anchor{1d6}
@subsection No_Exceptions
@@ -12696,7 +12715,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{1d6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d7}
@subsection No_Finalization
@@ -12737,7 +12756,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{1d7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-fixed-point}@anchor{1d8}
@subsection No_Fixed_Point
@@ -12747,7 +12766,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{1d8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-floating-point}@anchor{1d9}
@subsection No_Floating_Point
@@ -12757,7 +12776,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{1d9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-conditionals}@anchor{1da}
@subsection No_Implicit_Conditionals
@@ -12773,7 +12792,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{1da}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-dynamic-code}@anchor{1db}
@subsection No_Implicit_Dynamic_Code
@@ -12803,7 +12822,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{1db}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-heap-allocations}@anchor{1dc}
@subsection No_Implicit_Heap_Allocations
@@ -12812,7 +12831,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{1dc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-protected-object-allocations}@anchor{1dd}
@subsection No_Implicit_Protected_Object_Allocations
@@ -12822,7 +12841,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{1dd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-task-allocations}@anchor{1de}
@subsection No_Implicit_Task_Allocations
@@ -12831,7 +12850,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{1de}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-initialize-scalars}@anchor{1df}
@subsection No_Initialize_Scalars
@@ -12843,7 +12862,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{1df}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-io}@anchor{1e0}
@subsection No_IO
@@ -12854,7 +12873,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{1e0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-allocators}@anchor{1e1}
@subsection No_Local_Allocators
@@ -12865,7 +12884,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{1e1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-protected-objects}@anchor{1e2}
@subsection No_Local_Protected_Objects
@@ -12875,7 +12894,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{1e2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-timing-events}@anchor{1e3}
@subsection No_Local_Timing_Events
@@ -12885,7 +12904,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{1e3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-long-long-integers}@anchor{1e4}
@subsection No_Long_Long_Integers
@@ -12897,7 +12916,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{1e4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e5}
@subsection No_Multiple_Elaboration
@@ -12913,7 +12932,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{1e5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e6}
@subsection No_Nested_Finalization
@@ -12922,7 +12941,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{1e6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-type-allocators}@anchor{1e7}
@subsection No_Protected_Type_Allocators
@@ -12932,7 +12951,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{1e7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-types}@anchor{1e8}
@subsection No_Protected_Types
@@ -12942,7 +12961,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{1e8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-recursion}@anchor{1e9}
@subsection No_Recursion
@@ -12952,7 +12971,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{1e9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-reentrancy}@anchor{1ea}
@subsection No_Reentrancy
@@ -12962,7 +12981,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{1ea}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-relative-delay}@anchor{1eb}
@subsection No_Relative_Delay
@@ -12973,7 +12992,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{1eb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-requeue-statements}@anchor{1ec}
@subsection No_Requeue_Statements
@@ -12991,7 +13010,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{1ec}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-secondary-stack}@anchor{1ed}
@subsection No_Secondary_Stack
@@ -13004,7 +13023,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{1ed}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-select-statements}@anchor{1ee}
@subsection No_Select_Statements
@@ -13014,7 +13033,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{1ee}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specific-termination-handlers}@anchor{1ef}
@subsection No_Specific_Termination_Handlers
@@ -13024,7 +13043,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{1ef}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specification-of-aspect}@anchor{1f0}
@subsection No_Specification_of_Aspect
@@ -13035,7 +13054,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{1f0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-allocators-after-elaboration}@anchor{1f1}
@subsection No_Standard_Allocators_After_Elaboration
@@ -13047,7 +13066,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{1f1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-storage-pools}@anchor{1f2}
@subsection No_Standard_Storage_Pools
@@ -13059,7 +13078,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{1f2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-stream-optimizations}@anchor{1f3}
@subsection No_Stream_Optimizations
@@ -13072,7 +13091,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{1f3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-streams}@anchor{1f4}
@subsection No_Streams
@@ -13093,7 +13112,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{1f4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-allocators}@anchor{1f5}
@subsection No_Task_Allocators
@@ -13103,7 +13122,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{1f5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-at-interrupt-priority}@anchor{1f6}
@subsection No_Task_At_Interrupt_Priority
@@ -13115,7 +13134,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{1f6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-attributes-package}@anchor{1f7}
@subsection No_Task_Attributes_Package
@@ -13132,7 +13151,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{1f7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-hierarchy}@anchor{1f8}
@subsection No_Task_Hierarchy
@@ -13142,7 +13161,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{1f8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-termination}@anchor{1f9}
@subsection No_Task_Termination
@@ -13151,7 +13170,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{1f9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-tasking}@anchor{1fa}
@subsection No_Tasking
@@ -13164,7 +13183,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{1fa}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-terminate-alternatives}@anchor{1fb}
@subsection No_Terminate_Alternatives
@@ -13173,7 +13192,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{1fb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-access}@anchor{1fc}
@subsection No_Unchecked_Access
@@ -13183,7 +13202,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{1fc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-conversion}@anchor{1fd}
@subsection No_Unchecked_Conversion
@@ -13193,7 +13212,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{1fd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-deallocation}@anchor{1fe}
@subsection No_Unchecked_Deallocation
@@ -13203,7 +13222,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{1fe}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-use-of-entity}@anchor{1ff}
@subsection No_Use_Of_Entity
@@ -13223,7 +13242,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{1ff}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions pure-barriers}@anchor{200}
@subsection Pure_Barriers
@@ -13274,7 +13293,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{200}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions simple-barriers}@anchor{201}
@subsection Simple_Barriers
@@ -13293,7 +13312,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{201}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-priorities}@anchor{202}
@subsection Static_Priorities
@@ -13304,7 +13323,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{202}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-storage-size}@anchor{203}
@subsection Static_Storage_Size
@@ -13314,7 +13333,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 id3}@anchor{203}@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{204}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{204}@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{205}
@section Program Unit Level Restrictions
@@ -13326,6 +13345,7 @@ other compilation units in the partition.
@menu
* No_Elaboration_Code::
+* No_Dynamic_Accessibility_Checks::
* No_Dynamic_Sized_Objects::
* No_Entry_Queue::
* No_Implementation_Aspect_Specifications::
@@ -13343,8 +13363,8 @@ 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{205}
+@node No_Elaboration_Code,No_Dynamic_Accessibility_Checks,,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-elaboration-code}@anchor{206}
@subsection No_Elaboration_Code
@@ -13399,8 +13419,57 @@ used, the compiler is allowed to suppress the elaboration counter normally
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{206}
+@node No_Dynamic_Accessibility_Checks,No_Dynamic_Sized_Objects,No_Elaboration_Code,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-accessibility-checks}@anchor{207}
+@subsection No_Dynamic_Accessibility_Checks
+
+
+@geindex No_Dynamic_Accessibility_Checks
+
+[GNAT] No dynamic accessibility checks are generated when this restriction is
+in effect. Instead, dangling references are prevented via more conservative
+compile-time checking. More specifically, existing compile-time checks are
+enforced but with more conservative assumptions about the accessibility levels
+of the relevant entities. These conservative assumptions eliminate the need for
+dynamic accessibility checks.
+
+These new rules for computing (at compile-time) the accessibility level of an
+anonymous access type T are as follows:
+
+
+@itemize *
+
+@item
+If T is a function result type then, from the caller’s perspective, its level
+is that of the innermost master enclosing the function call. From the callee’s
+perspective, the level of parameters and local variables of the callee is
+statically deeper than the level of T.
+
+For any other accessibility level L such that the level of parameters and local
+variables of the callee is statically deeper than L, the level of T (from the
+callee’s perspective) is also statically deeper than L.
+
+@item
+If T is the type of a formal parameter then, from the caller’s perspective,
+its level is at least as deep as that of the type of the corresponding actual
+parameter (whatever that actual parameter might be). From the callee’s
+perspective, the level of parameters and local variables of the callee is
+statically deeper than the level of T.
+
+@item
+If T is the type of a discriminant then its level is that of the discriminated
+type.
+
+@item
+If T is the type of a stand-alone object then its level is the level of the
+object.
+
+@item
+In all other cases, the level of T is as defined by the existing rules of Ada.
+@end itemize
+
+@node No_Dynamic_Sized_Objects,No_Entry_Queue,No_Dynamic_Accessibility_Checks,Program Unit Level Restrictions
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-sized-objects}@anchor{208}
@subsection No_Dynamic_Sized_Objects
@@ -13418,7 +13487,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{207}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-queue}@anchor{209}
@subsection No_Entry_Queue
@@ -13431,7 +13500,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{208}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-aspect-specifications}@anchor{20a}
@subsection No_Implementation_Aspect_Specifications
@@ -13442,7 +13511,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{209}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-attributes}@anchor{20b}
@subsection No_Implementation_Attributes
@@ -13454,7 +13523,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{20a}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-identifiers}@anchor{20c}
@subsection No_Implementation_Identifiers
@@ -13465,7 +13534,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{20b}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-pragmas}@anchor{20d}
@subsection No_Implementation_Pragmas
@@ -13476,7 +13545,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{20c}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-restrictions}@anchor{20e}
@subsection No_Implementation_Restrictions
@@ -13488,7 +13557,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{20d}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-units}@anchor{20f}
@subsection No_Implementation_Units
@@ -13499,7 +13568,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{20e}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-aliasing}@anchor{210}
@subsection No_Implicit_Aliasing
@@ -13514,7 +13583,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{20f}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-loops}@anchor{211}
@subsection No_Implicit_Loops
@@ -13531,7 +13600,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{210}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-obsolescent-features}@anchor{212}
@subsection No_Obsolescent_Features
@@ -13541,7 +13610,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{211}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-wide-characters}@anchor{213}
@subsection No_Wide_Characters
@@ -13555,7 +13624,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{212}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-dispatch-tables}@anchor{214}
@subsection Static_Dispatch_Tables
@@ -13565,7 +13634,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{213}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions spark-05}@anchor{215}
@subsection SPARK_05
@@ -13588,7 +13657,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{214}@anchor{gnat_rm/implementation_advice id1}@anchor{215}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}
+@anchor{gnat_rm/implementation_advice doc}@anchor{216}@anchor{gnat_rm/implementation_advice id1}@anchor{217}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}
@chapter Implementation Advice
@@ -13686,7 +13755,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{216}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-20-error-detection}@anchor{218}
@section RM 1.1.3(20): Error Detection
@@ -13703,7 +13772,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{217}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-31-child-units}@anchor{219}
@section RM 1.1.3(31): Child Units
@@ -13719,7 +13788,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{218}
+@anchor{gnat_rm/implementation_advice rm-1-1-5-12-bounded-errors}@anchor{21a}
@section RM 1.1.5(12): Bounded Errors
@@ -13736,7 +13805,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{219}@anchor{gnat_rm/implementation_advice rm-2-8-16-pragmas}@anchor{21a}
+@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
@@ -13849,7 +13918,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{21b}
+@anchor{gnat_rm/implementation_advice rm-2-8-17-19-pragmas}@anchor{21d}
@section RM 2.8(17-19): Pragmas
@@ -13870,14 +13939,14 @@ replacing @code{library_items}.”
@end itemize
@end quotation
-See @ref{21a,,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{21c}
+@anchor{gnat_rm/implementation_advice rm-3-5-2-5-alternative-character-sets}@anchor{21e}
@section RM 3.5.2(5): Alternative Character Sets
@@ -13905,7 +13974,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{21d}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-28-integer-types}@anchor{21f}
@section RM 3.5.4(28): Integer Types
@@ -13924,7 +13993,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{21e}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-29-integer-types}@anchor{220}
@section RM 3.5.4(29): Integer Types
@@ -13940,7 +14009,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{21f}
+@anchor{gnat_rm/implementation_advice rm-3-5-5-8-enumeration-values}@anchor{221}
@section RM 3.5.5(8): Enumeration Values
@@ -13960,7 +14029,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{220}
+@anchor{gnat_rm/implementation_advice rm-3-5-7-17-float-types}@anchor{222}
@section RM 3.5.7(17): Float Types
@@ -13990,7 +14059,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{221}
+@anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{223}
@section RM 3.6.2(11): Multidimensional Arrays
@@ -14008,7 +14077,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{222}
+@anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{224}
@section RM 9.6(30-31): Duration’Small
@@ -14029,7 +14098,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{223}
+@anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{225}
@section RM 10.2.1(12): Consistent Representation
@@ -14051,7 +14120,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{224}
+@anchor{gnat_rm/implementation_advice rm-11-4-1-19-exception-information}@anchor{226}
@section RM 11.4.1(19): Exception Information
@@ -14082,7 +14151,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{225}
+@anchor{gnat_rm/implementation_advice rm-11-5-28-suppression-of-checks}@anchor{227}
@section RM 11.5(28): Suppression of Checks
@@ -14097,7 +14166,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{226}
+@anchor{gnat_rm/implementation_advice rm-13-1-21-24-representation-clauses}@anchor{228}
@section RM 13.1 (21-24): Representation Clauses
@@ -14146,7 +14215,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{227}
+@anchor{gnat_rm/implementation_advice rm-13-2-6-8-packed-types}@anchor{229}
@section RM 13.2(6-8): Packed Types
@@ -14185,7 +14254,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{228}
+@anchor{gnat_rm/implementation_advice rm-13-3-14-19-address-clauses}@anchor{22a}
@section RM 13.3(14-19): Address Clauses
@@ -14238,7 +14307,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{229}
+@anchor{gnat_rm/implementation_advice rm-13-3-29-35-alignment-clauses}@anchor{22b}
@section RM 13.3(29-35): Alignment Clauses
@@ -14295,7 +14364,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{22a}
+@anchor{gnat_rm/implementation_advice rm-13-3-42-43-size-clauses}@anchor{22c}
@section RM 13.3(42-43): Size Clauses
@@ -14313,7 +14382,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{22b}
+@anchor{gnat_rm/implementation_advice rm-13-3-50-56-size-clauses}@anchor{22d}
@section RM 13.3(50-56): Size Clauses
@@ -14364,7 +14433,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{22c}
+@anchor{gnat_rm/implementation_advice rm-13-3-71-73-component-size-clauses}@anchor{22e}
@section RM 13.3(71-73): Component Size Clauses
@@ -14398,7 +14467,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{22d}
+@anchor{gnat_rm/implementation_advice rm-13-4-9-10-enumeration-representation-clauses}@anchor{22f}
@section RM 13.4(9-10): Enumeration Representation Clauses
@@ -14420,7 +14489,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{22e}
+@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
@@ -14480,7 +14549,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{22f}
+@anchor{gnat_rm/implementation_advice rm-13-5-2-5-storage-place-attributes}@anchor{231}
@section RM 13.5.2(5): Storage Place Attributes
@@ -14500,7 +14569,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{230}
+@anchor{gnat_rm/implementation_advice rm-13-5-3-7-8-bit-ordering}@anchor{232}
@section RM 13.5.3(7-8): Bit Ordering
@@ -14520,7 +14589,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{231}
+@anchor{gnat_rm/implementation_advice rm-13-7-37-address-as-private}@anchor{233}
@section RM 13.7(37): Address as Private
@@ -14538,7 +14607,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{232}
+@anchor{gnat_rm/implementation_advice rm-13-7-1-16-address-operations}@anchor{234}
@section RM 13.7.1(16): Address Operations
@@ -14556,7 +14625,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{233}
+@anchor{gnat_rm/implementation_advice rm-13-9-14-17-unchecked-conversion}@anchor{235}
@section RM 13.9(14-17): Unchecked Conversion
@@ -14600,7 +14669,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{234}
+@anchor{gnat_rm/implementation_advice rm-13-11-23-25-implicit-heap-usage}@anchor{236}
@section RM 13.11(23-25): Implicit Heap Usage
@@ -14651,7 +14720,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{235}
+@anchor{gnat_rm/implementation_advice rm-13-11-2-17-unchecked-deallocation}@anchor{237}
@section RM 13.11.2(17): Unchecked Deallocation
@@ -14666,7 +14735,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{236}
+@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
@@ -14697,7 +14766,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{237}
+@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
@@ -14715,7 +14784,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{238}
+@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}
@@ -14732,7 +14801,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{239}
+@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
@@ -14747,7 +14816,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{23a}
+@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
@@ -14776,7 +14845,7 @@ condition here to hold true.
@geindex Get_Immediate
@node RM A 10 7 23 Get_Immediate,RM A 18 Containers,RM A 5 2 46-47 Random Number Generation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23b}
+@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23d}
@section RM A.10.7(23): @code{Get_Immediate}
@@ -14800,7 +14869,7 @@ this functionality.
@geindex Containers
@node RM A 18 Containers,RM B 1 39-41 Pragma Export,RM A 10 7 23 Get_Immediate,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-18-containers}@anchor{23c}
+@anchor{gnat_rm/implementation_advice rm-a-18-containers}@anchor{23e}
@section RM A.18: @code{Containers}
@@ -14821,7 +14890,7 @@ follow the implementation advice.
@geindex Export
@node RM B 1 39-41 Pragma Export,RM B 2 12-13 Package Interfaces,RM A 18 Containers,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23d}
+@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23f}
@section RM B.1(39-41): Pragma @code{Export}
@@ -14869,7 +14938,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{23e}
+@anchor{gnat_rm/implementation_advice rm-b-2-12-13-package-interfaces}@anchor{240}
@section RM B.2(12-13): Package @code{Interfaces}
@@ -14899,7 +14968,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{23f}
+@anchor{gnat_rm/implementation_advice rm-b-3-63-71-interfacing-with-c}@anchor{241}
@section RM B.3(63-71): Interfacing with C
@@ -14987,7 +15056,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{240}
+@anchor{gnat_rm/implementation_advice rm-b-4-95-98-interfacing-with-cobol}@anchor{242}
@section RM B.4(95-98): Interfacing with COBOL
@@ -15028,7 +15097,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{241}
+@anchor{gnat_rm/implementation_advice rm-b-5-22-26-interfacing-with-fortran}@anchor{243}
@section RM B.5(22-26): Interfacing with Fortran
@@ -15079,7 +15148,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{242}
+@anchor{gnat_rm/implementation_advice rm-c-1-3-5-access-to-machine-operations}@anchor{244}
@section RM C.1(3-5): Access to Machine Operations
@@ -15114,7 +15183,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{243}
+@anchor{gnat_rm/implementation_advice rm-c-1-10-16-access-to-machine-operations}@anchor{245}
@section RM C.1(10-16): Access to Machine Operations
@@ -15175,7 +15244,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{244}
+@anchor{gnat_rm/implementation_advice rm-c-3-28-interrupt-support}@anchor{246}
@section RM C.3(28): Interrupt Support
@@ -15193,7 +15262,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{245}
+@anchor{gnat_rm/implementation_advice rm-c-3-1-20-21-protected-procedure-handlers}@anchor{247}
@section RM C.3.1(20-21): Protected Procedure Handlers
@@ -15219,7 +15288,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{246}
+@anchor{gnat_rm/implementation_advice rm-c-3-2-25-package-interrupts}@anchor{248}
@section RM C.3.2(25): Package @code{Interrupts}
@@ -15237,7 +15306,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{247}
+@anchor{gnat_rm/implementation_advice rm-c-4-14-pre-elaboration-requirements}@anchor{249}
@section RM C.4(14): Pre-elaboration Requirements
@@ -15253,7 +15322,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{248}
+@anchor{gnat_rm/implementation_advice rm-c-5-8-pragma-discard-names}@anchor{24a}
@section RM C.5(8): Pragma @code{Discard_Names}
@@ -15271,7 +15340,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{249}
+@anchor{gnat_rm/implementation_advice rm-c-7-2-30-the-package-task-attributes}@anchor{24b}
@section RM C.7.2(30): The Package Task_Attributes
@@ -15292,7 +15361,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{24a}
+@anchor{gnat_rm/implementation_advice rm-d-3-17-locking-policies}@anchor{24c}
@section RM D.3(17): Locking Policies
@@ -15309,7 +15378,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{24b}
+@anchor{gnat_rm/implementation_advice rm-d-4-16-entry-queuing-policies}@anchor{24d}
@section RM D.4(16): Entry Queuing Policies
@@ -15324,7 +15393,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{24c}
+@anchor{gnat_rm/implementation_advice rm-d-6-9-10-preemptive-abort}@anchor{24e}
@section RM D.6(9-10): Preemptive Abort
@@ -15350,7 +15419,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{24d}
+@anchor{gnat_rm/implementation_advice rm-d-7-21-tasking-restrictions}@anchor{24f}
@section RM D.7(21): Tasking Restrictions
@@ -15369,7 +15438,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{24e}
+@anchor{gnat_rm/implementation_advice rm-d-8-47-49-monotonic-time}@anchor{250}
@section RM D.8(47-49): Monotonic Time
@@ -15404,7 +15473,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{24f}
+@anchor{gnat_rm/implementation_advice rm-e-5-28-29-partition-communication-subsystem}@anchor{251}
@section RM E.5(28-29): Partition Communication Subsystem
@@ -15432,7 +15501,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{250}
+@anchor{gnat_rm/implementation_advice rm-f-7-cobol-support}@anchor{252}
@section RM F(7): COBOL Support
@@ -15452,7 +15521,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{251}
+@anchor{gnat_rm/implementation_advice rm-f-1-2-decimal-radix-support}@anchor{253}
@section RM F.1(2): Decimal Radix Support
@@ -15468,7 +15537,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{252}
+@anchor{gnat_rm/implementation_advice rm-g-numerics}@anchor{254}
@section RM G: Numerics
@@ -15488,7 +15557,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{253}
+@anchor{gnat_rm/implementation_advice rm-g-1-1-56-58-complex-types}@anchor{255}
@section RM G.1.1(56-58): Complex Types
@@ -15550,7 +15619,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{254}
+@anchor{gnat_rm/implementation_advice rm-g-1-2-49-complex-elementary-functions}@anchor{256}
@section RM G.1.2(49): Complex Elementary Functions
@@ -15572,7 +15641,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{255}
+@anchor{gnat_rm/implementation_advice rm-g-2-4-19-accuracy-requirements}@anchor{257}
@section RM G.2.4(19): Accuracy Requirements
@@ -15596,7 +15665,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{256}
+@anchor{gnat_rm/implementation_advice rm-g-2-6-15-complex-arithmetic-accuracy}@anchor{258}
@section RM G.2.6(15): Complex Arithmetic Accuracy
@@ -15614,7 +15683,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{257}
+@anchor{gnat_rm/implementation_advice rm-h-6-15-2-pragma-partition-elaboration-policy}@anchor{259}
@section RM H.6(15/2): Pragma Partition_Elaboration_Policy
@@ -15629,7 +15698,7 @@ immediately terminated.”
Not followed.
@node Implementation Defined Characteristics,Intrinsic Subprograms,Implementation Advice,Top
-@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{258}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{259}@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}
+@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{25a}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{25b}@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}
@chapter Implementation Defined Characteristics
@@ -15705,7 +15774,13 @@ See separate section on source representation.
@itemize *
@item
-“The control functions allowed in comments. See 2.1(14).”
+
+@table @asis
+
+@item “The semantics of an Ada program whose text is not in
+
+Normalization Form C. See 2.1(4).”
+@end table
@end itemize
See separate section on source representation.
@@ -15758,15 +15833,15 @@ not.
@itemize *
@item
-“The sequence of characters of the value returned by
-@code{S'Image} when some of the graphic characters of
-@code{S'Wide_Image} are not defined in @code{Character}. See
-3.5(37).”
+“The message string associated with the Assertion_Error exception raised
+by the failure of a predicate check if there is no applicable
+Predicate_Failure aspect. See 3.2.4(31).”
@end itemize
-The sequence of characters is as defined by the wide character encoding
-method used for the source. See section on source representation for
-further details.
+In the case of a Dynamic_Predicate aspect, the string is
+“Dynamic_Predicate failed at <source position>”, where
+“<source position>” might be something like “foo.adb:123”.
+The Static_Predicate case is handled analogously.
@itemize *
@@ -15925,12 +16000,12 @@ IEEE 80-bit Extended on x86 architecture
@end multitable
-The default rounding mode specified by the IEEE 754 Standard is assumed for
-static computations, i.e. round to nearest, ties to even. The input routines
-yield correctly rounded values for Short_Float, Float and Long_Float at least.
-The output routines can compute up to twice as many exact digits as the value
-of @code{T'Digits} for any type, for example 30 digits for Long_Float; if more
-digits are requested, zeros are printed.
+The default rounding mode specified by the IEEE 754 Standard is assumed both
+for static and dynamic computations (that is, round to nearest, ties to even).
+The input routines yield correctly rounded values for Short_Float, Float, and
+Long_Float at least. The output routines can compute up to twice as many exact
+digits as the value of @code{T'Digits} for any type, for example 30 digits for
+Long_Float; if more digits are requested, zeros are printed.
@itemize *
@@ -15986,6 +16061,19 @@ decimal integer are allocated.
@itemize *
@item
+“The sequence of characters of the value returned by Tags.Expanded_Name
+(respectively, Tags.Wide_Expanded_Name) when some of the graphic
+characters of Tags.Wide_Wide_Expanded_Name are not defined in Character
+(respectively, Wide_Character). See 3.9(10.1).”
+@end itemize
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+
+@itemize *
+
+@item
“Implementation-defined attributes. See 4.1.4(12).”
@end itemize
@@ -15995,6 +16083,90 @@ See @ref{8,,Implementation Defined Attributes}.
@itemize *
@item
+“The value of the parameter to Empty for some container aggregates.
+See 4.3.5(40).”
+@end itemize
+
+As per the suggestion given in the Annotated Ada RM, the default value
+of the formal parameter is used if one exists and zero is used otherwise.
+
+
+@itemize *
+
+@item
+“The maximum number of chunks for a parallel reduction expression without
+a chunk_specification. See 4.5.10(21).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“Rounding of real static expressions which are exactly half-way between
+two machine numbers. See 4.9(38).”
+@end itemize
+
+Round to even is used in all such cases.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The maximum number of chunks for a parallel generalized iterator without
+
+a chunk_specification. See 5.5.2(10).”
+@end table
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“The number of chunks for an array component iterator. See 5.5.2(11).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“Any extensions of the Global aspect. See 6.1.2(43).”
+@end itemize
+
+Feature unimplemented.
+
+
+@itemize *
+
+@item
+“The circumstances the implementation passes in the null value for a view
+conversion of an access type used as an out parameter. See 6.4.1(19).”
+@end itemize
+
+Difficult to characterize.
+
+
+@itemize *
+
+@item
+“Any extensions of the Default_Initial_Condition aspect. See 7.3.3(11).”
+@end itemize
+
+SPARK allows specifying @emph{null} as the Default_Initial_Condition
+aspect of a type. See the SPARK reference manual for further details.
+
+
+@itemize *
+
+@item
“Any implementation-defined time types. See 9.6(6).”
@end itemize
@@ -16004,7 +16176,7 @@ There are no implementation-defined time types.
@itemize *
@item
-“The time base associated with relative delays.”
+“The time base associated with relative delays. See 9.6(20).”
@end itemize
See 9.6(20). The time base used is that provided by the C library
@@ -16014,8 +16186,7 @@ function @code{gettimeofday}.
@itemize *
@item
-“The time base of the type @code{Calendar.Time}. See
-9.6(23).”
+“The time base of the type @code{Calendar.Time}. See 9.6(23).”
@end itemize
The time base used is that provided by the C library function
@@ -16047,14 +16218,25 @@ There are no such limits.
@itemize *
@item
-“Whether or not two non-overlapping parts of a composite
-object are independently addressable, in the case where packing, record
-layout, or @code{Component_Size} is specified for the object. See
-9.10(1).”
+
+@table @asis
+
+@item “The result of Calendar.Formatting.Image if its argument represents more
+
+than 100 hours. See 9.6.1(86).”
+@end table
+@end itemize
+
+Calendar.Time_Error is raised.
+
+
+@itemize *
+
+@item
+“Implementation-defined conflict check policies. See 9.10.1(5).”
@end itemize
-Separate components are independently addressable if they do not share
-overlapping storage units.
+There are no implementation-defined conflict check policies.
@itemize *
@@ -16119,9 +16301,8 @@ options, refer to @emph{GNAT Make Program gnatmake} in the
@itemize *
@item
-“The implementation-defined means, if any, of specifying
-which compilation units are needed by a given compilation unit. See
-10.2(2).”
+“The implementation-defined means, if any, of specifying which compilation
+units are needed by a given compilation unit. See 10.2(2).”
@end itemize
The units needed by a given compilation unit are as defined in
@@ -16144,18 +16325,14 @@ corresponding @code{ALI} file as the input parameter to the binder.
@itemize *
@item
-“The order of elaboration of @emph{library_items}. See
-10.2(18).”
+“The order of elaboration of @emph{library_items}. See 10.2(18).”
@end itemize
The first constraint on ordering is that it meets the requirements of
Chapter 10 of the Ada Reference Manual. This still leaves some
-implementation dependent choices, which are resolved by first
-elaborating bodies as early as possible (i.e., in preference to specs
-where there is a choice), and second by evaluating the immediate with
-clauses of a unit to determine the probably best choice, and
-third by elaborating in alphabetical order of unit names
-where a choice still remains.
+implementation-dependent choices, which are resolved by analyzing
+the elaboration code of each unit and identifying implicit
+elaboration-order dependencies.
@itemize *
@@ -16174,14 +16351,13 @@ may have been set by a call to @code{Ada.Command_Line.Set_Exit_Status}).
@itemize *
@item
-“The mechanisms for building and running partitions. See
-10.2(24).”
+“The mechanisms for building and running partitions. See 10.2(24).”
@end itemize
-GNAT itself supports programs with only a single partition. The GNATDIST
+GNAT itself supports programs with only a single partition. The GNATDIST
tool provided with the GLADE package (which also includes an implementation
of the PCS) provides a completely flexible method for building and running
-programs consisting of multiple partitions. See the separate GLADE manual
+programs consisting of multiple partitions. See the separate GLADE manual
for details.
@@ -16203,15 +16379,14 @@ implementation. See 10.2(28).”
@end itemize
Passive partitions are supported on targets where shared memory is
-provided by the operating system. See the GLADE reference manual for
+provided by the operating system. See the GLADE reference manual for
further details.
@itemize *
@item
-“The information returned by @code{Exception_Message}. See
-11.4.1(10).”
+“The information returned by @code{Exception_Message}. See 11.4.1(10).”
@end itemize
Exception message returns the null string unless a specific message has
@@ -16282,6 +16457,54 @@ the last line is a single @code{LF} character (@code{16#0A#}).
@itemize *
@item
+“The sequence of characters of the value returned by
+Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name)
+when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name
+are not defined in Character (respectively, Wide_Character).
+See 11.4.1(12.1).”
+@end itemize
+
+This is handled in the same way as the implementation-defined behavior
+referenced in A.4.12(34).
+
+
+@itemize *
+
+@item
+“The information returned by Exception_Information. See 11.4.1(13).”
+@end itemize
+
+The exception name and the source location at which the exception was
+raised are included.
+
+
+@itemize *
+
+@item
+“Implementation-defined policy_identifiers and assertion_aspect_marks
+allowed in a pragma Assertion_Policy. See 11.4.2(9).”
+@end itemize
+
+Implementation-defined assertion_aspect_marks include Assert_And_Cut,
+Assume, Contract_Cases, Debug, Ghost, Initial_Condition, Loop_Invariant,
+Loop_Variant, Postcondition, Precondition, Predicate, Refined_Post,
+Statement_Assertions, and Subprogram_Variant. Implementation-defined
+policy_identifiers include Ignore and Suppressible.
+
+
+@itemize *
+
+@item
+“The default assertion policy. See 11.4.2(10).”
+@end itemize
+
+The default assertion policy is Ignore, although this can be overridden
+via compiler switches such as “-gnata”.
+
+
+@itemize *
+
+@item
“Implementation-defined check names. See 11.5(27).”
@end itemize
@@ -16295,8 +16518,33 @@ Check_Name. See the description of pragma @code{Suppress} for full details.
@itemize *
@item
-“The interpretation of each aspect of representation. See
-13.1(20).”
+“Existence and meaning of second parameter of pragma Unsuppress.
+See 11.5(27.1).”
+@end itemize
+
+The legality rules for and semantics of the second parameter of pragma
+Unsuppress match those for the second argument of pragma Suppress.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The cases that cause conflicts between the representation of the
+
+ancestors of a type_declaration. See 13.1(13.1).”
+@end table
+@end itemize
+
+No such cases exist.
+
+
+@itemize *
+
+@item
+“The interpretation of each representation aspect. See 13.1(20).”
@end itemize
See separate section on data representations.
@@ -16305,8 +16553,8 @@ See separate section on data representations.
@itemize *
@item
-“Any restrictions placed upon representation items. See
-13.1(20).”
+“Any restrictions placed upon the specification of representation aspects.
+See 13.1(20).”
@end itemize
See separate section on data representations.
@@ -16315,20 +16563,46 @@ See separate section on data representations.
@itemize *
@item
-“The meaning of @code{Size} for indefinite subtypes. See
-13.3(48).”
+“Implementation-defined aspects, including the syntax for specifying
+such aspects and the legality rules for such aspects. See 13.1.1(38).”
+@end itemize
+
+See @ref{121,,Implementation Defined Aspects}.
+
+
+@itemize *
+
+@item
+“The set of machine scalars. See 13.3(8.1).”
@end itemize
-Size for an indefinite subtype is the maximum possible size, except that
-for the case of a subprogram parameter, the size of the parameter object
-is the actual size.
+See separate section on data representations.
@itemize *
@item
-“The default external representation for a type tag. See
-13.3(75).”
+“The meaning of @code{Size} for indefinite subtypes. See 13.3(48).”
+@end itemize
+
+The Size attribute of an indefinite subtype is not less than the Size
+attribute of any object of that type.
+
+
+@itemize *
+
+@item
+“The meaning of Object_Size for indefinite subtypes. See 13.3(58).”
+@end itemize
+
+The Object_Size attribute of an indefinite subtype is not less than the
+Object_Size attribute of any object of that type.
+
+
+@itemize *
+
+@item
+“The default external representation for a type tag. See 13.3(75).”
@end itemize
The default external representation for a type tag is the fully expanded
@@ -16371,13 +16645,11 @@ bit ordering corresponds to the natural endianness of the target architecture.
@itemize *
@item
-“The contents of the visible part of package @code{System}
-and its language-defined children. See 13.7(2).”
+“The contents of the visible part of package @code{System}. See 13.7(2).”
@end itemize
-See the definition of these packages in files @code{system.ads} and
-@code{s-stoele.ads}. Note that two declarations are added to package
-System.
+See the definition of package System in @code{system.ads}.
+Note that two declarations are added to package System.
@example
Max_Priority : constant Positive := Priority'Last;
@@ -16388,9 +16660,19 @@ Max_Interrupt_Priority : constant Positive := Interrupt_Priority'Last;
@itemize *
@item
-“The contents of the visible part of package
-@code{System.Machine_Code}, and the meaning of
-@emph{code_statements}. See 13.8(7).”
+“The range of Storage_Elements.Storage_Offset, the modulus of
+Storage_Elements.Storage_Element, and the declaration of
+Storage_Elements.Integer_Address. See 13.7.1(11).”
+@end itemize
+
+See the definition of package System.Storage_Elements in @code{s-stoele.ads}.
+
+
+@itemize *
+
+@item
+“The contents of the visible part of package @code{System.Machine_Code},
+and the meaning of @emph{code_statements}. See 13.8(7).”
@end itemize
See the definition and documentation in file @code{s-maccod.ads}.
@@ -16399,7 +16681,8 @@ See the definition and documentation in file @code{s-maccod.ads}.
@itemize *
@item
-“The effect of unchecked conversion. See 13.9(11).”
+“The result of unchecked conversion for instances with scalar result
+types whose result is not defined by the language. See 13.9(11).”
@end itemize
Unchecked conversion between types of the same size
@@ -16420,65 +16703,36 @@ made with appropriate alignment
@itemize *
@item
-“The semantics of operations on invalid representations.
-See 13.9.2(10-11).”
+“The result of unchecked conversion for instances with nonscalar result
+types whose result is not defined by the language. See 13.9(11).”
@end itemize
-For assignments and other operations where the use of invalid values cannot
-result in erroneous behavior, the compiler ignores the possibility of invalid
-values. An exception is raised at the point where an invalid value would
-result in erroneous behavior. For example executing:
-
-@example
-procedure invalidvals is
- X : Integer := -1;
- Y : Natural range 1 .. 10;
- for Y'Address use X'Address;
- Z : Natural range 1 .. 10;
- A : array (Natural range 1 .. 10) of Integer;
-begin
- Z := Y; -- no exception
- A (Z) := 3; -- exception raised;
-end;
-@end example
-
-As indicated, an exception is raised on the array assignment, but not
-on the simple assignment of the invalid negative value from Y to Z.
+See preceding definition for the scalar result case.
@itemize *
@item
-“The manner of choosing a storage pool for an access type
-when @code{Storage_Pool} is not specified for the type. See 13.11(17).”
+“Whether or not the implementation provides user-accessible
+names for the standard pool type(s). See 13.11(17).”
@end itemize
There are 3 different standard pools used by the compiler when
@code{Storage_Pool} is not specified depending whether the type is local
to a subprogram or defined at the library level and whether
-@code{Storage_Size`@w{`}is specified or not. See documentation in the runtime
+@code{Storage_Size`@w{`}is specified or not. See documentation in the runtime
library units `@w{`}System.Pool_Global}, @code{System.Pool_Size} and
@code{System.Pool_Local} in files @code{s-poosiz.ads},
@code{s-pooglo.ads} and @code{s-pooloc.ads} for full details on the
-default pools used.
-
-
-@itemize *
-
-@item
-“Whether or not the implementation provides user-accessible
-names for the standard pool type(s). See 13.11(17).”
-@end itemize
-
-See documentation in the sources of the run time mentioned in the previous
-paragraph. All these pools are accessible by means of @cite{with}ing
+default pools used. All these pools are accessible by means of @cite{with}ing
these units.
@itemize *
@item
-“The meaning of @code{Storage_Size}. See 13.11(18).”
+“The meaning of @code{Storage_Size} when neither the Storage_Size nor the
+Storage_Pool is specified for an access type. See 13.11(18).”
@end itemize
@code{Storage_Size} is measured in storage units, and refers to the
@@ -16489,20 +16743,19 @@ stack space for a task.
@itemize *
@item
-“Implementation-defined aspects of storage pools. See
-13.11(22).”
+“The effect of specifying aspect Default_Storage_Pool on an instance
+of a language-defined generic unit. See 13.11.3(5).”
@end itemize
-See documentation in the sources of the run time mentioned in the
-paragraph about standard storage pools above
-for details on GNAT-defined aspects of storage pools.
+Instances of language-defined generic units are treated the same as other
+instances with respect to the Default_Storage_Pool aspect.
@itemize *
@item
-“The set of restrictions allowed in a pragma
-@code{Restrictions}. See 13.12(7).”
+“Implementation-defined restrictions allowed in a pragma
+@code{Restrictions}. See 13.12(8.7).”
@end itemize
See @ref{9,,Standard and Implementation Defined Restrictions}.
@@ -16515,17 +16768,26 @@ See @ref{9,,Standard and Implementation Defined Restrictions}.
@code{Restrictions} pragmas. See 13.12(9).”
@end itemize
-Restrictions that can be checked at compile time result in illegalities
-if violated. Currently there are no other consequences of violating
-restrictions.
+Restrictions that can be checked at compile time are enforced at
+compile time; violations are illegal. For other restrictions, any
+violation during program execution results in erroneous execution.
+
+
+@itemize *
+
+@item
+“Implementation-defined usage profiles allowed in a pragma Profile.
+See 13.12(15).”
+@end itemize
+
+See @ref{7,,Implementation Defined Pragmas}.
@itemize *
@item
-“The representation used by the @code{Read} and
-@code{Write} attributes of elementary types in terms of stream
-elements. See 13.13.2(9).”
+“The contents of the stream elements read and written by the Read and
+Write attributes of elementary types. See 13.13.2(9).”
@end itemize
The representation is the in-memory representation of the base type of
@@ -16546,13 +16808,38 @@ See items describing the integer and floating-point types supported.
@itemize *
@item
-“The string returned by @code{Character_Set_Version}.
-See A.3.5(3).”
+“The values returned by Strings.Hash. See A.4.9(3).”
+@end itemize
+
+This hash function has predictable collisions and is subject to
+equivalent substring attacks. It is not suitable for construction of a
+hash table keyed on possibly malicious user input.
+
+
+@itemize *
+
+@item
+“The value returned by a call to a Text_Buffer Get procedure if any
+character in the returned sequence is not defined in Character.
+See A.4.12(34).”
+@end itemize
+
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Get is the result of passing that
+UTF_8 string to UTF_Encoding.Strings.Decode.
+
+
+@itemize *
+
+@item
+“The value returned by a call to a Text_Buffer Wide_Get procedure if
+any character in the returned sequence is not defined in Wide_Character.
+See A.4.12(34).”
@end itemize
-@code{Ada.Wide_Characters.Handling.Character_Set_Version} returns
-the string “Unicode 4.0”, referring to version 4.0 of the
-Unicode specification.
+The contents of a buffer is represented internally as a UTF_8 string.
+The value return by Text_Buffer.Wide_Get is the result of passing that
+UTF_8 string to UTF_Encoding.Wide_Strings.Decode.
@itemize *
@@ -16601,18 +16888,6 @@ Maximum image width is 6864, see library file @code{s-rannum.ads}.
@itemize *
@item
-“The algorithms for random number generation. See
-A.5.2(32).”
-@end itemize
-
-The algorithm is the Mersenne Twister, as documented in the source file
-@code{s-rannum.adb}. This version of the algorithm has a period of
-2**19937-1.
-
-
-@itemize *
-
-@item
“The string representation of a random number generator’s
state. See A.5.2(38).”
@end itemize
@@ -16625,44 +16900,20 @@ of the state vector.
@itemize *
@item
-“The minimum time interval between calls to the
-time-dependent Reset procedure that are guaranteed to initiate different
-random number sequences. See A.5.2(45).”
-@end itemize
-
-The minimum period between reset calls to guarantee distinct series of
-random numbers is one microsecond.
-
-
-@itemize *
-
-@item
“The values of the @code{Model_Mantissa},
@code{Model_Emin}, @code{Model_Epsilon}, @code{Model},
@code{Safe_First}, and @code{Safe_Last} attributes, if the Numerics
Annex is not supported. See A.5.3(72).”
@end itemize
-Run the compiler with @emph{-gnatS} to produce a listing of package
-@code{Standard}, has the values of all numeric attributes.
-
-
-@itemize *
-
-@item
-“Any implementation-defined characteristics of the
-input-output packages. See A.7(14).”
-@end itemize
-
-There are no special implementation defined characteristics for these
-packages.
+Running the compiler with @emph{-gnatS} to produce a listing of package
+@code{Standard} displays the values of these attributes.
@itemize *
@item
-“The value of @code{Buffer_Size} in @code{Storage_IO}. See
-A.9(10).”
+“The value of @code{Buffer_Size} in @code{Storage_IO}. See A.9(10).”
@end itemize
All type representations are contiguous, and the @code{Buffer_Size} is
@@ -16678,14 +16929,13 @@ standard error See A.10(5).”
@end itemize
These files are mapped onto the files provided by the C streams
-libraries. See source file @code{i-cstrea.ads} for further details.
+libraries. See source file @code{i-cstrea.ads} for further details.
@itemize *
@item
-“The accuracy of the value produced by @code{Put}. See
-A.10.9(36).”
+“The accuracy of the value produced by @code{Put}. See A.10.9(36).”
@end itemize
If more digits are requested in the output than are represented by the
@@ -16696,168 +16946,140 @@ significant digit positions.
@itemize *
@item
-“The meaning of @code{Argument_Count}, @code{Argument}, and
-@code{Command_Name}. See A.15(1).”
+“Current size for a stream file for which positioning is not supported.
+See A.12.1(1.1).”
@end itemize
-These are mapped onto the @code{argv} and @code{argc} parameters of the
-main program in the natural manner.
+Positioning is supported.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Create_Directory}. See A.16(56).”
+“The meaning of @code{Argument_Count}, @code{Argument}, and
+@code{Command_Name}. See A.15(1).”
@end itemize
-The @code{Form} parameter is not used.
+These are mapped onto the @code{argv} and @code{argc} parameters of the
+main program in the natural manner.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Create_Path}. See A.16(60).”
+“The interpretation of file names and directory names. See A.16(46).”
@end itemize
-The @code{Form} parameter is not used.
+These names are interpreted consistently with the underlying file system.
@itemize *
@item
-“The interpretation of the @code{Form} parameter in procedure
-@code{Copy_File}. See A.16(68).”
+“The maxium value for a file size in Directories. See A.16(87).”
@end itemize
-The @code{Form} parameter is case-insensitive.
-Two fields are recognized in the @code{Form} parameter:
-
-@example
-*preserve=<value>*
-*mode=<value>*
-@end example
-
-<value> starts immediately after the character ‘=’ and ends with the
-character immediately preceding the next comma (‘,’) or with the last
-character of the parameter.
-
-The only possible values for preserve= are:
-
-
-@multitable {xxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
-@headitem
-
-Value
+Directories.File_Size’Last is equal to Long_Long_Integer’Last .
-@tab
-
-Meaning
-@item
-
-@emph{no_attributes}
+@itemize *
-@tab
+@item
-Do not try to preserve any file attributes. This is the
-default if no preserve= is found in Form.
+@table @asis
-@item
+@item “The result for Directories.Size for a directory or special file.
-@emph{all_attributes}
+See A.16(93).”
+@end table
+@end itemize
-@tab
+Name_Error is raised.
-Try to preserve all file attributes (timestamps, access rights).
-@item
+@itemize *
-@emph{timestamps}
+@item
-@tab
+@table @asis
-Preserve the timestamp of the copied file, but not the other
-file attributes.
+@item “The result for Directories.Modification_Time for a directory or special file.
-@end multitable
+See A.16(93).”
+@end table
+@end itemize
+Name_Error is raised.
-The only possible values for mode= are:
+@itemize *
-@multitable {xxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
-@headitem
+@item
-Value
+@table @asis
-@tab
+@item “The interpretation of a nonnull search pattern in Directories.
-Meaning
+See A.16(104).”
+@end table
+@end itemize
-@item
+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.
-@emph{copy}
+See @ref{25c,,GNAT.Regexp (g-regexp.ads)}.
-@tab
-Only do the copy if the destination file does not already exist.
-If it already exists, Copy_File fails.
+@itemize *
-@item
+@item
-@emph{overwrite}
+@table @asis
-@tab
+@item “The results of a Directories search if the contents of the directory are
-Copy the file in all cases. Overwrite an already existing destination file.
+altered while a search is in progress. See A.16(110).”
+@end table
+@end itemize
-@item
+The effect of a call to Get_Next_Entry is determined by the current
+state of the directory.
-@emph{append}
-@tab
+@itemize *
-Append the original file to the destination file. If the destination file
-does not exist, the destination file is a copy of the source file.
-When mode=append, the field preserve=, if it exists, is not taken into account.
+@item
+“The definition and meaning of an environment variable. See A.17(1).”
+@end itemize
-@end multitable
+This definition is determined by the underlying operating system.
-If the Form parameter includes one or both of the fields and the value or
-values are incorrect, Copy_file fails with Use_Error.
+@itemize *
-Examples of correct Forms:
+@item
+“The circumstances where an environment variable cannot be defined.
+See A.17(16).”
-@example
-Form => "preserve=no_attributes,mode=overwrite" (the default)
-Form => "mode=append"
-Form => "mode=copy, preserve=all_attributes"
-@end example
+There are no such implementation-defined circumstances.
-Examples of incorrect Forms:
+@item
+“Environment names for which Set has the effect of Clear. See A.17(17).”
+@end itemize
-@example
-Form => "preserve=junk"
-Form => "mode=internal, preserve=timestamps"
-@end example
+There are no such names.
@itemize *
@item
-“The interpretation of the @code{Pattern} parameter, when not the null string,
-in the @code{Start_Search} and @code{Search} procedures.
-See A.16(104) and A.16(112).”
+“The value of Containers.Hash_Type’Modulus. The value of
+Containers.Count_Type’Last. See A.18.1(7).”
@end itemize
-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{25a,,GNAT.Regexp (g-regexp.ads)}.
+Containers.Hash_Type’Modulus is 2**32.
+Containers.Count_Type’Last is 2**31 - 1.
@itemize *
@@ -17055,9 +17277,8 @@ Link names are the actual names used by the linker.
@itemize *
@item
-“The manner of choosing link names when neither the link
-name nor the address of an imported or exported entity is specified. See
-B.1(36).”
+“The manner of choosing link names when neither the link name nor the
+address of an imported or exported entity is specified. See B.1(36).”
@end itemize
The default linker name is that which would be assigned by the relevant
@@ -17110,6 +17331,16 @@ See files with prefix @code{i-} in the distributed library.
@itemize *
@item
+“The definitions of certain types and constants in Interfaces.C.
+See B.3(41).”
+@end itemize
+
+See source file @code{i-c.ads}.
+
+
+@itemize *
+
+@item
“The types @code{Floating}, @code{Long_Floating},
@code{Binary}, @code{Long_Binary}, @code{Decimal_ Element}, and
@code{COBOL_Character}; and the initialization of the variables
@@ -17184,65 +17415,87 @@ For initialization, see the file @code{i-cobol.ads} in the distributed library.
@itemize *
@item
-“Support for access to machine instructions. See C.1(1).”
+“The types Fortran_Integer, Real, Double_Precision, and Character_Set
+in Interfaces.Fortran. See B.5(17).”
@end itemize
-See documentation in file @code{s-maccod.ads} in the distributed library.
+See source file @code{i-fortra.ads}. These types are derived, respectively,
+from Integer, Float, Long_Float, and Character.
@itemize *
@item
-“Implementation-defined aspects of access to machine
-operations. See C.1(9).”
+“Implementation-defined intrinsic subprograms. See C.1(1).”
@end itemize
-See documentation in file @code{s-maccod.ads} in the distributed library.
+See separate section on Intrinsic Subprograms.
@itemize *
@item
-“Implementation-defined aspects of interrupts. See C.3(2).”
+“Any restrictions on a protected procedure or its containing type when an
+aspect Attach_handler or Interrupt_Handler is specified. See C.3.1(17).”
@end itemize
-Interrupts are mapped to signals or conditions as appropriate. See
-definition of unit
-@code{Ada.Interrupt_Names} in source file @code{a-intnam.ads} for details
-on the interrupts supported on a particular target.
+There are no such restrictions.
@itemize *
@item
-“Implementation-defined aspects of pre-elaboration. See
-C.4(13).”
+“Any other forms of interrupt handler supported by the Attach_Handler and
+Interrupt_Handler aspects. See C.3.1(19).”
@end itemize
-GNAT does not permit a partition to be restarted without reloading,
-except under control of the debugger.
+There are no such forms.
@itemize *
@item
-“The semantics of pragma @code{Discard_Names}. See C.5(7).”
+
+@table @asis
+
+@item “The semantics of some attributes and functions of an entity for which
+
+aspect Discard_Names is True. See C.5(7).”
+@end table
@end itemize
-Pragma @code{Discard_Names} causes names of enumeration literals to
-be suppressed. In the presence of this pragma, the Image attribute
+If Discard_Names is True for an enumeration type, the Image attribute
provides the image of the Pos of the literal, and Value accepts
Pos values.
-For tagged types, when pragmas @code{Discard_Names} and @code{No_Tagged_Streams}
-simultaneously apply, their Expanded_Name and External_Tag are initialized
-with empty strings. This is useful to avoid exposing entity names at binary
+If both of the aspects`@w{`}Discard_Names`@w{`} and @code{No_Tagged_Streams} are true
+for a tagged type, its Expanded_Name and External_Tag values are
+empty strings. This is useful to avoid exposing entity names at binary
level.
@itemize *
@item
+“The modulus and size of Test_and_Set_Flag. See C.6.3(8).”
+@end itemize
+
+The modulus is 2**8. The size is 8.
+
+
+@itemize *
+
+@item
+“The value used to represent the set value for Atomic_Test_and_Set.
+See C.6.3(10).”
+@end itemize
+
+The value is 1.
+
+
+@itemize *
+
+@item
“The result of the @code{Task_Identification.Image}
attribute. See C.7.1(7).”
@end itemize
@@ -17286,41 +17539,12 @@ convenient thread, so the value of @code{Current_Task} is undefined.
@itemize *
@item
-“The effect of calling @code{Current_Task} from an entry
-body or interrupt handler. See C.7.1(19).”
-@end itemize
-
-When GNAT can determine statically that @code{Current_Task} is called directly in
-the body of an entry (or barrier) then a warning is emitted and @code{Program_Error}
-is raised at run time. Otherwise, the effect of calling @code{Current_Task} from an
-entry body or interrupt handler is to return the identification of the task
-currently executing the code.
-
-
-@itemize *
-
-@item
-“Implementation-defined aspects of
-@code{Task_Attributes}. See C.7.2(19).”
-@end itemize
-
-There are no implementation-defined aspects of @code{Task_Attributes}.
-
-
-@itemize *
-
-@item
-“Values of all @code{Metrics}. See D(2).”
+“Granularity of locking for Task_Attributes. See C.7.2(16).”
@end itemize
-The metrics information for GNAT depends on the performance of the
-underlying operating system. The sources of the run-time for tasking
-implementation, together with the output from @emph{-gnatG} can be
-used to determine the exact sequence of operating systems calls made
-to implement various tasking constructs. Together with appropriate
-information on the performance of the underlying operating system,
-on the exact target in use, this information can be used to determine
-the required metrics.
+No locking is needed if the formal type Attribute has the size and
+alignment of either Integer or System.Address and the bit representation
+of Initial_Value is all zeroes. Otherwise, locking is performed.
@itemize *
@@ -17368,32 +17592,19 @@ underlying operating system.
@itemize *
@item
-“Implementation-defined @emph{policy_identifiers} allowed
-in a pragma @code{Task_Dispatching_Policy}. See D.2.2(3).”
-@end itemize
-
-There are no implementation-defined policy-identifiers allowed in this
-pragma.
-
-
-@itemize *
-
-@item
-“Implementation-defined aspects of priority inversion. See
-D.2.2(16).”
+“Implementation-defined task dispatching policies. See D.2.2(3).”
@end itemize
-Execution of a task cannot be preempted by the implementation processing
-of delay expirations for lower priority tasks.
+There are no implementation-defined task dispatching policies.
@itemize *
@item
-“Implementation-defined task dispatching. See D.2.2(18).”
+“The value of Default_Quantum in Dispatching.Round_Robin. See D.2.5(4).”
@end itemize
-The policy is the same as that of the underlying threads implementation.
+The value is 10 milliseconds.
@itemize *
@@ -17448,13 +17659,10 @@ There are no implementation-defined queuing policies.
@itemize *
@item
-“On a multiprocessor, any conditions that cause the
-completion of an aborted construct to be delayed later than what is
-specified for a single processor. See D.6(3).”
+“Implementation-defined admission policies. See D.4.1(1).”
@end itemize
-The semantics for abort on a multi-processor is the same as on a single
-processor, there are no further delays.
+There are no implementation-defined admission policies.
@itemize *
@@ -17471,8 +17679,39 @@ task creation.
@itemize *
@item
-“What happens when a task terminates in the presence of
-pragma @code{No_Task_Termination}. See D.7(15).”
+“When restriction No_Dynamic_CPU_Assignment applies to a partition, the
+processor on which a task with a CPU value of a Not_A_Specific_CPU will
+execute. See D.7(10).”
+@end itemize
+
+Unknown.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “When restriction No_Task_Termination applies to a partition, what happens
+
+when a task terminates. See D.7(15.1).”
+@end table
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “The behavior when restriction Max_Storage_At_Blocking is violated.
+
+See D.7(17).”
+@end table
@end itemize
Execution is erroneous in that case.
@@ -17481,43 +17720,85 @@ Execution is erroneous in that case.
@itemize *
@item
-“Implementation-defined aspects of pragma
-@code{Restrictions}. See D.7(20).”
+“The behavior when restriction Max_Asynchronous_Select_Nesting is violated.
+See D.7(18).”
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+“The behavior when restriction Max_Tasks is violated. See D.7(19).”
+@end itemize
+
+Execution is erroneous in that case.
+
+
+@itemize *
+
+@item
+
+@table @asis
+
+@item “Whether the use of pragma Restrictions results in a reduction in program
+
+code or data size or execution time. See D.7(20).”
+
+Yes it can, but the precise circumstances and properties of such reductions
+are difficult to characterize.
+@end table
+
+@item
+“The value of Barrier_Limit’Last in Synchronous_Barriers. See D.10.1(4).”
+@end itemize
+
+Synchronous_Barriers.Barrier_Limit’Last is Integer’Last .
+
+
+@itemize *
+
+@item
+“When an aborted task that is waiting on a Synchronous_Barrier is aborted.
+See D.10.1(13).”
@end itemize
-There are no such implementation-defined aspects.
+Difficult to characterize.
@itemize *
@item
-“Implementation-defined aspects of package
-@code{Real_Time}. See D.8(17).”
+
+@table @asis
+
+@item “The value of Min_Handler_Ceiling in Execution_Time.Group_Budgets.
+
+See D.14.2(7).”
+@end table
@end itemize
-There are no implementation defined aspects of package @code{Real_Time}.
+See source file @code{a-etgrbu.ads}.
@itemize *
@item
-“Implementation-defined aspects of
-@emph{delay_statements}. See D.9(8).”
+“The value of CPU_Range’Last in System.Multiprocessors. See D.16(4).”
@end itemize
-Any difference greater than one microsecond will cause the task to be
-delayed (see D.9(7)).
+See source file @code{s-multip.ads}.
@itemize *
@item
-“The upper bound on the duration of interrupt blocking
-caused by the implementation. See D.12(5).”
+“The processor on which the environment task executes in the absence
+of a value for the aspect CPU. See D.16(13).”
@end itemize
-The upper bound is determined by the underlying operating system. In
-no cases is it more than 10 milliseconds.
+Unknown.
@itemize *
@@ -17528,7 +17809,7 @@ programs. See E(5).”
@end itemize
The GLADE package provides a utility GNATDIST for creating and executing
-distributed programs. See the GLADE reference manual for further details.
+distributed programs. See the GLADE reference manual for further details.
@itemize *
@@ -17544,9 +17825,8 @@ See the GLADE reference manual for full details on such events.
@itemize *
@item
-“The scheduling policies, treatment of priorities, and
-management of shared resources between partitions in certain cases. See
-E.1(11).”
+“The scheduling policies, treatment of priorities, and management of
+shared resources between partitions in certain cases. See E.1(11).”
@end itemize
See the GLADE reference manual for full details on these aspects of
@@ -17556,20 +17836,6 @@ multi-partition execution.
@itemize *
@item
-“Events that cause the version of a compilation unit to
-change. See E.3(5).”
-@end itemize
-
-Editing the source file of a compilation unit, or the source files of
-any units on which it is dependent in a significant way cause the version
-to change. No other actions cause the version number to change. All changes
-are significant except those which affect only layout, capitalization or
-comments.
-
-
-@itemize *
-
-@item
“Whether the execution of the remote subprogram is
immediately aborted as a result of cancellation. See E.4(13).”
@end itemize
@@ -17581,18 +17847,16 @@ a distributed application.
@itemize *
@item
-“Implementation-defined aspects of the PCS. See E.5(25).”
+“The range of type System.RPC.Partition_Id. See E.5(14).”
@end itemize
-See the GLADE reference manual for a full description of all implementation
-defined aspects of the PCS.
+System.RPC.Partion_ID’Last is Integer’Last. See source file @code{s-rpc.ads}.
@itemize *
@item
-“Implementation-defined interfaces in the PCS. See
-E.5(26).”
+“Implementation-defined interfaces in the PCS. See E.5(26).”
@end itemize
See the GLADE reference manual for a full description of all
@@ -17770,9 +18034,8 @@ Not relevant, division is IEEE exact.
@itemize *
@item
-“The definition of close result set, which determines the
-accuracy of certain fixed point multiplications and divisions. See
-G.2.3(5).”
+“The definition of close result set, which determines the accuracy of
+certain fixed point multiplications and divisions. See G.2.3(5).”
@end itemize
Operations in the close result set are performed using IEEE long format
@@ -17865,47 +18128,45 @@ Information on those subjects is not yet available.
@itemize *
@item
-“Information regarding bounded errors and erroneous
-execution. See H.2(1).”
-@end itemize
-
-Information on this subject is not yet available.
+@table @asis
-@itemize *
+@item “The accuracy requirements for the subprograms Solve, Inverse,
-@item
-“Implementation-defined aspects of pragma
-@code{Inspection_Point}. See H.3.2(8).”
+Determinant, Eigenvalues and Eigensystem for type Real_Matrix.
+See G.3.1(81).”
+@end table
@end itemize
-Pragma @code{Inspection_Point} ensures that the variable is live and can
-be examined by the debugger at the inspection point.
+Information on those subjects is not yet available.
@itemize *
@item
-“Implementation-defined aspects of pragma
-@code{Restrictions}. See H.4(25).”
+
+@table @asis
+
+@item “The accuracy requirements for the subprograms Solve, Inverse,
+
+Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.
+See G.3.2(149).”
+@end table
@end itemize
-There are no implementation-defined aspects of pragma @code{Restrictions}. The
-use of pragma @code{Restrictions [No_Exceptions]} has no effect on the
-generated code. Checks must suppressed by use of pragma @code{Suppress}.
+Information on those subjects is not yet available.
@itemize *
@item
-“Any restrictions on pragma @code{Restrictions}. See
-H.4(27).”
+“The consequences of violating No_Hidden_Indirect_Globals. See H.4(23.9).”
@end itemize
-There are no restrictions on pragma @code{Restrictions}.
+Execution is erroneous in that case.
@node Intrinsic Subprograms,Representation Clauses and Pragmas,Implementation Defined Characteristics,Top
-@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25b}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25c}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}
+@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25d}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25e}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}
@chapter Intrinsic Subprograms
@@ -17943,7 +18204,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{25d}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{25e}
+@anchor{gnat_rm/intrinsic_subprograms id2}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{260}
@section Intrinsic Operators
@@ -17974,7 +18235,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 compilation-iso-date}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{260}
+@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{261}@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{262}
@section Compilation_ISO_Date
@@ -17988,7 +18249,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{261}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{262}
+@anchor{gnat_rm/intrinsic_subprograms compilation-date}@anchor{263}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{264}
@section Compilation_Date
@@ -17998,7 +18259,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{263}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{264}
+@anchor{gnat_rm/intrinsic_subprograms compilation-time}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{266}
@section Compilation_Time
@@ -18012,7 +18273,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 enclosing-entity}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{266}
+@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{268}
@section Enclosing_Entity
@@ -18026,7 +18287,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 exception-information}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{268}
+@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{269}@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{26a}
@section Exception_Information
@@ -18040,7 +18301,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{269}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{26a}
+@anchor{gnat_rm/intrinsic_subprograms exception-message}@anchor{26b}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{26c}
@section Exception_Message
@@ -18054,7 +18315,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{26b}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26c}
+@anchor{gnat_rm/intrinsic_subprograms exception-name}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26e}
@section Exception_Name
@@ -18068,7 +18329,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 file}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26e}
+@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26f}@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{270}
@section File
@@ -18082,7 +18343,7 @@ application program should simply call the function
file.
@node Line,Shifts and Rotates,File,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{26f}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{270}
+@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{272}
@section Line
@@ -18096,7 +18357,7 @@ application program should simply call the function
source line.
@node Shifts and Rotates,Source_Location,Line,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{272}
+@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{274}
@section Shifts and Rotates
@@ -18139,7 +18400,7 @@ corresponding operator for modular type. In particular, shifting a negative
number may change its sign bit to positive.
@node Source_Location,,Shifts and Rotates,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{274}
+@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{275}@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{276}
@section Source_Location
@@ -18153,7 +18414,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 doc}@anchor{275}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{276}@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}
+@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{278}@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}
@chapter Representation Clauses and Pragmas
@@ -18199,7 +18460,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 alignment-clauses}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{278}
+@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{279}@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{27a}
@section Alignment Clauses
@@ -18221,7 +18482,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{18d,,Attribute Maximum_Alignment}.)
+@code{Standard'Maximum_Alignment}; see @ref{18e,,Attribute Maximum_Alignment}.)
@geindex Maximum_Alignment attribute
@@ -18330,7 +18591,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{279}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{27a}
+@anchor{gnat_rm/representation_clauses_and_pragmas id3}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{27c}
@section Size Clauses
@@ -18407,7 +18668,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 id4}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27d}@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27e}
@section Storage_Size Clauses
@@ -18480,7 +18741,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{27d}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{27e}
+@anchor{gnat_rm/representation_clauses_and_pragmas id5}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{280}
@section Size of Variant Record Objects
@@ -18590,7 +18851,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 biased-representation}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{280}
+@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{281}@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{282}
@section Biased Representation
@@ -18628,7 +18889,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{281}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{282}
+@anchor{gnat_rm/representation_clauses_and_pragmas id7}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{284}
@section Value_Size and Object_Size Clauses
@@ -18944,7 +19205,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 component-size-clauses}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{284}
+@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{285}@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{286}
@section Component_Size Clauses
@@ -18992,7 +19253,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{285}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{286}
+@anchor{gnat_rm/representation_clauses_and_pragmas bit-order-clauses}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{288}
@section Bit_Order Clauses
@@ -19098,7 +19359,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 effect-of-bit-order-on-byte-ordering}@anchor{287}@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}@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{28a}
@section Effect of Bit_Order on Byte Ordering
@@ -19355,7 +19616,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 id11}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28a}
+@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28c}
@section Pragma Pack for Arrays
@@ -19475,7 +19736,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 id12}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28d}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28e}
@section Pragma Pack for Records
@@ -19559,7 +19820,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{28d}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{28e}
+@anchor{gnat_rm/representation_clauses_and_pragmas id13}@anchor{28f}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{290}
@section Record Representation Clauses
@@ -19638,7 +19899,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{28f}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{290}
+@anchor{gnat_rm/representation_clauses_and_pragmas handling-of-records-with-holes}@anchor{291}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{292}
@section Handling of Records with Holes
@@ -19714,7 +19975,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{291}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{292}
+@anchor{gnat_rm/representation_clauses_and_pragmas enumeration-clauses}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{294}
@section Enumeration Clauses
@@ -19757,7 +20018,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 address-clauses}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{294}
+@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{295}@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{296}
@section Address Clauses
@@ -20086,7 +20347,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{295}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{296}
+@anchor{gnat_rm/representation_clauses_and_pragmas id17}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{298}
@section Use of Address Clauses for Memory-Mapped I/O
@@ -20144,7 +20405,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 effect-of-convention-on-representation}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{298}
+@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{299}@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{29a}
@section Effect of Convention on Representation
@@ -20222,7 +20483,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{299}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{29a}
+@anchor{gnat_rm/representation_clauses_and_pragmas conventions-and-anonymous-access-types}@anchor{29b}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{29c}
@section Conventions and Anonymous Access Types
@@ -20298,7 +20559,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 determining-the-representations-chosen-by-gnat}@anchor{29b}@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}@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29e}
@section Determining the Representations chosen by GNAT
@@ -20450,7 +20711,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 doc}@anchor{29d}@anchor{gnat_rm/standard_library_routines id1}@anchor{29e}@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}
+@anchor{gnat_rm/standard_library_routines doc}@anchor{29f}@anchor{gnat_rm/standard_library_routines id1}@anchor{2a0}@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}
@chapter Standard Library Routines
@@ -21274,7 +21535,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 doc}@anchor{29f}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a0}@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{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a2}@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}
@chapter The Implementation of Standard I/O
@@ -21326,7 +21587,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 id2}@anchor{2a1}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a4}
@section Standard I/O Packages
@@ -21397,7 +21658,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{2a3}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o form-strings}@anchor{2a5}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a6}
@section FORM Strings
@@ -21423,7 +21684,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{2a5}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o direct-io}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a8}
@section Direct_IO
@@ -21443,7 +21704,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 id5}@anchor{2a7}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2aa}
@section Sequential_IO
@@ -21490,7 +21751,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{2a9}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2aa}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id6}@anchor{2ab}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2ac}
@section Text_IO
@@ -21573,7 +21834,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{2ab}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2ac}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id7}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2ae}
@subsection Stream Pointer Positioning
@@ -21609,7 +21870,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 id8}@anchor{2ad}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2b0}
@subsection Reading and Writing Non-Regular Files
@@ -21660,7 +21921,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{2af}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2b0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o get-immediate}@anchor{2b1}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2b2}
@subsection Get_Immediate
@@ -21678,7 +21939,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{2b1}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id10}@anchor{2b3}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b4}
@subsection Treating Text_IO Files as Streams
@@ -21694,7 +21955,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{2b3}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id11}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b6}
@subsection Text_IO Extensions
@@ -21722,7 +21983,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 id12}@anchor{2b5}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b8}
@subsection Text_IO Facilities for Unbounded Strings
@@ -21770,7 +22031,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 id13}@anchor{2b7}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2ba}
@section Wide_Text_IO
@@ -22017,12 +22278,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 id14}@anchor{2b9}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2bc}
@subsection Stream Pointer Positioning
@code{Ada.Wide_Text_IO} is similar to @code{Ada.Text_IO} in its handling
-of stream pointer positioning (@ref{2aa,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ac,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -22041,7 +22302,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 id15}@anchor{2bb}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2be}
@subsection Reading and Writing Non-Regular Files
@@ -22052,7 +22313,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{2bd}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2be}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id16}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2c0}
@section Wide_Wide_Text_IO
@@ -22221,12 +22482,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 id17}@anchor{2bf}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2c2}
@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{2aa,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ac,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -22245,7 +22506,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{2c1}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id18}@anchor{2c3}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c4}
@subsection Reading and Writing Non-Regular Files
@@ -22256,7 +22517,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{2c3}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id19}@anchor{2c5}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c6}
@section Stream_IO
@@ -22278,7 +22539,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{2c5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id20}@anchor{2c7}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c8}
@section Text Translation
@@ -22312,7 +22573,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{2c7}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2c8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id21}@anchor{2c9}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2ca}
@section Shared Files
@@ -22375,7 +22636,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{2c9}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2ca}
+@anchor{gnat_rm/the_implementation_of_standard_i_o filenames-encoding}@anchor{2cb}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2cc}
@section Filenames encoding
@@ -22415,7 +22676,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{2cb}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2cc}
+@anchor{gnat_rm/the_implementation_of_standard_i_o file-content-encoding}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2ce}
@section File content encoding
@@ -22448,7 +22709,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 id24}@anchor{2cd}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2d0}
@section Open Modes
@@ -22551,7 +22812,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 id25}@anchor{2cf}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2d2}
@section Operations on C Streams
@@ -22711,7 +22972,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 id26}@anchor{2d1}@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}@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d4}
@section Interfacing to C Streams
@@ -22804,7 +23065,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 doc}@anchor{2d3}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d4}@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}
+@anchor{gnat_rm/the_gnat_library doc}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d6}@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}
@chapter The GNAT Library
@@ -22998,7 +23259,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 ada-characters-latin-9-a-chlat9-ads}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id2}@anchor{2d6}
+@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d7}@anchor{gnat_rm/the_gnat_library id2}@anchor{2d8}
@section @code{Ada.Characters.Latin_9} (@code{a-chlat9.ads})
@@ -23015,7 +23276,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{2d7}@anchor{gnat_rm/the_gnat_library id3}@anchor{2d8}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-1-a-cwila1-ads}@anchor{2d9}@anchor{gnat_rm/the_gnat_library id3}@anchor{2da}
@section @code{Ada.Characters.Wide_Latin_1} (@code{a-cwila1.ads})
@@ -23032,7 +23293,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 ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2d9}@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}@anchor{gnat_rm/the_gnat_library id4}@anchor{2dc}
@section @code{Ada.Characters.Wide_Latin_9} (@code{a-cwila1.ads})
@@ -23049,7 +23310,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{2db}@anchor{gnat_rm/the_gnat_library id5}@anchor{2dc}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-1-a-chzla1-ads}@anchor{2dd}@anchor{gnat_rm/the_gnat_library id5}@anchor{2de}
@section @code{Ada.Characters.Wide_Wide_Latin_1} (@code{a-chzla1.ads})
@@ -23066,7 +23327,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{2dd}@anchor{gnat_rm/the_gnat_library id6}@anchor{2de}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-9-a-chzla9-ads}@anchor{2df}@anchor{gnat_rm/the_gnat_library id6}@anchor{2e0}
@section @code{Ada.Characters.Wide_Wide_Latin_9} (@code{a-chzla9.ads})
@@ -23083,7 +23344,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 ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2df}@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}@anchor{gnat_rm/the_gnat_library id7}@anchor{2e2}
@section @code{Ada.Containers.Formal_Doubly_Linked_Lists} (@code{a-cfdlli.ads})
@@ -23102,7 +23363,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 ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e1}@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}@anchor{gnat_rm/the_gnat_library id8}@anchor{2e4}
@section @code{Ada.Containers.Formal_Hashed_Maps} (@code{a-cfhama.ads})
@@ -23121,7 +23382,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 ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e3}@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}@anchor{gnat_rm/the_gnat_library id9}@anchor{2e6}
@section @code{Ada.Containers.Formal_Hashed_Sets} (@code{a-cfhase.ads})
@@ -23140,7 +23401,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 ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e5}@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}@anchor{gnat_rm/the_gnat_library id10}@anchor{2e8}
@section @code{Ada.Containers.Formal_Ordered_Maps} (@code{a-cforma.ads})
@@ -23159,7 +23420,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{2e7}@anchor{gnat_rm/the_gnat_library id11}@anchor{2e8}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-sets-a-cforse-ads}@anchor{2e9}@anchor{gnat_rm/the_gnat_library id11}@anchor{2ea}
@section @code{Ada.Containers.Formal_Ordered_Sets} (@code{a-cforse.ads})
@@ -23178,7 +23439,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 ada-containers-formal-vectors-a-cofove-ads}@anchor{2e9}@anchor{gnat_rm/the_gnat_library id12}@anchor{2ea}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2eb}@anchor{gnat_rm/the_gnat_library id12}@anchor{2ec}
@section @code{Ada.Containers.Formal_Vectors} (@code{a-cofove.ads})
@@ -23197,7 +23458,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 ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2eb}@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}@anchor{gnat_rm/the_gnat_library id13}@anchor{2ee}
@section @code{Ada.Containers.Formal_Indefinite_Vectors} (@code{a-cfinve.ads})
@@ -23216,7 +23477,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 ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ed}@anchor{gnat_rm/the_gnat_library id14}@anchor{2ee}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ef}@anchor{gnat_rm/the_gnat_library id14}@anchor{2f0}
@section @code{Ada.Containers.Functional_Vectors} (@code{a-cofuve.ads})
@@ -23238,7 +23499,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{2ef}@anchor{gnat_rm/the_gnat_library id15}@anchor{2f0}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-sets-a-cofuse-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id15}@anchor{2f2}
@section @code{Ada.Containers.Functional_Sets} (@code{a-cofuse.ads})
@@ -23260,7 +23521,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 ada-containers-functional-maps-a-cofuma-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id16}@anchor{2f2}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f3}@anchor{gnat_rm/the_gnat_library id16}@anchor{2f4}
@section @code{Ada.Containers.Functional_Maps} (@code{a-cofuma.ads})
@@ -23282,7 +23543,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{2f3}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f4}
+@anchor{gnat_rm/the_gnat_library ada-containers-bounded-holders-a-coboho-ads}@anchor{2f5}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f6}
@section @code{Ada.Containers.Bounded_Holders} (@code{a-coboho.ads})
@@ -23294,7 +23555,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{2f5}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f6}
+@anchor{gnat_rm/the_gnat_library ada-command-line-environment-a-colien-ads}@anchor{2f7}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f8}
@section @code{Ada.Command_Line.Environment} (@code{a-colien.ads})
@@ -23307,7 +23568,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 ada-command-line-remove-a-colire-ads}@anchor{2f7}@anchor{gnat_rm/the_gnat_library id19}@anchor{2f8}
+@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f9}@anchor{gnat_rm/the_gnat_library id19}@anchor{2fa}
@section @code{Ada.Command_Line.Remove} (@code{a-colire.ads})
@@ -23325,7 +23586,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 ada-command-line-response-file-a-clrefi-ads}@anchor{2f9}@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}@anchor{gnat_rm/the_gnat_library id20}@anchor{2fc}
@section @code{Ada.Command_Line.Response_File} (@code{a-clrefi.ads})
@@ -23345,7 +23606,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 ada-direct-io-c-streams-a-diocst-ads}@anchor{2fb}@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}@anchor{gnat_rm/the_gnat_library id21}@anchor{2fe}
@section @code{Ada.Direct_IO.C_Streams} (@code{a-diocst.ads})
@@ -23360,7 +23621,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 ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2fd}@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}@anchor{gnat_rm/the_gnat_library id22}@anchor{300}
@section @code{Ada.Exceptions.Is_Null_Occurrence} (@code{a-einuoc.ads})
@@ -23374,7 +23635,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 ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{2ff}@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}@anchor{gnat_rm/the_gnat_library id23}@anchor{302}
@section @code{Ada.Exceptions.Last_Chance_Handler} (@code{a-elchha.ads})
@@ -23388,7 +23649,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{301}@anchor{gnat_rm/the_gnat_library id24}@anchor{302}
+@anchor{gnat_rm/the_gnat_library ada-exceptions-traceback-a-exctra-ads}@anchor{303}@anchor{gnat_rm/the_gnat_library id24}@anchor{304}
@section @code{Ada.Exceptions.Traceback} (@code{a-exctra.ads})
@@ -23401,7 +23662,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{303}@anchor{gnat_rm/the_gnat_library id25}@anchor{304}
+@anchor{gnat_rm/the_gnat_library ada-sequential-io-c-streams-a-siocst-ads}@anchor{305}@anchor{gnat_rm/the_gnat_library id25}@anchor{306}
@section @code{Ada.Sequential_IO.C_Streams} (@code{a-siocst.ads})
@@ -23416,7 +23677,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 ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{305}@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}@anchor{gnat_rm/the_gnat_library id26}@anchor{308}
@section @code{Ada.Streams.Stream_IO.C_Streams} (@code{a-ssicst.ads})
@@ -23431,7 +23692,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{307}@anchor{gnat_rm/the_gnat_library id27}@anchor{308}
+@anchor{gnat_rm/the_gnat_library ada-strings-unbounded-text-io-a-suteio-ads}@anchor{309}@anchor{gnat_rm/the_gnat_library id27}@anchor{30a}
@section @code{Ada.Strings.Unbounded.Text_IO} (@code{a-suteio.ads})
@@ -23448,7 +23709,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 ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{309}@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}@anchor{gnat_rm/the_gnat_library id28}@anchor{30c}
@section @code{Ada.Strings.Wide_Unbounded.Wide_Text_IO} (@code{a-swuwti.ads})
@@ -23465,7 +23726,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 ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30b}@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}@anchor{gnat_rm/the_gnat_library id29}@anchor{30e}
@section @code{Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Text_IO} (@code{a-szuzti.ads})
@@ -23482,7 +23743,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{30d}@anchor{gnat_rm/the_gnat_library id30}@anchor{30e}
+@anchor{gnat_rm/the_gnat_library ada-task-initialization-a-tasini-ads}@anchor{30f}@anchor{gnat_rm/the_gnat_library id30}@anchor{310}
@section @code{Ada.Task_Initialization} (@code{a-tasini.ads})
@@ -23494,7 +23755,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{30f}@anchor{gnat_rm/the_gnat_library id31}@anchor{310}
+@anchor{gnat_rm/the_gnat_library ada-text-io-c-streams-a-tiocst-ads}@anchor{311}@anchor{gnat_rm/the_gnat_library id31}@anchor{312}
@section @code{Ada.Text_IO.C_Streams} (@code{a-tiocst.ads})
@@ -23509,7 +23770,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{311}@anchor{gnat_rm/the_gnat_library id32}@anchor{312}
+@anchor{gnat_rm/the_gnat_library ada-text-io-reset-standard-files-a-tirsfi-ads}@anchor{313}@anchor{gnat_rm/the_gnat_library id32}@anchor{314}
@section @code{Ada.Text_IO.Reset_Standard_Files} (@code{a-tirsfi.ads})
@@ -23524,7 +23785,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 ada-wide-characters-unicode-a-wichun-ads}@anchor{313}@anchor{gnat_rm/the_gnat_library id33}@anchor{314}
+@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{315}@anchor{gnat_rm/the_gnat_library id33}@anchor{316}
@section @code{Ada.Wide_Characters.Unicode} (@code{a-wichun.ads})
@@ -23537,7 +23798,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 ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{315}@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}@anchor{gnat_rm/the_gnat_library id34}@anchor{318}
@section @code{Ada.Wide_Text_IO.C_Streams} (@code{a-wtcstr.ads})
@@ -23552,7 +23813,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{317}@anchor{gnat_rm/the_gnat_library id35}@anchor{318}
+@anchor{gnat_rm/the_gnat_library ada-wide-text-io-reset-standard-files-a-wrstfi-ads}@anchor{319}@anchor{gnat_rm/the_gnat_library id35}@anchor{31a}
@section @code{Ada.Wide_Text_IO.Reset_Standard_Files} (@code{a-wrstfi.ads})
@@ -23567,7 +23828,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 ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{319}@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}@anchor{gnat_rm/the_gnat_library id36}@anchor{31c}
@section @code{Ada.Wide_Wide_Characters.Unicode} (@code{a-zchuni.ads})
@@ -23580,7 +23841,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 ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31b}@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}@anchor{gnat_rm/the_gnat_library id37}@anchor{31e}
@section @code{Ada.Wide_Wide_Text_IO.C_Streams} (@code{a-ztcstr.ads})
@@ -23595,7 +23856,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{31d}@anchor{gnat_rm/the_gnat_library id38}@anchor{31e}
+@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-reset-standard-files-a-zrstfi-ads}@anchor{31f}@anchor{gnat_rm/the_gnat_library id38}@anchor{320}
@section @code{Ada.Wide_Wide_Text_IO.Reset_Standard_Files} (@code{a-zrstfi.ads})
@@ -23610,7 +23871,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{31f}@anchor{gnat_rm/the_gnat_library id39}@anchor{320}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-g-altive-ads}@anchor{321}@anchor{gnat_rm/the_gnat_library id39}@anchor{322}
@section @code{GNAT.Altivec} (@code{g-altive.ads})
@@ -23623,7 +23884,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{321}@anchor{gnat_rm/the_gnat_library id40}@anchor{322}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-conversions-g-altcon-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id40}@anchor{324}
@section @code{GNAT.Altivec.Conversions} (@code{g-altcon.ads})
@@ -23634,7 +23895,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 gnat-altivec-vector-operations-g-alveop-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id41}@anchor{324}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{325}@anchor{gnat_rm/the_gnat_library id41}@anchor{326}
@section @code{GNAT.Altivec.Vector_Operations} (@code{g-alveop.ads})
@@ -23648,7 +23909,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{325}@anchor{gnat_rm/the_gnat_library id42}@anchor{326}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-types-g-alvety-ads}@anchor{327}@anchor{gnat_rm/the_gnat_library id42}@anchor{328}
@section @code{GNAT.Altivec.Vector_Types} (@code{g-alvety.ads})
@@ -23660,7 +23921,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{327}@anchor{gnat_rm/the_gnat_library id43}@anchor{328}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-views-g-alvevi-ads}@anchor{329}@anchor{gnat_rm/the_gnat_library id43}@anchor{32a}
@section @code{GNAT.Altivec.Vector_Views} (@code{g-alvevi.ads})
@@ -23675,7 +23936,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{329}@anchor{gnat_rm/the_gnat_library id44}@anchor{32a}
+@anchor{gnat_rm/the_gnat_library gnat-array-split-g-arrspl-ads}@anchor{32b}@anchor{gnat_rm/the_gnat_library id44}@anchor{32c}
@section @code{GNAT.Array_Split} (@code{g-arrspl.ads})
@@ -23688,7 +23949,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 gnat-awk-g-awk-ads}@anchor{32b}@anchor{gnat_rm/the_gnat_library id45}@anchor{32c}
+@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32d}@anchor{gnat_rm/the_gnat_library id45}@anchor{32e}
@section @code{GNAT.AWK} (@code{g-awk.ads})
@@ -23703,7 +23964,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 gnat-bind-environment-g-binenv-ads}@anchor{32d}@anchor{gnat_rm/the_gnat_library id46}@anchor{32e}
+@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id46}@anchor{330}
@section @code{GNAT.Bind_Environment} (@code{g-binenv.ads})
@@ -23716,7 +23977,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 gnat-branch-prediction-g-brapre-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id47}@anchor{330}
+@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{331}@anchor{gnat_rm/the_gnat_library id47}@anchor{332}
@section @code{GNAT.Branch_Prediction} (@code{g-brapre.ads})
@@ -23727,7 +23988,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{331}@anchor{gnat_rm/the_gnat_library id48}@anchor{332}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{333}@anchor{gnat_rm/the_gnat_library id48}@anchor{334}
@section @code{GNAT.Bounded_Buffers} (@code{g-boubuf.ads})
@@ -23742,7 +24003,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{333}@anchor{gnat_rm/the_gnat_library id49}@anchor{334}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{335}@anchor{gnat_rm/the_gnat_library id49}@anchor{336}
@section @code{GNAT.Bounded_Mailboxes} (@code{g-boumai.ads})
@@ -23755,7 +24016,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{335}@anchor{gnat_rm/the_gnat_library id50}@anchor{336}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id50}@anchor{338}
@section @code{GNAT.Bubble_Sort} (@code{g-bubsor.ads})
@@ -23770,7 +24031,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 gnat-bubble-sort-a-g-busora-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id51}@anchor{338}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{339}@anchor{gnat_rm/the_gnat_library id51}@anchor{33a}
@section @code{GNAT.Bubble_Sort_A} (@code{g-busora.ads})
@@ -23786,7 +24047,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{339}@anchor{gnat_rm/the_gnat_library id52}@anchor{33a}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{33b}@anchor{gnat_rm/the_gnat_library id52}@anchor{33c}
@section @code{GNAT.Bubble_Sort_G} (@code{g-busorg.ads})
@@ -23802,7 +24063,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{33b}@anchor{gnat_rm/the_gnat_library id53}@anchor{33c}
+@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{33d}@anchor{gnat_rm/the_gnat_library id53}@anchor{33e}
@section @code{GNAT.Byte_Order_Mark} (@code{g-byorma.ads})
@@ -23818,7 +24079,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{33d}@anchor{gnat_rm/the_gnat_library id54}@anchor{33e}
+@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{33f}@anchor{gnat_rm/the_gnat_library id54}@anchor{340}
@section @code{GNAT.Byte_Swapping} (@code{g-bytswa.ads})
@@ -23832,7 +24093,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 gnat-calendar-g-calend-ads}@anchor{33f}@anchor{gnat_rm/the_gnat_library id55}@anchor{340}
+@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{341}@anchor{gnat_rm/the_gnat_library id55}@anchor{342}
@section @code{GNAT.Calendar} (@code{g-calend.ads})
@@ -23846,7 +24107,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 gnat-calendar-time-io-g-catiio-ads}@anchor{341}@anchor{gnat_rm/the_gnat_library id56}@anchor{342}
+@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{343}@anchor{gnat_rm/the_gnat_library id56}@anchor{344}
@section @code{GNAT.Calendar.Time_IO} (@code{g-catiio.ads})
@@ -23857,7 +24118,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 gnat-crc32-g-crc32-ads}@anchor{343}@anchor{gnat_rm/the_gnat_library id57}@anchor{344}
+@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{345}@anchor{gnat_rm/the_gnat_library id57}@anchor{346}
@section @code{GNAT.CRC32} (@code{g-crc32.ads})
@@ -23874,7 +24135,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 gnat-case-util-g-casuti-ads}@anchor{345}@anchor{gnat_rm/the_gnat_library id58}@anchor{346}
+@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id58}@anchor{348}
@section @code{GNAT.Case_Util} (@code{g-casuti.ads})
@@ -23889,7 +24150,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 gnat-cgi-g-cgi-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id59}@anchor{348}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{349}@anchor{gnat_rm/the_gnat_library id59}@anchor{34a}
@section @code{GNAT.CGI} (@code{g-cgi.ads})
@@ -23904,7 +24165,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{349}@anchor{gnat_rm/the_gnat_library id60}@anchor{34a}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{34b}@anchor{gnat_rm/the_gnat_library id60}@anchor{34c}
@section @code{GNAT.CGI.Cookie} (@code{g-cgicoo.ads})
@@ -23919,7 +24180,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{34b}@anchor{gnat_rm/the_gnat_library id61}@anchor{34c}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id61}@anchor{34e}
@section @code{GNAT.CGI.Debug} (@code{g-cgideb.ads})
@@ -23931,7 +24192,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 gnat-command-line-g-comlin-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id62}@anchor{34e}
+@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34f}@anchor{gnat_rm/the_gnat_library id62}@anchor{350}
@section @code{GNAT.Command_Line} (@code{g-comlin.ads})
@@ -23944,7 +24205,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{34f}@anchor{gnat_rm/the_gnat_library id63}@anchor{350}
+@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{351}@anchor{gnat_rm/the_gnat_library id63}@anchor{352}
@section @code{GNAT.Compiler_Version} (@code{g-comver.ads})
@@ -23962,7 +24223,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 gnat-ctrl-c-g-ctrl-c-ads}@anchor{351}@anchor{gnat_rm/the_gnat_library id64}@anchor{352}
+@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id64}@anchor{354}
@section @code{GNAT.Ctrl_C} (@code{g-ctrl_c.ads})
@@ -23973,7 +24234,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 gnat-current-exception-g-curexc-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id65}@anchor{354}
+@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{355}@anchor{gnat_rm/the_gnat_library id65}@anchor{356}
@section @code{GNAT.Current_Exception} (@code{g-curexc.ads})
@@ -23990,7 +24251,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{355}@anchor{gnat_rm/the_gnat_library id66}@anchor{356}
+@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{357}@anchor{gnat_rm/the_gnat_library id66}@anchor{358}
@section @code{GNAT.Debug_Pools} (@code{g-debpoo.ads})
@@ -24007,7 +24268,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{357}@anchor{gnat_rm/the_gnat_library id67}@anchor{358}
+@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{359}@anchor{gnat_rm/the_gnat_library id67}@anchor{35a}
@section @code{GNAT.Debug_Utilities} (@code{g-debuti.ads})
@@ -24020,7 +24281,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{359}@anchor{gnat_rm/the_gnat_library id68}@anchor{35a}
+@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{35b}@anchor{gnat_rm/the_gnat_library id68}@anchor{35c}
@section @code{GNAT.Decode_String} (@code{g-decstr.ads})
@@ -24044,7 +24305,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{35b}@anchor{gnat_rm/the_gnat_library id69}@anchor{35c}
+@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{35d}@anchor{gnat_rm/the_gnat_library id69}@anchor{35e}
@section @code{GNAT.Decode_UTF8_String} (@code{g-deutst.ads})
@@ -24065,7 +24326,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 gnat-directory-operations-g-dirope-ads}@anchor{35d}@anchor{gnat_rm/the_gnat_library id70}@anchor{35e}
+@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35f}@anchor{gnat_rm/the_gnat_library id70}@anchor{360}
@section @code{GNAT.Directory_Operations} (@code{g-dirope.ads})
@@ -24078,7 +24339,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 gnat-directory-operations-iteration-g-diopit-ads}@anchor{35f}@anchor{gnat_rm/the_gnat_library id71}@anchor{360}
+@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id71}@anchor{362}
@section @code{GNAT.Directory_Operations.Iteration} (@code{g-diopit.ads})
@@ -24090,7 +24351,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 gnat-dynamic-htables-g-dynhta-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id72}@anchor{362}
+@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{363}@anchor{gnat_rm/the_gnat_library id72}@anchor{364}
@section @code{GNAT.Dynamic_HTables} (@code{g-dynhta.ads})
@@ -24108,7 +24369,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{363}@anchor{gnat_rm/the_gnat_library id73}@anchor{364}
+@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id73}@anchor{366}
@section @code{GNAT.Dynamic_Tables} (@code{g-dyntab.ads})
@@ -24128,7 +24389,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 gnat-encode-string-g-encstr-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id74}@anchor{366}
+@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{367}@anchor{gnat_rm/the_gnat_library id74}@anchor{368}
@section @code{GNAT.Encode_String} (@code{g-encstr.ads})
@@ -24150,7 +24411,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{367}@anchor{gnat_rm/the_gnat_library id75}@anchor{368}
+@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{369}@anchor{gnat_rm/the_gnat_library id75}@anchor{36a}
@section @code{GNAT.Encode_UTF8_String} (@code{g-enutst.ads})
@@ -24171,7 +24432,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{369}@anchor{gnat_rm/the_gnat_library id76}@anchor{36a}
+@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{36b}@anchor{gnat_rm/the_gnat_library id76}@anchor{36c}
@section @code{GNAT.Exception_Actions} (@code{g-excact.ads})
@@ -24184,7 +24445,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{36b}@anchor{gnat_rm/the_gnat_library id77}@anchor{36c}
+@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{36d}@anchor{gnat_rm/the_gnat_library id77}@anchor{36e}
@section @code{GNAT.Exception_Traces} (@code{g-exctra.ads})
@@ -24198,7 +24459,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 gnat-exceptions-g-except-ads}@anchor{36d}@anchor{gnat_rm/the_gnat_library id78}@anchor{36e}
+@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36f}@anchor{gnat_rm/the_gnat_library id78}@anchor{370}
@section @code{GNAT.Exceptions} (@code{g-except.ads})
@@ -24219,7 +24480,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 gnat-expect-g-expect-ads}@anchor{36f}@anchor{gnat_rm/the_gnat_library id79}@anchor{370}
+@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{371}@anchor{gnat_rm/the_gnat_library id79}@anchor{372}
@section @code{GNAT.Expect} (@code{g-expect.ads})
@@ -24235,7 +24496,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 gnat-expect-tty-g-exptty-ads}@anchor{371}@anchor{gnat_rm/the_gnat_library id80}@anchor{372}
+@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{373}@anchor{gnat_rm/the_gnat_library id80}@anchor{374}
@section @code{GNAT.Expect.TTY} (@code{g-exptty.ads})
@@ -24247,7 +24508,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 gnat-float-control-g-flocon-ads}@anchor{373}@anchor{gnat_rm/the_gnat_library id81}@anchor{374}
+@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{375}@anchor{gnat_rm/the_gnat_library id81}@anchor{376}
@section @code{GNAT.Float_Control} (@code{g-flocon.ads})
@@ -24261,7 +24522,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 gnat-formatted-string-g-forstr-ads}@anchor{375}@anchor{gnat_rm/the_gnat_library id82}@anchor{376}
+@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id82}@anchor{378}
@section @code{GNAT.Formatted_String} (@code{g-forstr.ads})
@@ -24276,7 +24537,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 gnat-heap-sort-g-heasor-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id83}@anchor{378}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{379}@anchor{gnat_rm/the_gnat_library id83}@anchor{37a}
@section @code{GNAT.Heap_Sort} (@code{g-heasor.ads})
@@ -24290,7 +24551,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{379}@anchor{gnat_rm/the_gnat_library id84}@anchor{37a}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{37b}@anchor{gnat_rm/the_gnat_library id84}@anchor{37c}
@section @code{GNAT.Heap_Sort_A} (@code{g-hesora.ads})
@@ -24306,7 +24567,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 gnat-heap-sort-g-g-hesorg-ads}@anchor{37b}@anchor{gnat_rm/the_gnat_library id85}@anchor{37c}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37d}@anchor{gnat_rm/the_gnat_library id85}@anchor{37e}
@section @code{GNAT.Heap_Sort_G} (@code{g-hesorg.ads})
@@ -24320,7 +24581,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 gnat-htable-g-htable-ads}@anchor{37d}@anchor{gnat_rm/the_gnat_library id86}@anchor{37e}
+@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37f}@anchor{gnat_rm/the_gnat_library id86}@anchor{380}
@section @code{GNAT.HTable} (@code{g-htable.ads})
@@ -24333,7 +24594,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 gnat-io-g-io-ads}@anchor{37f}@anchor{gnat_rm/the_gnat_library id87}@anchor{380}
+@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{381}@anchor{gnat_rm/the_gnat_library id87}@anchor{382}
@section @code{GNAT.IO} (@code{g-io.ads})
@@ -24349,7 +24610,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 gnat-io-aux-g-io-aux-ads}@anchor{381}@anchor{gnat_rm/the_gnat_library id88}@anchor{382}
+@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{383}@anchor{gnat_rm/the_gnat_library id88}@anchor{384}
@section @code{GNAT.IO_Aux} (@code{g-io_aux.ads})
@@ -24363,7 +24624,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 gnat-lock-files-g-locfil-ads}@anchor{383}@anchor{gnat_rm/the_gnat_library id89}@anchor{384}
+@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{385}@anchor{gnat_rm/the_gnat_library id89}@anchor{386}
@section @code{GNAT.Lock_Files} (@code{g-locfil.ads})
@@ -24377,7 +24638,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 gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{385}@anchor{gnat_rm/the_gnat_library id90}@anchor{386}
+@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{387}@anchor{gnat_rm/the_gnat_library id90}@anchor{388}
@section @code{GNAT.MBBS_Discrete_Random} (@code{g-mbdira.ads})
@@ -24389,7 +24650,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 gnat-mbbs-float-random-g-mbflra-ads}@anchor{387}@anchor{gnat_rm/the_gnat_library id91}@anchor{388}
+@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{389}@anchor{gnat_rm/the_gnat_library id91}@anchor{38a}
@section @code{GNAT.MBBS_Float_Random} (@code{g-mbflra.ads})
@@ -24401,7 +24662,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 gnat-md5-g-md5-ads}@anchor{389}@anchor{gnat_rm/the_gnat_library id92}@anchor{38a}
+@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id92}@anchor{38c}
@section @code{GNAT.MD5} (@code{g-md5.ads})
@@ -24414,7 +24675,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 gnat-memory-dump-g-memdum-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id93}@anchor{38c}
+@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38d}@anchor{gnat_rm/the_gnat_library id93}@anchor{38e}
@section @code{GNAT.Memory_Dump} (@code{g-memdum.ads})
@@ -24427,7 +24688,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{38d}@anchor{gnat_rm/the_gnat_library id94}@anchor{38e}
+@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{38f}@anchor{gnat_rm/the_gnat_library id94}@anchor{390}
@section @code{GNAT.Most_Recent_Exception} (@code{g-moreex.ads})
@@ -24441,7 +24702,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{38f}@anchor{gnat_rm/the_gnat_library id95}@anchor{390}
+@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{391}@anchor{gnat_rm/the_gnat_library id95}@anchor{392}
@section @code{GNAT.OS_Lib} (@code{g-os_lib.ads})
@@ -24457,7 +24718,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{391}@anchor{gnat_rm/the_gnat_library id96}@anchor{392}
+@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{393}@anchor{gnat_rm/the_gnat_library id96}@anchor{394}
@section @code{GNAT.Perfect_Hash_Generators} (@code{g-pehage.ads})
@@ -24475,7 +24736,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{393}@anchor{gnat_rm/the_gnat_library id97}@anchor{394}
+@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{395}@anchor{gnat_rm/the_gnat_library id97}@anchor{396}
@section @code{GNAT.Random_Numbers} (@code{g-rannum.ads})
@@ -24487,7 +24748,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 gnat-regexp-g-regexp-ads}@anchor{25a}@anchor{gnat_rm/the_gnat_library id98}@anchor{395}
+@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25c}@anchor{gnat_rm/the_gnat_library id98}@anchor{397}
@section @code{GNAT.Regexp} (@code{g-regexp.ads})
@@ -24503,7 +24764,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 gnat-registry-g-regist-ads}@anchor{396}@anchor{gnat_rm/the_gnat_library id99}@anchor{397}
+@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{398}@anchor{gnat_rm/the_gnat_library id99}@anchor{399}
@section @code{GNAT.Registry} (@code{g-regist.ads})
@@ -24517,7 +24778,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 gnat-regpat-g-regpat-ads}@anchor{398}@anchor{gnat_rm/the_gnat_library id100}@anchor{399}
+@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id100}@anchor{39b}
@section @code{GNAT.Regpat} (@code{g-regpat.ads})
@@ -24532,7 +24793,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 gnat-rewrite-data-g-rewdat-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id101}@anchor{39b}
+@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39c}@anchor{gnat_rm/the_gnat_library id101}@anchor{39d}
@section @code{GNAT.Rewrite_Data} (@code{g-rewdat.ads})
@@ -24546,7 +24807,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{39c}@anchor{gnat_rm/the_gnat_library id102}@anchor{39d}
+@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id102}@anchor{39f}
@section @code{GNAT.Secondary_Stack_Info} (@code{g-sestin.ads})
@@ -24558,7 +24819,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 gnat-semaphores-g-semaph-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id103}@anchor{39f}
+@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{3a0}@anchor{gnat_rm/the_gnat_library id103}@anchor{3a1}
@section @code{GNAT.Semaphores} (@code{g-semaph.ads})
@@ -24569,7 +24830,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{3a0}@anchor{gnat_rm/the_gnat_library id104}@anchor{3a1}
+@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{3a2}@anchor{gnat_rm/the_gnat_library id104}@anchor{3a3}
@section @code{GNAT.Serial_Communications} (@code{g-sercom.ads})
@@ -24581,7 +24842,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{3a2}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a3}
+@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{3a4}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a5}
@section @code{GNAT.SHA1} (@code{g-sha1.ads})
@@ -24594,7 +24855,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{3a4}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a5}
+@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{3a6}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a7}
@section @code{GNAT.SHA224} (@code{g-sha224.ads})
@@ -24607,7 +24868,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{3a6}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a7}
+@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{3a8}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a9}
@section @code{GNAT.SHA256} (@code{g-sha256.ads})
@@ -24620,7 +24881,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 gnat-sha384-g-sha384-ads}@anchor{3a8}@anchor{gnat_rm/the_gnat_library id108}@anchor{3a9}
+@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id108}@anchor{3ab}
@section @code{GNAT.SHA384} (@code{g-sha384.ads})
@@ -24633,7 +24894,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 gnat-sha512-g-sha512-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id109}@anchor{3ab}
+@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3ac}@anchor{gnat_rm/the_gnat_library id109}@anchor{3ad}
@section @code{GNAT.SHA512} (@code{g-sha512.ads})
@@ -24646,7 +24907,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{3ac}@anchor{gnat_rm/the_gnat_library id110}@anchor{3ad}
+@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3ae}@anchor{gnat_rm/the_gnat_library id110}@anchor{3af}
@section @code{GNAT.Signals} (@code{g-signal.ads})
@@ -24658,7 +24919,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{3ae}@anchor{gnat_rm/the_gnat_library id111}@anchor{3af}
+@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3b0}@anchor{gnat_rm/the_gnat_library id111}@anchor{3b1}
@section @code{GNAT.Sockets} (@code{g-socket.ads})
@@ -24673,7 +24934,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{3b0}@anchor{gnat_rm/the_gnat_library id112}@anchor{3b1}
+@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3b2}@anchor{gnat_rm/the_gnat_library id112}@anchor{3b3}
@section @code{GNAT.Source_Info} (@code{g-souinf.ads})
@@ -24687,7 +24948,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{3b2}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b3}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3b4}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b5}
@section @code{GNAT.Spelling_Checker} (@code{g-speche.ads})
@@ -24699,7 +24960,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{3b4}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b5}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3b6}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b7}
@section @code{GNAT.Spelling_Checker_Generic} (@code{g-spchge.ads})
@@ -24712,7 +24973,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{3b6}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b7}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b9}
@section @code{GNAT.Spitbol.Patterns} (@code{g-spipat.ads})
@@ -24728,7 +24989,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 gnat-spitbol-g-spitbo-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id116}@anchor{3b9}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3ba}@anchor{gnat_rm/the_gnat_library id116}@anchor{3bb}
@section @code{GNAT.Spitbol} (@code{g-spitbo.ads})
@@ -24743,7 +25004,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{3ba}@anchor{gnat_rm/the_gnat_library id117}@anchor{3bb}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3bc}@anchor{gnat_rm/the_gnat_library id117}@anchor{3bd}
@section @code{GNAT.Spitbol.Table_Boolean} (@code{g-sptabo.ads})
@@ -24758,7 +25019,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{3bc}@anchor{gnat_rm/the_gnat_library id118}@anchor{3bd}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3be}@anchor{gnat_rm/the_gnat_library id118}@anchor{3bf}
@section @code{GNAT.Spitbol.Table_Integer} (@code{g-sptain.ads})
@@ -24775,7 +25036,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 gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3be}@anchor{gnat_rm/the_gnat_library id119}@anchor{3bf}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id119}@anchor{3c1}
@section @code{GNAT.Spitbol.Table_VString} (@code{g-sptavs.ads})
@@ -24792,7 +25053,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 gnat-sse-g-sse-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id120}@anchor{3c1}
+@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c2}@anchor{gnat_rm/the_gnat_library id120}@anchor{3c3}
@section @code{GNAT.SSE} (@code{g-sse.ads})
@@ -24804,7 +25065,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{3c2}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c3}
+@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3c4}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c5}
@section @code{GNAT.SSE.Vector_Types} (@code{g-ssvety.ads})
@@ -24813,7 +25074,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{3c4}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c5}
+@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c7}
@section @code{GNAT.String_Hash} (@code{g-strhas.ads})
@@ -24825,7 +25086,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 gnat-strings-g-string-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c7}
+@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c8}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c9}
@section @code{GNAT.Strings} (@code{g-string.ads})
@@ -24835,7 +25096,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{3c8}@anchor{gnat_rm/the_gnat_library id124}@anchor{3c9}
+@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3ca}@anchor{gnat_rm/the_gnat_library id124}@anchor{3cb}
@section @code{GNAT.String_Split} (@code{g-strspl.ads})
@@ -24849,7 +25110,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 gnat-table-g-table-ads}@anchor{3ca}@anchor{gnat_rm/the_gnat_library id125}@anchor{3cb}
+@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3cc}@anchor{gnat_rm/the_gnat_library id125}@anchor{3cd}
@section @code{GNAT.Table} (@code{g-table.ads})
@@ -24869,7 +25130,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 gnat-task-lock-g-tasloc-ads}@anchor{3cc}@anchor{gnat_rm/the_gnat_library id126}@anchor{3cd}
+@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id126}@anchor{3cf}
@section @code{GNAT.Task_Lock} (@code{g-tasloc.ads})
@@ -24886,7 +25147,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 gnat-time-stamp-g-timsta-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id127}@anchor{3cf}
+@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3d0}@anchor{gnat_rm/the_gnat_library id127}@anchor{3d1}
@section @code{GNAT.Time_Stamp} (@code{g-timsta.ads})
@@ -24901,7 +25162,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{3d0}@anchor{gnat_rm/the_gnat_library id128}@anchor{3d1}
+@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3d2}@anchor{gnat_rm/the_gnat_library id128}@anchor{3d3}
@section @code{GNAT.Threads} (@code{g-thread.ads})
@@ -24918,7 +25179,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 gnat-traceback-g-traceb-ads}@anchor{3d2}@anchor{gnat_rm/the_gnat_library id129}@anchor{3d3}
+@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d4}@anchor{gnat_rm/the_gnat_library id129}@anchor{3d5}
@section @code{GNAT.Traceback} (@code{g-traceb.ads})
@@ -24930,7 +25191,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 gnat-traceback-symbolic-g-trasym-ads}@anchor{3d4}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d5}
+@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d7}
@section @code{GNAT.Traceback.Symbolic} (@code{g-trasym.ads})
@@ -24939,7 +25200,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 gnat-utf-32-g-table-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d7}
+@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d8}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d9}
@section @code{GNAT.UTF_32} (@code{g-table.ads})
@@ -24958,7 +25219,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{3d8}@anchor{gnat_rm/the_gnat_library id132}@anchor{3d9}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3da}@anchor{gnat_rm/the_gnat_library id132}@anchor{3db}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-u3spch.ads})
@@ -24971,7 +25232,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{3da}@anchor{gnat_rm/the_gnat_library id133}@anchor{3db}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id133}@anchor{3dd}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-wispch.ads})
@@ -24983,7 +25244,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 gnat-wide-string-split-g-wistsp-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id134}@anchor{3dd}
+@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3de}@anchor{gnat_rm/the_gnat_library id134}@anchor{3df}
@section @code{GNAT.Wide_String_Split} (@code{g-wistsp.ads})
@@ -24997,7 +25258,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{3de}@anchor{gnat_rm/the_gnat_library id135}@anchor{3df}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3e0}@anchor{gnat_rm/the_gnat_library id135}@anchor{3e1}
@section @code{GNAT.Wide_Wide_Spelling_Checker} (@code{g-zspche.ads})
@@ -25009,7 +25270,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{3e0}@anchor{gnat_rm/the_gnat_library id136}@anchor{3e1}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3e2}@anchor{gnat_rm/the_gnat_library id136}@anchor{3e3}
@section @code{GNAT.Wide_Wide_String_Split} (@code{g-zistsp.ads})
@@ -25023,7 +25284,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 id137}@anchor{3e2}@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e3}
+@anchor{gnat_rm/the_gnat_library id137}@anchor{3e4}@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e5}
@section @code{Interfaces.C.Extensions} (@code{i-cexten.ads})
@@ -25034,7 +25295,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{3e4}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e5}
+@anchor{gnat_rm/the_gnat_library id138}@anchor{3e6}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e7}
@section @code{Interfaces.C.Streams} (@code{i-cstrea.ads})
@@ -25047,7 +25308,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 id139}@anchor{3e6}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e7}
+@anchor{gnat_rm/the_gnat_library id139}@anchor{3e8}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e9}
@section @code{Interfaces.Packed_Decimal} (@code{i-pacdec.ads})
@@ -25062,7 +25323,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 id140}@anchor{3e8}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e9}
+@anchor{gnat_rm/the_gnat_library id140}@anchor{3ea}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3eb}
@section @code{Interfaces.VxWorks} (@code{i-vxwork.ads})
@@ -25078,7 +25339,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 id141}@anchor{3ea}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3eb}
+@anchor{gnat_rm/the_gnat_library id141}@anchor{3ec}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3ed}
@section @code{Interfaces.VxWorks.Int_Connection} (@code{i-vxinco.ads})
@@ -25094,7 +25355,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 id142}@anchor{3ec}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ed}
+@anchor{gnat_rm/the_gnat_library id142}@anchor{3ee}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ef}
@section @code{Interfaces.VxWorks.IO} (@code{i-vxwoio.ads})
@@ -25117,7 +25378,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 id143}@anchor{3ee}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ef}
+@anchor{gnat_rm/the_gnat_library id143}@anchor{3f0}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3f1}
@section @code{System.Address_Image} (@code{s-addima.ads})
@@ -25133,7 +25394,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{3f0}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3f1}
+@anchor{gnat_rm/the_gnat_library id144}@anchor{3f2}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3f3}
@section @code{System.Assertions} (@code{s-assert.ads})
@@ -25149,7 +25410,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{3f2}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f3}
+@anchor{gnat_rm/the_gnat_library id145}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f5}
@section @code{System.Atomic_Counters} (@code{s-atocou.ads})
@@ -25163,7 +25424,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 id146}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f5}
+@anchor{gnat_rm/the_gnat_library id146}@anchor{3f6}@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f7}
@section @code{System.Memory} (@code{s-memory.ads})
@@ -25181,7 +25442,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{3f6}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f7}
+@anchor{gnat_rm/the_gnat_library id147}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f9}
@section @code{System.Multiprocessors} (@code{s-multip.ads})
@@ -25194,7 +25455,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 id148}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f9}
+@anchor{gnat_rm/the_gnat_library id148}@anchor{3fa}@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3fb}
@section @code{System.Multiprocessors.Dispatching_Domains} (@code{s-mudido.ads})
@@ -25207,7 +25468,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{3fa}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3fb}
+@anchor{gnat_rm/the_gnat_library id149}@anchor{3fc}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3fd}
@section @code{System.Partition_Interface} (@code{s-parint.ads})
@@ -25220,7 +25481,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{3fc}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3fd}
+@anchor{gnat_rm/the_gnat_library id150}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3ff}
@section @code{System.Pool_Global} (@code{s-pooglo.ads})
@@ -25237,7 +25498,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 id151}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3ff}
+@anchor{gnat_rm/the_gnat_library id151}@anchor{400}@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{401}
@section @code{System.Pool_Local} (@code{s-pooloc.ads})
@@ -25254,7 +25515,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{400}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{401}
+@anchor{gnat_rm/the_gnat_library id152}@anchor{402}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{403}
@section @code{System.Restrictions} (@code{s-restri.ads})
@@ -25270,7 +25531,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 id153}@anchor{402}@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{403}
+@anchor{gnat_rm/the_gnat_library id153}@anchor{404}@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{405}
@section @code{System.Rident} (@code{s-rident.ads})
@@ -25286,7 +25547,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{404}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{405}
+@anchor{gnat_rm/the_gnat_library id154}@anchor{406}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{407}
@section @code{System.Strings.Stream_Ops} (@code{s-ststop.ads})
@@ -25302,7 +25563,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 id155}@anchor{406}@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{407}
+@anchor{gnat_rm/the_gnat_library id155}@anchor{408}@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{409}
@section @code{System.Unsigned_Types} (@code{s-unstyp.ads})
@@ -25315,7 +25576,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 id156}@anchor{408}@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{409}
+@anchor{gnat_rm/the_gnat_library id156}@anchor{40a}@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{40b}
@section @code{System.Wch_Cnv} (@code{s-wchcnv.ads})
@@ -25336,7 +25597,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{40a}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{40b}
+@anchor{gnat_rm/the_gnat_library id157}@anchor{40c}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{40d}
@section @code{System.Wch_Con} (@code{s-wchcon.ads})
@@ -25348,7 +25609,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 doc}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40d}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}
+@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40f}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}
@chapter Interfacing to Other Languages
@@ -25366,7 +25627,7 @@ provided.
@end menu
@node Interfacing to C,Interfacing to C++,,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40f}
+@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{410}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{411}
@section Interfacing to C
@@ -25506,7 +25767,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 id3}@anchor{47}@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{410}
+@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{48}@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{412}
@section Interfacing to C++
@@ -25563,7 +25824,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{411}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{412}
+@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{413}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{414}
@section Interfacing to COBOL
@@ -25571,7 +25832,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{413}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{414}
+@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{415}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{416}
@section Interfacing to Fortran
@@ -25581,7 +25842,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 id7}@anchor{415}@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}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{418}
@section Interfacing to non-GNAT Ada code
@@ -25605,7 +25866,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 doc}@anchor{417}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{418}@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}
+@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{419}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{41a}@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}
@chapter Specialized Needs Annexes
@@ -25646,7 +25907,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 doc}@anchor{419}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41a}@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{41b}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}
@chapter Implementation of Specific Ada Features
@@ -25665,7 +25926,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 id2}@anchor{41b}@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{166}
+@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41d}@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{167}
@section Machine Code Insertions
@@ -25833,7 +26094,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 gnat-implementation-of-tasking}@anchor{41c}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41f}
@section GNAT Implementation of Tasking
@@ -25849,7 +26110,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 id4}@anchor{41e}@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}@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{421}
@subsection Mapping Ada Tasks onto the Underlying Kernel Threads
@@ -25918,7 +26179,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 ensuring-compliance-with-the-real-time-annex}@anchor{420}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{423}
@subsection Ensuring Compliance with the Real-Time Annex
@@ -25969,7 +26230,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{422}
+@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{424}
@subsection Support for Locking Policies
@@ -26003,7 +26264,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 gnat-implementation-of-shared-passive-packages}@anchor{423}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{426}
@section GNAT Implementation of Shared Passive Packages
@@ -26101,7 +26362,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{425}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{426}
+@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{428}
@section Code Generation for Array Aggregates
@@ -26132,7 +26393,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 id8}@anchor{427}@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}@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{42a}
@subsection Static constant aggregates with static bounds
@@ -26179,7 +26440,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{429}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{42a}
+@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{42c}
@subsection Constant aggregates with unconstrained nominal types
@@ -26194,7 +26455,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 aggregates-with-static-bounds}@anchor{42b}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42e}
@subsection Aggregates with static bounds
@@ -26222,7 +26483,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 aggregates-with-nonstatic-bounds}@anchor{42d}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{430}
@subsection Aggregates with nonstatic bounds
@@ -26233,7 +26494,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 aggregates-in-assignment-statements}@anchor{42f}@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}@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{432}
@subsection Aggregates in assignment statements
@@ -26275,7 +26536,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,Image Values For Nonscalar Types,Code Generation for Array Aggregates,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{431}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{432}
+@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{434}
@section The Size of Discriminated Records with Default Discriminants
@@ -26355,7 +26616,7 @@ say) must be consistent, so it is imperative that the object, once created,
remain invariant.
@node Image Values For Nonscalar Types,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 id14}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features image-values-for-nonscalar-types}@anchor{434}
+@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{435}@anchor{gnat_rm/implementation_of_specific_ada_features image-values-for-nonscalar-types}@anchor{436}
@section Image Values For Nonscalar Types
@@ -26375,7 +26636,7 @@ control of image text is required for some type T, then T’Put_Image should be
explicitly specified.
@node Strict Conformance to the Ada Reference Manual,,Image Values For Nonscalar Types,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id15}@anchor{435}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{436}
+@anchor{gnat_rm/implementation_of_specific_ada_features id15}@anchor{437}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{438}
@section Strict Conformance to the Ada Reference Manual
@@ -26401,8 +26662,8 @@ machines that are not fully compliant with this standard, such as Alpha, the
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{437}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{438}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}
+@node Implementation of Ada 2012 Features,Security Hardening Features,Implementation of Specific Ada Features,Top
+@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{439}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{43a}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}
@chapter Implementation of Ada 2012 Features
@@ -28567,8 +28828,102 @@ where the type of the returned value is an anonymous access type.
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 doc}@anchor{439}@anchor{gnat_rm/obsolescent_features id1}@anchor{43a}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15}
+@node Security Hardening Features,Obsolescent Features,Implementation of Ada 2012 Features,Top
+@anchor{gnat_rm/security_hardening_features doc}@anchor{43b}@anchor{gnat_rm/security_hardening_features id1}@anchor{43c}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
+@chapter Security Hardening Features
+
+
+This chapter describes Ada extensions aimed at security hardening that
+are provided by GNAT.
+
+@c Register Scrubbing:
+
+@menu
+* Register Scrubbing::
+* Stack Scrubbing::
+
+@end menu
+
+@node Register Scrubbing,Stack Scrubbing,,Security Hardening Features
+@anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{43d}
+@section Register Scrubbing
+
+
+GNAT can generate code to zero-out hardware registers before returning
+from a subprogram.
+
+It can be enabled with the @emph{-fzero-call-used-regs} command line
+option, to affect all subprograms in a compilation, and with a
+@code{Machine_Attribute} pragma, to affect only specific subprograms.
+
+@example
+procedure Foo;
+pragma Machine_Attribute (Foo, "zero_call_used_regs", "used");
+-- Before returning, Foo scrubs only call-clobbered registers
+-- that it uses itself.
+
+function Bar return Integer;
+pragma Machine_Attribute (Bar, "zero_call_used_regs", "all");
+-- Before returning, Bar scrubs all call-clobbered registers.
+@end example
+
+For usage and more details on the command line option, and on the
+@code{zero_call_used_regs} attribute, see @cite{Using the GNU Compiler Collection (GCC)}.
+
+@c Stack Scrubbing:
+
+@node Stack Scrubbing,,Register Scrubbing,Security Hardening Features
+@anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{43e}
+@section Stack Scrubbing
+
+
+GNAT can generate code to zero-out stack frames used by subprograms.
+
+It can be activated with the @code{Machine_Attribute} pragma, on
+specific subprograms and variables.
+
+@example
+function Foo returns Integer;
+pragma Machine_Attribute (Foo, "strub");
+-- Foo and its callers are modified so as to scrub the stack
+-- space used by Foo after it returns.
+
+procedure Bar;
+pragma Machine_Attribute (Bar, "strub", "internal");
+-- Bar is turned into a wrapper for its original body,
+-- and they scrub the stack used by the original body.
+
+Var : Integer;
+pragma Machine_Attribute (Var, "strub");
+-- Reading from Var in a subprogram enables stack scrubbing
+-- of the stack space used by the subprogram.
+@end example
+
+There are also @emph{-fstrub} command line options to control default
+settings. For usage and more details on the command line option, and
+on the @code{strub} attribute, see @cite{Using the GNU Compiler Collection (GCC)}.
+
+Note that Ada secondary stacks are not scrubbed. The restriction
+@code{No_Secondary_Stack} avoids their use, and thus their accidental
+preservation of data that should be scrubbed.
+
+Also note that the machine attribute is not integrated in the Ada type
+system. Though it may modify subprogram and variable interfaces, it
+is not fully reflected in Ada types, @code{Access} attributes, renaming
+and overriding. Every access type, renaming, and overriding and
+overridden dispatching operations that may refer to an entity with an
+attribute-modified interface must be annotated with the same
+interface-modifying attribute, or with an interface-compatible one.
+
+Even then, the pragma is currently only functional when applied to
+subprograms and scalar variables; other uses, such as directly on
+types and subtypes, may be silently ignored. Specifically, it is not
+currently recommended to rely on any effects this pragma might be
+expected to have when calling subprograms through access-to-subprogram
+variables.
+
+@node Obsolescent Features,Compatibility and Porting Guide,Security Hardening Features,Top
+@anchor{gnat_rm/obsolescent_features doc}@anchor{43f}@anchor{gnat_rm/obsolescent_features id1}@anchor{440}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
@chapter Obsolescent Features
@@ -28587,7 +28942,7 @@ compatibility purposes.
@end menu
@node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id2}@anchor{43b}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{43c}
+@anchor{gnat_rm/obsolescent_features id2}@anchor{441}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{442}
@section pragma No_Run_Time
@@ -28600,7 +28955,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{43d}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43e}
+@anchor{gnat_rm/obsolescent_features id3}@anchor{443}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{444}
@section pragma Ravenscar
@@ -28609,7 +28964,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 id4}@anchor{43f}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{440}
+@anchor{gnat_rm/obsolescent_features id4}@anchor{445}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{446}
@section pragma Restricted_Run_Time
@@ -28619,7 +28974,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 id5}@anchor{441}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{442}
+@anchor{gnat_rm/obsolescent_features id5}@anchor{447}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{448}
@section pragma Task_Info
@@ -28645,7 +29000,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{443}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{444}
+@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{449}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{44a}
@section package System.Task_Info (@code{s-tasinf.ads})
@@ -28655,7 +29010,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 doc}@anchor{445}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{446}
+@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{44c}
@chapter Compatibility and Porting Guide
@@ -28677,7 +29032,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{447}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{448}
+@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{44e}
@section Writing Portable Fixed-Point Declarations
@@ -28799,7 +29154,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{449}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{44a}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{450}
@section Compatibility with Ada 83
@@ -28827,7 +29182,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{44b}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{44c}
+@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{452}
@subsection Legal Ada 83 programs that are illegal in Ada 95
@@ -28927,7 +29282,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 id5}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44e}
+@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{454}
@subsection More deterministic semantics
@@ -28955,7 +29310,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 changed-semantics}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{450}
+@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{456}
@subsection Changed semantics
@@ -28997,7 +29352,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 id7}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{452}
+@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{458}
@subsection Other language compatibility issues
@@ -29030,7 +29385,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{453}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{454}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{45a}
@section Compatibility between Ada 95 and Ada 2005
@@ -29102,7 +29457,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 id9}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{456}
+@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{45c}
@section Implementation-dependent characteristics
@@ -29125,7 +29480,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 id10}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{458}
+@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{45e}
@subsection Implementation-defined pragmas
@@ -29147,7 +29502,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{459}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{45a}
+@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{460}
@subsection Implementation-defined attributes
@@ -29161,7 +29516,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 id12}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45c}
+@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{461}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{462}
@subsection Libraries
@@ -29190,7 +29545,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{45d}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45e}
+@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{463}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{464}
@subsection Elaboration order
@@ -29226,7 +29581,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 id14}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{460}
+@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{465}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{466}
@subsection Target-specific aspects
@@ -29239,10 +29594,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{461,,Representation Clauses}.
+GNAT’s approach to these issues is described in @ref{467,,Representation Clauses}.
@node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{463}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{468}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{469}
@section Compatibility with Other Ada Systems
@@ -29285,7 +29640,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 id16}@anchor{464}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{461}
+@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{46a}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{467}
@section Representation Clauses
@@ -29378,7 +29733,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{465}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{466}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{46b}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{46c}
@section Compatibility with HP Ada 83
@@ -29408,7 +29763,7 @@ extension of package System.
@end itemize
@node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
-@anchor{share/gnu_free_documentation_license doc}@anchor{467}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{468}
+@anchor{share/gnu_free_documentation_license doc}@anchor{46d}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{46e}
@chapter GNU Free Documentation License
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 713a662..28f2f19 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 , Jun 23, 2021
+GNAT User's Guide for Native Platforms , Sep 28, 2021
AdaCore
@@ -2814,16 +2814,12 @@ C_Pass_By_Copy
Check_Float_Overflow
Check_Name
Check_Policy
-Compile_Time_Error
-Compile_Time_Warning
-Compiler_Unit
-Compiler_Unit_Warning
Component_Alignment
Convention_Identifier
Debug_Policy
-Detect_Blocking
Default_Scalar_Storage_Order
Default_Storage_Pool
+Detect_Blocking
Disable_Atomic_Synchronization
Discard_Names
Elaboration_Checks
@@ -2842,7 +2838,6 @@ License
Locking_Policy
No_Component_Reordering
No_Heap_Finalization
-No_Run_Time
No_Strict_Aliasing
Normalize_Scalars
Optimize_Alignment
@@ -2854,17 +2849,12 @@ Prefix_Exception_Messages
Priority_Specific_Dispatching
Profile
Profile_Warnings
-Propagate_Exceptions
Queuing_Policy
-Rational
-Ravenscar
Rename_Pragma
-Restricted_Run_Time
Restrictions
-Restrictions_Warnings
+Restriction_Warnings
Reviewable
Short_Circuit_And_Or
-Short_Descriptors
Source_File_Name
Source_File_Name_Project
SPARK_Mode
@@ -2873,7 +2863,6 @@ Suppress
Suppress_Exception_Locations
Task_Dispatching_Policy
Unevaluated_Use_Of_Old
-Universal_Data
Unsuppress
Use_VADS_Size
Validity_Checks
@@ -2925,7 +2914,7 @@ only to the unit in which the pragma appears, and not to any other units.
The exception is No_Elaboration_Code which always applies to the entire
object file from a compilation, i.e. to the body, spec, and all subunits.
This restriction can be specified in a configuration pragma file, or it
-can be on the body and/or the spec (in eithe case it applies to all the
+can be on the body and/or the spec (in either case it applies to all the
relevant units). It can appear on a subunit only if it has previously
appeared in the body of spec.
@@ -6421,10 +6410,10 @@ as comments, to be completed manually if needed.
some extensions (e.g. vector types) are not supported
@item
-pointers to pointers or complex structures are mapped to System.Address
+pointers to pointers are mapped to System.Address
@item
-identifiers with identical name (except casing) will generate compilation
+identifiers with identical name (except casing) may generate compilation
errors (e.g. @code{shm_get} vs @code{SHM_GET}).
@end itemize
@@ -6450,15 +6439,18 @@ spec files for the header files specified on the command line, and all
header files needed by these files transitively. For example:
@example
-$ g++ -c -fdump-ada-spec -C /usr/include/time.h
+$ gcc -c -fdump-ada-spec -C /usr/include/time.h
$ gcc -c *.ads
@end example
will generate, under GNU/Linux, the following files: @code{time_h.ads},
@code{bits_time_h.ads}, @code{stddef_h.ads}, @code{bits_types_h.ads} which
correspond to the files @code{/usr/include/time.h},
-@code{/usr/include/bits/time.h}, etc…, and will then compile these Ada specs
-in Ada 2005 mode.
+@code{/usr/include/bits/time.h}, etc…, and then compile these Ada specs.
+That is to say, the name of the Ada specs is in keeping with the relative path
+under @code{/usr/include/} of the header files. This behavior is specific to
+paths ending with @code{/include/}; in all the other cases, the name of the
+Ada specs is derived from the simple name of the header files instead.
The @code{-C} switch tells @code{gcc} to extract comments from headers,
and will attempt to generate corresponding Ada comments.
@@ -6469,46 +6461,15 @@ can use instead the @code{-fdump-ada-spec-slim} switch.
You can optionally specify a parent unit, of which all generated units will
be children, using @code{-fada-spec-parent=@emph{unit}}.
-Note that we recommend when possible to use the @emph{g++} driver to
-generate bindings, even for most C headers, since this will in general
-generate better Ada specs. For generating bindings for C++ headers, it is
-mandatory to use the @emph{g++} command, or @emph{gcc -x c++} which
-is equivalent in this case. If @emph{g++} cannot work on your C headers
-because of incompatibilities between C and C++, then you can fallback to
-@code{gcc} instead.
-
-For an example of better bindings generated from the C++ front-end,
-the name of the parameters (when available) are actually ignored by the C
-front-end. Consider the following C header:
-
-@example
-extern void foo (int variable);
-@end example
-
-with the C front-end, @code{variable} is ignored, and the above is handled as:
-
-@example
-extern void foo (int);
-@end example
-
-generating a generic:
-
-@example
-procedure foo (param1 : int);
-@end example
-
-with the C++ front-end, the name is available, and we generate:
-
-@example
-procedure foo (variable : int);
-@end example
+The simple @code{gcc`}-based command works only for C headers. For C++ headers
+you need to use either the @code{g++} command or the combination @code{gcc -x c++`}.
In some cases, the generated bindings will be more complete or more meaningful
when defining some macros, which you can do via the @code{-D} switch. This
is for example the case with @code{Xlib.h} under GNU/Linux:
@example
-$ g++ -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
+$ gcc -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h
@end example
The above will generate more complete bindings than a straight call without
@@ -6530,7 +6491,7 @@ lines in e.g. @code{readline1.h}:
and then generate Ada bindings from this file:
@example
-$ g++ -c -fdump-ada-spec readline1.h
+$ gcc -c -fdump-ada-spec readline1.h
@end example
@node Generating Bindings for C++ Headers,Switches,Running the Binding Generator,Generating Ada Bindings for C and C++ headers
@@ -6799,7 +6760,7 @@ call subprograms, reference objects, and constants.
This section compares the GNAT model with the approaches taken in
-other environents, first the C/C++ model and then the mechanism that
+other environments, first the C/C++ model and then the mechanism that
has been used in other Ada systems, in particular those traditionally
used for Ada 83.
@@ -8961,9 +8922,10 @@ also suppresses generation of cross-reference information
@item @code{-gnateA}
Check that the actual parameters of a subprogram call are not aliases of one
-another. To qualify as aliasing, the actuals must denote objects of a composite
-type, their memory locations must be identical or overlapping, and at least one
-of the corresponding formal parameters must be of mode OUT or IN OUT.
+another. To qualify as aliasing, their memory locations must be identical or
+overlapping, at least one of the corresponding formal parameters must be of
+mode OUT or IN OUT, and at least one of the corresponding formal parameters
+must have its parameter passing mechanism not specified.
@example
type Rec_Typ is record
@@ -12633,8 +12595,8 @@ See @ref{e6,,Static Stack Usage Analysis} for details.
This switch enables most warnings from the GCC back end.
The code generator detects a number of warning situations that are missed
by the GNAT front end, and this switch can be used to activate them.
-The use of this switch also sets the default front end warning mode to
-@code{-gnatwa}, that is, most front end warnings activated as well.
+The use of this switch also sets the default front-end warning mode to
+@code{-gnatwa}, that is, most front-end warnings are activated as well.
@end table
@geindex -w (gcc)
@@ -12645,8 +12607,8 @@ The use of this switch also sets the default front end warning mode to
@item @code{-w}
Conversely, this switch suppresses warnings from the GCC back end.
-The use of this switch also sets the default front end warning mode to
-@code{-gnatws}, that is, front end warnings suppressed as well.
+The use of this switch also sets the default front-end warning mode to
+@code{-gnatws}, that is, front-end warnings are suppressed as well.
@end table
@geindex -Werror (gcc)
@@ -12659,6 +12621,9 @@ The use of this switch also sets the default front end warning mode to
This switch causes warnings from the GCC back end to be treated as
errors. The warning string still appears, but the warning messages are
counted as errors, and prevent the generation of an object file.
+The use of this switch also sets the default front-end warning mode to
+@code{-gnatwe}, that is, front-end warning messages and style check
+messages are treated as errors as well.
@end table
A string of warning parameters can be used in the same parameter. For example:
@@ -22642,7 +22607,10 @@ Ignore : constant Boolean :=
@end quotation
It gets the effective user id, and if it’s not 0 (i.e. root), it raises
-Program_Error.
+Program_Error. Note that if you re running the code in a container, this may
+not be sufficient, as you may have sufficient priviledge on the container,
+but not on the host machine running the container, so check that you also
+have sufficient priviledge for running the container image.
@geindex Linux
@@ -23100,9 +23068,9 @@ calling convention. All convention specifiers are ignored on this
platform.
When a subprogram @code{F} (caller) calls a subprogram @code{G}
-(callee), there are several ways to push @code{G}’s parameters on the
+(callee), there are several ways to push @code{G}‘s parameters on the
stack and there are several possible scenarios to clean up the stack
-upon @code{G}’s return. A calling convention is an agreed upon software
+upon @code{G}‘s return. A calling convention is an agreed upon software
protocol whereby the responsibilities between the caller (@code{F}) and
the callee (@code{G}) are clearly defined. Several calling conventions
are available for Windows:
diff --git a/gcc/ada/gnatbind.adb b/gcc/ada/gnatbind.adb
index 5cb2df0..90d8af4 100644
--- a/gcc/ada/gnatbind.adb
+++ b/gcc/ada/gnatbind.adb
@@ -125,7 +125,6 @@ procedure Gnatbind is
Scan_ALI
(F => Std_Lib_File,
T => Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => Debug_Flag_I);
@@ -770,7 +769,6 @@ begin
Id := Scan_ALI
(F => Main_Lib_File,
T => Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => Debug_Flag_I,
Directly_Scanned => True);
diff --git a/gcc/ada/gnatfind.adb b/gcc/ada/gnatfind.adb
index c3fc25e..83bafff 100644
--- a/gcc/ada/gnatfind.adb
+++ b/gcc/ada/gnatfind.adb
@@ -347,6 +347,11 @@ procedure Gnatfind is
-- Start of processing for Gnatfind
begin
+ Put_Line
+ ("WARNING: gnatfind is obsolete and will be removed in the next release");
+ Put_Line
+ ("Consider using Libadalang or GNAT Studio python scripting instead");
+
Parse_Cmd_Line;
if not Have_Entity then
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 52e714a..a321bf3 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1531,7 +1531,6 @@ begin
A := Scan_ALI
(F,
T,
- Ignore_ED => False,
Err => False,
Ignore_Errors => True);
diff --git a/gcc/ada/gnatls.adb b/gcc/ada/gnatls.adb
index 353e36d..68990e1 100644
--- a/gcc/ada/gnatls.adb
+++ b/gcc/ada/gnatls.adb
@@ -234,9 +234,8 @@ procedure Gnatls is
-- already been initialized.
procedure Add_Directories
- (Self : in out String_Access;
- Path : String;
- Prepend : Boolean := False);
+ (Self : in out String_Access;
+ Path : String);
-- Add one or more directories to the path. Directories added with this
-- procedure are added in order after the current directory and before
-- the path given by the environment variable GPR_PROJECT_PATH. A value
@@ -1239,9 +1238,8 @@ procedure Gnatls is
---------------------
procedure Add_Directories
- (Self : in out String_Access;
- Path : String;
- Prepend : Boolean := False)
+ (Self : in out String_Access;
+ Path : String)
is
Tmp : String_Access;
@@ -1250,11 +1248,7 @@ procedure Gnatls is
Self := new String'(Uninitialized_Prefix & Path);
else
Tmp := Self;
- if Prepend then
- Self := new String'(Path & Path_Separator & Tmp.all);
- else
- Self := new String'(Tmp.all & Path_Separator & Path);
- end if;
+ Self := new String'(Tmp.all & Path_Separator & Path);
Free (Tmp);
end if;
end Add_Directories;
@@ -2278,7 +2272,6 @@ begin
Scan_ALI
(Ali_File,
Text,
- Ignore_ED => False,
Err => False,
Ignore_Errors => True);
end;
diff --git a/gcc/ada/gnatxref.adb b/gcc/ada/gnatxref.adb
index 9a3935c..3737f66 100644
--- a/gcc/ada/gnatxref.adb
+++ b/gcc/ada/gnatxref.adb
@@ -299,6 +299,11 @@ procedure Gnatxref is
end Write_Usage;
begin
+ Put_Line
+ ("WARNING: gnatxref is obsolete and will be removed in the next release");
+ Put_Line
+ ("Consider using Libadalang or GNAT Studio python scripting instead");
+
Parse_Cmd_Line;
if not Have_File then
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index b99f3fd..5fe1353 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -23,14 +23,14 @@
-- --
------------------------------------------------------------------------------
-with Errout; use Errout;
-with Sinfo; use Sinfo;
-with Sinfo.Nodes; use Sinfo.Nodes;
-with Fname.UF; use Fname.UF;
-with Lib; use Lib;
-with Namet; use Namet;
-with Opt; use Opt;
-with Uname; use Uname;
+with Errout; use Errout;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Fname.UF; use Fname.UF;
+with Lib; use Lib;
+with Namet; use Namet;
+with Opt; use Opt;
+with Uname; use Uname;
-- Note: this package body is used by GNAT Studio and GNATBench to supply a
-- list of entries for help on available library routines.
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index c48e244..dbd8516 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -661,6 +661,28 @@ __gnat_install_handler (void)
#include <signal.h>
#include <unistd.h>
+/* SA_SIGINFO is not supported by default on LynxOS, so all we have
+ available here is the "sig" argument. On newer LynxOS versions it's
+ possible to support SA_SIGINFO by setting a kernel configuration macro.
+
+ To wit:
+
+ #define NONPOSIX_SA_HANDLER_PROTO (0)
+
+ This macro must be set to 1 in either sys/bsp.<bspname>/uparam.h
+ or in the associated uparam.h customization file sys/bsp.<bspname>/xparam.h
+ (uparam.h includes xparam.h for customization)
+
+ The NONPOSIX_SA_HANDLER_PROTO macro makes it possible to provide
+ signal-catching function with 'info' and 'context' input parameters
+ even if SA_SIGINFO flag is not set or it is set for a non-realtime signal.
+
+ It also allows signal-catching function to update thread context even
+ if SA_UPDATECTX flag is not set.
+
+ This would be useful, but relying on that would transmit the requirement
+ to users to configure that feature as well, which is undesirable. */
+
static void
__gnat_error_handler (int sig)
{
@@ -2529,6 +2551,7 @@ __gnat_install_handler (void)
#include <signal.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
#include "sigtramp.h"
void
diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index 6c330b2..773b376 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -4215,8 +4215,6 @@ package body Inline is
(Subp : Entity_Id;
Decls : List_Id) return Boolean
is
- D : Node_Id;
-
function Is_Unchecked_Conversion (D : Node_Id) return Boolean;
-- Nested subprograms make a given body ineligible for inlining, but
-- we make an exception for instantiations of unchecked conversion.
@@ -4250,6 +4248,10 @@ package body Inline is
and then Is_Intrinsic_Subprogram (Conv);
end Is_Unchecked_Conversion;
+ -- Local variables
+
+ Decl : Node_Id;
+
-- Start of processing for Has_Excluded_Declaration
begin
@@ -4259,19 +4261,19 @@ package body Inline is
return False;
end if;
- D := First (Decls);
- while Present (D) loop
+ Decl := First (Decls);
+ while Present (Decl) loop
-- First declarations universally excluded
- if Nkind (D) = N_Package_Declaration then
+ if Nkind (Decl) = N_Package_Declaration then
Cannot_Inline
- ("cannot inline & (nested package declaration)?", D, Subp);
+ ("cannot inline & (nested package declaration)?", Decl, Subp);
return True;
- elsif Nkind (D) = N_Package_Instantiation then
+ elsif Nkind (Decl) = N_Package_Instantiation then
Cannot_Inline
- ("cannot inline & (nested package instantiation)?", D, Subp);
+ ("cannot inline & (nested package instantiation)?", Decl, Subp);
return True;
end if;
@@ -4280,51 +4282,50 @@ package body Inline is
if Back_End_Inlining then
null;
- elsif Nkind (D) = N_Task_Type_Declaration
- or else Nkind (D) = N_Single_Task_Declaration
+ elsif Nkind (Decl) = N_Task_Type_Declaration
+ or else Nkind (Decl) = N_Single_Task_Declaration
then
Cannot_Inline
- ("cannot inline & (nested task type declaration)?", D, Subp);
+ ("cannot inline & (nested task type declaration)?", Decl, Subp);
return True;
- elsif Nkind (D) = N_Protected_Type_Declaration
- or else Nkind (D) = N_Single_Protected_Declaration
+ elsif Nkind (Decl) in N_Protected_Type_Declaration
+ | N_Single_Protected_Declaration
then
Cannot_Inline
("cannot inline & (nested protected type declaration)?",
- D, Subp);
+ Decl, Subp);
return True;
- elsif Nkind (D) = N_Subprogram_Body then
+ elsif Nkind (Decl) = N_Subprogram_Body then
Cannot_Inline
- ("cannot inline & (nested subprogram)?", D, Subp);
+ ("cannot inline & (nested subprogram)?", Decl, Subp);
return True;
- elsif Nkind (D) = N_Function_Instantiation
- and then not Is_Unchecked_Conversion (D)
+ elsif Nkind (Decl) = N_Function_Instantiation
+ and then not Is_Unchecked_Conversion (Decl)
then
Cannot_Inline
- ("cannot inline & (nested function instantiation)?", D, Subp);
+ ("cannot inline & (nested function instantiation)?", Decl, Subp);
return True;
- elsif Nkind (D) = N_Procedure_Instantiation then
+ elsif Nkind (Decl) = N_Procedure_Instantiation then
Cannot_Inline
- ("cannot inline & (nested procedure instantiation)?", D, Subp);
+ ("cannot inline & (nested procedure instantiation)?",
+ Decl, Subp);
return True;
-- Subtype declarations with predicates will generate predicate
-- functions, i.e. nested subprogram bodies, so inlining is not
-- possible.
- elsif Nkind (D) = N_Subtype_Declaration
- and then Present (Aspect_Specifications (D))
- then
+ elsif Nkind (Decl) = N_Subtype_Declaration then
declare
A : Node_Id;
A_Id : Aspect_Id;
begin
- A := First (Aspect_Specifications (D));
+ A := First (Aspect_Specifications (Decl));
while Present (A) loop
A_Id := Get_Aspect_Id (Chars (Identifier (A)));
@@ -4334,7 +4335,7 @@ package body Inline is
then
Cannot_Inline
("cannot inline & (subtype declaration with "
- & "predicate)?", D, Subp);
+ & "predicate)?", Decl, Subp);
return True;
end if;
@@ -4343,7 +4344,7 @@ package body Inline is
end;
end if;
- Next (D);
+ Next (Decl);
end loop;
return False;
diff --git a/gcc/ada/itypes.adb b/gcc/ada/itypes.adb
index f51b44a..ffaa4fe 100644
--- a/gcc/ada/itypes.adb
+++ b/gcc/ada/itypes.adb
@@ -29,7 +29,6 @@ with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Stand; use Stand;
with Targparm; use Targparm;
-with Uintp; use Uintp;
package body Itypes is
@@ -62,9 +61,9 @@ package body Itypes is
end if;
-- Make sure Esize (Typ) was properly initialized, it should be since
- -- New_Internal_Entity/New_External_Entity call Init_Size_Align.
+ -- New_Internal_Entity/New_External_Entity call Reinit_Size_Align.
- pragma Assert (Esize (Typ) = Uint_0);
+ pragma Assert (not Known_Esize (Typ));
Set_Etype (Typ, Any_Type);
Set_Is_Itype (Typ);
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index e69386c..092f2f5 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -155,7 +155,7 @@ package body Layout is
exit when Esize (E) mod Abits = 0;
end loop;
- Init_Alignment (E, Abits / SSU);
+ Set_Alignment (E, UI_From_Int (Abits / SSU));
return;
end if;
@@ -243,8 +243,8 @@ package body Layout is
-- like or need the size to be set.
if Ekind (E) = E_String_Literal_Subtype then
- Set_Esize (E, Uint_0);
- Set_RM_Size (E, Uint_0);
+ Reinit_Esize (E);
+ Reinit_RM_Size (E);
return;
end if;
@@ -287,7 +287,7 @@ package body Layout is
elsif Ekind (E) = E_Access_Subtype then
Set_Size_Info (E, Base_Type (E));
- Set_RM_Size (E, RM_Size (Base_Type (E)));
+ Copy_RM_Size (To => E, From => Base_Type (E));
-- For other access types, we use either address size, or, if a fat
-- pointer is used (pointer-to-unconstrained array case), twice the
@@ -379,7 +379,7 @@ package body Layout is
-- If size is big enough, set it and exit
if S >= RM_Size (E) then
- Init_Esize (E, S);
+ Set_Esize (E, UI_From_Int (S));
exit;
-- If the RM_Size is greater than System_Max_Integer_Size
@@ -426,15 +426,15 @@ package body Layout is
begin
if not Known_Esize (E) then
- Set_Esize (E, Esize (PAT));
+ Copy_Esize (To => E, From => PAT);
end if;
if not Known_RM_Size (E) then
- Set_RM_Size (E, RM_Size (PAT));
+ Copy_RM_Size (To => E, From => PAT);
end if;
- if not Known_Alignment (E) and then Known_Alignment (PAT) then
- Set_Alignment (E, Alignment (PAT));
+ if not Known_Alignment (E) then
+ Copy_Alignment (To => E, From => PAT);
end if;
end;
end if;
@@ -624,13 +624,13 @@ package body Layout is
if Is_Scalar_Type (E) then
if Size <= SSU then
- Init_Esize (E, SSU);
+ Set_Esize (E, UI_From_Int (SSU));
elsif Size <= 16 then
- Init_Esize (E, 16);
+ Set_Esize (E, Uint_16);
elsif Size <= 32 then
- Init_Esize (E, 32);
+ Set_Esize (E, Uint_32);
else
- Set_Esize (E, (Size + 63) / 64 * 64);
+ Set_Esize (E, (Size + 63) / 64 * 64);
end if;
-- Finally, make sure that alignment is consistent with
@@ -899,7 +899,7 @@ package body Layout is
-- nothing to do with code.
if Is_Generic_Type (Root_Type (FST)) then
- Set_RM_Size (Def_Id, Uint_0);
+ Reinit_RM_Size (Def_Id);
-- If the subtype statically matches the first subtype, then it is
-- required to have exactly the same layout. This is required by
@@ -1021,7 +1021,7 @@ package body Layout is
-- this new calculated value.
if not Known_Alignment (E) then
- Init_Alignment (E, A);
+ Set_Alignment (E, UI_From_Int (A));
-- Cases where we have inherited an alignment
@@ -1030,7 +1030,7 @@ package body Layout is
-- sure that no constructed types have weird alignments.
elsif not Comes_From_Source (E) then
- Init_Alignment (E, A);
+ Set_Alignment (E, UI_From_Int (A));
-- If this inherited alignment is the same as the one we computed,
-- then obviously everything is fine, and we do not need to reset it.
@@ -1136,7 +1136,7 @@ package body Layout is
-- ACATS problem which seems to have disappeared anyway, and
-- in any case, this peculiarity was never documented.
- Init_Alignment (E, A);
+ Set_Alignment (E, UI_From_Int (A));
-- If no Size (or Object_Size) was specified, then we have
-- inherited the object size, so we should also inherit the
diff --git a/gcc/ada/libgnarl/a-intnam__rtems.ads b/gcc/ada/libgnarl/a-intnam__rtems.ads
index 89618f6..4654f00 100644
--- a/gcc/ada/libgnarl/a-intnam__rtems.ads
+++ b/gcc/ada/libgnarl/a-intnam__rtems.ads
@@ -34,81 +34,17 @@
------------------------------------------------------------------------------
-- This is a RTEMS version of this package
---
--- The following signals are reserved by the run time:
---
--- SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGTRAP, SIGABRT, SIGINT,
--- SIGALRM, SIGEMT, SIGKILL
---
--- The pragma Unreserve_All_Interrupts affects the following signal(s):
---
--- SIGINT: made available for Ada handlers
-
--- This target-dependent package spec contains names of interrupts
--- supported by the local system.
with System.OS_Interface;
--- used for names of interrupts
package Ada.Interrupts.Names is
- -- Beware that the mapping of names to signals may be
- -- many-to-one. There may be aliases. Also, for all
- -- signal names that are not supported on the current system
- -- the value of the corresponding constant will be zero.
-
- SIGHUP : constant Interrupt_ID :=
- System.OS_Interface.SIGHUP; -- hangup
-
- SIGINT : constant Interrupt_ID :=
- System.OS_Interface.SIGINT; -- interrupt (rubout)
-
- SIGQUIT : constant Interrupt_ID :=
- System.OS_Interface.SIGQUIT; -- quit (ASCD FS)
-
- SIGILL : constant Interrupt_ID :=
- System.OS_Interface.SIGILL; -- illegal instruction (not reset)
-
- SIGTRAP : constant Interrupt_ID :=
- System.OS_Interface.SIGTRAP; -- trace trap (not reset)
-
- SIGIOT : constant Interrupt_ID :=
- System.OS_Interface.SIGIOT; -- IOT instruction
-
- SIGABRT : constant Interrupt_ID := -- used by abort,
- System.OS_Interface.SIGABRT; -- replace SIGIOT in the future
-
- SIGEMT : constant Interrupt_ID :=
- System.OS_Interface.SIGEMT; -- EMT instruction
-
- SIGFPE : constant Interrupt_ID :=
- System.OS_Interface.SIGFPE; -- floating point exception
-
- SIGKILL : constant Interrupt_ID :=
- System.OS_Interface.SIGKILL; -- kill (cannot be caught or ignored)
-
- SIGBUS : constant Interrupt_ID :=
- System.OS_Interface.SIGBUS; -- bus error
-
- SIGSEGV : constant Interrupt_ID :=
- System.OS_Interface.SIGSEGV; -- segmentation violation
-
- SIGSYS : constant Interrupt_ID :=
- System.OS_Interface.SIGSYS; -- bad argument to system call
-
- SIGPIPE : constant Interrupt_ID := -- write on a pipe with
- System.OS_Interface.SIGPIPE; -- no one to read it
-
- SIGALRM : constant Interrupt_ID :=
- System.OS_Interface.SIGALRM; -- alarm clock
-
- SIGTERM : constant Interrupt_ID :=
- System.OS_Interface.SIGTERM; -- software termination signal from kill
+ -- All identifiers in this unit are implementation defined
- SIGUSR1 : constant Interrupt_ID :=
- System.OS_Interface.SIGUSR1; -- user defined signal 1
+ pragma Implementation_Defined;
- SIGUSR2 : constant Interrupt_ID :=
- System.OS_Interface.SIGUSR2; -- user defined signal 2
+ subtype Hardware_Interrupts is Interrupt_ID
+ range Interrupt_ID'First .. System.OS_Interface.Max_HW_Interrupt;
+ -- Range of values that can be used for hardware interrupts
end Ada.Interrupts.Names;
diff --git a/gcc/ada/libgnarl/a-tasini.adb b/gcc/ada/libgnarl/a-tasini.adb
index c0dfe70..a8981d6 100644
--- a/gcc/ada/libgnarl/a-tasini.adb
+++ b/gcc/ada/libgnarl/a-tasini.adb
@@ -26,13 +26,13 @@
-- --
------------------------------------------------------------------------------
-with Ada.Unchecked_Conversion;
-with System.Tasking;
-
package body Ada.Task_Initialization is
- function To_STIH is new Ada.Unchecked_Conversion
- (Initialization_Handler, System.Tasking.Initialization_Handler);
+ Global_Initialization_Handler : Initialization_Handler := null;
+ pragma Atomic (Global_Initialization_Handler);
+ pragma Export (Ada, Global_Initialization_Handler,
+ "__gnat_global_initialization_handler");
+ -- Global handler called when each task initializes.
--------------------------------
-- Set_Initialization_Handler --
@@ -40,7 +40,7 @@ package body Ada.Task_Initialization is
procedure Set_Initialization_Handler (Handler : Initialization_Handler) is
begin
- System.Tasking.Global_Initialization_Handler := To_STIH (Handler);
+ Global_Initialization_Handler := Handler;
end Set_Initialization_Handler;
end Ada.Task_Initialization;
diff --git a/gcc/ada/libgnarl/a-tasini.ads b/gcc/ada/libgnarl/a-tasini.ads
index dd2a17c..a754c06 100644
--- a/gcc/ada/libgnarl/a-tasini.ads
+++ b/gcc/ada/libgnarl/a-tasini.ads
@@ -30,12 +30,17 @@
-- when tasks start.
package Ada.Task_Initialization is
- pragma Preelaborate (Task_Initialization);
+ pragma Preelaborate;
+ pragma No_Elaboration_Code_All;
type Initialization_Handler is access procedure;
procedure Set_Initialization_Handler (Handler : Initialization_Handler);
- -- Set the global task initialization handler to Handler
+ -- Set the global task initialization handler to Handler.
+ -- Note that only tasks created after this procedure is called will trigger
+ -- a call to Handler. You can use Ada's elaboration rules and pragma
+ -- Elaborate_All, or the pragma Linker_Constructor to ensure this
+ -- procedure is called early.
private
pragma Favor_Top_Level (Initialization_Handler);
diff --git a/gcc/ada/libgnarl/s-inmaop__vxworks.adb b/gcc/ada/libgnarl/s-inmaop__hwint.adb
index 8496c82..52a92ac 100644
--- a/gcc/ada/libgnarl/s-inmaop__vxworks.adb
+++ b/gcc/ada/libgnarl/s-inmaop__hwint.adb
@@ -30,9 +30,10 @@
-- --
------------------------------------------------------------------------------
--- This is a VxWorks version of this package. Many operations are null as this
--- package supports the use of Ada interrupt handling facilities for signals,
--- while those facilities are used for hardware interrupts on these targets.
+-- This is a hardware interrupt version of this package. Many operations are
+-- null as this package supports the use of Ada interrupt handling facilities
+-- for signals, while those facilities are used for hardware interrupts on
+-- these targets.
with Ada.Exceptions;
diff --git a/gcc/ada/libgnarl/s-interr__hwint.adb b/gcc/ada/libgnarl/s-interr__hwint.adb
index be6b559..5f80174 100644
--- a/gcc/ada/libgnarl/s-interr__hwint.adb
+++ b/gcc/ada/libgnarl/s-interr__hwint.adb
@@ -29,29 +29,15 @@
-- --
------------------------------------------------------------------------------
--- Invariants:
-
--- All user-handlable signals are masked at all times in all tasks/threads
--- except possibly for the Interrupt_Manager task.
-
--- When a user task wants to have the effect of masking/unmasking an signal,
--- it must call Block_Interrupt/Unblock_Interrupt, which will have the effect
--- of unmasking/masking the signal in the Interrupt_Manager task. These
--- comments do not apply to vectored hardware interrupts, which may be masked
--- or unmasked using routined interfaced to the relevant embedded RTOS system
--- calls.
+-- This is reasonably generic version of this package, supporting vectored
+-- hardware interrupts using non-RTOS specific adapter routines which should
+-- easily implemented on any RTOS capable of supporting GNAT.
--- Once we associate a Signal_Server_Task with an signal, the task never goes
--- away, and we never remove the association. On the other hand, it is more
--- convenient to terminate an associated Interrupt_Server_Task for a vectored
--- hardware interrupt (since we use a binary semaphore for synchronization
--- with the umbrella handler).
+-- Invariants:
--- There is no more than one signal per Signal_Server_Task and no more than
--- one Signal_Server_Task per signal. The same relation holds for hardware
--- interrupts and Interrupt_Server_Task's at any given time. That is, only
--- one non-terminated Interrupt_Server_Task exists for a give interrupt at
--- any time.
+-- There is no more than one interrupt per Interrupt_Server_Task and no more
+-- than one Interrupt_Server_Task per interrupt. If an interrupt handler is
+-- detached, the corresponding Interrupt_Server_Task is terminated.
-- Within this package, the lock L is used to protect the various status
-- tables. If there is a Server_Task associated with a signal or interrupt,
@@ -59,10 +45,6 @@
-- status between Interrupt_Manager and Server_Task. Protection among service
-- requests are ensured via user calls to the Interrupt_Manager entries.
--- This is reasonably generic version of this package, supporting vectored
--- hardware interrupts using non-RTOS specific adapter routines which should
--- easily implemented on any RTOS capable of supporting GNAT.
-
with Ada.Unchecked_Conversion;
with Ada.Task_Identification;
@@ -151,13 +133,13 @@ package body System.Interrupts is
(others => (null, Static => False));
pragma Volatile_Components (User_Handler);
-- Holds the protected procedure handler (if any) and its Static
- -- information for each interrupt or signal. A handler is static iff it
+ -- information for each interrupt. A handler is static if and only if it
-- is specified through the pragma Attach_Handler.
User_Entry : array (Interrupt_ID) of Entry_Assoc :=
(others => (T => Null_Task, E => Null_Task_Entry));
pragma Volatile_Components (User_Entry);
- -- Holds the task and entry index (if any) for each interrupt / signal
+ -- Holds the task and entry index (if any) for each interrupt
-- Type and Head, Tail of the list containing Registered Interrupt
-- Handlers. These definitions are used to register the handlers
diff --git a/gcc/ada/libgnarl/s-interr__vxworks.adb b/gcc/ada/libgnarl/s-interr__vxworks.adb
index d496b74..db2ca95 100644
--- a/gcc/ada/libgnarl/s-interr__vxworks.adb
+++ b/gcc/ada/libgnarl/s-interr__vxworks.adb
@@ -66,7 +66,6 @@
with Ada.Unchecked_Conversion;
with Ada.Task_Identification;
-with Interfaces.C; use Interfaces.C;
with System.OS_Interface; use System.OS_Interface;
with System.Interrupt_Management;
with System.Task_Primitives.Operations;
@@ -76,12 +75,18 @@ with System.Tasking.Utilities;
with System.Tasking.Rendezvous;
pragma Elaborate_All (System.Tasking.Rendezvous);
+with System.VxWorks.Ext;
+
package body System.Interrupts is
use Tasking;
package POP renames System.Task_Primitives.Operations;
+ use type System.VxWorks.Ext.STATUS;
+ subtype STATUS is System.VxWorks.Ext.STATUS;
+ OK : constant STATUS := System.VxWorks.Ext.OK;
+
function To_Ada is new Ada.Unchecked_Conversion
(System.Tasking.Task_Id, Ada.Task_Identification.Task_Id);
@@ -199,7 +204,7 @@ package body System.Interrupts is
type Interrupt_Connector is access function
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
-- Profile must match VxWorks intConnect()
Interrupt_Connect : Interrupt_Connector :=
@@ -515,7 +520,7 @@ package body System.Interrupts is
Vec : constant Interrupt_Vector :=
Interrupt_Number_To_Vector (int (Interrupt));
- Status : int;
+ Result : STATUS;
begin
-- Only install umbrella handler when no Ada handler has already been
@@ -525,9 +530,9 @@ package body System.Interrupts is
-- number.
if not Handler_Installed (Interrupt) then
- Status :=
+ Result :=
Interrupt_Connect.all (Vec, Handler, System.Address (Interrupt));
- pragma Assert (Status = 0);
+ pragma Assert (Result = OK);
Handler_Installed (Interrupt) := True;
end if;
@@ -646,11 +651,11 @@ package body System.Interrupts is
procedure Notify_Interrupt (Param : System.Address) is
Interrupt : constant Interrupt_ID := Interrupt_ID (Param);
Id : constant Binary_Semaphore_Id := Semaphore_ID_Map (Interrupt);
- Status : int;
+ Result : STATUS;
begin
if Id /= 0 then
- Status := Binary_Semaphore_Release (Id);
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Release (Id);
+ pragma Assert (Result = OK);
end if;
end Notify_Interrupt;
@@ -787,13 +792,13 @@ package body System.Interrupts is
--------------------
procedure Unbind_Handler (Interrupt : Interrupt_ID) is
- Status : int;
+ Result : STATUS;
begin
-- Flush server task off semaphore, allowing it to terminate
- Status := Binary_Semaphore_Flush (Semaphore_ID_Map (Interrupt));
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Flush (Semaphore_ID_Map (Interrupt));
+ pragma Assert (Result = OK);
end Unbind_Handler;
--------------------------------
@@ -1067,7 +1072,7 @@ package body System.Interrupts is
Tmp_Handler : Parameterless_Handler;
Tmp_ID : Task_Id;
Tmp_Entry_Index : Task_Entry_Index;
- Status : int;
+ Result : STATUS;
begin
Semaphore_ID_Map (Interrupt) := Int_Sema;
@@ -1076,8 +1081,8 @@ package body System.Interrupts is
-- Pend on semaphore that will be triggered by the umbrella handler
-- when the associated interrupt comes in.
- Status := Binary_Semaphore_Obtain (Int_Sema);
- pragma Assert (Status = 0);
+ Result := Binary_Semaphore_Obtain (Int_Sema);
+ pragma Assert (Result = OK);
if User_Handler (Interrupt).H /= null then
@@ -1109,9 +1114,9 @@ package body System.Interrupts is
-- Delete the associated semaphore
- Status := Binary_Semaphore_Delete (Int_Sema);
+ Result := Binary_Semaphore_Delete (Int_Sema);
- pragma Assert (Status = 0);
+ pragma Assert (Result = OK);
-- Set status for the Interrupt_Manager
diff --git a/gcc/ada/libgnarl/s-intman__android.adb b/gcc/ada/libgnarl/s-intman__android.adb
index 6364ead..be9c50e 100644
--- a/gcc/ada/libgnarl/s-intman__android.adb
+++ b/gcc/ada/libgnarl/s-intman__android.adb
@@ -68,7 +68,7 @@ package body System.Interrupt_Management is
Exception_Interrupts : constant Interrupt_List :=
(SIGFPE, SIGILL, SIGSEGV, SIGBUS);
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-intman__lynxos.adb b/gcc/ada/libgnarl/s-intman__lynxos.adb
index c2e8f8a..2a1f9c8 100644
--- a/gcc/ada/libgnarl/s-intman__lynxos.adb
+++ b/gcc/ada/libgnarl/s-intman__lynxos.adb
@@ -68,7 +68,7 @@ package body System.Interrupt_Management is
Exception_Interrupts : constant Interrupt_List :=
(SIGFPE, SIGILL, SIGSEGV, SIGBUS);
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-intman__posix.adb b/gcc/ada/libgnarl/s-intman__posix.adb
index b0b0146..ae3d77e 100644
--- a/gcc/ada/libgnarl/s-intman__posix.adb
+++ b/gcc/ada/libgnarl/s-intman__posix.adb
@@ -68,7 +68,7 @@ package body System.Interrupt_Management is
Exception_Interrupts : constant Interrupt_List :=
(SIGFPE, SIGILL, SIGSEGV, SIGBUS);
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-intman__qnx.adb b/gcc/ada/libgnarl/s-intman__qnx.adb
index e983a9e..8934bdf 100644
--- a/gcc/ada/libgnarl/s-intman__qnx.adb
+++ b/gcc/ada/libgnarl/s-intman__qnx.adb
@@ -68,7 +68,7 @@ package body System.Interrupt_Management is
Exception_Interrupts : constant Interrupt_List :=
(SIGFPE, SIGILL, SIGSEGV, SIGBUS);
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-intman__rtems.adb b/gcc/ada/libgnarl/s-intman__rtems.adb
new file mode 100644
index 0000000..dedc67c
--- /dev/null
+++ b/gcc/ada/libgnarl/s-intman__rtems.adb
@@ -0,0 +1,93 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
+-- --
+-- S Y S T E M . I N T E R R U P T _ M A N A G E M E N T --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 1992-2021, Free Software Foundation, Inc. --
+-- --
+-- GNARL 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/>. --
+-- --
+-- GNARL was developed by the GNARL team at Florida State University. --
+-- Extensive contributions were provided by Ada Core Technologies, Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This is the RTEMS version of this package
+
+-- It is simpler than other versions because the Ada interrupt handling
+-- mechanisms are used for hardware interrupts rather than signals.
+
+package body System.Interrupt_Management is
+
+ use System.OS_Interface;
+
+ -----------------------
+ -- Local Subprograms --
+ -----------------------
+
+ function State (Int : Interrupt_ID) return Character;
+ pragma Import (C, State, "__gnat_get_interrupt_state");
+ -- Get interrupt state. Defined in init.c The input argument is the
+ -- hardware interrupt number, and the result is one of the following:
+
+ Runtime : constant Character := 'r';
+ Default : constant Character := 's';
+ -- 'n' this interrupt not set by any Interrupt_State pragma
+ -- 'u' Interrupt_State pragma set state to User
+ -- 'r' Interrupt_State pragma set state to Runtime
+ -- 's' Interrupt_State pragma set state to System (use "default"
+ -- system handler)
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ Initialized : Boolean := False;
+ -- Set to True once Initialize is called, further calls have no effect
+
+ procedure Initialize is
+
+ begin
+ if Initialized then
+ return;
+ end if;
+
+ Initialized := True;
+
+ -- Set the signal used to signal an abort to another task as defined in
+ -- System.OS_Interface.
+
+ Abort_Task_Interrupt := SIGADAABORT;
+
+ -- Initialize hardware interrupt handling
+
+ pragma Assert (Reserve = (Interrupt_ID'Range => False));
+
+ -- Check all interrupts for state that requires keeping them reserved
+
+ for J in Interrupt_ID'Range loop
+ if State (J) = Default or else State (J) = Runtime then
+ Reserve (J) := True;
+ end if;
+ end loop;
+
+ end Initialize;
+
+end System.Interrupt_Management;
diff --git a/gcc/ada/libgnarl/s-intman__rtems.ads b/gcc/ada/libgnarl/s-intman__rtems.ads
new file mode 100644
index 0000000..f3d53ec
--- /dev/null
+++ b/gcc/ada/libgnarl/s-intman__rtems.ads
@@ -0,0 +1,99 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
+-- --
+-- S Y S T E M . I N T E R R U P T _ M A N A G E M E N T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 1992-2021, Free Software Foundation, Inc. --
+-- --
+-- GNARL 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/>. --
+-- --
+-- GNARL was developed by the GNARL team at Florida State University. --
+-- Extensive contributions were provided by Ada Core Technologies, Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This is the RTEMS version of this package
+
+-- This package encapsulates and centralizes information about all
+-- uses of interrupts (or signals), including the target-dependent
+-- mapping of interrupts (or signals) to exceptions.
+
+-- Unlike the original design, System.Interrupt_Management can only
+-- be used for tasking systems.
+
+-- PLEASE DO NOT put any subprogram declarations with arguments of
+-- type Interrupt_ID into the visible part of this package. The type
+-- Interrupt_ID is used to derive the type in Ada.Interrupts, and
+-- adding more operations to that type would be illegal according
+-- to the Ada Reference Manual. This is the reason why the signals
+-- sets are implemented using visible arrays rather than functions.
+
+with System.OS_Interface;
+
+with Interfaces.C;
+
+package System.Interrupt_Management is
+ pragma Preelaborate;
+
+ type Interrupt_Mask is limited private;
+
+ type Interrupt_ID is new Interfaces.C.int
+ range 0 .. System.OS_Interface.Max_Interrupt;
+
+ type Interrupt_Set is array (Interrupt_ID) of Boolean;
+
+ subtype Signal_ID is Interrupt_ID range 0 .. System.OS_Interface.NSIG - 1;
+
+ type Signal_Set is array (Signal_ID) of Boolean;
+
+ -- The following objects serve as constants, but are initialized in the
+ -- body to aid portability. This permits us to use more portable names for
+ -- interrupts, where distinct names may map to the same interrupt ID
+ -- value.
+
+ -- For example, suppose SIGRARE is a signal that is not defined on all
+ -- systems, but is always reserved when it is defined. If we have the
+ -- convention that ID zero is not used for any "real" signals, and SIGRARE
+ -- = 0 when SIGRARE is not one of the locally supported signals, we can
+ -- write:
+ -- Reserved (SIGRARE) := True;
+ -- and the initialization code will be portable.
+
+ Abort_Task_Interrupt : Signal_ID;
+ -- The signal that is used to implement task abort if an interrupt is used
+ -- for that purpose. This is one of the reserved signals.
+
+ Reserve : Interrupt_Set := (others => False);
+ -- Reserve (I) is true iff the interrupt I is one that cannot be permitted
+ -- to be attached to a user handler. The possible reasons are many. For
+ -- example, it may be mapped to an exception used to implement task abort,
+ -- or used to implement time delays.
+
+ procedure Initialize;
+ -- Initialize the various variables defined in this package. This procedure
+ -- must be called before accessing any object from this package and can be
+ -- called multiple times (only the first call has any effect).
+
+private
+ type Interrupt_Mask is new System.OS_Interface.sigset_t;
+ -- In some implementation Interrupt_Mask can be represented as a linked
+ -- list.
+
+end System.Interrupt_Management;
diff --git a/gcc/ada/libgnarl/s-intman__solaris.adb b/gcc/ada/libgnarl/s-intman__solaris.adb
index 3871457..76002a7 100644
--- a/gcc/ada/libgnarl/s-intman__solaris.adb
+++ b/gcc/ada/libgnarl/s-intman__solaris.adb
@@ -47,7 +47,7 @@ package body System.Interrupt_Management is
Exception_Interrupts : constant Interrupt_List :=
(SIGFPE, SIGILL, SIGSEGV, SIGBUS);
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-intman__susv3.adb b/gcc/ada/libgnarl/s-intman__susv3.adb
index b33d76d..f2870cb 100644
--- a/gcc/ada/libgnarl/s-intman__susv3.adb
+++ b/gcc/ada/libgnarl/s-intman__susv3.adb
@@ -56,7 +56,7 @@ package body System.Interrupt_Management is
use Interfaces.C;
use System.OS_Interface;
- Unreserve_All_Interrupts : Interfaces.C.int;
+ Unreserve_All_Interrupts : constant Interfaces.C.int;
pragma Import
(C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
diff --git a/gcc/ada/libgnarl/s-osinte__rtems.adb b/gcc/ada/libgnarl/s-osinte__rtems.adb
index cd977d0..96883af 100644
--- a/gcc/ada/libgnarl/s-osinte__rtems.adb
+++ b/gcc/ada/libgnarl/s-osinte__rtems.adb
@@ -44,6 +44,54 @@ with Interfaces.C; use Interfaces.C;
package body System.OS_Interface is
+ ---------------
+ -- RTEMS API --
+ ---------------
+
+ type RTEMS_Attributes is new unsigned;
+
+ RTEMS_SIMPLE_BINARY_SEMAPHORE : constant := 16#00000020#;
+ RTEMS_FIFO : constant := 16#00000000#;
+
+ type RTEMS_Interval is new unsigned;
+
+ RTEMS_NO_TIMEOUT : constant := 0;
+
+ type RTEMS_Options is new unsigned;
+
+ RTEMS_WAIT : constant := 16#00000000#;
+ RTEMS_INTERRUPT_UNIQUE : constant := 16#00000001#;
+
+ type RTEMS_Name is new unsigned;
+
+ function RTEMS_Build_Name (C1, C2, C3, C4 : Character) return RTEMS_Name
+ with Import, External_Name => "rtems_build_name", Convention => C;
+
+ function RTEMS_Semaphore_Create
+ (Name : RTEMS_Name;
+ Count : unsigned;
+ Attributes : RTEMS_Attributes;
+ Priority_Ceiling : unsigned;
+ Semaphore : out Binary_Semaphore_Id) return int
+ with Import, External_Name => "rtems_semaphore_create", Convention => C;
+
+ function RTEMS_Semaphore_Delete (Semaphore : Binary_Semaphore_Id) return int
+ with Import, External_Name => "rtems_semaphore_delete", Convention => C;
+
+ function RTEMS_Semaphore_Flush (Semaphore : Binary_Semaphore_Id)
+ return int
+ with Import, External_Name => "rtems_semaphore_flush", Convention => C;
+
+ function RTEMS_Semaphore_Obtain
+ (Semaphore : Binary_Semaphore_Id;
+ Options : RTEMS_Options;
+ Timeout : RTEMS_Interval) return int
+ with Import, External_Name => "rtems_semaphore_obtain", Convention => C;
+
+ function RTEMS_Semaphore_Release (Semaphore : Binary_Semaphore_Id)
+ return int
+ with Import, External_Name => "rtems_semaphore_release", Convention => C;
+
-----------------
-- To_Duration --
-----------------
@@ -85,6 +133,108 @@ package body System.OS_Interface is
tv_nsec => long (Long_Long_Integer (F * 10#1#E9)));
end To_Timespec;
+ -----------------------------
+ -- Binary_Semaphore_Create --
+ -----------------------------
+
+ function Binary_Semaphore_Create return Binary_Semaphore_Id is
+ Semaphore : Binary_Semaphore_Id;
+ Status : int;
+ begin
+ Status :=
+ RTEMS_Semaphore_Create
+ (Name => RTEMS_Build_Name ('G', 'N', 'A', 'T'),
+ Count => 0,
+ Attributes => RTEMS_SIMPLE_BINARY_SEMAPHORE or RTEMS_FIFO,
+ Priority_Ceiling => 0,
+ Semaphore => Semaphore);
+
+ pragma Assert (Status = 0);
+
+ return Semaphore;
+ end Binary_Semaphore_Create;
+
+ -----------------------------
+ -- Binary_Semaphore_Delete --
+ -----------------------------
+
+ function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id)
+ return int is
+ begin
+ return RTEMS_Semaphore_Delete (ID);
+ end Binary_Semaphore_Delete;
+
+ -----------------------------
+ -- Binary_Semaphore_Obtain --
+ -----------------------------
+
+ function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id)
+ return int is
+ begin
+ return RTEMS_Semaphore_Obtain (ID, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ end Binary_Semaphore_Obtain;
+
+ ------------------------------
+ -- Binary_Semaphore_Release --
+ ------------------------------
+
+ function Binary_Semaphore_Release (ID : Binary_Semaphore_Id)
+ return int is
+ begin
+ return RTEMS_Semaphore_Release (ID);
+ end Binary_Semaphore_Release;
+
+ ----------------------------
+ -- Binary_Semaphore_Flush --
+ ----------------------------
+
+ function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int is
+ begin
+ return RTEMS_Semaphore_Flush (ID);
+ end Binary_Semaphore_Flush;
+
+ -----------------------
+ -- Interrupt_Connect --
+ -----------------------
+
+ function Interrupt_Connect
+ (Vector : Interrupt_Vector;
+ Handler : Interrupt_Handler;
+ Parameter : System.Address := System.Null_Address) return int
+ is
+ function RTEMS_Interrupt_Handler_Install
+ (Vector : Interrupt_Vector;
+ Info : char_array;
+ Options : RTEMS_Options;
+ Handler : Interrupt_Handler;
+ Parameter : System.Address) return int
+ with Import,
+ External_Name => "rtems_interrupt_handler_install",
+ Convention => C;
+
+ Info_String : constant char_array := To_C ("GNAT Interrupt Handler");
+ -- Handler name that is registered with RTEMS
+ begin
+ return
+ RTEMS_Interrupt_Handler_Install
+ (Vector => Vector,
+ Info => Info_String,
+ Options => RTEMS_INTERRUPT_UNIQUE,
+ Handler => Handler,
+ Parameter => Parameter);
+ end Interrupt_Connect;
+
+ --------------------------------
+ -- Interrupt_Number_To_Vector --
+ --------------------------------
+
+ function Interrupt_Number_To_Vector (intNum : int)
+ return Interrupt_Vector
+ is
+ begin
+ return Interrupt_Vector (intNum);
+ end Interrupt_Number_To_Vector;
+
------------------
-- pthread_init --
------------------
diff --git a/gcc/ada/libgnarl/s-osinte__rtems.ads b/gcc/ada/libgnarl/s-osinte__rtems.ads
index ffbfc3a..9a0561f 100644
--- a/gcc/ada/libgnarl/s-osinte__rtems.ads
+++ b/gcc/ada/libgnarl/s-osinte__rtems.ads
@@ -85,18 +85,20 @@ package System.OS_Interface is
ENOMEM : constant := System.OS_Constants.ENOMEM;
ETIMEDOUT : constant := System.OS_Constants.ETIMEDOUT;
- -------------
- -- Signals --
- -------------
+ ----------------------------
+ -- Signals and Interrupts --
+ ----------------------------
- Num_HW_Interrupts : constant := 256;
+ NSIG : constant := 64;
+ -- Number of signals on the target OS
+ type Signal is new int range 0 .. Interfaces.C."-" (NSIG, 1);
- Max_HW_Interrupt : constant := Num_HW_Interrupts - 1;
+ Max_HW_Interrupt : constant := 255;
type HW_Interrupt is new int range 0 .. Max_HW_Interrupt;
Max_Interrupt : constant := Max_HW_Interrupt;
-
- type Signal is new int range 0 .. Max_Interrupt;
+ subtype Interrupt_Range is Natural range 0 .. Max_HW_Interrupt;
+ -- For s-interr
SIGXCPU : constant := 0; -- XCPU
SIGHUP : constant := 1; -- hangup
@@ -546,34 +548,19 @@ package System.OS_Interface is
type Binary_Semaphore_Id is new rtems_id;
function Binary_Semaphore_Create return Binary_Semaphore_Id;
- pragma Import (
- C,
- Binary_Semaphore_Create,
- "__gnat_binary_semaphore_create");
+ pragma Inline (Binary_Semaphore_Create);
function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return int;
- pragma Import (
- C,
- Binary_Semaphore_Delete,
- "__gnat_binary_semaphore_delete");
+ pragma Inline (Binary_Semaphore_Delete);
function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return int;
- pragma Import (
- C,
- Binary_Semaphore_Obtain,
- "__gnat_binary_semaphore_obtain");
+ pragma Inline (Binary_Semaphore_Obtain);
function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return int;
- pragma Import (
- C,
- Binary_Semaphore_Release,
- "__gnat_binary_semaphore_release");
+ pragma Inline (Binary_Semaphore_Release);
function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int;
- pragma Import (
- C,
- Binary_Semaphore_Flush,
- "__gnat_binary_semaphore_flush");
+ pragma Inline (Binary_Semaphore_Flush);
------------------------------------------------------------
-- Hardware Interrupt Wrappers to Support Interrupt Tasks --
@@ -581,40 +568,24 @@ package System.OS_Interface is
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
+
type Interrupt_Vector is new System.Address;
function Interrupt_Connect
- (vector : Interrupt_Vector;
- handler : Interrupt_Handler;
- parameter : System.Address := System.Null_Address) return int;
- pragma Import (C, Interrupt_Connect, "__gnat_interrupt_connect");
+ (Vector : Interrupt_Vector;
+ Handler : Interrupt_Handler;
+ Parameter : System.Address := System.Null_Address) return int;
-- Use this to set up an user handler. The routine installs a
-- a user handler which is invoked after RTEMS has saved enough
-- context for a high-level language routine to be safely invoked.
- function Interrupt_Vector_Get
- (Vector : Interrupt_Vector) return Interrupt_Handler;
- pragma Import (C, Interrupt_Vector_Get, "__gnat_interrupt_get");
- -- Use this to get the existing handler for later restoral.
-
- procedure Interrupt_Vector_Set
- (Vector : Interrupt_Vector;
- Handler : Interrupt_Handler);
- pragma Import (C, Interrupt_Vector_Set, "__gnat_interrupt_set");
- -- Use this to restore a handler obtained using Interrupt_Vector_Get.
-
function Interrupt_Number_To_Vector (intNum : int) return Interrupt_Vector;
-- Convert a logical interrupt number to the hardware interrupt vector
-- number used to connect the interrupt.
- pragma Import (
- C,
- Interrupt_Number_To_Vector,
- "__gnat_interrupt_number_to_vector"
- );
private
- type sigset_t is new int;
+ type sigset_t is new unsigned_long;
type pid_t is new int;
diff --git a/gcc/ada/libgnarl/s-osinte__vxworks.adb b/gcc/ada/libgnarl/s-osinte__vxworks.adb
index cf3ece3..fbc8367 100644
--- a/gcc/ada/libgnarl/s-osinte__vxworks.adb
+++ b/gcc/ada/libgnarl/s-osinte__vxworks.adb
@@ -100,10 +100,11 @@ package body System.OS_Interface is
Ticks : Long_Long_Integer;
Rate_Duration : Duration;
Ticks_Duration : Duration;
+ IERR : constant int := -1;
begin
if D < 0.0 then
- return ERROR;
+ return IERR;
end if;
-- Ensure that the duration can be converted to ticks
@@ -142,7 +143,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Delete --
-----------------------------
- function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semDelete (SEM_ID (ID));
end Binary_Semaphore_Delete;
@@ -151,7 +153,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Obtain --
-----------------------------
- function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semTake (SEM_ID (ID), WAIT_FOREVER);
end Binary_Semaphore_Obtain;
@@ -160,7 +163,8 @@ package body System.OS_Interface is
-- Binary_Semaphore_Release --
------------------------------
- function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Release (ID : Binary_Semaphore_Id)
+ return STATUS is
begin
return semGive (SEM_ID (ID));
end Binary_Semaphore_Release;
@@ -169,7 +173,7 @@ package body System.OS_Interface is
-- Binary_Semaphore_Flush --
----------------------------
- function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int is
+ function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return STATUS is
begin
return semFlush (SEM_ID (ID));
end Binary_Semaphore_Flush;
@@ -190,7 +194,7 @@ package body System.OS_Interface is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int is
+ Parameter : System.Address := System.Null_Address) return STATUS is
begin
return
System.VxWorks.Ext.Interrupt_Connect
@@ -203,7 +207,7 @@ package body System.OS_Interface is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
return System.VxWorks.Ext.Interrupt_Context;
end Interrupt_Context;
diff --git a/gcc/ada/libgnarl/s-osinte__vxworks.ads b/gcc/ada/libgnarl/s-osinte__vxworks.ads
index a2d5620..e851645 100644
--- a/gcc/ada/libgnarl/s-osinte__vxworks.ads
+++ b/gcc/ada/libgnarl/s-osinte__vxworks.ads
@@ -47,6 +47,8 @@ with System.Parameters;
package System.OS_Interface is
pragma Preelaborate;
+ package SVE renames System.VxWorks.Ext;
+
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
subtype short is Short_Integer;
@@ -57,6 +59,10 @@ package System.OS_Interface is
type unsigned_long_long is mod 2 ** long_long'Size;
type size_t is mod 2 ** Standard'Address_Size;
+ subtype STATUS is SVE.STATUS;
+ subtype BOOL is SVE.BOOL;
+ subtype vx_freq_t is SVE.vx_freq_t;
+
-----------
-- Errno --
-----------
@@ -201,7 +207,7 @@ package System.OS_Interface is
oset : access sigset_t) return int;
pragma Import (C, pthread_sigmask, "sigprocmask");
- subtype t_id is System.VxWorks.Ext.t_id;
+ subtype t_id is SVE.t_id;
subtype Thread_Id is t_id;
-- Thread_Id and t_id are VxWorks identifiers for tasks. This value,
-- although represented as a Long_Integer, is in fact an address. With
@@ -211,27 +217,24 @@ package System.OS_Interface is
function kill (pid : t_id; sig : Signal) return int;
pragma Inline (kill);
- function getpid return t_id renames System.VxWorks.Ext.getpid;
+ function getpid return t_id renames SVE.getpid;
- function Task_Stop (tid : t_id) return int
- renames System.VxWorks.Ext.Task_Stop;
+ function Task_Stop (tid : t_id) return STATUS renames SVE.Task_Stop;
-- If we are in the kernel space, stop the task whose t_id is given in
-- parameter in such a way that it can be examined by the debugger. This
-- typically maps to taskSuspend on VxWorks 5 and to taskStop on VxWorks 6.
- function Task_Cont (tid : t_id) return int
- renames System.VxWorks.Ext.Task_Cont;
+ function Task_Cont (tid : t_id) return STATUS renames SVE.Task_Cont;
-- If we are in the kernel space, continue the task whose t_id is given
-- in parameter if it has been stopped previously to be examined by the
-- debugger (e.g. by taskStop). It typically maps to taskResume on VxWorks
-- 5 and to taskCont on VxWorks 6.
- function Int_Lock return int renames System.VxWorks.Ext.Int_Lock;
+ function Int_Lock return int renames SVE.Int_Lock;
-- If we are in the kernel space, lock interrupts. It typically maps to
-- intLock.
- function Int_Unlock (Old : int) return int
- renames System.VxWorks.Ext.Int_Unlock;
+ procedure Int_Unlock (Old : int) renames SVE.Int_Unlock;
-- If we are in the kernel space, unlock interrupts. It typically maps to
-- intUnlock. The parameter Old is only used on PowerPC where it contains
-- the returned value from Int_Lock (the old MPSR).
@@ -285,34 +288,28 @@ package System.OS_Interface is
-- VxWorks specific API --
--------------------------
- subtype STATUS is int;
- -- Equivalent of the C type STATUS
-
- OK : constant STATUS := 0;
- ERROR : constant STATUS := Interfaces.C.int (-1);
-
function taskIdVerify (tid : t_id) return STATUS;
pragma Import (C, taskIdVerify, "taskIdVerify");
function taskIdSelf return t_id;
pragma Import (C, taskIdSelf, "taskIdSelf");
- function taskOptionsGet (tid : t_id; pOptions : access int) return int;
+ function taskOptionsGet (tid : t_id; pOptions : access int) return STATUS;
pragma Import (C, taskOptionsGet, "taskOptionsGet");
- function taskSuspend (tid : t_id) return int;
+ function taskSuspend (tid : t_id) return STATUS;
pragma Import (C, taskSuspend, "taskSuspend");
- function taskResume (tid : t_id) return int;
+ function taskResume (tid : t_id) return STATUS;
pragma Import (C, taskResume, "taskResume");
- function taskIsSuspended (tid : t_id) return int;
+ function taskIsSuspended (tid : t_id) return BOOL;
pragma Import (C, taskIsSuspended, "taskIsSuspended");
- function taskDelay (ticks : int) return int;
+ function taskDelay (ticks : int) return STATUS;
pragma Import (C, taskDelay, "taskDelay");
- function sysClkRateGet return int;
+ function sysClkRateGet return vx_freq_t;
pragma Import (C, sysClkRateGet, "sysClkRateGet");
-- VxWorks 5.x specific functions
@@ -320,17 +317,17 @@ package System.OS_Interface is
-- taskVarLib: eg VxWorks 6 RTPs
function taskVarAdd
- (tid : t_id; pVar : access System.Address) return int;
+ (tid : t_id; pVar : access System.Address) return STATUS;
pragma Import (C, taskVarAdd, "taskVarAdd");
function taskVarDelete
- (tid : t_id; pVar : access System.Address) return int;
+ (tid : t_id; pVar : access System.Address) return STATUS;
pragma Import (C, taskVarDelete, "taskVarDelete");
function taskVarSet
(tid : t_id;
pVar : access System.Address;
- value : System.Address) return int;
+ value : System.Address) return STATUS;
pragma Import (C, taskVarSet, "taskVarSet");
function taskVarGet
@@ -379,15 +376,15 @@ package System.OS_Interface is
procedure taskDelete (tid : t_id);
pragma Import (C, taskDelete, "taskDelete");
- function Set_Time_Slice (ticks : int) return int
- renames System.VxWorks.Ext.Set_Time_Slice;
+ function Set_Time_Slice (ticks : int) return STATUS renames
+ SVE.Set_Time_Slice;
-- Calls kernelTimeSlice under VxWorks 5.x, VxWorks 653, or in VxWorks 6
-- kernel apps. Returns ERROR for RTPs, VxWorks 5 /CERT
- function taskPriorityGet (tid : t_id; pPriority : access int) return int;
+ function taskPriorityGet (tid : t_id; pPriority : access int) return STATUS;
pragma Import (C, taskPriorityGet, "taskPriorityGet");
- function taskPrioritySet (tid : t_id; newPriority : int) return int;
+ function taskPrioritySet (tid : t_id; newPriority : int) return STATUS;
pragma Import (C, taskPrioritySet, "taskPrioritySet");
-- Semaphore creation flags
@@ -419,7 +416,7 @@ package System.OS_Interface is
-- semTake() timeout with ticks > NO_WAIT
S_objLib_OBJ_TIMEOUT : constant := M_objLib + 4;
- subtype SEM_ID is System.VxWorks.Ext.SEM_ID;
+ subtype SEM_ID is SVE.SEM_ID;
-- typedef struct semaphore *SEM_ID;
-- We use two different kinds of VxWorks semaphores: mutex and binary
@@ -433,14 +430,13 @@ package System.OS_Interface is
function semMCreate (options : int) return SEM_ID;
pragma Import (C, semMCreate, "semMCreate");
- function semDelete (Sem : SEM_ID) return int
- renames System.VxWorks.Ext.semDelete;
+ function semDelete (Sem : SEM_ID) return STATUS renames SVE.semDelete;
-- Delete a semaphore
- function semGive (Sem : SEM_ID) return int;
+ function semGive (Sem : SEM_ID) return STATUS;
pragma Import (C, semGive, "semGive");
- function semTake (Sem : SEM_ID; timeout : int) return int;
+ function semTake (Sem : SEM_ID; timeout : int) return STATUS;
pragma Import (C, semTake, "semTake");
-- Attempt to take binary semaphore. Error is returned if operation
-- times out
@@ -458,16 +454,16 @@ package System.OS_Interface is
function Binary_Semaphore_Create return Binary_Semaphore_Id;
pragma Inline (Binary_Semaphore_Create);
- function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Delete (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Delete);
- function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Obtain (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Obtain);
- function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Release (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Release);
- function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return int;
+ function Binary_Semaphore_Flush (ID : Binary_Semaphore_Id) return STATUS;
pragma Inline (Binary_Semaphore_Flush);
------------------------------------------------------------
@@ -482,16 +478,16 @@ package System.OS_Interface is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Inline (Interrupt_Connect);
-- Use this to set up an user handler. The routine installs a user handler
-- which is invoked after the OS has saved enough context for a high-level
-- language routine to be safely invoked.
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Inline (Interrupt_Context);
- -- Return 1 if executing in an interrupt context; return 0 if executing in
- -- a task context.
+ -- Return 1 (TRUE) if executing in an interrupt context;
+ -- return 0 (FALSE) if executing in a task context.
function Interrupt_Number_To_Vector (intNum : int) return Interrupt_Vector;
pragma Inline (Interrupt_Number_To_Vector);
@@ -503,12 +499,12 @@ package System.OS_Interface is
--------------------------------
function taskCpuAffinitySet (tid : t_id; CPU : int) return int
- renames System.VxWorks.Ext.taskCpuAffinitySet;
+ renames SVE.taskCpuAffinitySet;
-- For SMP run-times the affinity to CPU.
-- For uniprocessor systems return ERROR status.
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int
- renames System.VxWorks.Ext.taskMaskAffinitySet;
+ renames SVE.taskMaskAffinitySet;
-- For SMP run-times the affinity to CPU_Set.
-- For uniprocessor systems return ERROR status.
@@ -524,5 +520,5 @@ private
ERROR_PID : constant pid_t := -1;
- type sigset_t is new System.VxWorks.Ext.sigset_t;
+ type sigset_t is new SVE.sigset_t;
end System.OS_Interface;
diff --git a/gcc/ada/libgnarl/s-taprob.adb b/gcc/ada/libgnarl/s-taprob.adb
index 754d175..1f304d9 100644
--- a/gcc/ada/libgnarl/s-taprob.adb
+++ b/gcc/ada/libgnarl/s-taprob.adb
@@ -47,7 +47,7 @@ package body System.Tasking.Protected_Objects is
-- Local Data --
----------------
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
-------------------------
diff --git a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
index ebd8941..9bded3a 100644
--- a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
+++ b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
@@ -87,10 +87,10 @@ package body System.Task_Primitives.Operations is
Unblocked_Signal_Mask : aliased sigset_t;
-- The set of signals that should unblocked in all tasks
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
-- Note: the reason that Locking_Policy is not needed is that this
diff --git a/gcc/ada/libgnarl/s-taprop__linux.adb b/gcc/ada/libgnarl/s-taprop__linux.adb
index 93ffb3a..1c8c6bd 100644
--- a/gcc/ada/libgnarl/s-taprop__linux.adb
+++ b/gcc/ada/libgnarl/s-taprop__linux.adb
@@ -84,13 +84,13 @@ package body System.Task_Primitives.Operations is
Next_Serial_Number : Task_Serial_Number := 100;
-- We start at 100 (reserve some special values for using in error checks)
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
diff --git a/gcc/ada/libgnarl/s-taprop__mingw.adb b/gcc/ada/libgnarl/s-taprop__mingw.adb
index 4d9b163..33d5977 100644
--- a/gcc/ada/libgnarl/s-taprop__mingw.adb
+++ b/gcc/ada/libgnarl/s-taprop__mingw.adb
@@ -109,10 +109,10 @@ package body System.Task_Primitives.Operations is
-- a time; it is used to execute in mutual exclusion from all other tasks.
-- Used to protect All_Tasks_List
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
function Get_Policy (Prio : System.Any_Priority) return Character;
diff --git a/gcc/ada/libgnarl/s-taprop__posix.adb b/gcc/ada/libgnarl/s-taprop__posix.adb
index 3dc12c8..c0766a0 100644
--- a/gcc/ada/libgnarl/s-taprop__posix.adb
+++ b/gcc/ada/libgnarl/s-taprop__posix.adb
@@ -83,7 +83,7 @@ package body System.Task_Primitives.Operations is
Environment_Task_Id : Task_Id;
-- A variable to hold Task_Id for the environment task
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
-- Value of the pragma Locking_Policy:
-- 'C' for Ceiling_Locking
@@ -99,10 +99,10 @@ package body System.Task_Primitives.Operations is
-- We start at 100, to reserve some special values for
-- using in error checking.
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
diff --git a/gcc/ada/libgnarl/s-taprop__qnx.adb b/gcc/ada/libgnarl/s-taprop__qnx.adb
index 9446e37..e7faf08 100644
--- a/gcc/ada/libgnarl/s-taprop__qnx.adb
+++ b/gcc/ada/libgnarl/s-taprop__qnx.adb
@@ -83,7 +83,7 @@ package body System.Task_Primitives.Operations is
Environment_Task_Id : Task_Id;
-- A variable to hold Task_Id for the environment task
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
-- Value of the pragma Locking_Policy:
-- 'C' for Ceiling_Locking
@@ -99,10 +99,10 @@ package body System.Task_Primitives.Operations is
-- We start at 100, to reserve some special values for
-- using in error checking.
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
diff --git a/gcc/ada/libgnarl/s-taprop__rtems.adb b/gcc/ada/libgnarl/s-taprop__rtems.adb
new file mode 100644
index 0000000..9153032
--- /dev/null
+++ b/gcc/ada/libgnarl/s-taprop__rtems.adb
@@ -0,0 +1,1347 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
+-- --
+-- S Y S T E M . T A S K _ P R I M I T I V E S . O P E R A T I O N S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 1992-2021, Free Software Foundation, Inc. --
+-- --
+-- GNARL 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/>. --
+-- --
+-- GNARL was developed by the GNARL team at Florida State University. --
+-- Extensive contributions were provided by Ada Core Technologies, Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This is the RTEMS version of this package
+
+-- This package contains all the GNULL primitives that interface directly with
+-- the underlying OS.
+
+with Ada.Unchecked_Conversion;
+
+with Interfaces.C;
+
+with System.Tasking.Debug;
+with System.Interrupt_Management;
+with System.OS_Constants;
+with System.OS_Primitives;
+with System.Task_Info;
+
+with System.Soft_Links;
+-- We use System.Soft_Links instead of System.Tasking.Initialization
+-- because the later is a higher level package that we shouldn't depend on.
+-- For example when using the restricted run time, it is replaced by
+-- System.Tasking.Restricted.Stages.
+
+package body System.Task_Primitives.Operations is
+
+ package OSC renames System.OS_Constants;
+ package SSL renames System.Soft_Links;
+
+ use System.Tasking.Debug;
+ use System.Tasking;
+ use Interfaces.C;
+ use System.OS_Interface;
+ use System.Parameters;
+ use System.OS_Primitives;
+
+ ----------------
+ -- Local Data --
+ ----------------
+
+ -- The followings are logically constants, but need to be initialized
+ -- at run time.
+
+ Single_RTS_Lock : aliased RTS_Lock;
+ -- This is a lock to allow only one thread of control in the RTS at
+ -- a time; it is used to execute in mutual exclusion from all other tasks.
+ -- Used to protect All_Tasks_List
+
+ Environment_Task_Id : Task_Id;
+ -- A variable to hold Task_Id for the environment task
+
+ Locking_Policy : constant Character;
+ pragma Import (C, Locking_Policy, "__gl_locking_policy");
+ -- Value of the pragma Locking_Policy:
+ -- 'C' for Ceiling_Locking
+ -- 'I' for Inherit_Locking
+ -- ' ' for none.
+
+ -- The followings are internal configuration constants needed
+
+ Next_Serial_Number : Task_Serial_Number := 100;
+ -- We start at 100, to reserve some special values for
+ -- using in error checking.
+
+ Time_Slice_Val : constant Integer;
+ pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
+
+ Dispatching_Policy : constant Character;
+ pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
+
+ Foreign_Task_Elaborated : aliased Boolean := True;
+ -- Used to identified fake tasks (i.e., non-Ada Threads)
+
+ Use_Alternate_Stack : constant Boolean := Alternate_Stack_Size /= 0;
+ -- Whether to use an alternate signal stack for stack overflows
+
+ Abort_Handler_Installed : Boolean := False;
+ -- True if a handler for the abort signal is installed
+
+ --------------------
+ -- Local Packages --
+ --------------------
+
+ package Specific is
+
+ procedure Initialize (Environment_Task : Task_Id);
+ pragma Inline (Initialize);
+ -- Initialize various data needed by this package
+
+ function Is_Valid_Task return Boolean;
+ pragma Inline (Is_Valid_Task);
+ -- Does executing thread have a TCB?
+
+ procedure Set (Self_Id : Task_Id);
+ pragma Inline (Set);
+ -- Set the self id for the current task
+
+ function Self return Task_Id;
+ pragma Inline (Self);
+ -- Return a pointer to the Ada Task Control Block of the calling task
+
+ end Specific;
+
+ package body Specific is separate;
+ -- The body of this package is target specific
+
+ package Monotonic is
+
+ function Monotonic_Clock return Duration;
+ pragma Inline (Monotonic_Clock);
+ -- Returns an absolute time, represented as an offset relative to some
+ -- unspecified starting point, typically system boot time. This clock
+ -- is not affected by discontinuous jumps in the system time.
+
+ function RT_Resolution return Duration;
+ pragma Inline (RT_Resolution);
+ -- Returns resolution of the underlying clock used to implement RT_Clock
+
+ procedure Timed_Sleep
+ (Self_ID : ST.Task_Id;
+ Time : Duration;
+ Mode : ST.Delay_Modes;
+ Reason : System.Tasking.Task_States;
+ Timedout : out Boolean;
+ Yielded : out Boolean);
+ -- Combination of Sleep (above) and Timed_Delay
+
+ procedure Timed_Delay
+ (Self_ID : ST.Task_Id;
+ Time : Duration;
+ Mode : ST.Delay_Modes);
+ -- Implement the semantics of the delay statement.
+ -- The caller should be abort-deferred and should not hold any locks.
+
+ end Monotonic;
+
+ package body Monotonic is separate;
+
+ ----------------------------------
+ -- ATCB allocation/deallocation --
+ ----------------------------------
+
+ package body ATCB_Allocation is separate;
+ -- The body of this package is shared across several targets
+
+ ---------------------------------
+ -- Support for foreign threads --
+ ---------------------------------
+
+ function Register_Foreign_Thread
+ (Thread : Thread_Id;
+ Sec_Stack_Size : Size_Type := Unspecified_Size) return Task_Id;
+ -- Allocate and initialize a new ATCB for the current Thread. The size of
+ -- the secondary stack can be optionally specified.
+
+ function Register_Foreign_Thread
+ (Thread : Thread_Id;
+ Sec_Stack_Size : Size_Type := Unspecified_Size)
+ return Task_Id is separate;
+
+ -----------------------
+ -- Local Subprograms --
+ -----------------------
+
+ procedure Abort_Handler (Sig : Signal);
+ -- Signal handler used to implement asynchronous abort.
+ -- See also comment before body, below.
+
+ function To_Address is
+ new Ada.Unchecked_Conversion (Task_Id, System.Address);
+
+ function GNAT_pthread_condattr_setup
+ (attr : access pthread_condattr_t) return int;
+ pragma Import (C,
+ GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup");
+
+ -------------------
+ -- Abort_Handler --
+ -------------------
+
+ -- Target-dependent binding of inter-thread Abort signal to the raising of
+ -- the Abort_Signal exception.
+
+ -- The technical issues and alternatives here are essentially the
+ -- same as for raising exceptions in response to other signals
+ -- (e.g. Storage_Error). See code and comments in the package body
+ -- System.Interrupt_Management.
+
+ -- Some implementations may not allow an exception to be propagated out of
+ -- a handler, and others might leave the signal or interrupt that invoked
+ -- this handler masked after the exceptional return to the application
+ -- code.
+
+ -- GNAT exceptions are originally implemented using setjmp()/longjmp(). On
+ -- most UNIX systems, this will allow transfer out of a signal handler,
+ -- which is usually the only mechanism available for implementing
+ -- asynchronous handlers of this kind. However, some systems do not
+ -- restore the signal mask on longjmp(), leaving the abort signal masked.
+
+ procedure Abort_Handler (Sig : Signal) is
+ pragma Unreferenced (Sig);
+
+ T : constant Task_Id := Self;
+ Old_Set : aliased sigset_t;
+ Unblocked_Mask : aliased sigset_t;
+ Result : Interfaces.C.int;
+ pragma Warnings (Off, Result);
+
+ begin
+ -- It's not safe to raise an exception when using GCC ZCX mechanism.
+ -- Note that we still need to install a signal handler, since in some
+ -- cases (e.g. shutdown of the Server_Task in System.Interrupts) we
+ -- need to send the Abort signal to a task.
+
+ if ZCX_By_Default then
+ return;
+ end if;
+
+ if T.Deferral_Level = 0
+ and then T.Pending_ATC_Level < T.ATC_Nesting_Level and then
+ not T.Aborting
+ then
+ T.Aborting := True;
+
+ -- Make sure signals used for RTS internal purpose are unmasked
+
+ Result := sigemptyset (Unblocked_Mask'Access);
+ pragma Assert (Result = 0);
+ Result :=
+ sigaddset
+ (Unblocked_Mask'Access,
+ Signal (Interrupt_Management.Abort_Task_Interrupt));
+ pragma Assert (Result = 0);
+ Result := sigaddset (Unblocked_Mask'Access, SIGBUS);
+ pragma Assert (Result = 0);
+ Result := sigaddset (Unblocked_Mask'Access, SIGFPE);
+ pragma Assert (Result = 0);
+ Result := sigaddset (Unblocked_Mask'Access, SIGILL);
+ pragma Assert (Result = 0);
+ Result := sigaddset (Unblocked_Mask'Access, SIGSEGV);
+ pragma Assert (Result = 0);
+
+ Result :=
+ pthread_sigmask
+ (SIG_UNBLOCK,
+ Unblocked_Mask'Access,
+ Old_Set'Access);
+ pragma Assert (Result = 0);
+
+ raise Standard'Abort_Signal;
+ end if;
+ end Abort_Handler;
+
+ -----------------
+ -- Stack_Guard --
+ -----------------
+
+ procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
+ Stack_Base : constant Address := Get_Stack_Base (T.Common.LL.Thread);
+ Page_Size : Address;
+ Res : Interfaces.C.int;
+
+ begin
+ if Stack_Base_Available then
+
+ -- Compute the guard page address
+
+ Page_Size := Address (Get_Page_Size);
+ Res :=
+ mprotect
+ (Stack_Base - (Stack_Base mod Page_Size) + Page_Size,
+ size_t (Page_Size),
+ prot => (if On then PROT_ON else PROT_OFF));
+ pragma Assert (Res = 0);
+ end if;
+ end Stack_Guard;
+
+ --------------------
+ -- Get_Thread_Id --
+ --------------------
+
+ function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
+ begin
+ return T.Common.LL.Thread;
+ end Get_Thread_Id;
+
+ ----------
+ -- Self --
+ ----------
+
+ function Self return Task_Id renames Specific.Self;
+
+ ---------------------
+ -- Initialize_Lock --
+ ---------------------
+
+ -- Note: mutexes and cond_variables needed per-task basis are initialized
+ -- in Initialize_TCB and the Storage_Error is handled. Other mutexes (such
+ -- as RTS_Lock, Memory_Lock...) used in RTS is initialized before any
+ -- status change of RTS. Therefore raising Storage_Error in the following
+ -- routines should be able to be handled safely.
+
+ procedure Initialize_Lock
+ (Prio : System.Any_Priority;
+ L : not null access Lock)
+ is
+ Attributes : aliased pthread_mutexattr_t;
+ Result : Interfaces.C.int;
+
+ begin
+ Result := pthread_mutexattr_init (Attributes'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ raise Storage_Error;
+ end if;
+
+ if Locking_Policy = 'C' then
+ Result := pthread_mutexattr_setprotocol
+ (Attributes'Access, PTHREAD_PRIO_PROTECT);
+ pragma Assert (Result = 0);
+
+ Result := pthread_mutexattr_setprioceiling
+ (Attributes'Access, Interfaces.C.int (Prio));
+ pragma Assert (Result = 0);
+
+ elsif Locking_Policy = 'I' then
+ Result := pthread_mutexattr_setprotocol
+ (Attributes'Access, PTHREAD_PRIO_INHERIT);
+ pragma Assert (Result = 0);
+ end if;
+
+ Result := pthread_mutex_init (L.WO'Access, Attributes'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ Result := pthread_mutexattr_destroy (Attributes'Access);
+ raise Storage_Error;
+ end if;
+
+ Result := pthread_mutexattr_destroy (Attributes'Access);
+ pragma Assert (Result = 0);
+ end Initialize_Lock;
+
+ procedure Initialize_Lock
+ (L : not null access RTS_Lock; Level : Lock_Level)
+ is
+ pragma Unreferenced (Level);
+
+ Attributes : aliased pthread_mutexattr_t;
+ Result : Interfaces.C.int;
+
+ begin
+ Result := pthread_mutexattr_init (Attributes'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ raise Storage_Error;
+ end if;
+
+ if Locking_Policy = 'C' then
+ Result := pthread_mutexattr_setprotocol
+ (Attributes'Access, PTHREAD_PRIO_PROTECT);
+ pragma Assert (Result = 0);
+
+ Result := pthread_mutexattr_setprioceiling
+ (Attributes'Access, Interfaces.C.int (System.Any_Priority'Last));
+ pragma Assert (Result = 0);
+
+ elsif Locking_Policy = 'I' then
+ Result := pthread_mutexattr_setprotocol
+ (Attributes'Access, PTHREAD_PRIO_INHERIT);
+ pragma Assert (Result = 0);
+ end if;
+
+ Result := pthread_mutex_init (L, Attributes'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ Result := pthread_mutexattr_destroy (Attributes'Access);
+ raise Storage_Error;
+ end if;
+
+ Result := pthread_mutexattr_destroy (Attributes'Access);
+ pragma Assert (Result = 0);
+ end Initialize_Lock;
+
+ -------------------
+ -- Finalize_Lock --
+ -------------------
+
+ procedure Finalize_Lock (L : not null access Lock) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_destroy (L.WO'Access);
+ pragma Assert (Result = 0);
+ end Finalize_Lock;
+
+ procedure Finalize_Lock (L : not null access RTS_Lock) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_destroy (L);
+ pragma Assert (Result = 0);
+ end Finalize_Lock;
+
+ ----------------
+ -- Write_Lock --
+ ----------------
+
+ procedure Write_Lock
+ (L : not null access Lock; Ceiling_Violation : out Boolean)
+ is
+ Result : Interfaces.C.int;
+
+ begin
+ Result := pthread_mutex_lock (L.WO'Access);
+
+ -- The cause of EINVAL is a priority ceiling violation
+
+ Ceiling_Violation := Result = EINVAL;
+ pragma Assert (Result = 0 or else Ceiling_Violation);
+ end Write_Lock;
+
+ procedure Write_Lock (L : not null access RTS_Lock) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_lock (L);
+ pragma Assert (Result = 0);
+ end Write_Lock;
+
+ procedure Write_Lock (T : Task_Id) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_lock (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end Write_Lock;
+
+ ---------------
+ -- Read_Lock --
+ ---------------
+
+ procedure Read_Lock
+ (L : not null access Lock; Ceiling_Violation : out Boolean) is
+ begin
+ Write_Lock (L, Ceiling_Violation);
+ end Read_Lock;
+
+ ------------
+ -- Unlock --
+ ------------
+
+ procedure Unlock (L : not null access Lock) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_unlock (L.WO'Access);
+ pragma Assert (Result = 0);
+ end Unlock;
+
+ procedure Unlock (L : not null access RTS_Lock) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_unlock (L);
+ pragma Assert (Result = 0);
+ end Unlock;
+
+ procedure Unlock (T : Task_Id) is
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_mutex_unlock (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ end Unlock;
+
+ -----------------
+ -- Set_Ceiling --
+ -----------------
+
+ -- Dynamic priority ceilings are not supported by the underlying system
+
+ procedure Set_Ceiling
+ (L : not null access Lock;
+ Prio : System.Any_Priority)
+ is
+ pragma Unreferenced (L, Prio);
+ begin
+ null;
+ end Set_Ceiling;
+
+ -----------
+ -- Sleep --
+ -----------
+
+ procedure Sleep
+ (Self_ID : Task_Id;
+ Reason : System.Tasking.Task_States)
+ is
+ pragma Unreferenced (Reason);
+
+ Result : Interfaces.C.int;
+
+ begin
+ Result :=
+ pthread_cond_wait
+ (cond => Self_ID.Common.LL.CV'Access,
+ mutex => Self_ID.Common.LL.L'Access);
+
+ -- EINTR is not considered a failure
+
+ pragma Assert (Result = 0 or else Result = EINTR);
+ end Sleep;
+
+ -----------------
+ -- Timed_Sleep --
+ -----------------
+
+ -- This is for use within the run-time system, so abort is
+ -- assumed to be already deferred, and the caller should be
+ -- holding its own ATCB lock.
+
+ procedure Timed_Sleep
+ (Self_ID : Task_Id;
+ Time : Duration;
+ Mode : ST.Delay_Modes;
+ Reason : Task_States;
+ Timedout : out Boolean;
+ Yielded : out Boolean) renames Monotonic.Timed_Sleep;
+
+ -----------------
+ -- Timed_Delay --
+ -----------------
+
+ -- This is for use in implementing delay statements, so we assume the
+ -- caller is abort-deferred but is holding no locks.
+
+ procedure Timed_Delay
+ (Self_ID : Task_Id;
+ Time : Duration;
+ Mode : ST.Delay_Modes) renames Monotonic.Timed_Delay;
+
+ ---------------------
+ -- Monotonic_Clock --
+ ---------------------
+
+ function Monotonic_Clock return Duration renames Monotonic.Monotonic_Clock;
+
+ -------------------
+ -- RT_Resolution --
+ -------------------
+
+ function RT_Resolution return Duration renames Monotonic.RT_Resolution;
+
+ ------------
+ -- Wakeup --
+ ------------
+
+ procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
+ pragma Unreferenced (Reason);
+ Result : Interfaces.C.int;
+ begin
+ Result := pthread_cond_signal (T.Common.LL.CV'Access);
+ pragma Assert (Result = 0);
+ end Wakeup;
+
+ -----------
+ -- Yield --
+ -----------
+
+ procedure Yield (Do_Yield : Boolean := True) is
+ Result : Interfaces.C.int;
+ pragma Unreferenced (Result);
+ begin
+ if Do_Yield then
+ Result := sched_yield;
+ end if;
+ end Yield;
+
+ ------------------
+ -- Set_Priority --
+ ------------------
+
+ procedure Set_Priority
+ (T : Task_Id;
+ Prio : System.Any_Priority;
+ Loss_Of_Inheritance : Boolean := False)
+ is
+ pragma Unreferenced (Loss_Of_Inheritance);
+
+ Result : Interfaces.C.int;
+ Param : aliased struct_sched_param;
+
+ function Get_Policy (Prio : System.Any_Priority) return Character;
+ pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
+ -- Get priority specific dispatching policy
+
+ Priority_Specific_Policy : constant Character := Get_Policy (Prio);
+ -- Upper case first character of the policy name corresponding to the
+ -- task as set by a Priority_Specific_Dispatching pragma.
+
+ begin
+ T.Common.Current_Priority := Prio;
+ Param.sched_priority := To_Target_Priority (Prio);
+
+ if Time_Slice_Supported
+ and then (Dispatching_Policy = 'R'
+ or else Priority_Specific_Policy = 'R'
+ or else Time_Slice_Val > 0)
+ then
+ Result := pthread_setschedparam
+ (T.Common.LL.Thread, SCHED_RR, Param'Access);
+
+ elsif Dispatching_Policy = 'F'
+ or else Priority_Specific_Policy = 'F'
+ or else Time_Slice_Val = 0
+ then
+ Result := pthread_setschedparam
+ (T.Common.LL.Thread, SCHED_FIFO, Param'Access);
+
+ else
+ Result := pthread_setschedparam
+ (T.Common.LL.Thread, SCHED_OTHER, Param'Access);
+ end if;
+
+ pragma Assert (Result = 0);
+ end Set_Priority;
+
+ ------------------
+ -- Get_Priority --
+ ------------------
+
+ function Get_Priority (T : Task_Id) return System.Any_Priority is
+ begin
+ return T.Common.Current_Priority;
+ end Get_Priority;
+
+ ----------------
+ -- Enter_Task --
+ ----------------
+
+ procedure Enter_Task (Self_ID : Task_Id) is
+ begin
+ Self_ID.Common.LL.Thread := pthread_self;
+ Self_ID.Common.LL.LWP := lwp_self;
+
+ Specific.Set (Self_ID);
+
+ if Use_Alternate_Stack then
+ declare
+ Stack : aliased stack_t;
+ Result : Interfaces.C.int;
+ begin
+ Stack.ss_sp := Self_ID.Common.Task_Alternate_Stack;
+ Stack.ss_size := Alternate_Stack_Size;
+ Stack.ss_flags := 0;
+ Result := sigaltstack (Stack'Access, null);
+ pragma Assert (Result = 0);
+ end;
+ end if;
+ end Enter_Task;
+
+ -------------------
+ -- Is_Valid_Task --
+ -------------------
+
+ function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
+
+ -----------------------------
+ -- Register_Foreign_Thread --
+ -----------------------------
+
+ function Register_Foreign_Thread return Task_Id is
+ begin
+ if Is_Valid_Task then
+ return Self;
+ else
+ return Register_Foreign_Thread (pthread_self);
+ end if;
+ end Register_Foreign_Thread;
+
+ --------------------
+ -- Initialize_TCB --
+ --------------------
+
+ procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
+ Mutex_Attr : aliased pthread_mutexattr_t;
+ Result : Interfaces.C.int;
+ Cond_Attr : aliased pthread_condattr_t;
+
+ begin
+ -- Give the task a unique serial number
+
+ Self_ID.Serial_Number := Next_Serial_Number;
+ Next_Serial_Number := Next_Serial_Number + 1;
+ pragma Assert (Next_Serial_Number /= 0);
+
+ Result := pthread_mutexattr_init (Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = 0 then
+ if Locking_Policy = 'C' then
+ Result :=
+ pthread_mutexattr_setprotocol
+ (Mutex_Attr'Access,
+ PTHREAD_PRIO_PROTECT);
+ pragma Assert (Result = 0);
+
+ Result :=
+ pthread_mutexattr_setprioceiling
+ (Mutex_Attr'Access,
+ Interfaces.C.int (System.Any_Priority'Last));
+ pragma Assert (Result = 0);
+
+ elsif Locking_Policy = 'I' then
+ Result :=
+ pthread_mutexattr_setprotocol
+ (Mutex_Attr'Access,
+ PTHREAD_PRIO_INHERIT);
+ pragma Assert (Result = 0);
+ end if;
+
+ Result :=
+ pthread_mutex_init
+ (Self_ID.Common.LL.L'Access,
+ Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+ end if;
+
+ if Result /= 0 then
+ Succeeded := False;
+ return;
+ end if;
+
+ Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
+ pragma Assert (Result = 0);
+
+ Result := pthread_condattr_init (Cond_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = 0 then
+ Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+
+ Result :=
+ pthread_cond_init
+ (Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+ end if;
+
+ if Result = 0 then
+ Succeeded := True;
+ else
+ Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+ Succeeded := False;
+ end if;
+
+ Result := pthread_condattr_destroy (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+ end Initialize_TCB;
+
+ -----------------
+ -- Create_Task --
+ -----------------
+
+ procedure Create_Task
+ (T : Task_Id;
+ Wrapper : System.Address;
+ Stack_Size : System.Parameters.Size_Type;
+ Priority : System.Any_Priority;
+ Succeeded : out Boolean)
+ is
+ Attributes : aliased pthread_attr_t;
+ Adjusted_Stack_Size : Interfaces.C.size_t;
+ Page_Size : constant Interfaces.C.size_t :=
+ Interfaces.C.size_t (Get_Page_Size);
+ Result : Interfaces.C.int;
+
+ function Thread_Body_Access is new
+ Ada.Unchecked_Conversion (System.Address, Thread_Body);
+
+ use System.Task_Info;
+
+ begin
+ Adjusted_Stack_Size :=
+ Interfaces.C.size_t (Stack_Size + Alternate_Stack_Size);
+
+ if Stack_Base_Available then
+
+ -- If Stack Checking is supported then allocate 2 additional pages:
+
+ -- In the worst case, stack is allocated at something like
+ -- N * Get_Page_Size - epsilon, we need to add the size for 2 pages
+ -- to be sure the effective stack size is greater than what
+ -- has been asked.
+
+ Adjusted_Stack_Size := Adjusted_Stack_Size + 2 * Page_Size;
+ end if;
+
+ -- Round stack size as this is required by some OSes (Darwin)
+
+ Adjusted_Stack_Size := Adjusted_Stack_Size + Page_Size - 1;
+ Adjusted_Stack_Size :=
+ Adjusted_Stack_Size - Adjusted_Stack_Size mod Page_Size;
+
+ Result := pthread_attr_init (Attributes'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result /= 0 then
+ Succeeded := False;
+ return;
+ end if;
+
+ Result :=
+ pthread_attr_setdetachstate
+ (Attributes'Access, PTHREAD_CREATE_DETACHED);
+ pragma Assert (Result = 0);
+
+ Result :=
+ pthread_attr_setstacksize
+ (Attributes'Access, Adjusted_Stack_Size);
+ pragma Assert (Result = 0);
+
+ if T.Common.Task_Info /= Default_Scope then
+ case T.Common.Task_Info is
+ when System.Task_Info.Process_Scope =>
+ Result :=
+ pthread_attr_setscope
+ (Attributes'Access, PTHREAD_SCOPE_PROCESS);
+
+ when System.Task_Info.System_Scope =>
+ Result :=
+ pthread_attr_setscope
+ (Attributes'Access, PTHREAD_SCOPE_SYSTEM);
+
+ when System.Task_Info.Default_Scope =>
+ Result := 0;
+ end case;
+
+ pragma Assert (Result = 0);
+ end if;
+
+ -- Since the initial signal mask of a thread is inherited from the
+ -- creator, and the Environment task has all its signals masked, we
+ -- do not need to manipulate caller's signal mask at this point.
+ -- All tasks in RTS will have All_Tasks_Mask initially.
+
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
+ Result := pthread_create
+ (T.Common.LL.Thread'Unrestricted_Access,
+ Attributes'Access,
+ Thread_Body_Access (Wrapper),
+ To_Address (T));
+ pragma Assert (Result = 0 or else Result = EAGAIN);
+
+ Succeeded := Result = 0;
+
+ Result := pthread_attr_destroy (Attributes'Access);
+ pragma Assert (Result = 0);
+
+ if Succeeded then
+ Set_Priority (T, Priority);
+ end if;
+ end Create_Task;
+
+ ------------------
+ -- Finalize_TCB --
+ ------------------
+
+ procedure Finalize_TCB (T : Task_Id) is
+ Result : Interfaces.C.int;
+
+ begin
+ Result := pthread_mutex_destroy (T.Common.LL.L'Access);
+ pragma Assert (Result = 0);
+
+ Result := pthread_cond_destroy (T.Common.LL.CV'Access);
+ pragma Assert (Result = 0);
+
+ if T.Known_Tasks_Index /= -1 then
+ Known_Tasks (T.Known_Tasks_Index) := null;
+ end if;
+
+ ATCB_Allocation.Free_ATCB (T);
+ end Finalize_TCB;
+
+ ---------------
+ -- Exit_Task --
+ ---------------
+
+ procedure Exit_Task is
+ begin
+ -- Mark this task as unknown, so that if Self is called, it won't
+ -- return a dangling pointer.
+
+ Specific.Set (null);
+ end Exit_Task;
+
+ ----------------
+ -- Abort_Task --
+ ----------------
+
+ procedure Abort_Task (T : Task_Id) is
+ Result : Interfaces.C.int;
+ begin
+ if Abort_Handler_Installed then
+ Result :=
+ pthread_kill
+ (T.Common.LL.Thread,
+ Signal (System.Interrupt_Management.Abort_Task_Interrupt));
+ pragma Assert (Result = 0);
+ end if;
+ end Abort_Task;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (S : in out Suspension_Object) is
+ Mutex_Attr : aliased pthread_mutexattr_t;
+ Cond_Attr : aliased pthread_condattr_t;
+ Result : Interfaces.C.int;
+
+ begin
+ -- Initialize internal state (always to False (RM D.10 (6)))
+
+ S.State := False;
+ S.Waiting := False;
+
+ -- Initialize internal mutex
+
+ Result := pthread_mutexattr_init (Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ raise Storage_Error;
+ end if;
+
+ Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result = ENOMEM then
+ Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
+ pragma Assert (Result = 0);
+
+ raise Storage_Error;
+ end if;
+
+ Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
+ pragma Assert (Result = 0);
+
+ -- Initialize internal condition variable
+
+ Result := pthread_condattr_init (Cond_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result /= 0 then
+ Result := pthread_mutex_destroy (S.L'Access);
+ pragma Assert (Result = 0);
+
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
+
+ else
+ Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+ end if;
+
+ Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
+ pragma Assert (Result = 0 or else Result = ENOMEM);
+
+ if Result /= 0 then
+ Result := pthread_mutex_destroy (S.L'Access);
+ pragma Assert (Result = 0);
+
+ Result := pthread_condattr_destroy (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
+ end if;
+
+ Result := pthread_condattr_destroy (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+ end Initialize;
+
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (S : in out Suspension_Object) is
+ Result : Interfaces.C.int;
+
+ begin
+ -- Destroy internal mutex
+
+ Result := pthread_mutex_destroy (S.L'Access);
+ pragma Assert (Result = 0);
+
+ -- Destroy internal condition variable
+
+ Result := pthread_cond_destroy (S.CV'Access);
+ pragma Assert (Result = 0);
+ end Finalize;
+
+ -------------------
+ -- Current_State --
+ -------------------
+
+ function Current_State (S : Suspension_Object) return Boolean is
+ begin
+ -- We do not want to use lock on this read operation. State is marked
+ -- as Atomic so that we ensure that the value retrieved is correct.
+
+ return S.State;
+ end Current_State;
+
+ ---------------
+ -- Set_False --
+ ---------------
+
+ procedure Set_False (S : in out Suspension_Object) is
+ Result : Interfaces.C.int;
+
+ begin
+ SSL.Abort_Defer.all;
+
+ Result := pthread_mutex_lock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ S.State := False;
+
+ Result := pthread_mutex_unlock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ SSL.Abort_Undefer.all;
+ end Set_False;
+
+ --------------
+ -- Set_True --
+ --------------
+
+ procedure Set_True (S : in out Suspension_Object) is
+ Result : Interfaces.C.int;
+
+ begin
+ SSL.Abort_Defer.all;
+
+ Result := pthread_mutex_lock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ -- If there is already a task waiting on this suspension object then
+ -- we resume it, leaving the state of the suspension object to False,
+ -- as it is specified in (RM D.10(9)). Otherwise, it just leaves
+ -- the state to True.
+
+ if S.Waiting then
+ S.Waiting := False;
+ S.State := False;
+
+ Result := pthread_cond_signal (S.CV'Access);
+ pragma Assert (Result = 0);
+
+ else
+ S.State := True;
+ end if;
+
+ Result := pthread_mutex_unlock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ SSL.Abort_Undefer.all;
+ end Set_True;
+
+ ------------------------
+ -- Suspend_Until_True --
+ ------------------------
+
+ procedure Suspend_Until_True (S : in out Suspension_Object) is
+ Result : Interfaces.C.int;
+
+ begin
+ SSL.Abort_Defer.all;
+
+ Result := pthread_mutex_lock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ if S.Waiting then
+
+ -- Program_Error must be raised upon calling Suspend_Until_True
+ -- if another task is already waiting on that suspension object
+ -- (RM D.10(10)).
+
+ Result := pthread_mutex_unlock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ SSL.Abort_Undefer.all;
+
+ raise Program_Error;
+
+ else
+ -- Suspend the task if the state is False. Otherwise, the task
+ -- continues its execution, and the state of the suspension object
+ -- is set to False (ARM D.10 par. 9).
+
+ if S.State then
+ S.State := False;
+ else
+ S.Waiting := True;
+
+ loop
+ -- Loop in case pthread_cond_wait returns earlier than expected
+ -- (e.g. in case of EINTR caused by a signal).
+
+ Result := pthread_cond_wait (S.CV'Access, S.L'Access);
+ pragma Assert (Result = 0 or else Result = EINTR);
+
+ exit when not S.Waiting;
+ end loop;
+ end if;
+
+ Result := pthread_mutex_unlock (S.L'Access);
+ pragma Assert (Result = 0);
+
+ SSL.Abort_Undefer.all;
+ end if;
+ end Suspend_Until_True;
+
+ ----------------
+ -- Check_Exit --
+ ----------------
+
+ -- Dummy version
+
+ function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
+ pragma Unreferenced (Self_ID);
+ begin
+ return True;
+ end Check_Exit;
+
+ --------------------
+ -- Check_No_Locks --
+ --------------------
+
+ function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
+ pragma Unreferenced (Self_ID);
+ begin
+ return True;
+ end Check_No_Locks;
+
+ ----------------------
+ -- Environment_Task --
+ ----------------------
+
+ function Environment_Task return Task_Id is
+ begin
+ return Environment_Task_Id;
+ end Environment_Task;
+
+ --------------
+ -- Lock_RTS --
+ --------------
+
+ procedure Lock_RTS is
+ begin
+ Write_Lock (Single_RTS_Lock'Access);
+ end Lock_RTS;
+
+ ----------------
+ -- Unlock_RTS --
+ ----------------
+
+ procedure Unlock_RTS is
+ begin
+ Unlock (Single_RTS_Lock'Access);
+ end Unlock_RTS;
+
+ ------------------
+ -- Suspend_Task --
+ ------------------
+
+ function Suspend_Task
+ (T : ST.Task_Id;
+ Thread_Self : Thread_Id) return Boolean
+ is
+ pragma Unreferenced (T, Thread_Self);
+ begin
+ return False;
+ end Suspend_Task;
+
+ -----------------
+ -- Resume_Task --
+ -----------------
+
+ function Resume_Task
+ (T : ST.Task_Id;
+ Thread_Self : Thread_Id) return Boolean
+ is
+ pragma Unreferenced (T, Thread_Self);
+ begin
+ return False;
+ end Resume_Task;
+
+ --------------------
+ -- Stop_All_Tasks --
+ --------------------
+
+ procedure Stop_All_Tasks is
+ begin
+ null;
+ end Stop_All_Tasks;
+
+ ---------------
+ -- Stop_Task --
+ ---------------
+
+ function Stop_Task (T : ST.Task_Id) return Boolean is
+ pragma Unreferenced (T);
+ begin
+ return False;
+ end Stop_Task;
+
+ -------------------
+ -- Continue_Task --
+ -------------------
+
+ function Continue_Task (T : ST.Task_Id) return Boolean is
+ pragma Unreferenced (T);
+ begin
+ return False;
+ end Continue_Task;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (Environment_Task : Task_Id) is
+ act : aliased struct_sigaction;
+ old_act : aliased struct_sigaction;
+ Tmp_Set : aliased sigset_t;
+ Result : Interfaces.C.int;
+
+ function State
+ (Int : System.Interrupt_Management.Interrupt_ID) return Character;
+ pragma Import (C, State, "__gnat_get_interrupt_state");
+ -- Get interrupt state. Defined in a-init.c
+ -- The input argument is the interrupt number,
+ -- and the result is one of the following:
+
+ Default : constant Character := 's';
+ -- 'n' this interrupt not set by any Interrupt_State pragma
+ -- 'u' Interrupt_State pragma set state to User
+ -- 'r' Interrupt_State pragma set state to Runtime
+ -- 's' Interrupt_State pragma set state to System (use "default"
+ -- system handler)
+
+ begin
+ Environment_Task_Id := Environment_Task;
+
+ Interrupt_Management.Initialize;
+
+ -- Initialize the lock used to synchronize chain of all ATCBs
+
+ Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
+
+ Specific.Initialize (Environment_Task);
+
+ if Use_Alternate_Stack then
+ Environment_Task.Common.Task_Alternate_Stack :=
+ Alternate_Stack'Address;
+ end if;
+
+ -- Make environment task known here because it doesn't go through
+ -- Activate_Tasks, which does it for all other tasks.
+
+ Known_Tasks (Known_Tasks'First) := Environment_Task;
+ Environment_Task.Known_Tasks_Index := Known_Tasks'First;
+
+ Enter_Task (Environment_Task);
+
+ if State
+ (System.Interrupt_Management.Abort_Task_Interrupt) /= Default
+ then
+ act.sa_flags := 0;
+ act.sa_handler := Abort_Handler'Address;
+
+ Result := sigemptyset (Tmp_Set'Access);
+ pragma Assert (Result = 0);
+ act.sa_mask := Tmp_Set;
+
+ Result :=
+ sigaction
+ (Signal (System.Interrupt_Management.Abort_Task_Interrupt),
+ act'Unchecked_Access,
+ old_act'Unchecked_Access);
+ pragma Assert (Result = 0);
+ Abort_Handler_Installed := True;
+ end if;
+ end Initialize;
+
+ -----------------------
+ -- Set_Task_Affinity --
+ -----------------------
+
+ procedure Set_Task_Affinity (T : ST.Task_Id) is
+ pragma Unreferenced (T);
+
+ begin
+ -- Setting task affinity is not supported by the underlying system
+
+ null;
+ end Set_Task_Affinity;
+
+end System.Task_Primitives.Operations;
diff --git a/gcc/ada/libgnarl/s-taprop__solaris.adb b/gcc/ada/libgnarl/s-taprop__solaris.adb
index 4c449b6..faaaeea 100644
--- a/gcc/ada/libgnarl/s-taprop__solaris.adb
+++ b/gcc/ada/libgnarl/s-taprop__solaris.adb
@@ -128,13 +128,13 @@ package body System.Task_Primitives.Operations is
-- External Configuration Values --
-----------------------------------
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
diff --git a/gcc/ada/libgnarl/s-taprop__vxworks.adb b/gcc/ada/libgnarl/s-taprop__vxworks.adb
index a87d1a0..ff21410 100644
--- a/gcc/ada/libgnarl/s-taprop__vxworks.adb
+++ b/gcc/ada/libgnarl/s-taprop__vxworks.adb
@@ -62,12 +62,17 @@ package body System.Task_Primitives.Operations is
use System.Tasking;
use System.OS_Interface;
use System.Parameters;
- use type System.VxWorks.Ext.t_id;
use type Interfaces.C.int;
use type System.OS_Interface.unsigned;
+ use type System.VxWorks.Ext.t_id;
+ use type System.VxWorks.Ext.STATUS;
+ use type System.VxWorks.Ext.BOOL;
- subtype int is System.OS_Interface.int;
+ subtype int is System.OS_Interface.int;
subtype unsigned is System.OS_Interface.unsigned;
+ subtype STATUS is System.VxWorks.Ext.STATUS;
+
+ OK : constant STATUS := System.VxWorks.Ext.OK;
Relative : constant := 0;
@@ -83,13 +88,13 @@ package body System.Task_Primitives.Operations is
-- The followings are internal configuration constants needed
- Dispatching_Policy : Character;
+ Dispatching_Policy : constant Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
-- Used to identified fake tasks (i.e., non-Ada Threads)
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
Mutex_Protocol : Priority_Type;
@@ -99,7 +104,7 @@ package body System.Task_Primitives.Operations is
-- time; it is used to execute in mutual exclusion from all other tasks.
-- Used to protect All_Tasks_List
- Time_Slice_Val : Integer;
+ Time_Slice_Val : constant Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
Null_Thread_Id : constant Thread_Id := 0;
@@ -333,17 +338,17 @@ package body System.Task_Primitives.Operations is
-------------------
procedure Finalize_Lock (L : not null access Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Finalize_Lock;
procedure Finalize_Lock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Finalize_Lock;
----------------
@@ -354,7 +359,7 @@ package body System.Task_Primitives.Operations is
(L : not null access Lock;
Ceiling_Violation : out Boolean)
is
- Result : int;
+ Result : STATUS;
begin
if L.Protocol = Prio_Protect
@@ -367,21 +372,21 @@ package body System.Task_Primitives.Operations is
end if;
Result := semTake (L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
procedure Write_Lock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semTake (L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
procedure Write_Lock (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semTake (T.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Write_Lock;
---------------
@@ -400,24 +405,24 @@ package body System.Task_Primitives.Operations is
------------
procedure Unlock (L : not null access Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
procedure Unlock (L : not null access RTS_Lock) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
procedure Unlock (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semGive (T.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Unlock;
-----------------
@@ -442,7 +447,7 @@ package body System.Task_Primitives.Operations is
procedure Sleep (Self_ID : Task_Id; Reason : System.Tasking.Task_States) is
pragma Unreferenced (Reason);
- Result : int;
+ Result : STATUS;
begin
pragma Assert (Self_ID = Self);
@@ -450,7 +455,7 @@ package body System.Task_Primitives.Operations is
-- Release the mutex before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Perform a blocking operation to take the CV semaphore. Note that a
-- blocking operation in VxWorks will reenable task scheduling. When we
@@ -458,12 +463,12 @@ package body System.Task_Primitives.Operations is
-- again be disabled.
Result := semTake (Self_ID.Common.LL.CV, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Take the mutex back
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Sleep;
-----------------
@@ -486,7 +491,7 @@ package body System.Task_Primitives.Operations is
Orig : constant Duration := Monotonic_Clock;
Absolute : Duration;
Ticks : int;
- Result : int;
+ Result : STATUS;
Wakeup : Boolean := False;
begin
@@ -516,7 +521,7 @@ package body System.Task_Primitives.Operations is
-- Release the mutex before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Perform a blocking operation to take the CV semaphore. Note
-- that a blocking operation in VxWorks will reenable task
@@ -525,7 +530,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.CV, Ticks);
- if Result = 0 then
+ if Result = OK then
-- Somebody may have called Wakeup for us
@@ -556,7 +561,7 @@ package body System.Task_Primitives.Operations is
-- Take the mutex back
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Timedout or Wakeup;
end loop;
@@ -590,7 +595,7 @@ package body System.Task_Primitives.Operations is
Timedout : Boolean;
Aborted : Boolean := False;
- Result : int;
+ Result : STATUS;
pragma Warnings (Off, Result);
begin
@@ -617,7 +622,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
Self_ID.Common.State := Delay_Sleep;
Timedout := False;
@@ -628,13 +633,13 @@ package body System.Task_Primitives.Operations is
-- Release the TCB before sleeping
Result := semGive (Self_ID.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Aborted;
Result := semTake (Self_ID.Common.LL.CV, Ticks);
- if Result /= 0 then
+ if Result /= OK then
-- If Ticks = int'last, it was most probably truncated, so make
-- another round after recomputing Ticks from absolute time.
@@ -655,7 +660,7 @@ package body System.Task_Primitives.Operations is
Result := semTake (Self_ID.Common.LL.L.Mutex, WAIT_FOREVER);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
exit when Timedout;
end loop;
@@ -697,10 +702,10 @@ package body System.Task_Primitives.Operations is
procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
pragma Unreferenced (Reason);
- Result : int;
+ Result : STATUS;
begin
Result := semGive (T.Common.LL.CV);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
end Wakeup;
-----------
@@ -709,7 +714,7 @@ package body System.Task_Primitives.Operations is
procedure Yield (Do_Yield : Boolean := True) is
pragma Unreferenced (Do_Yield);
- Result : int;
+ Result : STATUS;
pragma Unreferenced (Result);
begin
Result := taskDelay (0);
@@ -726,13 +731,13 @@ package body System.Task_Primitives.Operations is
is
pragma Unreferenced (Loss_Of_Inheritance);
- Result : int;
+ Result : STATUS;
begin
Result :=
taskPrioritySet
(T.Common.LL.Thread, To_VxWorks_Priority (int (Prio)));
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
-- Note: in VxWorks 6.6 (or earlier), the task is placed at the end of
-- the priority queue instead of the head. This is not the behavior
@@ -938,16 +943,16 @@ package body System.Task_Primitives.Operations is
------------------
procedure Finalize_TCB (T : Task_Id) is
- Result : int;
+ Result : STATUS;
begin
Result := semDelete (T.Common.LL.L.Mutex);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
T.Common.LL.Thread := Null_Thread_Id;
Result := semDelete (T.Common.LL.CV);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
if T.Known_Tasks_Index /= -1 then
Known_Tasks (T.Known_Tasks_Index) := null;
@@ -1137,7 +1142,7 @@ package body System.Task_Primitives.Operations is
S.State := False;
Result := semGive (S.L);
- pragma Assert (Result = 0);
+ pragma Assert (Result = OK);
SSL.Abort_Undefer.all;
@@ -1218,7 +1223,7 @@ package body System.Task_Primitives.Operations is
if T.Common.LL.Thread /= Null_Thread_Id
and then T.Common.LL.Thread /= Thread_Self
then
- return taskSuspend (T.Common.LL.Thread) = 0;
+ return taskSuspend (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1236,7 +1241,7 @@ package body System.Task_Primitives.Operations is
if T.Common.LL.Thread /= Null_Thread_Id
and then T.Common.LL.Thread /= Thread_Self
then
- return taskResume (T.Common.LL.Thread) = 0;
+ return taskResume (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1251,7 +1256,7 @@ package body System.Task_Primitives.Operations is
Thread_Self : constant Thread_Id := taskIdSelf;
C : Task_Id;
- Dummy : int;
+ Dummy : STATUS;
Old : int;
begin
@@ -1268,7 +1273,7 @@ package body System.Task_Primitives.Operations is
C := C.Common.All_Tasks_Link;
end loop;
- Dummy := Int_Unlock (Old);
+ Int_Unlock (Old);
end Stop_All_Tasks;
---------------
@@ -1278,7 +1283,7 @@ package body System.Task_Primitives.Operations is
function Stop_Task (T : ST.Task_Id) return Boolean is
begin
if T.Common.LL.Thread /= Null_Thread_Id then
- return Task_Stop (T.Common.LL.Thread) = 0;
+ return Task_Stop (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1292,7 +1297,7 @@ package body System.Task_Primitives.Operations is
is
begin
if T.Common.LL.Thread /= Null_Thread_Id then
- return Task_Cont (T.Common.LL.Thread) = 0;
+ return Task_Cont (T.Common.LL.Thread) = OK;
else
return True;
end if;
@@ -1304,7 +1309,7 @@ package body System.Task_Primitives.Operations is
function Is_Task_Context return Boolean is
begin
- return System.OS_Interface.Interrupt_Context /= 1;
+ return OSI.Interrupt_Context = 0;
end Is_Task_Context;
----------------
@@ -1312,7 +1317,7 @@ package body System.Task_Primitives.Operations is
----------------
procedure Initialize (Environment_Task : Task_Id) is
- Result : int;
+ Result : STATUS;
pragma Unreferenced (Result);
begin
diff --git a/gcc/ada/libgnarl/s-taskin.adb b/gcc/ada/libgnarl/s-taskin.adb
index 0090964..ab50af1 100644
--- a/gcc/ada/libgnarl/s-taskin.adb
+++ b/gcc/ada/libgnarl/s-taskin.adb
@@ -173,13 +173,13 @@ package body System.Tasking is
Main_Task_Image : constant String := "main_task";
-- Image of environment task
- Main_Priority : Integer;
+ Main_Priority : constant Integer;
pragma Import (C, Main_Priority, "__gl_main_priority");
-- Priority for main task. Note that this is of type Integer, not Priority,
-- because we use the value -1 to indicate the default main priority, and
-- that is of course not in Priority'range.
- Main_CPU : Integer;
+ Main_CPU : constant Integer;
pragma Import (C, Main_CPU, "__gl_main_cpu");
-- Affinity for main task. Note that this is of type Integer, not
-- CPU_Range, because we use the value -1 to indicate the unassigned
diff --git a/gcc/ada/libgnarl/s-taskin.ads b/gcc/ada/libgnarl/s-taskin.ads
index 5c03829..cf560b5 100644
--- a/gcc/ada/libgnarl/s-taskin.ads
+++ b/gcc/ada/libgnarl/s-taskin.ads
@@ -368,14 +368,6 @@ package System.Tasking is
-- Used to represent protected procedures to be executed when task
-- terminates.
- type Initialization_Handler is access procedure;
- pragma Favor_Top_Level (Initialization_Handler);
- -- Use to represent procedures to be executed at task initialization.
-
- Global_Initialization_Handler : Initialization_Handler := null;
- pragma Atomic (Global_Initialization_Handler);
- -- Global handler called when each task initializes.
-
------------------------------------
-- Dispatching domain definitions --
------------------------------------
diff --git a/gcc/ada/libgnarl/s-tasque.adb b/gcc/ada/libgnarl/s-tasque.adb
index 28f033a..79382c4 100644
--- a/gcc/ada/libgnarl/s-tasque.adb
+++ b/gcc/ada/libgnarl/s-tasque.adb
@@ -44,7 +44,7 @@ package body System.Tasking.Queuing is
-- Entry Queues implemented as doubly linked list
- Queuing_Policy : Character;
+ Queuing_Policy : constant Character;
pragma Import (C, Queuing_Policy, "__gl_queuing_policy");
Priority_Queuing : constant Boolean := Queuing_Policy = 'P';
diff --git a/gcc/ada/libgnarl/s-tassta.adb b/gcc/ada/libgnarl/s-tassta.adb
index 88850c2..bbc7d14 100644
--- a/gcc/ada/libgnarl/s-tassta.adb
+++ b/gcc/ada/libgnarl/s-tassta.adb
@@ -35,6 +35,7 @@ pragma Partition_Elaboration_Policy (Concurrent);
with Ada.Exceptions;
with Ada.Unchecked_Deallocation;
+with Ada.Task_Initialization;
with System.Interrupt_Management;
with System.Tasking.Debug;
@@ -1177,6 +1178,14 @@ package body System.Tasking.Stages is
Debug.Signal_Debug_Event (Debug.Debug_Event_Run, Self_ID);
end if;
+ declare
+ use Ada.Task_Initialization;
+
+ Global_Initialization_Handler : Initialization_Handler;
+ pragma Atomic (Global_Initialization_Handler);
+ pragma Import (Ada, Global_Initialization_Handler,
+ "__gnat_global_initialization_handler");
+
begin
-- We are separating the following portion of the code in order to
-- place the exception handlers in a different block. In this way,
diff --git a/gcc/ada/libgnarl/s-tpoben.adb b/gcc/ada/libgnarl/s-tpoben.adb
index 896ee0c..0cb3677 100644
--- a/gcc/ada/libgnarl/s-tpoben.adb
+++ b/gcc/ada/libgnarl/s-tpoben.adb
@@ -58,7 +58,7 @@ package body System.Tasking.Protected_Objects.Entries is
-- Local Data --
----------------
- Locking_Policy : Character;
+ Locking_Policy : constant Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
--------------
diff --git a/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb b/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
index e5d4089..1343f6b 100644
--- a/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
+++ b/gcc/ada/libgnarl/s-tpopsp__vxworks-rtp.adb
@@ -35,6 +35,8 @@
separate (System.Task_Primitives.Operations)
package body Specific is
+ ERROR : constant STATUS := System.VxWorks.Ext.ERROR;
+
ATCB_Key : int := 0;
-- Key used to find the Ada Task_Id associated with a thread
@@ -43,9 +45,10 @@ package body Specific is
----------------
procedure Initialize is
+ IERR : constant := -1;
begin
ATCB_Key := tlsKeyCreate;
- pragma Assert (ATCB_Key /= ERROR);
+ pragma Assert (ATCB_Key /= IERR);
end Initialize;
-------------------
diff --git a/gcc/ada/libgnarl/s-tpopsp__vxworks.adb b/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
index 2d7cf00..9dc5d8b 100644
--- a/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
+++ b/gcc/ada/libgnarl/s-tpopsp__vxworks.adb
@@ -35,6 +35,8 @@
separate (System.Task_Primitives.Operations)
package body Specific is
+ ERROR : constant STATUS := System.VxWorks.Ext.ERROR;
+
ATCB_Key : aliased System.Address := System.Null_Address;
-- Key used to find the Ada Task_Id associated with a thread
@@ -70,8 +72,9 @@ package body Specific is
-------------------
function Is_Valid_Task return Boolean is
+ IERR : constant := -1;
begin
- return taskVarGet (taskIdSelf, ATCB_Key'Access) /= ERROR;
+ return taskVarGet (taskIdSelf, ATCB_Key'Access) /= IERR;
end Is_Valid_Task;
---------
diff --git a/gcc/ada/libgnarl/s-vxwext.adb b/gcc/ada/libgnarl/s-vxwext.adb
index 0e1a792..d50d93d 100644
--- a/gcc/ada/libgnarl/s-vxwext.adb
+++ b/gcc/ada/libgnarl/s-vxwext.adb
@@ -30,7 +30,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
------------------------
-- taskCpuAffinitySet --
@@ -39,7 +39,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -49,7 +49,7 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnarl/s-vxwext.ads b/gcc/ada/libgnarl/s-vxwext.ads
index 915db33..ab73415 100644
--- a/gcc/ada/libgnarl/s-vxwext.ads
+++ b/gcc/ada/libgnarl/s-vxwext.ads
@@ -46,6 +46,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -54,7 +66,7 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Import (C, Int_Lock, "intLock");
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Import (C, Int_Unlock, "intUnlock");
function Interrupt_Connect
@@ -63,7 +75,7 @@ package System.VxWorks.Ext is
Parameter : System.Address := System.Null_Address) return int;
pragma Import (C, Interrupt_Connect, "intConnect");
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Import (C, Interrupt_Context, "intContext");
function Interrupt_Number_To_Vector
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb b/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
index ea1f71c..b78e078 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__kernel-smp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,25 +41,25 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
---------------
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function Os_Sem_Delete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function Os_Sem_Delete (Sem : SEM_ID) return STATUS;
pragma Import (C, Os_Sem_Delete, "semDelete");
begin
return Os_Sem_Delete (Sem);
@@ -92,8 +92,8 @@ package body System.VxWorks.Ext is
-- Task_Cont --
---------------
- function Task_Cont (tid : t_id) return int is
- function taskCont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS is
+ function taskCont (tid : t_id) return STATUS;
pragma Import (C, taskCont, "taskCont");
begin
return taskCont (tid);
@@ -103,8 +103,8 @@ package body System.VxWorks.Ext is
-- Task_Stop --
---------------
- function Task_Stop (tid : t_id) return int is
- function taskStop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS is
+ function taskStop (tid : t_id) return STATUS;
pragma Import (C, taskStop, "taskStop");
begin
return taskStop (tid);
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel.adb b/gcc/ada/libgnarl/s-vxwext__kernel.adb
index 4743540..2f00059 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel.adb
+++ b/gcc/ada/libgnarl/s-vxwext__kernel.adb
@@ -34,7 +34,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -49,17 +49,17 @@ package body System.VxWorks.Ext is
-- Int_Unlock --
----------------
- function intUnlock (Old : int) return int;
+ procedure intUnlock (Old : int);
pragma Import (C, intUnlock, "intUnlock");
- function Int_Unlock (Old : int) return int renames intUnlock;
+ procedure Int_Unlock (Old : int) renames intUnlock;
---------------
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function Os_Sem_Delete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function Os_Sem_Delete (Sem : SEM_ID) return STATUS;
pragma Import (C, Os_Sem_Delete, "semDelete");
begin
return Os_Sem_Delete (Sem);
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -82,15 +82,15 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
---------------
-- Task_Cont --
---------------
- function Task_Cont (tid : t_id) return int is
- function taskCont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS is
+ function taskCont (tid : t_id) return STATUS;
pragma Import (C, taskCont, "taskCont");
begin
return taskCont (tid);
@@ -100,8 +100,8 @@ package body System.VxWorks.Ext is
-- Task_Stop --
---------------
- function Task_Stop (tid : t_id) return int is
- function taskStop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS is
+ function taskStop (tid : t_id) return STATUS;
pragma Import (C, taskStop, "taskStop");
begin
return taskStop (tid);
diff --git a/gcc/ada/libgnarl/s-vxwext__kernel.ads b/gcc/ada/libgnarl/s-vxwext__kernel.ads
index 3c200a1..7b299b9 100644
--- a/gcc/ada/libgnarl/s-vxwext__kernel.ads
+++ b/gcc/ada/libgnarl/s-vxwext__kernel.ads
@@ -45,6 +45,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -53,29 +65,29 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Convention (C, Int_Lock);
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Convention (C, Int_Unlock);
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Import (C, Interrupt_Connect, "intConnect");
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Import (C, Interrupt_Context, "intContext");
function Interrupt_Number_To_Vector
(intNum : int) return Interrupt_Vector;
pragma Import (C, Interrupt_Number_To_Vector, "__gnat_inum_to_ivec");
- function semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS;
pragma Convention (C, semDelete);
- function Task_Cont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS;
pragma Convention (C, Task_Cont);
- function Task_Stop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS;
pragma Convention (C, Task_Stop);
function kill (pid : t_id; sig : int) return int;
@@ -84,7 +96,7 @@ package System.VxWorks.Ext is
function getpid return t_id;
pragma Import (C, getpid, "taskIdSelf");
- function Set_Time_Slice (ticks : int) return int;
+ function Set_Time_Slice (ticks : int) return STATUS;
pragma Import (C, Set_Time_Slice, "kernelTimeSlice");
type UINT64 is mod 2 ** Long_Long_Integer'Size;
diff --git a/gcc/ada/libgnarl/s-vxwext__noints.adb b/gcc/ada/libgnarl/s-vxwext__noints.adb
deleted file mode 100644
index 421781f..0000000
--- a/gcc/ada/libgnarl/s-vxwext__noints.adb
+++ /dev/null
@@ -1,126 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
--- --
--- S Y S T E M . V X W O R K S . E X T --
--- --
--- B o d y --
--- --
--- Copyright (C) 2008-2021, 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/>. --
--- --
-------------------------------------------------------------------------------
-
--- This package provides vxworks specific support functions needed
--- by System.OS_Interface.
-
--- This is a version for VxWorks 5 based systems with no interrupts:
--- HI-Ravenscar for VxWorks 5, VxWorks 653 vThreads (not ravenscar-cert)
-
-package body System.VxWorks.Ext is
-
- ERROR : constant := -1;
-
- --------------
- -- Int_Lock --
- --------------
-
- function Int_Lock return int is
- begin
- return ERROR;
- end Int_Lock;
-
- ----------------
- -- Int_Unlock --
- ----------------
-
- function Int_Unlock (Old : int) return int is
- pragma Unreferenced (Old);
- begin
- return ERROR;
- end Int_Unlock;
-
- -----------------------
- -- Interrupt_Connect --
- -----------------------
-
- function Interrupt_Connect
- (Vector : Interrupt_Vector;
- Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int
- is
- pragma Unreferenced (Vector, Handler, Parameter);
- begin
- return ERROR;
- end Interrupt_Connect;
-
- -----------------------
- -- Interrupt_Context --
- -----------------------
-
- function Interrupt_Context return int is
- begin
- -- For VxWorks 653 vThreads, never in an interrupt context
-
- return 0;
- end Interrupt_Context;
-
- --------------------------------
- -- Interrupt_Number_To_Vector --
- --------------------------------
-
- function Interrupt_Number_To_Vector
- (intNum : int) return Interrupt_Vector
- is
- pragma Unreferenced (intNum);
- begin
- return 0;
- end Interrupt_Number_To_Vector;
-
- ---------------
- -- semDelete --
- ---------------
-
- function semDelete (Sem : SEM_ID) return int is
- function Os_Sem_Delete (Sem : SEM_ID) return int;
- pragma Import (C, Os_Sem_Delete, "semDelete");
- begin
- return Os_Sem_Delete (Sem);
- end semDelete;
-
- ------------------------
- -- taskCpuAffinitySet --
- ------------------------
-
- function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
- pragma Unreferenced (tid, CPU);
- begin
- return ERROR;
- end taskCpuAffinitySet;
-
- -------------------------
- -- taskMaskAffinitySet --
- -------------------------
-
- function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
- pragma Unreferenced (tid, CPU_Set);
- begin
- return ERROR;
- end taskMaskAffinitySet;
-
-end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb b/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
index 241a8f5..5bf6ae5 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__rtp-smp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,17 +41,17 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
-----------------------
@@ -61,7 +61,7 @@ package body System.VxWorks.Ext is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int
+ Parameter : System.Address := System.Null_Address) return STATUS
is
pragma Unreferenced (Vector, Handler, Parameter);
begin
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
-- For RTPs, never in an interrupt context
@@ -95,8 +95,8 @@ package body System.VxWorks.Ext is
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function OS_semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function OS_semDelete (Sem : SEM_ID) return STATUS;
pragma Import (C, OS_semDelete, "semDelete");
begin
return OS_semDelete (Sem);
@@ -106,7 +106,7 @@ package body System.VxWorks.Ext is
-- Set_Time_Slice --
--------------------
- function Set_Time_Slice (ticks : int) return int is
+ function Set_Time_Slice (ticks : int) return STATUS is
pragma Unreferenced (ticks);
begin
return ERROR;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp.adb b/gcc/ada/libgnarl/s-vxwext__rtp.adb
index f188ff8..543f152 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp.adb
+++ b/gcc/ada/libgnarl/s-vxwext__rtp.adb
@@ -33,7 +33,7 @@
package body System.VxWorks.Ext is
- ERROR : constant := -1;
+ IERR : constant := -1;
--------------
-- Int_Lock --
@@ -41,17 +41,17 @@ package body System.VxWorks.Ext is
function Int_Lock return int is
begin
- return ERROR;
+ return IERR;
end Int_Lock;
----------------
-- Int_Unlock --
----------------
- function Int_Unlock (Old : int) return int is
+ procedure Int_Unlock (Old : int) is
pragma Unreferenced (Old);
begin
- return ERROR;
+ null;
end Int_Unlock;
-----------------------
@@ -61,7 +61,7 @@ package body System.VxWorks.Ext is
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int
+ Parameter : System.Address := System.Null_Address) return STATUS
is
pragma Unreferenced (Vector, Handler, Parameter);
begin
@@ -72,7 +72,7 @@ package body System.VxWorks.Ext is
-- Interrupt_Context --
-----------------------
- function Interrupt_Context return int is
+ function Interrupt_Context return BOOL is
begin
-- For RTPs, never in an interrupt context
@@ -95,8 +95,8 @@ package body System.VxWorks.Ext is
-- semDelete --
---------------
- function semDelete (Sem : SEM_ID) return int is
- function OS_semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS is
+ function OS_semDelete (Sem : SEM_ID) return STATUS;
pragma Import (C, OS_semDelete, "semDelete");
begin
return OS_semDelete (Sem);
@@ -106,7 +106,7 @@ package body System.VxWorks.Ext is
-- Set_Time_Slice --
--------------------
- function Set_Time_Slice (ticks : int) return int is
+ function Set_Time_Slice (ticks : int) return STATUS is
pragma Unreferenced (ticks);
begin
return ERROR;
@@ -119,7 +119,7 @@ package body System.VxWorks.Ext is
function taskCpuAffinitySet (tid : t_id; CPU : int) return int is
pragma Unreferenced (tid, CPU);
begin
- return ERROR;
+ return IERR;
end taskCpuAffinitySet;
-------------------------
@@ -129,7 +129,7 @@ package body System.VxWorks.Ext is
function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int is
pragma Unreferenced (tid, CPU_Set);
begin
- return ERROR;
+ return IERR;
end taskMaskAffinitySet;
end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnarl/s-vxwext__rtp.ads b/gcc/ada/libgnarl/s-vxwext__rtp.ads
index d13344e..995d098 100644
--- a/gcc/ada/libgnarl/s-vxwext__rtp.ads
+++ b/gcc/ada/libgnarl/s-vxwext__rtp.ads
@@ -45,6 +45,18 @@ package System.VxWorks.Ext is
subtype int is Interfaces.C.int;
subtype unsigned is Interfaces.C.unsigned;
+ type STATUS is new int;
+ -- Equivalent of the C type STATUS
+
+ OK : constant STATUS := 0;
+ ERROR : constant STATUS := -1;
+
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
+ type vx_freq_t is new unsigned;
+ -- Equivalent of the C type _Vx_freq_t
+
type Interrupt_Handler is access procedure (parameter : System.Address);
pragma Convention (C, Interrupt_Handler);
@@ -53,29 +65,29 @@ package System.VxWorks.Ext is
function Int_Lock return int;
pragma Inline (Int_Lock);
- function Int_Unlock (Old : int) return int;
+ procedure Int_Unlock (Old : int);
pragma Inline (Int_Unlock);
function Interrupt_Connect
(Vector : Interrupt_Vector;
Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
+ Parameter : System.Address := System.Null_Address) return STATUS;
pragma Convention (C, Interrupt_Connect);
- function Interrupt_Context return int;
+ function Interrupt_Context return BOOL;
pragma Convention (C, Interrupt_Context);
function Interrupt_Number_To_Vector
(intNum : int) return Interrupt_Vector;
pragma Convention (C, Interrupt_Number_To_Vector);
- function semDelete (Sem : SEM_ID) return int;
+ function semDelete (Sem : SEM_ID) return STATUS;
pragma Convention (C, semDelete);
- function Task_Cont (tid : t_id) return int;
+ function Task_Cont (tid : t_id) return STATUS;
pragma Import (C, Task_Cont, "taskResume");
- function Task_Stop (tid : t_id) return int;
+ function Task_Stop (tid : t_id) return STATUS;
pragma Import (C, Task_Stop, "taskSuspend");
function kill (pid : t_id; sig : int) return int;
@@ -84,7 +96,7 @@ package System.VxWorks.Ext is
function getpid return t_id;
pragma Import (C, getpid, "getpid");
- function Set_Time_Slice (ticks : int) return int;
+ function Set_Time_Slice (ticks : int) return STATUS;
pragma Inline (Set_Time_Slice);
--------------------------------
diff --git a/gcc/ada/libgnarl/s-vxwext__vthreads.ads b/gcc/ada/libgnarl/s-vxwext__vthreads.ads
deleted file mode 100644
index e97561e..0000000
--- a/gcc/ada/libgnarl/s-vxwext__vthreads.ads
+++ /dev/null
@@ -1,109 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
--- --
--- S Y S T E M . V X W O R K S . E X T --
--- --
--- S p e c --
--- --
--- Copyright (C) 2008-2021, 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/>. --
--- --
-------------------------------------------------------------------------------
-
--- This package provides VxWorks specific support functions needed
--- by System.OS_Interface.
-
--- This is the VxWorks 653 vThreads version of this package
-
-with Interfaces.C;
-
-package System.VxWorks.Ext is
- pragma Preelaborate;
-
- subtype SEM_ID is Long_Integer;
- -- typedef struct semaphore *SEM_ID;
-
- type sigset_t is mod 2 ** Interfaces.C.long'Size;
-
- type t_id is new Long_Integer;
- subtype int is Interfaces.C.int;
- subtype unsigned is Interfaces.C.unsigned;
-
- type Interrupt_Handler is access procedure (parameter : System.Address);
- pragma Convention (C, Interrupt_Handler);
-
- type Interrupt_Vector is new System.Address;
- function Int_Lock return int;
- pragma Inline (Int_Lock);
-
- function Int_Unlock (Old : int) return int;
- pragma Inline (Int_Unlock);
-
- function Interrupt_Connect
- (Vector : Interrupt_Vector;
- Handler : Interrupt_Handler;
- Parameter : System.Address := System.Null_Address) return int;
- pragma Convention (C, Interrupt_Connect);
-
- function Interrupt_Context return int;
- pragma Convention (C, Interrupt_Context);
-
- function Interrupt_Number_To_Vector
- (intNum : int) return Interrupt_Vector;
- pragma Convention (C, Interrupt_Number_To_Vector);
-
- function semDelete (Sem : SEM_ID) return int;
- pragma Convention (C, semDelete);
-
- function Task_Cont (tid : t_id) return int;
- pragma Import (C, Task_Cont, "taskResume");
-
- function Task_Stop (tid : t_id) return int;
- pragma Import (C, Task_Stop, "taskSuspend");
-
- function kill (pid : t_id; sig : int) return int;
- pragma Import (C, kill, "kill");
-
- function getpid return t_id;
- pragma Import (C, getpid, "taskIdSelf");
-
- function Set_Time_Slice (ticks : int) return int;
- pragma Import (C, Set_Time_Slice, "kernelTimeSlice");
-
- type UINT64 is mod 2 ** Long_Long_Integer'Size;
-
- function tickGet return UINT64;
- -- "tickGet" not available for cert vThreads:
- pragma Import (C, tickGet, "tick64Get");
-
- --------------------------------
- -- Processor Affinity for SMP --
- --------------------------------
-
- function taskCpuAffinitySet (tid : t_id; CPU : int) return int;
- pragma Convention (C, taskCpuAffinitySet);
- -- For SMP run-times set the CPU affinity.
- -- For uniprocessor systems return ERROR status.
-
- function taskMaskAffinitySet (tid : t_id; CPU_Set : unsigned) return int;
- pragma Convention (C, taskMaskAffinitySet);
- -- For SMP run-times set the CPU mask affinity.
- -- For uniprocessor systems return ERROR status.
-
-end System.VxWorks.Ext;
diff --git a/gcc/ada/libgnat/a-calend.adb b/gcc/ada/libgnat/a-calend.adb
index 8295a7c..b24e95d 100644
--- a/gcc/ada/libgnat/a-calend.adb
+++ b/gcc/ada/libgnat/a-calend.adb
@@ -35,6 +35,8 @@ with Interfaces.C;
with System.OS_Primitives;
+with System.OS_Lib;
+
package body Ada.Calendar with
SPARK_Mode => Off
is
@@ -147,7 +149,7 @@ is
-- Leap seconds control --
--------------------------
- Flag : Integer;
+ Flag : constant Integer;
pragma Import (C, Flag, "__gl_leap_seconds_support");
-- This imported value is used to determine whether the compilation had
-- binder flag "-y" present which enables leap seconds. A value of zero
@@ -685,13 +687,10 @@ is
type int_Pointer is access all Interfaces.C.int;
type long_Pointer is access all Interfaces.C.long;
- type time_t is
- range -(2 ** (Standard'Address_Size - Integer'(1))) ..
- +(2 ** (Standard'Address_Size - Integer'(1)) - 1);
- type time_t_Pointer is access all time_t;
+ type OS_Time_Pointer is access all System.OS_Lib.OS_Time;
procedure localtime_tzoff
- (timer : time_t_Pointer;
+ (timer : OS_Time_Pointer;
is_historic : int_Pointer;
off : long_Pointer);
pragma Import (C, localtime_tzoff, "__gnat_localtime_tzoff");
@@ -708,7 +707,7 @@ is
Date_N : Time_Rep;
Flag : aliased Interfaces.C.int;
Offset : aliased Interfaces.C.long;
- Secs_T : aliased time_t;
+ Secs_T : aliased System.OS_Lib.OS_Time;
-- Start of processing for UTC_Time_Offset
@@ -745,7 +744,7 @@ is
-- Convert the date into seconds
- Secs_T := time_t (Date_N / Nano);
+ Secs_T := System.OS_Lib.To_Ada (Long_Long_Integer (Date_N / Nano));
-- Determine whether to treat the input date as historical or not. A
-- value of "0" signifies that the date is NOT historic.
diff --git a/gcc/ada/libgnat/a-cbdlli.adb b/gcc/ada/libgnat/a-cbdlli.adb
index 143805e..3752ca9 100644
--- a/gcc/ada/libgnat/a-cbdlli.adb
+++ b/gcc/ada/libgnat/a-cbdlli.adb
@@ -27,6 +27,8 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
+with Ada.Containers.Stable_Sorting; use Ada.Containers.Stable_Sorting;
+
with System; use type System.Address;
with System.Put_Images;
@@ -858,74 +860,6 @@ is
procedure Sort (Container : in out List) is
N : Node_Array renames Container.Nodes;
-
- procedure Partition (Pivot, Back : Count_Type);
- -- What does this do ???
-
- procedure Sort (Front, Back : Count_Type);
- -- Internal procedure, what does it do??? rename it???
-
- ---------------
- -- Partition --
- ---------------
-
- procedure Partition (Pivot, Back : Count_Type) is
- Node : Count_Type;
-
- begin
- Node := N (Pivot).Next;
- while Node /= Back loop
- if N (Node).Element < N (Pivot).Element then
- declare
- Prev : constant Count_Type := N (Node).Prev;
- Next : constant Count_Type := N (Node).Next;
-
- begin
- N (Prev).Next := Next;
-
- if Next = 0 then
- Container.Last := Prev;
- else
- N (Next).Prev := Prev;
- end if;
-
- N (Node).Next := Pivot;
- N (Node).Prev := N (Pivot).Prev;
-
- N (Pivot).Prev := Node;
-
- if N (Node).Prev = 0 then
- Container.First := Node;
- else
- N (N (Node).Prev).Next := Node;
- end if;
-
- Node := Next;
- end;
-
- else
- Node := N (Node).Next;
- end if;
- end loop;
- end Partition;
-
- ----------
- -- Sort --
- ----------
-
- procedure Sort (Front, Back : Count_Type) is
- Pivot : constant Count_Type :=
- (if Front = 0 then Container.First else N (Front).Next);
- begin
- if Pivot /= Back then
- Partition (Pivot, Back);
- Sort (Front, Pivot);
- Sort (Pivot, Back);
- end if;
- end Sort;
-
- -- Start of processing for Sort
-
begin
if Container.Length <= 1 then
return;
@@ -941,8 +875,43 @@ is
declare
Lock : With_Lock (Container.TC'Unchecked_Access);
+
+ package Descriptors is new List_Descriptors
+ (Node_Ref => Count_Type, Nil => 0);
+ use Descriptors;
+
+ function Next (Idx : Count_Type) return Count_Type is
+ (N (Idx).Next);
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type)
+ with Inline;
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type)
+ with Inline;
+ function "<" (L, R : Count_Type) return Boolean is
+ (N (L).Element < N (R).Element);
+ procedure Update_Container (List : List_Descriptor) with Inline;
+
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type) is
+ begin
+ N (Idx).Next := Next;
+ end Set_Next;
+
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type) is
+ begin
+ N (Idx).Prev := Prev;
+ end Set_Prev;
+
+ procedure Update_Container (List : List_Descriptor) is
+ begin
+ Container.First := List.First;
+ Container.Last := List.Last;
+ Container.Length := List.Length;
+ end Update_Container;
+
+ procedure Sort_List is new Doubly_Linked_List_Sort;
begin
- Sort (Front => 0, Back => 0);
+ Sort_List (List_Descriptor'(First => Container.First,
+ Last => Container.Last,
+ Length => Container.Length));
end;
pragma Assert (N (Container.First).Prev = 0);
diff --git a/gcc/ada/libgnat/a-cbdlli.ads b/gcc/ada/libgnat/a-cbdlli.ads
index ab55086..f4086ea 100644
--- a/gcc/ada/libgnat/a-cbdlli.ads
+++ b/gcc/ada/libgnat/a-cbdlli.ads
@@ -57,11 +57,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append);
- pragma Preelaborable_Initialization (List);
+ Add_Unnamed => Append),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_List : constant List;
diff --git a/gcc/ada/libgnat/a-cbhama.ads b/gcc/ada/libgnat/a-cbhama.ads
index 8be64c8..cdd4135 100644
--- a/gcc/ada/libgnat/a-cbhama.ads
+++ b/gcc/ada/libgnat/a-cbhama.ads
@@ -59,12 +59,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
-- Map objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbhase.ads b/gcc/ada/libgnat/a-cbhase.ads
index 92926c1..78b31cf 100644
--- a/gcc/ada/libgnat/a-cbhase.ads
+++ b/gcc/ada/libgnat/a-cbhase.ads
@@ -61,12 +61,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
-- Set objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbmutr.ads b/gcc/ada/libgnat/a-cbmutr.ads
index c7e221a..3712039 100644
--- a/gcc/ada/libgnat/a-cbmutr.ads
+++ b/gcc/ada/libgnat/a-cbmutr.ads
@@ -53,11 +53,11 @@ is
with Constant_Indexing => Constant_Reference,
Variable_Indexing => Reference,
Default_Iterator => Iterate,
- Iterator_Element => Element_Type;
- pragma Preelaborable_Initialization (Tree);
+ Iterator_Element => Element_Type,
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Tree : constant Tree;
diff --git a/gcc/ada/libgnat/a-cborma.ads b/gcc/ada/libgnat/a-cborma.ads
index f87522a..9d40a51 100644
--- a/gcc/ada/libgnat/a-cborma.ads
+++ b/gcc/ada/libgnat/a-cborma.ads
@@ -60,12 +60,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
diff --git a/gcc/ada/libgnat/a-cborse.ads b/gcc/ada/libgnat/a-cborse.ads
index 06bd20f..31b8b91 100644
--- a/gcc/ada/libgnat/a-cborse.ads
+++ b/gcc/ada/libgnat/a-cborse.ads
@@ -59,12 +59,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
diff --git a/gcc/ada/libgnat/a-cdlili.adb b/gcc/ada/libgnat/a-cdlili.adb
index d989751..1d48ed9 100644
--- a/gcc/ada/libgnat/a-cdlili.adb
+++ b/gcc/ada/libgnat/a-cdlili.adb
@@ -29,6 +29,8 @@
with Ada.Unchecked_Deallocation;
+with Ada.Containers.Stable_Sorting; use Ada.Containers.Stable_Sorting;
+
with System; use type System.Address;
with System.Put_Images;
@@ -674,156 +676,6 @@ is
----------
procedure Sort (Container : in out List) is
-
- type List_Descriptor is
- record
- First, Last : Node_Access;
- Length : Count_Type;
- end record;
-
- function Merge_Sort (Arg : List_Descriptor) return List_Descriptor;
- -- Sort list of given length using MergeSort; length must be >= 2.
- -- As required by RM, the sort is stable.
-
- ----------------
- -- Merge_Sort --
- ----------------
-
- function Merge_Sort (Arg : List_Descriptor) return List_Descriptor
- is
- procedure Split_List
- (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor);
- -- Split list into two parts for divide-and-conquer.
- -- Unsplit.Length must be >= 2.
-
- function Merge_Parts
- (Part1, Part2 : List_Descriptor) return List_Descriptor;
- -- Merge two sorted lists, preserving sorted property.
-
- ----------------
- -- Split_List --
- ----------------
-
- procedure Split_List
- (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor)
- is
- Rover : Node_Access := Unsplit.First;
- Bump_Count : constant Count_Type := (Unsplit.Length - 1) / 2;
- begin
- for Iter in 1 .. Bump_Count loop
- Rover := Rover.Next;
- end loop;
-
- Part1 := (First => Unsplit.First,
- Last => Rover,
- Length => Bump_Count + 1);
-
- Part2 := (First => Rover.Next,
- Last => Unsplit.Last,
- Length => Unsplit.Length - Part1.Length);
-
- -- Detach
- Part1.Last.Next := null;
- Part2.First.Prev := null;
- end Split_List;
-
- -----------------
- -- Merge_Parts --
- -----------------
-
- function Merge_Parts
- (Part1, Part2 : List_Descriptor) return List_Descriptor
- is
- Empty : constant List_Descriptor := (null, null, 0);
-
- procedure Detach_First (Source : in out List_Descriptor;
- Detached : out Node_Access);
- -- Detach the first element from a non-empty list and
- -- return the detached node via the Detached parameter.
-
- ------------------
- -- Detach_First --
- ------------------
-
- procedure Detach_First (Source : in out List_Descriptor;
- Detached : out Node_Access) is
- begin
- Detached := Source.First;
-
- if Source.Length = 1 then
- Source := Empty;
- else
- Source := (Source.First.Next,
- Source.Last,
- Source.Length - 1);
-
- Detached.Next.Prev := null;
- Detached.Next := null;
- end if;
- end Detach_First;
-
- P1 : List_Descriptor := Part1;
- P2 : List_Descriptor := Part2;
- Merged : List_Descriptor := Empty;
-
- Take_From_P2 : Boolean;
- Detached : Node_Access;
-
- -- Start of processing for Merge_Parts
-
- begin
- while (P1.Length /= 0) or (P2.Length /= 0) loop
- if P1.Length = 0 then
- Take_From_P2 := True;
- elsif P2.Length = 0 then
- Take_From_P2 := False;
- else
- -- If the compared elements are equal then Take_From_P2
- -- must be False in order to ensure stability.
-
- Take_From_P2 := P2.First.Element < P1.First.Element;
- end if;
-
- if Take_From_P2 then
- Detach_First (P2, Detached);
- else
- Detach_First (P1, Detached);
- end if;
-
- if Merged.Length = 0 then
- Merged := (First | Last => Detached, Length => 1);
- else
- Detached.Prev := Merged.Last;
- Merged.Last.Next := Detached;
- Merged.Last := Detached;
- Merged.Length := Merged.Length + 1;
- end if;
- end loop;
- return Merged;
- end Merge_Parts;
-
- -- Start of processing for Merge_Sort
-
- begin
- if Arg.Length < 2 then
- -- already sorted
- return Arg;
- end if;
-
- declare
- Part1, Part2 : List_Descriptor;
- begin
- Split_List (Unsplit => Arg, Part1 => Part1, Part2 => Part2);
-
- Part1 := Merge_Sort (Part1);
- Part2 := Merge_Sort (Part2);
-
- return Merge_Parts (Part1, Part2);
- end;
- end Merge_Sort;
-
- -- Start of processing for Sort
-
begin
if Container.Length <= 1 then
return;
@@ -838,28 +690,43 @@ is
-- element tampering by a generic actual subprogram.
declare
- Lock : With_Lock (Container.TC'Unchecked_Access);
+ Lock : With_Lock (Container.TC'Unchecked_Access);
+
+ package Descriptors is new List_Descriptors
+ (Node_Ref => Node_Access, Nil => null);
+ use Descriptors;
+
+ function Next (N : Node_Access) return Node_Access is (N.Next);
+ procedure Set_Next (N : Node_Access; Next : Node_Access)
+ with Inline;
+ procedure Set_Prev (N : Node_Access; Prev : Node_Access)
+ with Inline;
+ function "<" (L, R : Node_Access) return Boolean is
+ (L.Element < R.Element);
+ procedure Update_Container (List : List_Descriptor) with Inline;
+
+ procedure Set_Next (N : Node_Access; Next : Node_Access) is
+ begin
+ N.Next := Next;
+ end Set_Next;
- Unsorted : constant List_Descriptor :=
- (First => Container.First,
- Last => Container.Last,
- Length => Container.Length);
+ procedure Set_Prev (N : Node_Access; Prev : Node_Access) is
+ begin
+ N.Prev := Prev;
+ end Set_Prev;
+
+ procedure Update_Container (List : List_Descriptor) is
+ begin
+ Container.First := List.First;
+ Container.Last := List.Last;
+ Container.Length := List.Length;
+ end Update_Container;
- Sorted : List_Descriptor;
+ procedure Sort_List is new Doubly_Linked_List_Sort;
begin
- -- If a call to the formal < operator references the container
- -- during sorting, seeing an empty container seems preferable
- -- to seeing an internally inconsistent container.
- --
- Container.First := null;
- Container.Last := null;
- Container.Length := 0;
-
- Sorted := Merge_Sort (Unsorted);
-
- Container.First := Sorted.First;
- Container.Last := Sorted.Last;
- Container.Length := Sorted.Length;
+ Sort_List (List_Descriptor'(First => Container.First,
+ Last => Container.Last,
+ Length => Container.Length));
end;
pragma Assert (Container.First.Prev = null);
diff --git a/gcc/ada/libgnat/a-cfdlli.adb b/gcc/ada/libgnat/a-cfdlli.adb
index b289def..c9897c7 100644
--- a/gcc/ada/libgnat/a-cfdlli.adb
+++ b/gcc/ada/libgnat/a-cfdlli.adb
@@ -25,6 +25,8 @@
-- <http://www.gnu.org/licenses/>. --
------------------------------------------------------------------------------
+with Ada.Containers.Stable_Sorting; use Ada.Containers.Stable_Sorting;
+
with System; use type System.Address;
package body Ada.Containers.Formal_Doubly_Linked_Lists with
@@ -976,77 +978,6 @@ is
procedure Sort (Container : in out List) is
N : Node_Array renames Container.Nodes;
-
- procedure Partition (Pivot : Count_Type; Back : Count_Type);
- procedure Sort (Front : Count_Type; Back : Count_Type);
-
- ---------------
- -- Partition --
- ---------------
-
- procedure Partition (Pivot : Count_Type; Back : Count_Type) is
- Node : Count_Type;
-
- begin
- Node := N (Pivot).Next;
- while Node /= Back loop
- if N (Node).Element < N (Pivot).Element then
- declare
- Prev : constant Count_Type := N (Node).Prev;
- Next : constant Count_Type := N (Node).Next;
-
- begin
- N (Prev).Next := Next;
-
- if Next = 0 then
- Container.Last := Prev;
- else
- N (Next).Prev := Prev;
- end if;
-
- N (Node).Next := Pivot;
- N (Node).Prev := N (Pivot).Prev;
-
- N (Pivot).Prev := Node;
-
- if N (Node).Prev = 0 then
- Container.First := Node;
- else
- N (N (Node).Prev).Next := Node;
- end if;
-
- Node := Next;
- end;
-
- else
- Node := N (Node).Next;
- end if;
- end loop;
- end Partition;
-
- ----------
- -- Sort --
- ----------
-
- procedure Sort (Front : Count_Type; Back : Count_Type) is
- Pivot : Count_Type;
-
- begin
- if Front = 0 then
- Pivot := Container.First;
- else
- Pivot := N (Front).Next;
- end if;
-
- if Pivot /= Back then
- Partition (Pivot, Back);
- Sort (Front, Pivot);
- Sort (Pivot, Back);
- end if;
- end Sort;
-
- -- Start of processing for Sort
-
begin
if Container.Length <= 1 then
return;
@@ -1055,7 +986,44 @@ is
pragma Assert (N (Container.First).Prev = 0);
pragma Assert (N (Container.Last).Next = 0);
- Sort (Front => 0, Back => 0);
+ declare
+ package Descriptors is new List_Descriptors
+ (Node_Ref => Count_Type, Nil => 0);
+ use Descriptors;
+
+ function Next (Idx : Count_Type) return Count_Type is
+ (N (Idx).Next);
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type)
+ with Inline;
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type)
+ with Inline;
+ function "<" (L, R : Count_Type) return Boolean is
+ (N (L).Element < N (R).Element);
+ procedure Update_Container (List : List_Descriptor) with Inline;
+
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type) is
+ begin
+ N (Idx).Next := Next;
+ end Set_Next;
+
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type) is
+ begin
+ N (Idx).Prev := Prev;
+ end Set_Prev;
+
+ procedure Update_Container (List : List_Descriptor) is
+ begin
+ Container.First := List.First;
+ Container.Last := List.Last;
+ Container.Length := List.Length;
+ end Update_Container;
+
+ procedure Sort_List is new Doubly_Linked_List_Sort;
+ begin
+ Sort_List (List_Descriptor'(First => Container.First,
+ Last => Container.Last,
+ Length => Container.Length));
+ end;
pragma Assert (N (Container.First).Prev = 0);
pragma Assert (N (Container.Last).Next = 0);
diff --git a/gcc/ada/libgnat/a-cfdlli.ads b/gcc/ada/libgnat/a-cfdlli.ads
index 8713d33..ded496b 100644
--- a/gcc/ada/libgnat/a-cfdlli.ads
+++ b/gcc/ada/libgnat/a-cfdlli.ads
@@ -44,6 +44,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type List (Capacity : Count_Type) is private with
@@ -1596,8 +1597,7 @@ is
M_Elements_Sorted'Result =
(for all I in 1 .. M.Length (Container) =>
(for all J in I .. M.Length (Container) =>
- Element (Container, I) = Element (Container, J)
- or Element (Container, I) < Element (Container, J)));
+ not (Element (Container, J) < Element (Container, I))));
pragma Annotate (GNATprove, Inline_For_Proof, M_Elements_Sorted);
end Formal_Model;
diff --git a/gcc/ada/libgnat/a-cfhama.ads b/gcc/ada/libgnat/a-cfhama.ads
index 2b49c13..59e295d 100644
--- a/gcc/ada/libgnat/a-cfhama.ads
+++ b/gcc/ada/libgnat/a-cfhama.ads
@@ -69,6 +69,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Map (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfhase.ads b/gcc/ada/libgnat/a-cfhase.ads
index 9bcd8ce..23b3b6d 100644
--- a/gcc/ada/libgnat/a-cfhase.ads
+++ b/gcc/ada/libgnat/a-cfhase.ads
@@ -67,6 +67,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Set (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfinve.ads b/gcc/ada/libgnat/a-cfinve.ads
index 9b95437..bd0c334 100644
--- a/gcc/ada/libgnat/a-cfinve.ads
+++ b/gcc/ada/libgnat/a-cfinve.ads
@@ -60,6 +60,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-cforma.ads b/gcc/ada/libgnat/a-cforma.ads
index a1cad03..048e7cb 100644
--- a/gcc/ada/libgnat/a-cforma.ads
+++ b/gcc/ada/libgnat/a-cforma.ads
@@ -68,6 +68,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Keys (Left, Right : Key_Type) return Boolean with
diff --git a/gcc/ada/libgnat/a-cforse.ads b/gcc/ada/libgnat/a-cforse.ads
index e1d7c91..db7c586 100644
--- a/gcc/ada/libgnat/a-cforse.ads
+++ b/gcc/ada/libgnat/a-cforse.ads
@@ -64,6 +64,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Elements (Left, Right : Element_Type) return Boolean
diff --git a/gcc/ada/libgnat/a-chahan.adb b/gcc/ada/libgnat/a-chahan.adb
index 827794c..411d485 100644
--- a/gcc/ada/libgnat/a-chahan.adb
+++ b/gcc/ada/libgnat/a-chahan.adb
@@ -29,11 +29,19 @@
-- --
------------------------------------------------------------------------------
+-- Loop invariants in this unit are meant for analysis only, not for run-time
+-- checking, as it would be too costly otherwise. This is enforced by setting
+-- the assertion policy to Ignore.
+
+pragma Assertion_Policy (Loop_Invariant => Ignore);
+
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
with Ada.Strings.Maps; use Ada.Strings.Maps;
with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
-package body Ada.Characters.Handling is
+package body Ada.Characters.Handling
+ with SPARK_Mode
+is
------------------------------------
-- Character Classification Table --
@@ -299,9 +307,7 @@ package body Ada.Characters.Handling is
------------------
function Is_Character (Item : Wide_Character) return Boolean is
- begin
- return Wide_Character'Pos (Item) < 256;
- end Is_Character;
+ (Wide_Character'Pos (Item) < 256);
----------------
-- Is_Control --
@@ -344,9 +350,7 @@ package body Ada.Characters.Handling is
----------------
function Is_ISO_646 (Item : Character) return Boolean is
- begin
- return Item in ISO_646;
- end Is_ISO_646;
+ (Item in ISO_646);
-- Note: much more efficient coding of the following function is possible
-- by testing several 16#80# bits in a complete word in a single operation
@@ -357,6 +361,8 @@ package body Ada.Characters.Handling is
if Item (J) not in ISO_646 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_ISO_646 (Item (K)));
end loop;
return True;
@@ -456,6 +462,8 @@ package body Ada.Characters.Handling is
if Wide_Character'Pos (Item (J)) >= 256 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_Character (Item (K)));
end loop;
return True;
@@ -475,15 +483,18 @@ package body Ada.Characters.Handling is
--------------
function To_Basic (Item : Character) return Character is
- begin
- return Value (Basic_Map, Item);
- end To_Basic;
+ (Value (Basic_Map, Item));
function To_Basic (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Basic_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Basic (Item (K)));
end loop;
end return;
end To_Basic;
@@ -511,24 +522,25 @@ package body Ada.Characters.Handling is
function To_ISO_646
(Item : Character;
Substitute : ISO_646 := ' ') return ISO_646
- is
- begin
- return (if Item in ISO_646 then Item else Substitute);
- end To_ISO_646;
+ is (if Item in ISO_646 then Item else Substitute);
function To_ISO_646
(Item : String;
Substitute : ISO_646 := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) :=
- (if Item (J) in ISO_646 then Item (J) else Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ (if Item (J) in ISO_646 then Item (J) else Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_ISO_646 (Item (K), Substitute));
+ end loop;
+ end return;
end To_ISO_646;
--------------
@@ -536,15 +548,18 @@ package body Ada.Characters.Handling is
--------------
function To_Lower (Item : Character) return Character is
- begin
- return Value (Lower_Case_Map, Item);
- end To_Lower;
+ (Value (Lower_Case_Map, Item));
function To_Lower (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Lower_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Lower (Item (K)));
end loop;
end return;
end To_Lower;
@@ -557,34 +572,40 @@ package body Ada.Characters.Handling is
(Item : Wide_String;
Substitute : Character := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Character (Item (J), Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ To_Character (Item (J), Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_Character (Item (K), Substitute));
+ end loop;
+ end return;
end To_String;
--------------
-- To_Upper --
--------------
- function To_Upper
- (Item : Character) return Character
- is
- begin
- return Value (Upper_Case_Map, Item);
- end To_Upper;
+ function To_Upper (Item : Character) return Character is
+ (Value (Upper_Case_Map, Item));
function To_Upper
(Item : String) return String
is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Upper_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Upper (Item (K)));
end loop;
end return;
end To_Upper;
@@ -607,14 +628,19 @@ package body Ada.Characters.Handling is
function To_Wide_String
(Item : String) return Wide_String
is
- Result : Wide_String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
- end loop;
-
- return Result;
+ return Result : Wide_String (1 .. Item'Length)
+ with Relaxed_Initialization
+ do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Wide_Character (Item (K)));
+ end loop;
+ end return;
end To_Wide_String;
end Ada.Characters.Handling;
diff --git a/gcc/ada/libgnat/a-chahan.ads b/gcc/ada/libgnat/a-chahan.ads
index 2f93e7c..093237d 100644
--- a/gcc/ada/libgnat/a-chahan.ads
+++ b/gcc/ada/libgnat/a-chahan.ads
@@ -33,7 +33,16 @@
-- --
------------------------------------------------------------------------------
-package Ada.Characters.Handling is
+-- Postconditions in this unit are meant for analysis only, not for run-time
+-- checking, in order not to slow down the execution of these functions.
+
+pragma Assertion_Policy (Post => Ignore);
+
+with Ada.Characters.Latin_1;
+
+package Ada.Characters.Handling
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -41,54 +50,296 @@ package Ada.Characters.Handling is
-- Character Classification Functions --
----------------------------------------
- function Is_Control (Item : Character) return Boolean;
- function Is_Graphic (Item : Character) return Boolean;
- function Is_Letter (Item : Character) return Boolean;
- function Is_Lower (Item : Character) return Boolean;
- function Is_Upper (Item : Character) return Boolean;
- function Is_Basic (Item : Character) return Boolean;
- function Is_Digit (Item : Character) return Boolean;
+ -- In the description below for each function that returns a Boolean
+ -- result, the effect is described in terms of the conditions under which
+ -- the value True is returned. If these conditions are not met, then the
+ -- function returns False.
+ --
+ -- Each of the following classification functions has a formal Character
+ -- parameter, Item, and returns a Boolean result.
+
+ function Is_Control (Item : Character) return Boolean
+ with
+ Post => Is_Control'Result =
+ (Character'Pos (Item) in 0 .. 31 | 127 .. 159);
+ -- True if Item is a control character. A control character is a character
+ -- whose position is in one of the ranges 0..31 or 127..159.
+
+ function Is_Graphic (Item : Character) return Boolean
+ with
+ Post => Is_Graphic'Result =
+ (Character'Pos (Item) in 32 .. 126 | 160 .. 255);
+ -- True if Item is a graphic character. A graphic character is a character
+ -- whose position is in one of the ranges 32..126 or 160..255.
+
+ function Is_Letter (Item : Character) return Boolean
+ with
+ Post => Is_Letter'Result =
+ (Item in 'A' .. 'Z' | 'a' .. 'z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 246 | 248 .. 255);
+ -- True if Item is a letter. A letter is a character that is in one of the
+ -- ranges 'A'..'Z' or 'a'..'z', or whose position is in one of the ranges
+ -- 192..214, 216..246, or 248..255.
+
+ function Is_Lower (Item : Character) return Boolean
+ with
+ Post => Is_Lower'Result =
+ (Item in 'a' .. 'z'
+ or else Character'Pos (Item) in 223 .. 246 | 248 .. 255);
+ -- True if Item is a lower-case letter. A lower-case letter is a character
+ -- that is in the range 'a'..'z', or whose position is in one of the ranges
+ -- 223..246 or 248..255.
+
+ function Is_Upper (Item : Character) return Boolean
+ with
+ Post => Is_Upper'Result =
+ (Item in 'A' .. 'Z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 222);
+ -- True if Item is an upper-case letter. An upper-case letter is a
+ -- character that is in the range 'A'..'Z' or whose position is in one
+ -- of the ranges 192..214 or 216..222.
+
+ function Is_Basic (Item : Character) return Boolean
+ with
+ Post => Is_Basic'Result =
+ (Item in 'A' .. 'Z'
+ | 'a' .. 'z'
+ | Latin_1.UC_AE_Diphthong
+ | Latin_1.LC_AE_Diphthong
+ | Latin_1.UC_Icelandic_Eth
+ | Latin_1.LC_Icelandic_Eth
+ | Latin_1.UC_Icelandic_Thorn
+ | Latin_1.LC_Icelandic_Thorn
+ | Latin_1.LC_German_Sharp_S);
+ -- True if Item is a basic letter. A basic letter is a character that
+ -- is in one of the ranges 'A'..'Z' and 'a'..'z', or that is one of
+ -- the following: UC_AE_Diphthong, LC_AE_Diphthong, UC_Icelandic_Eth,
+ -- LC_Icelandic_Eth, UC_Icelandic_Thorn, LC_Icelandic_Thorn, or
+ -- LC_German_Sharp_S.
+
+ function Is_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Digit'Result = (Item in '0' .. '9');
+ -- True if Item is a decimal digit. A decimal digit is a character in the
+ -- range '0'..'9'.
+
function Is_Decimal_Digit (Item : Character) return Boolean
renames Is_Digit;
- function Is_Hexadecimal_Digit (Item : Character) return Boolean;
- function Is_Alphanumeric (Item : Character) return Boolean;
- function Is_Special (Item : Character) return Boolean;
- function Is_Line_Terminator (Item : Character) return Boolean;
- function Is_Mark (Item : Character) return Boolean;
- function Is_Other_Format (Item : Character) return Boolean;
- function Is_Punctuation_Connector (Item : Character) return Boolean;
- function Is_Space (Item : Character) return Boolean;
- function Is_NFKC (Item : Character) return Boolean;
+
+ function Is_Hexadecimal_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Hexadecimal_Digit'Result =
+ (Is_Decimal_Digit (Item) or Item in 'A' .. 'F' | 'a' .. 'f');
+ -- True if Item is a hexadecimal digit. A hexadecimal digit is a character
+ -- that is either a decimal digit or that is in one of the ranges 'A'..'F'
+ -- or 'a'..'f'.
+
+ function Is_Alphanumeric (Item : Character) return Boolean
+ with
+ Post => Is_Alphanumeric'Result =
+ (Is_Letter (Item) or Is_Decimal_Digit (Item));
+ -- True if Item is an alphanumeric character. An alphanumeric character is
+ -- a character that is either a letter or a decimal digit.
+
+ function Is_Special (Item : Character) return Boolean
+ with
+ Post => Is_Special'Result =
+ (Is_Graphic (Item) and not Is_Alphanumeric (Item));
+ -- True if Item is a special graphic character. A special graphic character
+ -- is a graphic character that is not alphanumeric.
+
+ function Is_Line_Terminator (Item : Character) return Boolean
+ with
+ Post => Is_Line_Terminator'Result =
+ (Character'Pos (Item) in 10 .. 13 | 133);
+ -- True if Item is a character with position 10..13 (Line_Feed,
+ -- Line_Tabulation, Form_Feed, Carriage_Return) or 133 (Next_Line).
+
+ function Is_Mark (Item : Character) return Boolean
+ with
+ Post => Is_Mark'Result = False;
+ -- Never True (no value of type Character has categories Mark, Non-Spacing
+ -- or Mark, Spacing Combining).
+
+ function Is_Other_Format (Item : Character) return Boolean
+ with
+ Post => Is_Other_Format'Result = (Character'Pos (Item) = 173);
+ -- True if Item is a character with position 173 (Soft_Hyphen).
+
+ function Is_Punctuation_Connector (Item : Character) return Boolean
+ with
+ Post => Is_Punctuation_Connector'Result =
+ (Character'Pos (Item) = 95);
+ -- True if Item is a character with position 95 ('_', known as Low_Line or
+ -- Underscore).
+
+ function Is_Space (Item : Character) return Boolean
+ with
+ Post => Is_Space'Result = (Character'Pos (Item) in 32 | 160);
+ -- True if Item is a character with position 32 (' ') or 160
+ -- (No_Break_Space).
+
+ function Is_NFKC (Item : Character) return Boolean
+ with
+ Post => Is_NFKC'Result =
+ (Character'Pos (Item) not in
+ 160 | 168 | 170 | 175 | 178 | 179 | 180
+ | 181 | 184 | 185 | 186 | 188 | 189 | 190);
+ -- True if Item could be present in a string normalized to Normalization
+ -- Form KC (as defined by Clause 21 of ISO/IEC 10646:2017); this includes
+ -- all characters except those with positions 160, 168, 170, 175, 178, 179,
+ -- 180, 181, 184, 185, 186, 188, 189, and 190.
---------------------------------------------------
-- Conversion Functions for Character and String --
---------------------------------------------------
- function To_Lower (Item : Character) return Character;
- function To_Upper (Item : Character) return Character;
- function To_Basic (Item : Character) return Character;
+ -- Each of the names To_Lower, To_Upper, and To_Basic refers to two
+ -- functions: one that converts from Character to Character, and
+ -- the other that converts from String to String. The result of each
+ -- Character-to-Character function is described below, in terms of
+ -- the conversion applied to Item, its formal Character parameter. The
+ -- result of each String-to-String conversion is obtained by applying
+ -- to each element of the function's String parameter the corresponding
+ -- Character-to-Character conversion; the result is the null String if the
+ -- value of the formal parameter is the null String. The lower bound of the
+ -- result String is 1.
+
+ function To_Lower (Item : Character) return Character
+ with
+ Post => To_Lower'Result =
+ (if Is_Upper (Item) then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('a') - Character'Pos ('A')
+ else
+ Character'Pos (Latin_1.LC_A_Grave)
+ - Character'Pos (Latin_1.UC_A_Grave)))
+ else
+ Item);
+ -- Returns the corresponding lower-case value for Item if Is_Upper(Item),
+ -- and returns Item otherwise.
- function To_Lower (Item : String) return String;
- function To_Upper (Item : String) return String;
- function To_Basic (Item : String) return String;
+ function To_Upper (Item : Character) return Character
+ with
+ Post => To_Upper'Result =
+ (if Is_Lower (Item)
+ and then Item not in Latin_1.LC_German_Sharp_S
+ | Latin_1.LC_Y_Diaeresis
+ then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('A') - Character'Pos ('a')
+ else
+ Character'Pos (Latin_1.UC_A_Grave)
+ - Character'Pos (Latin_1.LC_A_Grave)))
+ else
+ Item);
+ -- Returns the corresponding upper-case value for Item if Is_Lower(Item)
+ -- and Item has an upper-case form, and returns Item otherwise. The lower
+ -- case letters LC_German_Sharp_S and LC_Y_Diaeresis do not have upper case
+ -- forms.
+
+ function To_Basic (Item : Character) return Character
+ with
+ Post => To_Basic'Result =
+ (if not Is_Letter (Item) or else Is_Basic (Item) then
+ Item
+ else
+ (case Item is
+ when Latin_1.UC_A_Grave .. Latin_1.UC_A_Ring => 'A',
+ when Latin_1.UC_C_Cedilla => 'C',
+ when Latin_1.UC_E_Grave .. Latin_1.UC_E_Diaeresis => 'E',
+ when Latin_1.UC_I_Grave .. Latin_1.UC_I_Diaeresis => 'I',
+ when Latin_1.UC_N_Tilde => 'N',
+ when Latin_1.UC_O_Grave .. Latin_1.UC_O_Diaeresis => 'O',
+ when Latin_1.UC_O_Oblique_Stroke => 'O',
+ when Latin_1.UC_U_Grave .. Latin_1.UC_U_Diaeresis => 'U',
+ when Latin_1.UC_Y_Acute => 'Y',
+ when Latin_1.LC_A_Grave .. Latin_1.LC_A_Ring => 'a',
+ when Latin_1.LC_C_Cedilla => 'c',
+ when Latin_1.LC_E_Grave .. Latin_1.LC_E_Diaeresis => 'e',
+ when Latin_1.LC_I_Grave .. Latin_1.LC_I_Diaeresis => 'i',
+ when Latin_1.LC_N_Tilde => 'n',
+ when Latin_1.LC_O_Grave .. Latin_1.LC_O_Diaeresis => 'o',
+ when Latin_1.LC_O_Oblique_Stroke => 'o',
+ when Latin_1.LC_U_Grave .. Latin_1.LC_U_Diaeresis => 'u',
+ when Latin_1.LC_Y_Acute => 'y',
+ when Latin_1.LC_Y_Diaeresis => 'y',
+ when others => raise Program_Error));
+ -- Returns the letter corresponding to Item but with no diacritical mark,
+ -- if Item is a letter but not a basic letter; returns Item otherwise.
+
+ function To_Lower (Item : String) return String
+ with
+ Post => To_Lower'Result'First = 1
+ and then To_Lower'Result'Length = Item'Length
+ and then
+ (for all J in To_Lower'Result'Range =>
+ To_Lower'Result (J) = To_Lower (Item (Item'First + (J - 1))));
+
+ function To_Upper (Item : String) return String
+ with
+ Post => To_Upper'Result'First = 1
+ and then To_Upper'Result'Length = Item'Length
+ and then
+ (for all J in To_Upper'Result'Range =>
+ To_Upper'Result (J) = To_Upper (Item (Item'First + (J - 1))));
+
+ function To_Basic (Item : String) return String
+ with
+ Post => To_Basic'Result'First = 1
+ and then To_Basic'Result'Length = Item'Length
+ and then
+ (for all J in To_Basic'Result'Range =>
+ To_Basic'Result (J) = To_Basic (Item (Item'First + (J - 1))));
----------------------------------------------------------------------
-- Classifications of and Conversions Between Character and ISO 646 --
----------------------------------------------------------------------
+ -- The following set of functions test for membership in the ISO 646
+ -- character range, or convert between ISO 646 and Character.
+
subtype ISO_646 is
Character range Character'Val (0) .. Character'Val (127);
- function Is_ISO_646 (Item : Character) return Boolean;
- function Is_ISO_646 (Item : String) return Boolean;
+ function Is_ISO_646 (Item : Character) return Boolean
+ with
+ Post => Is_ISO_646'Result = (Item in ISO_646);
+ -- The function whose formal parameter, Item, is of type Character returns
+ -- True if Item is in the subtype ISO_646.
+
+ function Is_ISO_646 (Item : String) return Boolean
+ with
+ Post => Is_ISO_646'Result =
+ (for all J in Item'Range => Is_ISO_646 (Item (J)));
+ -- The function whose formal parameter, Item, is of type String returns
+ -- True if Is_ISO_646(Item(I)) is True for each I in Item'Range.
function To_ISO_646
(Item : Character;
- Substitute : ISO_646 := ' ') return ISO_646;
+ Substitute : ISO_646 := ' ') return ISO_646
+ with
+ Post => To_ISO_646'Result =
+ (if Is_ISO_646 (Item) then Item else Substitute);
+ -- The function whose first formal parameter, Item, is of type Character
+ -- returns Item if Is_ISO_646(Item), and returns the Substitute ISO_646
+ -- character otherwise.
function To_ISO_646
(Item : String;
- Substitute : ISO_646 := ' ') return String;
+ Substitute : ISO_646 := ' ') return String
+ with
+ Post => To_ISO_646'Result'First = 1
+ and then To_ISO_646'Result'Length = Item'Length
+ and then
+ (for all J in To_ISO_646'Result'Range =>
+ To_ISO_646'Result (J) =
+ To_ISO_646 (Item (Item'First + (J - 1)), Substitute));
+ -- The function whose first formal parameter, Item, is of type String
+ -- returns the String whose Range is 1..Item'Length and each of whose
+ -- elements is given by To_ISO_646 of the corresponding element in Item.
------------------------------------------------------
-- Classifications of Wide_Character and Characters --
@@ -103,8 +354,18 @@ package Ada.Characters.Handling is
-- We do however have to flag these if the pragma No_Obsolescent_Features
-- restriction is active (see Restrict.Check_Obsolescent_2005_Entity).
- function Is_Character (Item : Wide_Character) return Boolean;
- function Is_String (Item : Wide_String) return Boolean;
+ function Is_Character (Item : Wide_Character) return Boolean
+ with
+ Post => Is_Character'Result =
+ (Wide_Character'Pos (Item) <= Character'Pos (Character'Last));
+ -- Returns True if Wide_Character'Pos(Item) <=
+ -- Character'Pos(Character'Last).
+
+ function Is_String (Item : Wide_String) return Boolean
+ with
+ Post => Is_String'Result =
+ (for all I in Item'Range => Is_Character (Item (I)));
+ -- Returns True if Is_Character(Item(I)) is True for each I in Item'Range.
------------------------------------------------------
-- Conversions between Wide_Character and Character --
@@ -121,17 +382,49 @@ package Ada.Characters.Handling is
function To_Character
(Item : Wide_Character;
- Substitute : Character := ' ') return Character;
+ Substitute : Character := ' ') return Character
+ with
+ Post => To_Character'Result =
+ (if Is_Character (Item) then
+ Character'Val (Wide_Character'Pos (Item))
+ else
+ Substitute);
+ -- Returns the Character corresponding to Item if Is_Character(Item), and
+ -- returns the Substitute Character otherwise.
function To_String
(Item : Wide_String;
- Substitute : Character := ' ') return String;
+ Substitute : Character := ' ') return String
+ with
+ Post => To_String'Result'First = 1
+ and then To_String'Result'Length = Item'Length
+ and then
+ (for all J in To_String'Result'Range =>
+ To_String'Result (J) =
+ To_Character (Item (Item'First + (J - 1)), Substitute));
+ -- Returns the String whose range is 1..Item'Length and each of whose
+ -- elements is given by To_Character of the corresponding element in Item.
function To_Wide_Character
- (Item : Character) return Wide_Character;
+ (Item : Character) return Wide_Character
+ with
+ Post => To_Wide_Character'Result =
+ Wide_Character'Val (Character'Pos (Item));
+ -- Returns the Wide_Character X such that Character'Pos(Item) =
+ -- Wide_Character'Pos (X).
function To_Wide_String
- (Item : String) return Wide_String;
+ (Item : String) return Wide_String
+ with
+ Post => To_Wide_String'Result'First = 1
+ and then To_Wide_String'Result'Length = Item'Length
+ and then
+ (for all J in To_Wide_String'Result'Range =>
+ To_Wide_String'Result (J) =
+ To_Wide_Character (Item (Item'First + (J - 1))));
+ -- Returns the Wide_String whose range is 1..Item'Length and each of whose
+ -- elements is given by To_Wide_Character of the corresponding element in
+ -- Item.
private
pragma Inline (Is_Alphanumeric);
diff --git a/gcc/ada/libgnat/a-cidlli.adb b/gcc/ada/libgnat/a-cidlli.adb
index 3fc57da..1cf9401 100644
--- a/gcc/ada/libgnat/a-cidlli.adb
+++ b/gcc/ada/libgnat/a-cidlli.adb
@@ -29,6 +29,8 @@
with Ada.Unchecked_Deallocation;
+with Ada.Containers.Stable_Sorting; use Ada.Containers.Stable_Sorting;
+
with System; use type System.Address;
with System.Put_Images;
@@ -731,73 +733,6 @@ is
----------
procedure Sort (Container : in out List) is
- procedure Partition (Pivot : Node_Access; Back : Node_Access);
- -- Comment ???
-
- procedure Sort (Front, Back : Node_Access);
- -- Comment??? Confusing name??? change name???
-
- ---------------
- -- Partition --
- ---------------
-
- procedure Partition (Pivot : Node_Access; Back : Node_Access) is
- Node : Node_Access;
-
- begin
- Node := Pivot.Next;
- while Node /= Back loop
- if Node.Element.all < Pivot.Element.all then
- declare
- Prev : constant Node_Access := Node.Prev;
- Next : constant Node_Access := Node.Next;
-
- begin
- Prev.Next := Next;
-
- if Next = null then
- Container.Last := Prev;
- else
- Next.Prev := Prev;
- end if;
-
- Node.Next := Pivot;
- Node.Prev := Pivot.Prev;
-
- Pivot.Prev := Node;
-
- if Node.Prev = null then
- Container.First := Node;
- else
- Node.Prev.Next := Node;
- end if;
-
- Node := Next;
- end;
-
- else
- Node := Node.Next;
- end if;
- end loop;
- end Partition;
-
- ----------
- -- Sort --
- ----------
-
- procedure Sort (Front, Back : Node_Access) is
- Pivot : constant Node_Access :=
- (if Front = null then Container.First else Front.Next);
- begin
- if Pivot /= Back then
- Partition (Pivot, Back);
- Sort (Front, Pivot);
- Sort (Pivot, Back);
- end if;
- end Sort;
-
- -- Start of processing for Sort
-
begin
if Container.Length <= 1 then
return;
@@ -813,8 +748,42 @@ is
declare
Lock : With_Lock (Container.TC'Unchecked_Access);
+
+ package Descriptors is new List_Descriptors
+ (Node_Ref => Node_Access, Nil => null);
+ use Descriptors;
+
+ function Next (N : Node_Access) return Node_Access is (N.Next);
+ procedure Set_Next (N : Node_Access; Next : Node_Access)
+ with Inline;
+ procedure Set_Prev (N : Node_Access; Prev : Node_Access)
+ with Inline;
+ function "<" (L, R : Node_Access) return Boolean is
+ (L.Element.all < R.Element.all);
+ procedure Update_Container (List : List_Descriptor) with Inline;
+
+ procedure Set_Next (N : Node_Access; Next : Node_Access) is
+ begin
+ N.Next := Next;
+ end Set_Next;
+
+ procedure Set_Prev (N : Node_Access; Prev : Node_Access) is
+ begin
+ N.Prev := Prev;
+ end Set_Prev;
+
+ procedure Update_Container (List : List_Descriptor) is
+ begin
+ Container.First := List.First;
+ Container.Last := List.Last;
+ Container.Length := List.Length;
+ end Update_Container;
+
+ procedure Sort_List is new Doubly_Linked_List_Sort;
begin
- Sort (Front => null, Back => null);
+ Sort_List (List_Descriptor'(First => Container.First,
+ Last => Container.Last,
+ Length => Container.Length));
end;
pragma Assert (Container.First.Prev = null);
diff --git a/gcc/ada/libgnat/a-coboho.ads b/gcc/ada/libgnat/a-coboho.ads
index 086f194..44269f0 100644
--- a/gcc/ada/libgnat/a-coboho.ads
+++ b/gcc/ada/libgnat/a-coboho.ads
@@ -70,7 +70,9 @@ package Ada.Containers.Bounded_Holders is
-- System.Storage_Unit; e.g. creating Holders from 5-bit objects won't
-- work.
- type Holder is private;
+ type Holder is private
+ with Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
function "=" (Left, Right : Holder) return Boolean;
diff --git a/gcc/ada/libgnat/a-cobove.ads b/gcc/ada/libgnat/a-cobove.ads
index 67c4419..5f3e1a7 100644
--- a/gcc/ada/libgnat/a-cobove.ads
+++ b/gcc/ada/libgnat/a-cobove.ads
@@ -63,12 +63,11 @@ package Ada.Containers.Bounded_Vectors is
Aggregate => (Empty => Empty,
Add_Unnamed => Append,
New_Indexed => New_Vector,
- Assign_Indexed => Replace_Element);
+ Assign_Indexed => Replace_Element),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Vector);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Vector : constant Vector;
diff --git a/gcc/ada/libgnat/a-cofove.ads b/gcc/ada/libgnat/a-cofove.ads
index a4ed7e5..6d3f486 100644
--- a/gcc/ada/libgnat/a-cofove.ads
+++ b/gcc/ada/libgnat/a-cofove.ads
@@ -50,6 +50,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-costso.adb b/gcc/ada/libgnat/a-costso.adb
new file mode 100644
index 0000000..e14ecbb
--- /dev/null
+++ b/gcc/ada/libgnat/a-costso.adb
@@ -0,0 +1,191 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- A D A . C O N T A I N E R S . S T A B L E _ S O R T I N G --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 1995-2021, AdaCore --
+-- --
+-- 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 Ada.Containers.Stable_Sorting is
+ package body List_Descriptors is
+ procedure Doubly_Linked_List_Sort (List : List_Descriptor) is
+
+ Empty : constant List_Descriptor := (Nil, Nil, 0);
+
+ function Merge_Sort (Arg : List_Descriptor) return List_Descriptor;
+ -- Sort list of given length using MergeSort; length must be >= 2.
+ -- As required by RM, the sort is stable.
+
+ ----------------
+ -- Merge_Sort --
+ ----------------
+
+ function Merge_Sort (Arg : List_Descriptor) return List_Descriptor
+ is
+ procedure Split_List
+ (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor);
+ -- Split list into two parts for divide-and-conquer.
+ -- Unsplit.Length must be >= 2.
+
+ function Merge_Parts
+ (Part1, Part2 : List_Descriptor) return List_Descriptor;
+ -- Merge two sorted lists, preserving sorted property.
+
+ ----------------
+ -- Split_List --
+ ----------------
+
+ procedure Split_List
+ (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor)
+ is
+ Rover : Node_Ref := Unsplit.First;
+ Bump_Count : constant Count_Type := (Unsplit.Length - 1) / 2;
+ begin
+ for Iter in 1 .. Bump_Count loop
+ Rover := Next (Rover);
+ end loop;
+
+ Part1 := (First => Unsplit.First,
+ Last => Rover,
+ Length => Bump_Count + 1);
+
+ Part2 := (First => Next (Rover),
+ Last => Unsplit.Last,
+ Length => Unsplit.Length - Part1.Length);
+
+ -- Detach
+ Set_Next (Part1.Last, Nil);
+ Set_Prev (Part2.First, Nil);
+ end Split_List;
+
+ -----------------
+ -- Merge_Parts --
+ -----------------
+
+ function Merge_Parts
+ (Part1, Part2 : List_Descriptor) return List_Descriptor
+ is
+ procedure Detach_First (Source : in out List_Descriptor;
+ Detached : out Node_Ref);
+ -- Detach the first element from a non-empty list and
+ -- return the detached node via the Detached parameter.
+
+ ------------------
+ -- Detach_First --
+ ------------------
+
+ procedure Detach_First (Source : in out List_Descriptor;
+ Detached : out Node_Ref) is
+ begin
+ Detached := Source.First;
+
+ if Source.Length = 1 then
+ Source := Empty;
+ else
+ Source := (Next (Source.First),
+ Source.Last,
+ Source.Length - 1);
+
+ Set_Prev (Next (Detached), Nil);
+ Set_Next (Detached, Nil);
+ end if;
+ end Detach_First;
+
+ P1 : List_Descriptor := Part1;
+ P2 : List_Descriptor := Part2;
+ Merged : List_Descriptor := Empty;
+
+ Take_From_P2 : Boolean;
+ Detached : Node_Ref;
+
+ -- Start of processing for Merge_Parts
+
+ begin
+ while (P1.Length /= 0) or (P2.Length /= 0) loop
+ if P1.Length = 0 then
+ Take_From_P2 := True;
+ elsif P2.Length = 0 then
+ Take_From_P2 := False;
+ else
+ -- If the compared elements are equal then Take_From_P2
+ -- must be False in order to ensure stability.
+
+ Take_From_P2 := P2.First < P1.First;
+ end if;
+
+ if Take_From_P2 then
+ Detach_First (P2, Detached);
+ else
+ Detach_First (P1, Detached);
+ end if;
+
+ if Merged.Length = 0 then
+ Merged := (First | Last => Detached, Length => 1);
+ else
+ Set_Prev (Detached, Merged.Last);
+ Set_Next (Merged.Last, Detached);
+ Merged.Last := Detached;
+ Merged.Length := Merged.Length + 1;
+ end if;
+ end loop;
+ return Merged;
+ end Merge_Parts;
+
+ -- Start of processing for Merge_Sort
+
+ begin
+ if Positive (Arg.Length) < 2 then
+ -- already sorted
+ return Arg;
+ end if;
+
+ declare
+ Part1, Part2 : List_Descriptor;
+ begin
+ Split_List (Unsplit => Arg, Part1 => Part1, Part2 => Part2);
+
+ Part1 := Merge_Sort (Part1);
+ Part2 := Merge_Sort (Part2);
+
+ return Merge_Parts (Part1, Part2);
+ end;
+ end Merge_Sort;
+
+ -- Start of processing for Sort
+
+ begin
+ if List.Length > 1 then
+ -- If a call to the formal "<" op references the container
+ -- during sorting, seeing an empty container seems preferable
+ -- to seeing an internally inconsistent container.
+ --
+ Update_Container (Empty);
+
+ Update_Container (Merge_Sort (List));
+ end if;
+ end Doubly_Linked_List_Sort;
+ end List_Descriptors;
+end Ada.Containers.Stable_Sorting;
diff --git a/gcc/ada/libgnat/a-costso.ads b/gcc/ada/libgnat/a-costso.ads
new file mode 100644
index 0000000..db0be24
--- /dev/null
+++ b/gcc/ada/libgnat/a-costso.ads
@@ -0,0 +1,71 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- A D A . C O N T A I N E R S . S T A B L E _ S O R T I N G --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 1995-2021, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Stable_Sorting package
+
+-- This package provides a generic stable sorting procedure that is
+-- intended for use by the various doubly linked list container generics.
+-- If a stable array sorting algorithm with better-than-quadratic worst
+-- case execution time is ever needed, then it could also reside here.
+
+private package Ada.Containers.Stable_Sorting is
+ pragma Annotate (CodePeer, Skip_Analysis);
+ pragma Pure;
+ pragma Remote_Types;
+
+ -- Stable sorting algorithms with N-log-N worst case execution time.
+
+ generic
+ type Node_Ref is private; -- access value or array index
+ Nil : Node_Ref;
+ package List_Descriptors is
+
+ type List_Descriptor is
+ record
+ First, Last : Node_Ref := Nil;
+ Length : Count_Type := 0;
+ end record;
+
+ -- We use a nested generic here so that the inner generic can
+ -- refer to the List_Descriptor type.
+
+ generic
+ with function Next (N : Node_Ref) return Node_Ref is <>;
+ with procedure Set_Next (N : Node_Ref; Next : Node_Ref) is <>;
+ with procedure Set_Prev (N : Node_Ref; Prev : Node_Ref) is <>;
+ with function "<" (L, R : Node_Ref) return Boolean is <>;
+
+ with procedure Update_Container (List : List_Descriptor) is <>;
+ procedure Doubly_Linked_List_Sort (List : List_Descriptor);
+
+ end List_Descriptors;
+
+end Ada.Containers.Stable_Sorting;
diff --git a/gcc/ada/libgnat/a-crdlli.adb b/gcc/ada/libgnat/a-crdlli.adb
index 6538b26..48cdb0c 100644
--- a/gcc/ada/libgnat/a-crdlli.adb
+++ b/gcc/ada/libgnat/a-crdlli.adb
@@ -27,6 +27,8 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
+with Ada.Containers.Stable_Sorting; use Ada.Containers.Stable_Sorting;
+
with System; use type System.Address;
package body Ada.Containers.Restricted_Doubly_Linked_Lists is
@@ -509,83 +511,53 @@ package body Ada.Containers.Restricted_Doubly_Linked_Lists is
procedure Sort (Container : in out List) is
N : Node_Array renames Container.Nodes;
-
- procedure Partition (Pivot, Back : Count_Type);
- procedure Sort (Front, Back : Count_Type);
-
- ---------------
- -- Partition --
- ---------------
-
- procedure Partition (Pivot, Back : Count_Type) is
- Node : Count_Type := N (Pivot).Next;
-
- begin
- while Node /= Back loop
- if N (Node).Element < N (Pivot).Element then
- declare
- Prev : constant Count_Type := N (Node).Prev;
- Next : constant Count_Type := N (Node).Next;
-
- begin
- N (Prev).Next := Next;
-
- if Next = 0 then
- Container.Last := Prev;
- else
- N (Next).Prev := Prev;
- end if;
-
- N (Node).Next := Pivot;
- N (Node).Prev := N (Pivot).Prev;
-
- N (Pivot).Prev := Node;
-
- if N (Node).Prev = 0 then
- Container.First := Node;
- else
- N (N (Node).Prev).Next := Node;
- end if;
-
- Node := Next;
- end;
-
- else
- Node := N (Node).Next;
- end if;
- end loop;
- end Partition;
-
- ----------
- -- Sort --
- ----------
-
- procedure Sort (Front, Back : Count_Type) is
- Pivot : constant Count_Type :=
- (if Front = 0 then Container.First else N (Front).Next);
- begin
- if Pivot /= Back then
- Partition (Pivot, Back);
- Sort (Front, Pivot);
- Sort (Pivot, Back);
- end if;
- end Sort;
-
- -- Start of processing for Sort
-
begin
if Container.Length <= 1 then
return;
end if;
- pragma Assert (N (Container.First).Prev = 0);
- pragma Assert (N (Container.Last).Next = 0);
-
-- if Container.Busy > 0 then
-- raise Program_Error;
-- end if;
- Sort (Front => 0, Back => 0);
+ declare
+ package Descriptors is new List_Descriptors
+ (Node_Ref => Count_Type, Nil => 0);
+ use Descriptors;
+
+ function Next (Idx : Count_Type) return Count_Type is
+ (N (Idx).Next);
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type)
+ with Inline;
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type)
+ with Inline;
+ function "<" (L, R : Count_Type) return Boolean is
+ (N (L).Element < N (R).Element);
+ procedure Update_Container (List : List_Descriptor) with Inline;
+
+ procedure Set_Next (Idx : Count_Type; Next : Count_Type) is
+ begin
+ N (Idx).Next := Next;
+ end Set_Next;
+
+ procedure Set_Prev (Idx : Count_Type; Prev : Count_Type) is
+ begin
+ N (Idx).Prev := Prev;
+ end Set_Prev;
+
+ procedure Update_Container (List : List_Descriptor) is
+ begin
+ Container.First := List.First;
+ Container.Last := List.Last;
+ Container.Length := List.Length;
+ end Update_Container;
+
+ procedure Sort_List is new Doubly_Linked_List_Sort;
+ begin
+ Sort_List (List_Descriptor'(First => Container.First,
+ Last => Container.Last,
+ Length => Container.Length));
+ end;
pragma Assert (N (Container.First).Prev = 0);
pragma Assert (N (Container.Last).Next = 0);
diff --git a/gcc/ada/libgnat/a-elchha__vxworks-ppc-full.adb b/gcc/ada/libgnat/a-elchha__vxworks-ppc-full.adb
deleted file mode 100644
index 69f5cc2..0000000
--- a/gcc/ada/libgnat/a-elchha__vxworks-ppc-full.adb
+++ /dev/null
@@ -1,150 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- A D A . E X C E P T I O N S . L A S T _ C H A N C E _ H A N D L E R --
--- --
--- B o d y --
--- --
--- Copyright (C) 2003-2021, 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. --
--- --
-------------------------------------------------------------------------------
-
-pragma Warnings (Off);
-with System.Standard_Library;
-pragma Warnings (On);
-
-with GNAT.Debug_Utilities; use GNAT.Debug_Utilities;
-with GNAT.IO; use GNAT.IO;
-
--- Default last chance handler for use with the full VxWorks 653 partition OS
--- Ada run-time library.
-
--- Logs error with health monitor, and dumps exception identity and argument
--- string for vxaddr2line for generation of a symbolic stack backtrace.
-
-procedure Ada.Exceptions.Last_Chance_Handler (Except : Exception_Occurrence) is
-
- ----------------------
- -- APEX definitions --
- ----------------------
-
- pragma Warnings (Off);
- type Error_Code_Type is (
- Deadline_Missed,
- Application_Error,
- Numeric_Error,
- Illegal_Request,
- Stack_Overflow,
- Memory_Violation,
- Hardware_Fault,
- Power_Fail);
- pragma Warnings (On);
- pragma Convention (C, Error_Code_Type);
- -- APEX Health Management error codes
-
- type Message_Addr_Type is new System.Address;
-
- type Apex_Integer is range -(2 ** 31) .. (2 ** 31) - 1;
- pragma Convention (C, Apex_Integer);
-
- Max_Error_Message_Size : constant := 64;
-
- type Error_Message_Size_Type is new Apex_Integer range
- 1 .. Max_Error_Message_Size;
-
- pragma Warnings (Off);
- type Return_Code_Type is (
- No_Error, -- request valid and operation performed
- No_Action, -- status of system unaffected by request
- Not_Available, -- resource required by request unavailable
- Invalid_Param, -- invalid parameter specified in request
- Invalid_Config, -- parameter incompatible with configuration
- Invalid_Mode, -- request incompatible with current mode
- Timed_Out); -- time-out tied up with request has expired
- pragma Warnings (On);
- pragma Convention (C, Return_Code_Type);
- -- APEX return codes
-
- procedure Raise_Application_Error
- (Error_Code : Error_Code_Type;
- Message_Addr : Message_Addr_Type;
- Length : Error_Message_Size_Type;
- Return_Code : out Return_Code_Type);
- pragma Import (C, Raise_Application_Error, "RAISE_APPLICATION_ERROR");
-
- procedure Unhandled_Terminate;
- pragma No_Return (Unhandled_Terminate);
- pragma Import (C, Unhandled_Terminate, "__gnat_unhandled_terminate");
- -- Perform system dependent shutdown code
-
- procedure Adainit;
- pragma Import (Ada, Adainit, "adainit");
-
- Adainit_Addr : constant System.Address := Adainit'Code_Address;
- -- Part of arguments to vxaddr2line
-
- Result : Return_Code_Type;
-
- Message : String :=
- Exception_Name (Except) & ": " & ASCII.LF &
- Exception_Message (Except) & ASCII.NUL;
-
- Message_Length : Error_Message_Size_Type;
-
-begin
- New_Line;
- Put_Line ("In last chance handler");
- Put_Line (Message (1 .. Message'Length - 1));
- New_Line;
-
- Put_Line ("adainit and traceback addresses for vxaddr2line:");
-
- Put (Image_C (Adainit_Addr)); Put (" ");
-
- for J in 1 .. Except.Num_Tracebacks loop
- Put (Image_C (Except.Tracebacks (J)));
- Put (" ");
- end loop;
-
- New_Line;
-
- if Message'Length > Error_Message_Size_Type'Last then
- Message_Length := Error_Message_Size_Type'Last;
- else
- Message_Length := Message'Length;
- end if;
-
- Raise_Application_Error
- (Error_Code => Application_Error,
- Message_Addr => Message_Addr_Type (Message (1)'Address),
- Length => Message_Length,
- Return_Code => Result);
-
- -- Shutdown the run-time library now. The rest of the procedure needs to be
- -- careful not to use anything that would require runtime support. In
- -- particular, functions returning strings are banned since the sec stack
- -- is no longer functional.
-
- System.Standard_Library.Adafinal;
- Unhandled_Terminate;
-end Ada.Exceptions.Last_Chance_Handler;
diff --git a/gcc/ada/libgnat/a-excach.adb b/gcc/ada/libgnat/a-excach.adb
index 3939287..a8e6a58 100644
--- a/gcc/ada/libgnat/a-excach.adb
+++ b/gcc/ada/libgnat/a-excach.adb
@@ -41,7 +41,7 @@ pragma Warnings (On);
separate (Ada.Exceptions)
procedure Call_Chain (Excep : EOA) is
- Exception_Tracebacks : Integer;
+ Exception_Tracebacks : constant Integer;
pragma Import (C, Exception_Tracebacks, "__gl_exception_tracebacks");
-- Boolean indicating whether tracebacks should be stored in exception
-- occurrences.
diff --git a/gcc/ada/libgnat/a-except.adb b/gcc/ada/libgnat/a-except.adb
index c332afa..631c35a 100644
--- a/gcc/ada/libgnat/a-except.adb
+++ b/gcc/ada/libgnat/a-except.adb
@@ -629,6 +629,96 @@ package body Ada.Exceptions is
pragma No_Return (Rcheck_CE_Invalid_Data_Ext);
pragma No_Return (Rcheck_CE_Range_Check_Ext);
+ -- Make all of these procedures callable from strub contexts.
+ -- These attributes are not visible to callers; they are made
+ -- visible in trans.c:build_raise_check.
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Access_Parameter,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Discriminant_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Divide_By_Zero,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Length_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Exception_Id,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Overflow_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Partition_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Tag_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Access_Before_Elaboration,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Accessibility_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Address_Of_Intrinsic,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Aliased_Parameters,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_All_Guards_Closed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Bad_Predicated_Generic_Type,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Build_In_Place_Mismatch,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Current_Task_In_Entry_Body,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Duplicated_Entry_Address,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Implicit_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Misaligned_Address_Value,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Missing_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Non_Transportable_Actual,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Overlaid_Controlled_Object,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Potentially_Blocking_Operation,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stream_Operation_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stubbed_Subprogram_Called,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Unchecked_Union_Restriction,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Finalize_Raised_Exception,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Empty_Storage_Pool,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Infinite_Recursion,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Object_Too_Large,
+ "strub", "callable");
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check_Ext,
+ "strub", "callable");
+
---------------------------------------------
-- Reason Strings for Run-Time Check Calls --
---------------------------------------------
@@ -1670,7 +1760,7 @@ package body Ada.Exceptions is
-- Wide_Exception_Name --
-------------------------
- WC_Encoding : Character;
+ WC_Encoding : constant Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
-- Encoding method for source, as exported by binder
diff --git a/gcc/ada/libgnat/a-except.ads b/gcc/ada/libgnat/a-except.ads
index 2b27adb..1608e79 100644
--- a/gcc/ada/libgnat/a-except.ads
+++ b/gcc/ada/libgnat/a-except.ads
@@ -184,6 +184,15 @@ private
-- Raise_Exception_Always if it can determine this is the case. The Export
-- allows this routine to be accessed from Pure units.
+ -- Make these callable from strub contexts.
+ pragma Machine_Attribute (Raise_Exception_Always,
+ "strub", "callable");
+ pragma Machine_Attribute (Raise_Exception,
+ "strub", "callable");
+ -- This property should arguably be visible to callers, but let's
+ -- keep it private for now. In practice, it doesn't matter, since
+ -- it's only checked in the back end.
+
procedure Raise_From_Controlled_Operation (X : Exception_Occurrence);
pragma No_Return (Raise_From_Controlled_Operation);
pragma Export
diff --git a/gcc/ada/libgnat/a-stbufi.adb b/gcc/ada/libgnat/a-stbufi.adb
index 0a8feab..656e7bd 100644
--- a/gcc/ada/libgnat/a-stbufi.adb
+++ b/gcc/ada/libgnat/a-stbufi.adb
@@ -45,7 +45,7 @@ package body Ada.Strings.Text_Buffers.Files is
end Put_UTF_8_Implementation;
function Create_From_FD
- (FD : GNAT.OS_Lib.File_Descriptor;
+ (FD : System.OS_Lib.File_Descriptor;
Close_Upon_Finalization : Boolean := True) return File_Buffer
is
use OS;
diff --git a/gcc/ada/libgnat/a-stbufi.ads b/gcc/ada/libgnat/a-stbufi.ads
index 2a2db90..b9444ab 100644
--- a/gcc/ada/libgnat/a-stbufi.ads
+++ b/gcc/ada/libgnat/a-stbufi.ads
@@ -30,7 +30,7 @@
------------------------------------------------------------------------------
with Ada.Finalization;
-with GNAT.OS_Lib;
+with System.OS_Lib;
package Ada.Strings.Text_Buffers.Files is
@@ -38,7 +38,7 @@ package Ada.Strings.Text_Buffers.Files is
-- Output written to a File_Buffer is written to the associated file.
function Create_From_FD
- (FD : GNAT.OS_Lib.File_Descriptor;
+ (FD : System.OS_Lib.File_Descriptor;
Close_Upon_Finalization : Boolean := True)
return File_Buffer;
-- file closed upon finalization if specified
@@ -47,9 +47,11 @@ package Ada.Strings.Text_Buffers.Files is
-- file closed upon finalization
function Create_Standard_Output_Buffer return File_Buffer is
- (Create_From_FD (GNAT.OS_Lib.Standout, Close_Upon_Finalization => False));
+ (Create_From_FD (System.OS_Lib.Standout,
+ Close_Upon_Finalization => False));
function Create_Standard_Error_Buffer return File_Buffer is
- (Create_From_FD (GNAT.OS_Lib.Standerr, Close_Upon_Finalization => False));
+ (Create_From_FD (System.OS_Lib.Standerr,
+ Close_Upon_Finalization => False));
private
@@ -60,7 +62,7 @@ private
package Mapping is new Output_Mapping (Put_UTF_8_Implementation);
- package OS renames GNAT.OS_Lib;
+ package OS renames System.OS_Lib;
type Self_Ref (Self : not null access File_Buffer)
is new Finalization.Limited_Controlled with null record;
diff --git a/gcc/ada/libgnat/a-strbou.adb b/gcc/ada/libgnat/a-strbou.adb
index 61b3d73..01a2002 100644
--- a/gcc/ada/libgnat/a-strbou.adb
+++ b/gcc/ada/libgnat/a-strbou.adb
@@ -29,7 +29,7 @@
-- --
------------------------------------------------------------------------------
-package body Ada.Strings.Bounded is
+package body Ada.Strings.Bounded with SPARK_Mode is
package body Generic_Bounded_Length is
diff --git a/gcc/ada/libgnat/a-strbou.ads b/gcc/ada/libgnat/a-strbou.ads
index f0cf7b2..e820184 100644
--- a/gcc/ada/libgnat/a-strbou.ads
+++ b/gcc/ada/libgnat/a-strbou.ads
@@ -33,25 +33,41 @@
-- --
------------------------------------------------------------------------------
--- 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.Strings.Maps;
+-- The language-defined package Strings.Bounded provides a generic package
+-- each of whose instances yields a private type Bounded_String and a set
+-- of operations. An object of a particular Bounded_String type represents
+-- a String whose low bound is 1 and whose length can vary conceptually
+-- between 0 and a maximum size established at the generic instantiation. The
+-- subprograms for fixed-length string handling are either overloaded directly
+-- for Bounded_String, or are modified as needed to reflect the variability in
+-- length. Additionally, since the Bounded_String type is private, appropriate
+-- constructor and selector operations are provided.
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
with Ada.Strings.Superbounded;
+with Ada.Strings.Search;
-package Ada.Strings.Bounded is
+package Ada.Strings.Bounded with SPARK_Mode is
pragma Preelaborate;
generic
Max : Positive;
-- Maximum length of a Bounded_String
- package Generic_Bounded_Length with
- Initial_Condition => Length (Null_Bounded_String) = 0
+ package Generic_Bounded_Length with SPARK_Mode,
+ Initial_Condition => Length (Null_Bounded_String) = 0,
+ Abstract_State => null
is
+ -- 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.
+ -- Postconditions and contract cases should not be executed at runtime
+ -- as well, in order not to slow down the execution of these functions.
+
+ pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
Max_Length : constant Positive := Max;
@@ -59,11 +75,16 @@ package Ada.Strings.Bounded is
pragma Preelaborable_Initialization (Bounded_String);
Null_Bounded_String : constant Bounded_String;
+ -- Null_Bounded_String represents the null string. If an object of type
+ -- Bounded_String is not otherwise initialized, it will be initialized
+ -- to the same value as Null_Bounded_String.
subtype Length_Range is Natural range 0 .. Max_Length;
function Length (Source : Bounded_String) return Length_Range with
Global => null;
+ -- The Length function returns the length of the string represented by
+ -- Source.
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -73,163 +94,466 @@ package Ada.Strings.Bounded is
(Source : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post =>
- Length (To_Bounded_String'Result)
- = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (To_Bounded_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
+ -- If Source'Length <= Max_Length, then this function returns a
+ -- Bounded_String that represents Source. Otherwise, the effect
+ -- depends on the value of Drop:
+ --
+ -- * If Drop=Left, then the result is a Bounded_String that represents
+ -- the string comprising the rightmost Max_Length characters of
+ -- Source.
+ --
+ -- * If Drop=Right, then the result is a Bounded_String that represents
+ -- the string comprising the leftmost Max_Length characters of Source.
+ --
+ -- * If Drop=Error, then Strings.Length_Error is propagated.
function To_String (Source : Bounded_String) return String with
- Post => To_String'Result'Length = Length (Source),
Global => null;
+ -- To_String returns the String value with lower bound 1
+ -- represented by Source. If B is a Bounded_String, then
+ -- B = To_Bounded_String(To_String(B)).
procedure Set_Bounded_String
(Target : out Bounded_String;
Source : String;
Drop : Truncation := Error)
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post => Length (Target) = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (Target) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (Target) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
pragma Ada_05 (Set_Bounded_String);
+ -- Equivalent to Target := To_Bounded_String (Source, Drop);
+
+ -- Each of the Append functions returns a Bounded_String obtained by
+ -- concatenating the string or character given or represented by one
+ -- of the parameters, with the string or character given or represented
+ -- by the other parameter, and applying To_Bounded_String to the
+ -- concatenation result string, with Drop as provided to the Append
+ -- function.
function Append
(Left : Bounded_String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Length (Left) > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Length (Left) + Length (Right)
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Length (Left) > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Slice (Left,
+ Length (Left) - Max_Length + Length (Right) + 1,
+ Length (Left)))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Length (Left))));
function Append
(Left : Bounded_String;
Right : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Right'Length > Max_Length - Length (Left)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Right'Length),
- Global => null;
-
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Right'Length
+ =>
+ Length (Append'Result) = Length (Left) + Right'Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ Right),
+
+ Length (Left) > Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Right'Length < Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ Slice (Append'Result, 1, Max_Length - Right'Length) =
+ Slice (Left,
+ Length (Left) - Max_Length + Right'Length + 1,
+ Length (Left))
+ and then
+ Slice (Append'Result,
+ Max_Length - Right'Length + 1, Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ To_String (Append'Result) =
+ Right (Right'Last - Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Right (Right'First
+ .. Max_Length - Length (Left) - 1 + Right'First)));
function Append
(Left : String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Left'Length > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Left'Length + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Left'Length <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Left'Length + Length (Right)
+ and then Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Left'Length + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Left'Length > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Left (Left'Last - Max_Length + Length (Right) + 1
+ .. Left'Last))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Left'Length < Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ Slice (Append'Result, Left'Length + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ To_String (Append'Result) =
+ Left (Left'First .. Max_Length - 1 + Left'First)));
function Append
(Left : Bounded_String;
Right : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Left) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + 1),
- Global => null;
+ Pre => (if Length (Left) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Left) < Max_Length
+ =>
+ Length (Append'Result) = Length (Left) + 1
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then Element (Append'Result, Length (Left) + 1) = Right,
+
+ Length (Left) = Max_Length and then Drop = Strings.Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Max_Length - 1) =
+ Slice (Left, 2, Max_Length)
+ and then Element (Append'Result, Max_Length) = Right);
function Append
(Left : Character;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Right) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, 1 + Length (Right)),
- Global => null;
+ Pre => (if Length (Right) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Right) < Max_Length
+ =>
+ Length (Append'Result) = Length (Right) + 1
+ and then
+ Slice (Append'Result, 2, Length (Right) + 1) =
+ To_String (Right)
+ and then Element (Append'Result, 1) = Left,
+
+ Length (Right) = Max_Length and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 2, Max_Length) =
+ Slice (Right, 1, Max_Length - 1)
+ and then Element (Append'Result, 1) = Left);
+
+ -- Each of the procedures Append(Source, New_Item, Drop) has the same
+ -- effect as the corresponding assignment
+ -- Source := Append(Source, New_Item, Drop).
procedure Append
(Source : in out Bounded_String;
New_Item : Bounded_String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if Length (Source) > Max_Length - Length (New_Item)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + Length (New_Item)),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - Length (New_Item)
+ =>
+ Length (Source) = Length (Source'Old) + Length (New_Item)
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (New_Item) > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ To_String (New_Item)),
+
+ Length (Source) > Max_Length - Length (New_Item)
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if Length (New_Item) < Max_Length then
+ Slice (Source, 1, Max_Length - Length (New_Item)) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + Length (New_Item)
+ + 1,
+ Length (Source'Old)))
+ and then
+ Slice (Source, Max_Length - Length (New_Item) + 1, Max_Length)
+ = To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ Slice (New_Item, 1, Max_Length - Length (Source'Old))));
procedure Append
(Source : in out Bounded_String;
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ New_Item),
+
+ Length (Source) > Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if New_Item'Length < Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + New_Item'Length + 1,
+ Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ To_String (Source) = New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Length (Source'Old) - 1
+ + New_Item'First)));
procedure Append
(Source : in out Bounded_String;
New_Item : Character;
Drop : Truncation := Error)
with
- Pre => (if Length (Source) = Max_Length then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + 1),
- Global => null;
+ Pre => (if Length (Source) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Source) < Max_Length
+ =>
+ Length (Source) = Length (Source'Old) + 1
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then Element (Source, Length (Source'Old) + 1) = New_Item,
+
+ Length (Source) = Max_Length and then Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then To_String (Source) = To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - 1) =
+ Slice (Source'Old, 2, Max_Length)
+ and then Element (Source, Max_Length) = New_Item);
+
+ -- Each of the "&" functions has the same effect as the corresponding
+ -- Append function, with Error as the Drop parameter.
function "&"
(Left : Bounded_String;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Left) <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Length (Left) + Length (Right),
- Global => null;
+ Pre => Length (Left) <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Length (Left) + Length (Right)
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : String) return Bounded_String
with
- Pre => Right'Length <= Max_Length - Length (Left),
- Post => Length ("&"'Result) = Length (Left) + Right'Length,
- Global => null;
+ Pre => Right'Length <= Max_Length - Length (Left),
+ Post => Length ("&"'Result) = Length (Left) + Right'Length
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ Right);
function "&"
(Left : String;
Right : Bounded_String) return Bounded_String
with
- Pre => Left'Length <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Left'Length + Length (Right),
- Global => null;
+ Pre => Left'Length <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Left'Length + Length (Right)
+ and then Slice ("&"'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Left'Length + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : Character) return Bounded_String
with
- Pre => Length (Left) < Max_Length,
- Post => Length ("&"'Result) = Length (Left) + 1,
- Global => null;
+ Pre => Length (Left) < Max_Length,
+ Post => Length ("&"'Result) = Length (Left) + 1
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then Element ("&"'Result, Length (Left) + 1) = Right;
function "&"
(Left : Character;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Right) < Max_Length,
- Post => Length ("&"'Result) = 1 + Length (Right),
- Global => null;
+ Pre => Length (Right) < Max_Length,
+ Post => Length ("&"'Result) = 1 + Length (Right)
+ and then Element ("&"'Result, 1) = Left
+ and then
+ Slice ("&"'Result, 2, Length ("&"'Result)) = To_String (Right);
function Element
(Source : Bounded_String;
@@ -237,6 +561,8 @@ package Ada.Strings.Bounded is
with
Pre => Index <= Length (Source),
Global => null;
+ -- Returns the character at position Index in the string represented by
+ -- Source; propagates Index_Error if Index > Length(Source).
procedure Replace_Element
(Source : in out Bounded_String;
@@ -244,8 +570,14 @@ package Ada.Strings.Bounded is
By : Character)
with
Pre => Index <= Length (Source),
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ (if K = Index then By else Element (Source'Old, K))),
Global => null;
+ -- Updates Source such that the character at position Index in the
+ -- string represented by Source is By; propagates Index_Error if
+ -- Index > Length(Source).
function Slice
(Source : Bounded_String;
@@ -253,8 +585,11 @@ package Ada.Strings.Bounded is
High : Natural) return String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Slice'Result'Length = Natural'Max (0, High - Low + 1),
Global => null;
+ -- Returns the slice at positions Low through High in the
+ -- string represented by Source; propagates Index_Error if
+ -- Low > Length(Source)+1 or High > Length(Source).
+ -- The bounds of the returned string are Low and High.
function Bounded_Slice
(Source : Bounded_String;
@@ -262,10 +597,12 @@ package Ada.Strings.Bounded is
High : Natural) return Bounded_String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post =>
- Length (Bounded_Slice'Result) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Bounded_Slice'Result) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- Returns the slice at positions Low through High in the string
+ -- represented by Source as a bounded string; propagates Index_Error
+ -- if Low > Length(Source)+1 or High > Length(Source).
procedure Bounded_Slice
(Source : Bounded_String;
@@ -274,112 +611,181 @@ package Ada.Strings.Bounded is
High : Natural)
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Length (Target) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Target) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- Equivalent to Target := Bounded_Slice (Source, Low, High);
+
+ -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same
+ -- result as the corresponding String operation applied to the String
+ -- values given or represented by the two parameters.
function "="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = To_String (Right)),
Global => null;
function "="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = Right),
Global => null;
function "="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (Left = To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < Right),
Global => null;
function "<"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (Left < To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= Right),
Global => null;
function "<="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (Left <= To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > Right),
Global => null;
function ">"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (Left > To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= Right),
Global => null;
function ">="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (Left >= To_String (Right)),
Global => null;
----------------------
-- Search Functions --
----------------------
+ -- Each of the search subprograms (Index, Index_Non_Blank, Count,
+ -- Find_Token) has the same effect as the corresponding subprogram in
+ -- Strings.Fixed applied to the string represented by the Bounded_String
+ -- parameter.
+
function Index
(Source : Bounded_String;
Pattern : String;
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 <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -387,8 +793,52 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -396,7 +846,43 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index'Result in 1 .. Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -405,11 +891,60 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -419,11 +954,61 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -433,23 +1018,147 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set)))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source)
+ 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) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
pragma Ada_05 (Index);
function Index_Non_Blank
(Source : Bounded_String;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then Element (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
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index_Non_Blank'Result
+ and then
+ (J < Index_Non_Blank'Result) = (Going = Forward)
+ then Element (Source, J) = ' '))),
+ Global => null;
function Index_Non_Blank
(Source : Bounded_String;
From : Positive;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Element (Source, J) = ' '))
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+ 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 Element (Source, Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (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 Element (Source, J) = ' '))),
+ Global => null;
pragma Ada_05 (Index_Non_Blank);
function Count
@@ -465,7 +1174,7 @@ package Ada.Strings.Bounded is
Pattern : String;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
Global => null;
function Count
@@ -482,8 +1191,53 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ 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.
+
+ (Length (Source) = 0
+ or else
+ (for all J in From .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), 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 .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), 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 < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
pragma Ada_2012 (Find_Token);
procedure Find_Token
@@ -493,44 +1247,127 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Global => null;
+ 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 1 and Last is set to 0.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+ =>
+ First = 1 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 1 .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between 1 and First satisfies the property Test
+ -- on Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), 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 < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
------------------------------------
+ -- Each of the Translate subprograms, when applied to a Bounded_String,
+ -- has an analogous effect to the corresponding subprogram in
+ -- Strings.Fixed. For the Translate function, the translation is applied
+ -- to the string represented by the Bounded_String parameter, and the
+ -- result is converted (via To_Bounded_String) to a Bounded_String. For
+ -- the Translate procedure, the string represented by the Bounded_String
+ -- parameter after the translation is given by the Translate function
+ -- for fixed-length strings applied to the string represented by the
+ -- original value of the parameter.
+
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping)
with
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source'Old, K))),
Global => null;
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping_Function) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Pre => Mapping /= null,
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) = Mapping (Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping_Function)
with
- Post => Length (Source) = Length (Source)'Old,
+ Pre => Mapping /= null,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) = Mapping (Element (Source'Old, K))),
Global => null;
---------------------------------------
-- String Transformation Subprograms --
---------------------------------------
+ -- Each of the transformation subprograms (Replace_Slice, Insert,
+ -- Overwrite, Delete), selector subprograms (Trim, Head, Tail), and
+ -- constructor functions ("*") has an effect based on its corresponding
+ -- subprogram in Strings.Fixed, and Replicate is based on Fixed."*".
+ -- In the case of a function, the corresponding fixed-length string
+ -- subprogram is applied to the string represented by the Bounded_String
+ -- parameter. To_Bounded_String is applied the result string, with Drop
+ -- (or Error in the case of Generic_Bounded_Length."*") determining
+ -- the effect when the string length exceeds Max_Length. In
+ -- the case of a procedure, the corresponding function in
+ -- Strings.Bounded.Generic_Bounded_Length is applied, with the
+ -- result assigned into the Source parameter.
+
function Replace_Slice
(Source : Bounded_String;
Low : Positive;
@@ -541,23 +1378,127 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Replace_Slice'Result)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source) - High,
- 0)),
- others =>
- Length (Replace_Slice'Result)
- = Natural'Min (Max_Length, Length (Source) + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Replace_Slice'Result) = Low - 1 + By'Length
+ + Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+ and then
+ Slice (Replace_Slice'Result, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source) then
+ Slice (Replace_Slice'Result,
+ Low + By'Length, Length (Replace_Slice'Result)) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Natural :=
+ Integer'Max
+ (Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are
+ -- dropped.
+
+ (if Final_Slice < Max_Length then
+ Slice (Replace_Slice'Result,
+ 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Replace_Slice'Result, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Replace_Slice'Result, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Replace_Slice'Result, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Integer'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Replace_Slice'Result,
+ Low + By'Length, Max_Length) =
+ Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
procedure Replace_Slice
(Source : in out Bounded_String;
@@ -569,23 +1510,119 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Natural'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Source)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High,
- 0)),
- others =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+ and then Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source'Old) then
+ Slice (Source, Low + By'Length, Length (Source)) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Integer :=
+ Integer'Max (0,
+ Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Source,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first characters of By are dropped
+
+ (if Final_Slice < Max_Length then
+ Slice (Source, 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Source,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source'Old,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Source, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Source, Low + By'Length, Max_Length) =
+ Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
function Insert
(Source : Bounded_String;
@@ -593,14 +1630,113 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Insert'Result)
- = Natural'Min (Max_Length, Length (Source) + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Insert'Result) = Length (Source) + New_Item'Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+ and then
+ Slice (Insert'Result, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Before + New_Item'Length, Length (Insert'Result)) =
+ Slice (Source, Before, Length (Source))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Max_Length - Length (Source) + Before, Max_Length) =
+ Slice (Source, Before, Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source) - Before + 1 < Max_Length then
+ Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Insert'Result,
+ Max_Length - Length (Source) - New_Item'Length + Before,
+ Max_Length - Length (Source) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source,
+ Length (Source) - Max_Length + New_Item'Length
+ + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Insert'Result, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then Slice (Insert'Result,
+ Before + New_Item'Length, Max_Length) =
+ Slice (Source,
+ Before, Max_Length - New_Item'Length)));
procedure Insert
(Source : in out Bounded_String;
@@ -608,14 +1744,112 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+ and then
+ Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source, Before + New_Item'Length, Length (Source)) =
+ Slice (Source'Old, Before, Length (Source'Old))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + Before, Max_Length) =
+ Slice (Source'Old, Before, Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source'Old) - Before + 1 < Max_Length then
+ Slice (Source,
+ 1, Max_Length - Length (Source'Old) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source'Old)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Source,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ + Before,
+ Max_Length - Length (Source'Old) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source'Old,
+ Length (Source'Old)
+ - Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Source, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ Slice (Source, Before + New_Item'Length, Max_Length) =
+ Slice (Source'Old,
+ Before, Max_Length - New_Item'Length)));
function Overwrite
(Source : Bounded_String;
@@ -623,16 +1857,85 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Overwrite'Result)
- = Natural'Max
- (Length (Source),
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further
+ -- than the end of Source. In this contract case, we suppose
+ -- New_Item doesn't overwrite further than Max_Length.
+
+ Length (Overwrite'Result) =
+ Integer'Max (Length (Source), Position - 1 + New_Item'Length)
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+ and then Slice (Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Overwrite'Result,
+ Position + New_Item'Length, Length (Source)) =
+ Slice (Source,
+ Position + New_Item'Length, Length (Source))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Overwrite'Result) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Overwrite'Result,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Overwrite'Result,
+ 1, Max_Length - New_Item'Length) =
+ Slice (Source,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Overwrite'Result) = Max_Length
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Slice (Overwrite'Result, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
procedure Overwrite
(Source : in out Bounded_String;
@@ -640,16 +1943,84 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Max
- (Length (Source)'Old,
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length of Source is unchanged, unless New_Item overwrites
+ -- further than the end of Source. In this contract case, we
+ -- suppose New_Item doesn't overwrite further than Max_Length.
+
+ Length (Source) = Integer'Max
+ (Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+ and then Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source'Old) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Source,
+ Position + New_Item'Length, Length (Source'Old)) =
+ Slice (Source'Old,
+ Position + New_Item'Length, Length (Source'Old))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Source) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Slice (Source, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
function Delete
(Source : Bounded_String;
@@ -657,13 +2028,20 @@ package Ada.Strings.Bounded is
Through : Natural) return Bounded_String
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Delete'Result) = Length (Source) - (Through - From + 1),
+ Length (Delete'Result) =
+ From - 1 + Natural'Max (Length (Source) - Through, 0)
+ and then
+ Slice (Delete'Result, 1, From - 1) =
+ Slice (Source, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Delete'Result, From, Length (Delete'Result)) =
+ Slice (Source, Through + 1, Length (Source))),
others =>
- Length (Delete'Result) = Length (Source)),
-
+ Delete'Result = Source),
Global => null;
procedure Delete
@@ -672,12 +2050,19 @@ package Ada.Strings.Bounded is
Through : Natural)
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Source) = Length (Source)'Old - (Through - From + 1),
+ Length (Source) =
+ From - 1 + Natural'Max (Length (Source'Old) - Through, 0)
+ and then
+ Slice (Source, 1, From - 1) = Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Source, From, Length (Source)) =
+ Slice (Source'Old, Through + 1, Length (Source'Old))),
others =>
- Length (Source) = Length (Source)'Old),
+ Source = Source'Old),
Global => null;
---------------------------------
@@ -688,31 +2073,111 @@ package Ada.Strings.Bounded is
(Source : Bounded_String;
Side : Trim_End) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source)
+ else Index_Non_Blank (Source, Backward));
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Side : Trim_End)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source'Old)
+ else Index_Non_Blank (Source'Old, Backward));
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Trim
(Source : Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source'Old, Right, Outside, Backward);
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Head
(Source : Bounded_String;
@@ -720,9 +2185,54 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Head'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Head'Result) = Slice (Source, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Count
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Count) =
+ (1 .. Count - Length (Source) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped at the left
+
+ To_String (Head'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the left
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Max_Length - Count + Length (Source)) =
+ Slice (Source, Count - Max_Length + 1, Length (Source))
+ and then
+ Slice (Head'Result,
+ Max_Length - Count + Length (Source) + 1, Max_Length) =
+ (1 .. Count - Length (Source) => Pad));
procedure Head
(Source : in out Bounded_String;
@@ -730,9 +2240,57 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Source) = Slice (Source'Old, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Count) =
+ (1 .. Count - Length (Source'Old) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source'Old) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Count + Length (Source'Old)) =
+ Slice (Source'Old,
+ Count - Max_Length + 1, Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - Count + Length (Source'Old) + 1, Max_Length) =
+ (1 .. Count - Length (Source'Old) => Pad));
function Tail
(Source : Bounded_String;
@@ -740,9 +2298,60 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Tail'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Tail'Result) =
+ Slice (Source, Length (Source) - Count + 1, Length (Source))
+ else Length (Tail'Result) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Count
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Count) =
+ To_String (Source),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Max_Length - Length (Source)) =
+ (1 .. Max_Length - Length (Source) => Pad)
+ and then
+ (if Length (Source) > 0 then
+ Slice (Tail'Result,
+ Max_Length - Length (Source) + 1, Max_Length) =
+ To_String (Source)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ To_String (Tail'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Max_Length) =
+ Slice (Source, 1, Max_Length - Count + Length (Source)));
procedure Tail
(Source : in out Bounded_String;
@@ -750,9 +2359,62 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Source) =
+ Slice (Source'Old,
+ Length (Source'Old) - Count + 1, Length (Source'Old))
+ else Length (Source) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Count) =
+ To_String (Source'Old),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Length (Source'Old)) =
+ (1 .. Max_Length - Length (Source'Old) => Pad)
+ and then
+ (if Length (Source'Old) > 0 then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + 1, Max_Length) =
+ To_String (Source'Old)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped at the right
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the right
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Max_Length) =
+ Slice (Source'Old,
+ 1, Max_Length - Count + Length (Source'Old)));
------------------------------------
-- String Constructor Subprograms --
@@ -762,64 +2424,113 @@ package Ada.Strings.Bounded is
(Left : Natural;
Right : Character) return Bounded_String
with
- Pre => Left <= Max_Length,
- Post => Length ("*"'Result) = Left,
- Global => null;
+ Pre => Left <= Max_Length,
+ Post => To_String ("*"'Result) = (1 .. Left => Right);
function "*"
(Left : Natural;
Right : String) return Bounded_String
with
- Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Right'Length,
- Global => null;
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Element ("*"'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length)));
function "*"
(Left : Natural;
Right : Bounded_String) return Bounded_String
with
- Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Length (Right),
- Global => null;
+ Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Length (Right)
+ and then
+ (if Length (Right) > 0 then
+ (for all K in 1 .. Left * Length (Right) =>
+ Element ("*"'Result, K) =
+ Element (Right, 1 + (K - 1) mod Length (Right))));
function Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post =>
+ To_String (Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item);
function Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Item'Length /= 0
- and then Count > Max_Length / Item'Length
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Length (Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length)));
function Replicate
(Count : Natural;
Item : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Length (Item) /= 0
- and then Count > Max_Length / Length (Item)
+ Pre =>
+ (if Count /= 0 and then Length (Item) > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Length (Item)),
- Global => null;
+ Contract_Cases =>
+ ((if Count /= 0 then Length (Item) <= Max_Length / Count)
+ =>
+ Length (Replicate'Result) = Count * Length (Item)
+ and then
+ (if Length (Item) > 0 then
+ (for all K in 1 .. Count * Length (Item) =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item)))),
+ Count /= 0
+ and then Length (Item) > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item))),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item,
+ Length (Item) - (Max_Length - K) mod Length (Item))));
private
-- Most of the implementation is in the separate non generic package
@@ -843,7 +2554,8 @@ package Ada.Strings.Bounded is
-- the generic instantiation is compatible with the Super_String
-- type declared in the Superbounded package.
- function From_String (Source : String) return Bounded_String;
+ function From_String (Source : String) return Bounded_String
+ with Pre => Source'Length <= Max_Length;
-- Private routine used only by Stream_Convert
pragma Stream_Convert (Bounded_String, From_String, To_String);
diff --git a/gcc/ada/libgnat/a-strfix.adb b/gcc/ada/libgnat/a-strfix.adb
index ee72b6b..31dea6c 100644
--- a/gcc/ada/libgnat/a-strfix.adb
+++ b/gcc/ada/libgnat/a-strfix.adb
@@ -38,10 +38,17 @@
-- bounds of function return results were also fixed, and use of & removed for
-- efficiency reasons.
+-- Ghost code, loop invariants and assertions in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
with Ada.Strings.Maps; use Ada.Strings.Maps;
-with Ada.Strings.Search;
-package body Ada.Strings.Fixed is
+package body Ada.Strings.Fixed with SPARK_Mode is
------------------------
-- Search Subprograms --
@@ -146,9 +153,12 @@ package body Ada.Strings.Fixed is
Right : Character) return String
is
begin
- return Result : String (1 .. Left) do
+ return Result : String (1 .. Left) with Relaxed_Initialization do
for J in Result'Range loop
Result (J) := Right;
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result (K)'Initialized and then Result (K) = Right);
end loop;
end return;
end "*";
@@ -157,12 +167,83 @@ package body Ada.Strings.Fixed is
(Left : Natural;
Right : String) return String
is
- Ptr : Integer := 1;
+ Ptr : Integer := 0;
+
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Integer) with
+ Ghost,
+ Pre =>
+ Right'Length /= 0
+ and then Ptr mod Right'Length = 0
+ and then Ptr in 0 .. Natural'Last - Right'Length
+ and then K in Ptr .. Ptr + Right'Length - 1,
+ Post => K mod Right'Length = K - Ptr;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Right'Length.
+
+ procedure Lemma_Split (Result : String) with
+ Ghost,
+ Relaxed_Initialization => Result,
+ Pre =>
+ Right'Length /= 0
+ and then Result'First = 1
+ and then Result'Last >= 0
+ and then Ptr mod Right'Length = 0
+ and then Ptr in 0 .. Result'Last - Right'Length
+ and then Result (Result'First .. Ptr + Right'Length)'Initialized
+ and then Result (Ptr + 1 .. Ptr + Right'Length) = Right,
+ Post =>
+ (for all K in Ptr + 1 .. Ptr + Right'Length =>
+ Result (K) = Right (Right'First + (K - 1) mod Right'Length));
+ -- Lemma_Split is used after Result (Ptr + 1 .. Ptr + Right'Length) is
+ -- updated to Right and concludes that the characters match for each
+ -- index when taken modulo Right'Length, as the considered slice starts
+ -- at index 1 modulo Right'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Integer) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split (Result : String)
+ is
+ begin
+ for K in Ptr + 1 .. Ptr + Right'Length loop
+ Lemma_Mod (K - 1);
+ pragma Loop_Invariant
+ (for all J in Ptr + 1 .. K =>
+ Result (J) = Right (Right'First + (J - 1) mod Right'Length));
+ end loop;
+ end Lemma_Split;
+
+ -- Start of processing for "*"
+
begin
- return Result : String (1 .. Left * Right'Length) do
+ if Right'Length = 0 then
+ return "";
+ end if;
+
+ return Result : String (1 .. Left * Right'Length)
+ with Relaxed_Initialization
+ do
for J in 1 .. Left loop
- Result (Ptr .. Ptr + Right'Length - 1) := Right;
+ Result (Ptr + 1 .. Ptr + Right'Length) := Right;
+ Lemma_Split (Result);
Ptr := Ptr + Right'Length;
+ pragma Loop_Invariant (Ptr = J * Right'Length);
+ pragma Loop_Invariant (Result (1 .. Ptr)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Ptr =>
+ Result (K) = Right (Right'First + (K - 1) mod Right'Length));
end loop;
end return;
end "*";
@@ -176,7 +257,6 @@ package body Ada.Strings.Fixed is
From : Positive;
Through : Natural) return String
is
- Front : Integer;
begin
if From > Through then
declare
@@ -204,13 +284,22 @@ package body Ada.Strings.Fixed is
end if;
else
- Front := From - Source'First;
- return Result : String (1 .. Source'Length - (Through - From + 1)) do
- Result (1 .. Front) :=
- Source (Source'First .. From - 1);
- Result (Front + 1 .. Result'Last) :=
- Source (Through + 1 .. Source'Last);
- end return;
+ declare
+ Front : constant Integer := From - Source'First;
+
+ begin
+ return Result : String (1 .. Source'Length - (Through - From + 1))
+ with Relaxed_Initialization
+ do
+ Result (1 .. Front) :=
+ Source (Source'First .. From - 1);
+
+ if Through < Source'Last then
+ Result (Front + 1 .. Result'Last) :=
+ Source (Through + 1 .. Source'Last);
+ end if;
+ end return;
+ end;
end if;
end Delete;
@@ -240,16 +329,19 @@ package body Ada.Strings.Fixed is
subtype Result_Type is String (1 .. Count);
begin
- if Count < Source'Length then
+ if Count <= Source'Length then
return
- Result_Type (Source (Source'First .. Source'First + Count - 1));
+ Result_Type (Source (Source'First .. Source'First + (Count - 1)));
else
- return Result : Result_Type do
+ return Result : Result_Type with Relaxed_Initialization do
Result (1 .. Source'Length) := Source;
for J in Source'Length + 1 .. Count loop
Result (J) := Pad;
+ pragma Loop_Invariant
+ (for all K in Source'Length + 1 .. J =>
+ Result (K)'Initialized and then Result (K) = Pad);
end loop;
end return;
end if;
@@ -281,17 +373,31 @@ package body Ada.Strings.Fixed is
Front : constant Integer := Before - Source'First;
begin
- if Before not in Source'First .. Source'Last + 1 then
+ if Before - 1 not in Source'First - 1 .. Source'Last then
raise Index_Error;
end if;
- return Result : String (1 .. Source'Length + New_Item'Length) do
+ return Result : String (1 .. Source'Length + New_Item'Length)
+ with Relaxed_Initialization
+ do
Result (1 .. Front) :=
Source (Source'First .. Before - 1);
Result (Front + 1 .. Front + New_Item'Length) :=
New_Item;
- Result (Front + New_Item'Length + 1 .. Result'Last) :=
- Source (Before .. Source'Last);
+ pragma Assert
+ (Result
+ (Before - Source'First + 1
+ .. Before - Source'First + New_Item'Length)
+ = New_Item);
+
+ if Before <= Source'Last then
+ Result (Front + New_Item'Length + 1 .. Result'Last) :=
+ Source (Before .. Source'Last);
+ end if;
+
+ pragma Assert
+ (Result (1 .. Before - Source'First)
+ = Source (Source'First .. Before - 1));
end return;
end Insert;
@@ -317,6 +423,7 @@ package body Ada.Strings.Fixed is
Drop : Truncation := Error;
Justify : Alignment := Left;
Pad : Character := Space)
+ with SPARK_Mode => Off
is
Sfirst : constant Integer := Source'First;
Slast : constant Integer := Source'Last;
@@ -423,7 +530,7 @@ package body Ada.Strings.Fixed is
Position : Positive;
New_Item : String) return String is
begin
- if Position not in Source'First .. Source'Last + 1 then
+ if Position - 1 not in Source'First - 1 .. Source'Last then
raise Index_Error;
end if;
@@ -434,11 +541,32 @@ package body Ada.Strings.Fixed is
Front : constant Integer := Position - Source'First;
begin
- return Result : String (1 .. Result_Length) do
+ return Result : String (1 .. Result_Length)
+ with Relaxed_Initialization
+ do
Result (1 .. Front) := Source (Source'First .. Position - 1);
+ pragma Assert
+ (Result (1 .. Position - Source'First)
+ = Source (Source'First .. Position - 1));
Result (Front + 1 .. Front + New_Item'Length) := New_Item;
- Result (Front + New_Item'Length + 1 .. Result'Length) :=
- Source (Position + New_Item'Length .. Source'Last);
+ pragma Assert
+ (Result
+ (Position - Source'First + 1
+ .. Position - Source'First + New_Item'Length)
+ = New_Item);
+
+ if Position <= Source'Last - New_Item'Length then
+ Result (Front + New_Item'Length + 1 .. Result'Last) :=
+ Source (Position + New_Item'Length .. Source'Last);
+ end if;
+
+ pragma Assert
+ (if Position <= Source'Last - New_Item'Length
+ then
+ Result
+ (Position - Source'First + New_Item'Length + 1
+ .. Result'Last)
+ = Source (Position + New_Item'Length .. Source'Last));
end return;
end;
end Overwrite;
@@ -463,10 +591,9 @@ package body Ada.Strings.Fixed is
(Source : String;
Low : Positive;
High : Natural;
- By : String) return String
- is
+ By : String) return String is
begin
- if Low > Source'Last + 1 or else High < Source'First - 1 then
+ if Low - 1 > Source'Last or else High < Source'First - 1 then
raise Index_Error;
end if;
@@ -484,11 +611,34 @@ package body Ada.Strings.Fixed is
-- Length of result
begin
- return Result : String (1 .. Result_Length) do
+ return Result : String (1 .. Result_Length)
+ with Relaxed_Initialization do
Result (1 .. Front_Len) := Source (Source'First .. Low - 1);
+ pragma Assert
+ (Result (1 .. Integer'Max (0, Low - Source'First))
+ = Source (Source'First .. Low - 1));
Result (Front_Len + 1 .. Front_Len + By'Length) := By;
- Result (Front_Len + By'Length + 1 .. Result'Length) :=
- Source (High + 1 .. Source'Last);
+
+ if High < Source'Last then
+ Result (Front_Len + By'Length + 1 .. Result'Last) :=
+ Source (High + 1 .. Source'Last);
+ end if;
+
+ pragma Assert
+ (Result (1 .. Integer'Max (0, Low - Source'First))
+ = Source (Source'First .. Low - 1));
+ pragma Assert
+ (Result
+ (Integer'Max (0, Low - Source'First) + 1
+ .. Integer'Max (0, Low - Source'First) + By'Length)
+ = By);
+ pragma Assert
+ (if High < Source'Last
+ then
+ Result
+ (Integer'Max (0, Low - Source'First) + By'Length + 1
+ .. Result'Last)
+ = Source (High + 1 .. Source'Last));
end return;
end;
else
@@ -521,18 +671,26 @@ package body Ada.Strings.Fixed is
subtype Result_Type is String (1 .. Count);
begin
- if Count < Source'Length then
+ if Count = 0 then
+ return "";
+
+ elsif Count < Source'Length then
return Result_Type (Source (Source'Last - Count + 1 .. Source'Last));
-- Pad on left
else
- return Result : Result_Type do
+ return Result : Result_Type with Relaxed_Initialization do
for J in 1 .. Count - Source'Length loop
Result (J) := Pad;
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result (K)'Initialized and then Result (K) = Pad);
end loop;
- Result (Count - Source'Length + 1 .. Count) := Source;
+ if Source'Length /= 0 then
+ Result (Count - Source'Length + 1 .. Count) := Source;
+ end if;
end return;
end if;
end Tail;
@@ -560,9 +718,18 @@ package body Ada.Strings.Fixed is
Mapping : Maps.Character_Mapping) return String
is
begin
- return Result : String (1 .. Source'Length) do
+ return Result : String (1 .. Source'Length)
+ with Relaxed_Initialization
+ do
for J in Source'Range loop
Result (J - (Source'First - 1)) := Value (Mapping, Source (J));
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Result (K - (Source'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Result (K - (Source'First - 1)) =
+ Value (Mapping, Source (K)));
end loop;
end return;
end Translate;
@@ -574,6 +741,9 @@ package body Ada.Strings.Fixed is
begin
for J in Source'Range loop
Source (J) := Value (Mapping, Source (J));
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Source (K) = Value (Mapping, Source'Loop_Entry (K)));
end loop;
end Translate;
@@ -583,9 +753,17 @@ package body Ada.Strings.Fixed is
is
pragma Unsuppress (Access_Check);
begin
- return Result : String (1 .. Source'Length) do
+ return Result : String (1 .. Source'Length)
+ with Relaxed_Initialization
+ do
for J in Source'Range loop
Result (J - (Source'First - 1)) := Mapping.all (Source (J));
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Result (K - (Source'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Result (K - (Source'First - 1)) = Mapping (Source (K)));
end loop;
end return;
end Translate;
@@ -598,6 +776,9 @@ package body Ada.Strings.Fixed is
begin
for J in Source'Range loop
Source (J) := Mapping.all (Source (J));
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ Source (K) = Mapping (Source'Loop_Entry (K)));
end loop;
end Translate;
@@ -609,6 +790,9 @@ package body Ada.Strings.Fixed is
(Source : String;
Side : Trim_End) return String
is
+ Empty_String : constant String (1 .. 0) := "";
+ -- Without declaring the empty string as a separate string starting
+ -- at 1, SPARK provers have trouble proving the postcondition.
begin
case Side is
when Strings.Left =>
@@ -618,7 +802,7 @@ package body Ada.Strings.Fixed is
-- All blanks case
if Low = 0 then
- return "";
+ return Empty_String;
end if;
declare
@@ -635,7 +819,7 @@ package body Ada.Strings.Fixed is
-- All blanks case
if High = 0 then
- return "";
+ return Empty_String;
end if;
declare
@@ -652,7 +836,7 @@ package body Ada.Strings.Fixed is
-- All blanks case
if Low = 0 then
- return "";
+ return Empty_String;
end if;
declare
@@ -687,7 +871,7 @@ package body Ada.Strings.Fixed is
High, Low : Integer;
begin
- Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
+ Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
-- Case where source comprises only characters in Left
@@ -695,8 +879,7 @@ package body Ada.Strings.Fixed is
return "";
end if;
- High :=
- Index (Source, Set => Right, Test => Outside, Going => Backward);
+ High := Index (Source, Set => Right, Test => Outside, Going => Backward);
-- Case where source comprises only characters in Right
@@ -705,7 +888,8 @@ package body Ada.Strings.Fixed is
end if;
declare
- subtype Result_Type is String (1 .. High - Low + 1);
+ Result_Length : constant Integer := High - Low + 1;
+ subtype Result_Type is String (1 .. Result_Length);
begin
return Result_Type (Source (Low .. High));
diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads
index 4214157..1d9fd1b 100644
--- a/gcc/ada/libgnat/a-strfix.ads
+++ b/gcc/ada/libgnat/a-strfix.ads
@@ -13,14 +13,6 @@
-- --
------------------------------------------------------------------------------
--- 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.Strings.Maps;
-
-- The language-defined package Strings.Fixed provides string-handling
-- subprograms for fixed-length strings; that is, for values of type
-- Standard.String. Several of these subprograms are procedures that modify
@@ -40,6 +32,20 @@ with Ada.Strings.Maps;
-- these effects. Similar control is provided by the string transformation
-- procedures.
+-- 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. Postconditions and
+-- contract cases should not be executed at runtime as well, in order not to
+-- slow down the execution of these functions.
+
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
+with Ada.Strings.Search;
+
package Ada.Strings.Fixed with SPARK_Mode is
pragma Preelaborate;
@@ -108,56 +114,60 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre =>
- Pattern'Length /= 0
- and then (if Source'Length /= 0 then From in Source'Range),
+ Pre => Pattern'Length > 0
+ and then Mapping /= null
+ and then (if Source'Length > 0 then From in Source'Range),
Post => Index'Result in 0 | Source'Range,
Contract_Cases =>
- -- If no slice in the considered range of Source matches Pattern,
- -- then 0 is returned.
+ -- If Source is the empty string, 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))
+ (Source'Length = 0
=>
Index'Result = 0,
- -- Otherwise, a valid index is returned
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
- others
+ Source'Length > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1) =>
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, J))
=>
-
-- 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)
+ Index'Result in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else 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
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, Index'Result)
- -- The result is the smallest or largest index which satisfies the
- -- matching, respectively when Going = Forward and
- -- Going = Backwards.
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
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))),
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Ada.Strings.Search.Match
+ (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
Global => null;
pragma Ada_05 (Index);
@@ -168,56 +178,59 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre =>
- Pattern'Length /= 0
- and then (if Source'Length /= 0 then From in Source'Range),
+ Pre => Pattern'Length > 0
+ and then (if Source'Length > 0 then From in Source'Range),
Post => Index'Result in 0 | Source'Range,
Contract_Cases =>
- -- If no slice in the considered range of Source matches Pattern,
- -- then 0 is returned.
+ -- If Source is the empty string, 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))
+ (Source'Length = 0
=>
Index'Result = 0,
- -- Otherwise, a valid index is returned
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
- others
+ Source'Length > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1) =>
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, J))
=>
-
-- 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)
+ Index'Result in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1)
- -- The slice beginning at the returned index matches Pattern
+ -- The slice beginning at the returned index matches Pattern
- and then
- Translate (Source (Index'Result
- .. Index'Result - 1 + Pattern'Length),
- Mapping)
- = Pattern
+ and then
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, Index'Result)
-- The result is the smallest or largest index which satisfies the
-- matching, respectively when Going = Forward and
- -- Going = Backwards.
+ -- Going = Backward.
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))),
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Ada.Strings.Search.Match
+ (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
Global => null;
pragma Ada_05 (Index);
@@ -245,37 +258,33 @@ package Ada.Strings.Fixed with SPARK_Mode is
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.
+ -- If Source is the empty string, 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
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
- others
+ Source'Length > 0
+ and then
+ (for some J in
+ Source'First .. Source'Last - (Pattern'Length - 1) =>
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, J))
=>
-
-- The result is in the considered range of Source
- Index'Result in Source'First .. Source'Last - Pattern'Length + 1
+ 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
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, Index'Result)
- -- The result is the smallest or largest index which satisfies the
- -- matching, respectively when Going = Forward and
- -- Going = Backwards.
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
and then
(for all J in Source'Range =>
@@ -283,9 +292,14 @@ package Ada.Strings.Fixed with SPARK_Mode is
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))),
+ then not (Ada.Strings.Search.Match
+ (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
Global => null;
function Index
@@ -294,42 +308,38 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length > 0,
+ Pre => Pattern'Length > 0 and then Mapping /= null,
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.
+ -- If Source is the empty string, 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
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
- others
+ Source'Length > 0
+ and then
+ (for some J in
+ Source'First .. Source'Last - (Pattern'Length - 1) =>
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, J))
=>
-
-- The result is in the considered range of Source
- Index'Result in Source'First .. Source'Last - Pattern'Length + 1
+ Index'Result in Source'First .. Source'Last - (Pattern'Length - 1)
- -- The slice beginning at the returned index matches Pattern
+ -- The slice beginning at the returned index matches Pattern
- and then
- Translate (Source (Index'Result
- .. Index'Result - 1 + Pattern'Length),
- Mapping)
- = Pattern
+ and then
+ Ada.Strings.Search.Match (Source, Pattern, Mapping, Index'Result)
- -- The result is the smallest or largest index which satisfies the
- -- matching, respectively when Going = Forward and
- -- Going = Backwards.
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
and then
(for all J in Source'Range =>
@@ -337,9 +347,14 @@ package Ada.Strings.Fixed with SPARK_Mode is
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))),
+ then not (Ada.Strings.Search.Match
+ (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
Global => null;
-- If Going = Forward, returns:
@@ -367,7 +382,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the range of Source is returned
+ -- Otherwise, an index in the range of Source is returned
others
=>
@@ -377,15 +392,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
Index'Result in Source'Range
-- The character at the returned index satisfies the property
- -- Test on Set
+ -- 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.
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
and then
(for all J in Source'Range =>
@@ -402,22 +417,23 @@ 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),
-
+ 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.
+ -- If Source is the empty string, or no character of 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)))
+ (Source'Length = 0
+ or else
+ (for all J in Source'Range =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (Source (J), Set)))
=>
Index'Result = 0,
- -- Otherwise, an index in the range of Source is returned
+ -- Otherwise, an index in the considered range of Source is returned
others
=>
@@ -426,7 +442,8 @@ package Ada.Strings.Fixed with SPARK_Mode is
Index'Result in Source'Range
and then (Index'Result = From
- or else (Index'Result > From) = (Going = Forward))
+ or else
+ (Index'Result > From) = (Going = Forward))
-- The character at the returned index satisfies the property
-- Test on Set.
@@ -435,19 +452,18 @@ package Ada.Strings.Fixed with SPARK_Mode is
(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.
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
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)))),
+ 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
@@ -469,12 +485,14 @@ package Ada.Strings.Fixed with SPARK_Mode is
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.
+ -- If Source is the empty string, or 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) = ' '))
+ (Source'Length = 0
+ or else
+ (for all J in Source'Range =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Source (J) = ' '))
=>
Index_Non_Blank'Result = 0,
@@ -496,7 +514,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- The result is the smallest or largest index which is not a
-- Space character, respectively when Going = Forward and
- -- Going = Backwards.
+ -- Going = Backward.
and then
(for all J in Source'Range =>
@@ -535,8 +553,8 @@ package Ada.Strings.Fixed with SPARK_Mode is
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.
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
and then
(for all J in Source'Range =>
@@ -560,7 +578,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
Pattern : String;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
Global => null;
-- Returns the maximum number of nonoverlapping slices of Source that match
@@ -646,6 +664,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
First : out Positive;
Last : out Natural)
with
+ Pre => Source'First > 0,
Contract_Cases =>
-- If Source is the empty string, or if no character of Source
@@ -701,6 +720,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : String;
Mapping : Maps.Character_Mapping_Function) return String
with
+ Pre => Mapping /= null,
Post =>
-- Lower bound of the returned string is 1
@@ -751,10 +771,11 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Mapping : Maps.Character_Mapping_Function)
with
+ Pre => Mapping /= null,
Post =>
- -- Each character in Source after the call is the translation of
- -- the character at the same position before the call, through Mapping.
+ -- 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;
@@ -765,8 +786,8 @@ package Ada.Strings.Fixed with SPARK_Mode is
with
Post =>
- -- Each character in Source after the call is the translation of
- -- the character at the same position before the call, through Mapping.
+ -- 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))),
@@ -778,32 +799,6 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- String Transformation Subprograms --
---------------------------------------
- procedure Replace_Slice
- (Source : in out String;
- Low : Positive;
- High : Natural;
- By : String;
- Drop : Truncation := Error;
- Justify : Alignment := Left;
- Pad : Character := Space)
- with
- Pre =>
-
- -- Incomplete contract
-
- Low - 1 <= Source'Last
- and then High >= Source'First - 1,
- Global => null;
- -- If Low > Source'Last+1, or High < Source'First - 1, then Index_Error is
- -- propagated. Otherwise:
- --
- -- * If High >= Low, then the returned string comprises
- -- Source (Source'First .. Low - 1)
- -- & By & Source(High + 1 .. Source'Last), but with lower bound 1.
- --
- -- * If High < Low, then the returned string is
- -- Insert (Source, Before => Low, New_Item => By).
-
function Replace_Slice
(Source : String;
Low : Positive;
@@ -834,19 +829,19 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- Length of the returned string
Replace_Slice'Result'Length
- = Natural'Max (0, Low - Source'First)
+ = Integer'Max (0, Low - Source'First)
+ By'Length
- + Natural'Max (Source'Last - High, 0)
+ + Integer'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))
+ Replace_Slice'Result (1 .. Integer'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)
+ (Integer'Max (0, Low - Source'First) + 1
+ .. Integer'Max (0, Low - Source'First) + By'Length)
= By
-- When there are remaining characters after the replaced slice,
@@ -856,7 +851,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
(if High < Source'Last
then
Replace_Slice'Result
- (Natural'Max (0, Low - Source'First) + By'Length + 1
+ (Integer'Max (0, Low - Source'First) + By'Length + 1
.. Replace_Slice'Result'Last)
= Source (High + 1 .. Source'Last)),
@@ -890,6 +885,38 @@ package Ada.Strings.Fixed with SPARK_Mode is
.. Replace_Slice'Result'Last)
= Source (Low .. Source'Last))),
Global => null;
+ -- If Low > Source'Last + 1, or High < Source'First - 1, then Index_Error
+ -- is propagated. Otherwise:
+ --
+ -- * If High >= Low, then the returned string comprises
+ -- Source (Source'First .. Low - 1)
+ -- & By & Source(High + 1 .. Source'Last), but with lower bound 1.
+ --
+ -- * If High < Low, then the returned string is
+ -- Insert (Source, Before => Low, New_Item => By).
+
+ procedure Replace_Slice
+ (Source : in out String;
+ Low : Positive;
+ High : Natural;
+ By : String;
+ Drop : Truncation := Error;
+ Justify : Alignment := Left;
+ Pad : Character := Space)
+ with
+ Pre =>
+ Low - 1 <= Source'Last
+ 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)
+ else Source'Length <= Natural'Last - By'Length),
+
+ -- Incomplete contract
+
+ Global => null;
-- Equivalent to:
--
-- Move (Replace_Slice (Source, Low, High, By),
@@ -929,7 +956,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- are appended to the returned string.
and then
- (if Before - 1 < Source'Last
+ (if Before <= Source'Last
then
Insert'Result
(Before - Source'First + New_Item'Length + 1
@@ -937,7 +964,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
= Source (Before .. Source'Last)),
Global => null;
-- Propagates Index_Error if Before is not in
- -- Source'First .. Source'Last+1; otherwise, returns
+ -- Source'First .. Source'Last + 1; otherwise, returns
-- Source (Source'First .. Before - 1)
-- & New_Item & Source(Before..Source'Last), but with lower bound 1.
@@ -947,7 +974,9 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Error)
with
- Pre => Before - 1 in Source'First - 1 .. Source'Last,
+ Pre =>
+ Before - 1 in Source'First - 1 .. Source'Last
+ and then Source'Length <= Natural'Last - New_Item'Length,
-- Incomplete contract
@@ -1014,7 +1043,11 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Right)
with
- Pre => Position - 1 in Source'First - 1 .. Source'Last,
+ 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),
-- Incomplete contract
@@ -1114,31 +1147,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- 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) = ' '))))),
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then Source'First
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Source'Last
+ else Index_Non_Blank (Source, Backward));
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading Space
-- characters (if Side = Left), all trailing Space characters (if
@@ -1184,30 +1201,13 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- 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)))))),
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading
-- characters in Left and all trailing characters in Right.
@@ -1384,9 +1384,8 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- 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),
+ (for all K in "*"'Result'Range =>
+ "*"'Result (K) = Right (Right'First + (K - 1) mod Right'Length)),
Global => null;
-- These functions replicate a character or string a specified number of
diff --git a/gcc/ada/libgnat/a-strmap.adb b/gcc/ada/libgnat/a-strmap.adb
index 8ad9f12..c87f4e5 100644
--- a/gcc/ada/libgnat/a-strmap.adb
+++ b/gcc/ada/libgnat/a-strmap.adb
@@ -35,7 +35,17 @@
-- is bit-by-bit or character-by-character and therefore rather slow.
-- Generally for character sets we favor the full 32-byte representation.
-package body Ada.Strings.Maps is
+-- Assertions, ghost code and loop invariants in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
+
+pragma Assertion_Policy (Assert => Ignore,
+ Ghost => Ignore,
+ Loop_Invariant => Ignore);
+
+package body Ada.Strings.Maps
+ with SPARK_Mode
+is
---------
-- "-" --
@@ -102,9 +112,7 @@ package body Ada.Strings.Maps is
(Element : Character;
Set : Character_Set) return Boolean
is
- begin
- return Set (Element);
- end Is_In;
+ (Set (Element));
---------------
-- Is_Subset --
@@ -122,18 +130,37 @@ package body Ada.Strings.Maps is
-- To_Domain --
---------------
- function To_Domain (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Domain (Map : Character_Mapping) return Character_Sequence is
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := C;
+ Indexes (C) := J;
end if;
+
+ pragma Loop_Invariant (if Map = Identity then J = 0);
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Result (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Result (Indexes (D)) = D));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. J) => Map (Char) /= Char);
end loop;
return Result (1 .. J);
@@ -146,7 +173,7 @@ package body Ada.Strings.Maps is
function To_Mapping
(From, To : Character_Sequence) return Character_Mapping
is
- Result : Character_Mapping;
+ Result : Character_Mapping with Relaxed_Initialization;
Inserted : Character_Set := Null_Set;
From_Len : constant Natural := From'Length;
To_Len : constant Natural := To'Length;
@@ -158,6 +185,9 @@ package body Ada.Strings.Maps is
for Char in Character loop
Result (Char) := Char;
+ pragma Loop_Invariant (Result (Result'First .. Char)'Initialized);
+ pragma Loop_Invariant
+ (for all C in Result'First .. Char => Result (C) = C);
end loop;
for J in From'Range loop
@@ -167,6 +197,23 @@ package body Ada.Strings.Maps is
Result (From (J)) := To (J - From'First + To'First);
Inserted (From (J)) := True;
+
+ pragma Loop_Invariant (Result'Initialized);
+ pragma Loop_Invariant
+ (for all K in From'First .. J =>
+ Result (From (K)) = To (K - From'First + To'First)
+ and then Inserted (From (K)));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (Inserted (Char) =
+ (for some K in From'First .. J => Char = From (K))));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (if not Inserted (Char) then Result (Char) = Char));
+ pragma Loop_Invariant
+ (if (for all K in From'First .. J =>
+ From (K) = To (J - From'First + To'First))
+ then Result = Identity);
end loop;
return Result;
@@ -176,19 +223,195 @@ package body Ada.Strings.Maps is
-- To_Range --
--------------
- function To_Range (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Range (Map : Character_Mapping) return Character_Sequence is
+
+ -- Extract from the postcondition of To_Domain the essential properties
+ -- that define Seq as the domain of Map.
+ function Is_Domain
+ (Map : Character_Mapping;
+ Seq : Character_Sequence)
+ return Boolean
+ is
+ (Seq'First = 1
+ and then
+ SPARK_Proof_Sorted_Character_Sequence (Seq)
+ and then
+ (for all Char in Character =>
+ (if (for all X of Seq => X /= Char)
+ then Map (Char) = Char))
+ and then
+ (for all Char of Seq => Map (Char) /= Char))
+ with
+ Ghost;
+
+ -- Given Map, there is a unique sequence Seq for which
+ -- Is_Domain(Map,Seq) holds.
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ with
+ Ghost,
+ Pre => Is_Domain (Map, Seq1)
+ and then Is_Domain (Map, Seq2),
+ Post => Seq1 = Seq2;
+
+ -- Isolate the proof that To_Domain(Map) returns a sequence for which
+ -- Is_Domain holds.
+ procedure Lemma_Is_Domain (Map : Character_Mapping)
+ with
+ Ghost,
+ Post => Is_Domain (Map, To_Domain (Map));
+
+ -- Deduce the alternative expression of sortedness from the one in
+ -- SPARK_Proof_Sorted_Character_Sequence which compares consecutive
+ -- elements.
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence)
+ with
+ Ghost,
+ Pre => SPARK_Proof_Sorted_Character_Sequence (Seq),
+ Post => (for all J in Seq'Range =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+
+ --------------------------
+ -- Lemma_Domain_Unicity --
+ --------------------------
+
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ is
+ J : Positive := 1;
+
+ begin
+ while J <= Seq1'Last
+ and then J <= Seq2'Last
+ and then Seq1 (J) = Seq2 (J)
+ loop
+ pragma Loop_Invariant
+ (Seq1 (Seq1'First .. J) = Seq2 (Seq2'First .. J));
+
+ if J = Positive'Last then
+ return;
+ end if;
+
+ J := J + 1;
+ end loop;
+
+ Lemma_Is_Sorted (Seq1);
+ Lemma_Is_Sorted (Seq2);
+
+ if J <= Seq1'Last
+ and then J <= Seq2'Last
+ then
+ if Seq1 (J) < Seq2 (J) then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+ else
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+
+ elsif J <= Seq1'Last then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+
+ elsif J <= Seq2'Last then
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+ end Lemma_Domain_Unicity;
+
+ ---------------------
+ -- Lemma_Is_Domain --
+ ---------------------
+
+ procedure Lemma_Is_Domain (Map : Character_Mapping) is
+ Ignore : constant Character_Sequence := To_Domain (Map);
+ begin
+ null;
+ end Lemma_Is_Domain;
+
+ ---------------------
+ -- Lemma_Is_Sorted --
+ ---------------------
+
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence) is
+ begin
+ for A in Seq'Range loop
+ exit when A = Positive'Last;
+
+ for B in A + 1 .. Seq'Last loop
+ pragma Loop_Invariant
+ (for all K in A + 1 .. B => Seq (A) < Seq (K));
+ end loop;
+
+ pragma Loop_Invariant
+ (for all J in Seq'First .. A =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+ end loop;
+ end Lemma_Is_Sorted;
+
+ -- Local variables
+
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+
+ -- Repeat the computation from To_Domain in ghost code, in order to
+ -- prove the relationship between Result and To_Domain(Map).
+
+ Domain : String (1 .. Map'Length) with Ghost, Relaxed_Initialization;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
+ -- Start of processing for To_Range
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := Map (C);
+ Domain (J) := C;
+ Indexes (C) := J;
end if;
+
+ -- Repeat the loop invariants from To_Domain regarding Domain and
+ -- Indexes. Add similar loop invariants for Result and Indexes.
+
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (Domain (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Domain (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Domain (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Domain (Indexes (D)) = D
+ and then Result (Indexes (D)) = Map (D)));
+ pragma Loop_Invariant
+ (for all Char of Domain (1 .. J) => Map (Char) /= Char);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result (K) = Map (Domain (K)));
end loop;
+ -- Show the equality of Domain and To_Domain(Map)
+
+ Lemma_Is_Domain (Map);
+ Lemma_Domain_Unicity (Map, Domain (1 .. J), To_Domain (Map));
+ pragma Assert
+ (for all K in 1 .. J => Domain (K) = To_Domain (Map) (K));
+ pragma Assert (To_Domain (Map)'Length = J);
+
return Result (1 .. J);
end To_Range;
@@ -197,18 +420,26 @@ package body Ada.Strings.Maps is
---------------
function To_Ranges (Set : Character_Set) return Character_Ranges is
- Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1);
+ Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1)
+ with Relaxed_Initialization;
Range_Num : Natural;
C : Character;
+ C_Iter : Character with Ghost;
begin
C := Character'First;
Range_Num := 0;
loop
+ C_Iter := C;
+
-- Skip gap between subsets
while not Set (C) loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C => not Set (Char));
exit when C = Character'Last;
C := Character'Succ (C);
end loop;
@@ -221,16 +452,45 @@ package body Ada.Strings.Maps is
-- Span a subset
loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C =>
+ (if Char /= C then Set (Char)));
exit when not Set (C) or else C = Character'Last;
C := Character'Succ (C);
end loop;
if Set (C) then
- Max_Ranges (Range_Num). High := C;
+ Max_Ranges (Range_Num).High := C;
exit;
else
- Max_Ranges (Range_Num). High := Character'Pred (C);
+ Max_Ranges (Range_Num).High := Character'Pred (C);
end if;
+
+ pragma Assert
+ (for all Char in C_Iter .. C =>
+ (Set (Char) =
+ (Char in Max_Ranges (Range_Num).Low ..
+ Max_Ranges (Range_Num).High)));
+ pragma Assert
+ (for all Char in Character'First .. C_Iter =>
+ (if Char /= C_Iter then
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num - 1) =>
+ Char in Span.Low .. Span.High))));
+
+ pragma Loop_Invariant (2 * Range_Num <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Max_Ranges (1 .. Range_Num)'Initialized);
+ pragma Loop_Invariant (not Set (C));
+ pragma Loop_Invariant
+ (for all Char in Character'First .. C =>
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num) =>
+ Char in Span.Low .. Span.High)));
+ pragma Loop_Invariant
+ (for all Span of Max_Ranges (1 .. Range_Num) =>
+ (for all Char in Span.Low .. Span.High => Set (Char)));
end loop;
return Max_Ranges (1 .. Range_Num);
@@ -241,7 +501,8 @@ package body Ada.Strings.Maps is
-----------------
function To_Sequence (Set : Character_Set) return Character_Sequence is
- Result : String (1 .. Character'Pos (Character'Last) + 1);
+ Result : String (1 .. Character'Pos (Character'Last) + 1)
+ with Relaxed_Initialization;
Count : Natural := 0;
begin
for Char in Set'Range loop
@@ -249,6 +510,17 @@ package body Ada.Strings.Maps is
Count := Count + 1;
Result (Count) := Char;
end if;
+
+ pragma Loop_Invariant (Count <= Character'Pos (Char) + 1);
+ pragma Loop_Invariant (Result (1 .. Count)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. Count => Result (K) <= Char);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. Count)));
+ pragma Loop_Invariant
+ (for all C in Set'First .. Char =>
+ (Set (C) = (for some X of Result (1 .. Count) => C = X)));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. Count) => Is_In (Char, Set));
end loop;
return Result (1 .. Count);
@@ -259,30 +531,37 @@ package body Ada.Strings.Maps is
------------
function To_Set (Ranges : Character_Ranges) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for R in Ranges'Range loop
for C in Ranges (R).Low .. Ranges (R).High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ ((for some Prev in Ranges'First .. R - 1 =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High)
+ or else (Char in Ranges (R).Low .. C)));
end loop;
+
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some Prev in Ranges'First .. R =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High));
end loop;
return Result;
end To_Set;
function To_Set (Span : Character_Range) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for C in Span.Low .. Span.High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) = (Char in Span.Low .. C));
end loop;
return Result;
@@ -293,6 +572,10 @@ package body Ada.Strings.Maps is
begin
for J in Sequence'Range loop
Result (Sequence (J)) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some K in Sequence'First .. J => Char = Sequence (K)));
end loop;
return Result;
@@ -313,8 +596,6 @@ package body Ada.Strings.Maps is
(Map : Character_Mapping;
Element : Character) return Character
is
- begin
- return Map (Element);
- end Value;
+ (Map (Element));
end Ada.Strings.Maps;
diff --git a/gcc/ada/libgnat/a-strmap.ads b/gcc/ada/libgnat/a-strmap.ads
index c35c392..1a15d5d 100644
--- a/gcc/ada/libgnat/a-strmap.ads
+++ b/gcc/ada/libgnat/a-strmap.ads
@@ -33,15 +33,24 @@
-- --
------------------------------------------------------------------------------
+-- The package Strings.Maps defines the types, operations, and other entities
+-- needed for character sets and character-to-character mappings.
+
-- 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.
+-- setting the corresponding assertion policy to Ignore. Postconditions and
+-- ghost code should not be executed at runtime as well, in order not to slow
+-- down the execution of these functions.
-pragma Assertion_Policy (Pre => Ignore);
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Ghost => Ignore);
with Ada.Characters.Latin_1;
-package Ada.Strings.Maps is
+package Ada.Strings.Maps
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -51,9 +60,10 @@ package Ada.Strings.Maps is
type Character_Set is private;
pragma Preelaborable_Initialization (Character_Set);
- -- Representation for a set of character values:
+ -- An object of type Character_Set represents a set of characters.
Null_Set : constant Character_Set;
+ -- Null_Set represents the set containing no characters.
---------------------------
-- Constructors for Sets --
@@ -63,9 +73,12 @@ package Ada.Strings.Maps is
Low : Character;
High : Character;
end record;
- -- Represents Character range Low .. High
+ -- An object Obj of type Character_Range represents the set of characters
+ -- in the range Obj.Low .. Obj.High.
type Character_Ranges is array (Positive range <>) of Character_Range;
+ -- An object Obj of type Character_Ranges represents the union of the sets
+ -- corresponding to Obj(I) for I in Obj'Range.
function To_Set (Ranges : Character_Ranges) return Character_Set with
Post =>
@@ -78,6 +91,8 @@ package Ada.Strings.Maps is
(for all Span of Ranges =>
(for all Char in Span.Low .. Span.High =>
Is_In (Char, To_Set'Result)));
+ -- If Ranges'Length=0 then Null_Set is returned; otherwise, the returned
+ -- value represents the set corresponding to Ranges.
function To_Set (Span : Character_Range) return Character_Set with
Post =>
@@ -87,6 +102,7 @@ package Ada.Strings.Maps is
(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));
+ -- The returned value represents the set containing each character in Span.
function To_Ranges (Set : Character_Set) return Character_Ranges with
Post =>
@@ -100,6 +116,12 @@ package Ada.Strings.Maps is
and then
(for all Span of To_Ranges'Result =>
(for all Char in Span.Low .. Span.High => Is_In (Char, Set)));
+ -- If Set = Null_Set, then an empty Character_Ranges array is returned;
+ -- otherwise, the shortest array of contiguous ranges of Character values
+ -- in Set, in increasing order of Low, is returned.
+ --
+ -- The postcondition above does not express that the result is the shortest
+ -- array and that it is sorted.
----------------------------------
-- Operations on Character Sets --
@@ -111,6 +133,13 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(Is_In (Char, Left) = Is_In (Char, Right)));
+ -- The function "=" returns True if Left and Right represent identical
+ -- sets, and False otherwise.
+
+ -- Each of the logical operators "not", "and", "or", and "xor" returns a
+ -- Character_Set value that represents the set obtained by applying the
+ -- corresponding operation to the set(s) represented by the parameter(s)
+ -- of the operator.
function "not" (Right : Character_Set) return Character_Set with
Post =>
@@ -146,10 +175,12 @@ package Ada.Strings.Maps is
(Is_In (Char, "-"'Result)
=
(Is_In (Char, Left) and not Is_In (Char, Right))));
+ -- "-"(Left, Right) is equivalent to "and"(Left, "not"(Right)).
function Is_In
(Element : Character;
Set : Character_Set) return Boolean;
+ -- Is_In returns True if Element is in Set, and False otherwise.
function Is_Subset
(Elements : Character_Set;
@@ -160,6 +191,8 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(if Is_In (Char, Elements) then Is_In (Char, Set)));
+ -- Is_Subset returns True if Elements is a subset of Set, and False
+ -- otherwise.
function "<="
(Left : Character_Set;
@@ -167,7 +200,23 @@ package Ada.Strings.Maps is
renames Is_Subset;
subtype Character_Sequence is String;
- -- Alternative representation for a set of character values
+ -- The Character_Sequence subtype is used to portray a set of character
+ -- values and also to identify the domain and range of a character mapping.
+
+ function SPARK_Proof_Sorted_Character_Sequence
+ (Seq : Character_Sequence) return Boolean
+ is
+ (for all J in Seq'Range =>
+ (if J /= Seq'Last then Seq (J) < Seq (J + 1)))
+ with
+ Ghost;
+ -- Check whether the Character_Sequence is sorted in stricly increasing
+ -- order, as expected from the result of To_Sequence and To_Domain.
+
+ -- Sequence portrays the set of character values that it explicitly
+ -- contains (ignoring duplicates). Singleton portrays the set comprising a
+ -- single Character. Each of the To_Set functions returns a Character_Set
+ -- value that represents the set portrayed by Sequence or Singleton.
function To_Set (Sequence : Character_Sequence) return Character_Set with
Post =>
@@ -197,10 +246,10 @@ package Ada.Strings.Maps is
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))));
+ SPARK_Proof_Sorted_Character_Sequence (To_Sequence'Result);
+ -- The function To_Sequence returns a Character_Sequence value containing
+ -- each of the characters in the set represented by Set, in ascending order
+ -- with no duplicates.
------------------------------------
-- Character Mapping Declarations --
@@ -208,13 +257,39 @@ package Ada.Strings.Maps is
type Character_Mapping is private;
pragma Preelaborable_Initialization (Character_Mapping);
- -- Representation for a character to character mapping:
+ -- An object of type Character_Mapping represents a Character-to-Character
+ -- mapping.
+
+ type SPARK_Proof_Character_Mapping_Model is
+ array (Character) of Character
+ with Ghost;
+ -- Publicly visible model of a Character_Mapping
+
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ with Ghost;
+ -- Creation of a publicly visible model of a Character_Mapping
function Value
(Map : Character_Mapping;
- Element : Character) return Character;
+ Element : Character) return Character
+ with
+ Post => Value'Result = SPARK_Proof_Model (Map) (Element);
+ -- The function Value returns the Character value to which Element maps
+ -- with respect to the mapping represented by Map.
+
+ -- A character C matches a pattern character P with respect to a given
+ -- Character_Mapping value Map if Value(Map, C) = P. A string S matches
+ -- a pattern string P with respect to a given Character_Mapping if
+ -- their lengths are the same and if each character in S matches its
+ -- corresponding character in the pattern string P.
+
+ -- String handling subprograms that deal with character mappings have
+ -- parameters whose type is Character_Mapping.
Identity : constant Character_Mapping;
+ -- Identity maps each Character to itself.
----------------------------
-- Operations on Mappings --
@@ -240,6 +315,10 @@ package Ada.Strings.Maps is
and then
(if (for all X of From => Char /= X)
then Value (To_Mapping'Result, Char) = Char)));
+ -- To_Mapping produces a Character_Mapping such that each element of From
+ -- maps to the corresponding element of To, and each other character maps
+ -- to itself. If From'Length /= To'Length, or if some character is repeated
+ -- in From, then Translation_Error is propagated.
function To_Domain
(Map : Character_Mapping) return Character_Sequence with
@@ -248,24 +327,40 @@ package Ada.Strings.Maps is
and then
To_Domain'Result'First = 1
and then
+ SPARK_Proof_Sorted_Character_Sequence (To_Domain'Result)
+ 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);
+ -- To_Domain returns the shortest Character_Sequence value D such that each
+ -- character not in D maps to itself, and such that the characters in D are
+ -- in ascending order. The lower bound of D is 1.
function To_Range
(Map : Character_Mapping) return Character_Sequence with
Post =>
To_Range'Result'First = 1
and then
- To_Range'Result'Last = To_Domain (Map)'Last
+ To_Range'Result'Length = To_Domain (Map)'Length
and then
(for all J in To_Range'Result'Range =>
To_Range'Result (J) = Value (Map, To_Domain (Map) (J)));
+ -- To_Range returns the Character_Sequence value R, such that if D =
+ -- To_Domain(Map), then R has the same bounds as D, and D(I) maps to
+ -- R(I) for each I in D'Range.
+ --
+ -- A direct encoding of the Ada RM would be the postcondition
+ -- To_Range'Result'Last = To_Domain (Map)'Last
+ -- which is not provable unless the postcondition of To_Domain is also
+ -- strengthened to state the value of the high bound for an empty result.
type Character_Mapping_Function is
access function (From : Character) return Character;
+ -- An object F of type Character_Mapping_Function maps a Character value C
+ -- to the Character value F.all(C), which is said to match C with respect
+ -- to mapping function F.
private
pragma Inline (Is_In);
@@ -285,6 +380,12 @@ private
type Character_Mapping is array (Character) of Character;
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ is
+ (SPARK_Proof_Character_Mapping_Model (Map));
+
package L renames Ada.Characters.Latin_1;
Identity : constant Character_Mapping :=
diff --git a/gcc/ada/libgnat/a-strsea.adb b/gcc/ada/libgnat/a-strsea.adb
index d96a4c7..243c92c 100644
--- a/gcc/ada/libgnat/a-strsea.adb
+++ b/gcc/ada/libgnat/a-strsea.adb
@@ -35,10 +35,18 @@
-- case of identity mappings for Count and Index, and also Index_Non_Blank
-- is specialized (rather than using the general Index routine).
+-- Ghost code, loop invariants and assertions in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
+
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
with Ada.Strings.Maps; use Ada.Strings.Maps;
with System; use System;
-package body Ada.Strings.Search is
+package body Ada.Strings.Search with SPARK_Mode is
-----------------------
-- Local Subprograms --
@@ -61,13 +69,9 @@ package body Ada.Strings.Search is
Set : Maps.Character_Set;
Test : Membership) return Boolean
is
- begin
- if Test = Inside then
- return Is_In (Element, Set);
- else
- return not Is_In (Element, Set);
- end if;
- end Belongs;
+ (if Test = Inside then
+ Is_In (Element, Set)
+ else not (Is_In (Element, Set)));
-----------
-- Count --
@@ -81,47 +85,63 @@ package body Ada.Strings.Search is
PL1 : constant Integer := Pattern'Length - 1;
Num : Natural;
Ind : Natural;
- Cur : Natural;
begin
if Pattern = "" then
raise Pattern_Error;
end if;
+ -- Isolating the null string case to ensure Source'First, Source'Last in
+ -- Positive.
+
+ if Source = "" then
+ return 0;
+ end if;
+
Num := 0;
- Ind := Source'First;
+ Ind := Source'First - 1;
-- Unmapped case
- if Mapping'Address = Maps.Identity'Address then
- while Ind <= Source'Last - PL1 loop
+ if Is_Identity (Mapping) then
+ while Ind < Source'Last - PL1 loop
+ Ind := Ind + 1;
if Pattern = Source (Ind .. Ind + PL1) then
Num := Num + 1;
- Ind := Ind + Pattern'Length;
- else
- Ind := Ind + 1;
+ Ind := Ind + PL1;
end if;
+
+ pragma Loop_Invariant (Num <= Ind - (Source'First - 1));
+ pragma Loop_Invariant (Ind >= Source'First);
end loop;
-- Mapped case
else
- while Ind <= Source'Last - PL1 loop
- Cur := Ind;
+ while Ind < Source'Last - PL1 loop
+ Ind := Ind + 1;
for K in Pattern'Range loop
- if Pattern (K) /= Value (Mapping, Source (Cur)) then
- Ind := Ind + 1;
+ if Pattern (K) /= Value (Mapping,
+ Source (Ind + (K - Pattern'First)))
+ then
+ pragma Assert (not (Match (Source, Pattern, Mapping, Ind)));
goto Cont;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Value (Mapping,
+ Source (Ind + (J - Pattern'First))));
end loop;
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
Num := Num + 1;
- Ind := Ind + Pattern'Length;
+ Ind := Ind + PL1;
- <<Cont>>
+ <<Cont>>
null;
+ pragma Loop_Invariant (Num <= Ind - (Source'First - 1));
+ pragma Loop_Invariant (Ind >= Source'First);
end loop;
end if;
@@ -138,13 +158,19 @@ package body Ada.Strings.Search is
PL1 : constant Integer := Pattern'Length - 1;
Num : Natural;
Ind : Natural;
- Cur : Natural;
begin
if Pattern = "" then
raise Pattern_Error;
end if;
+ -- Isolating the null string case to ensure Source'First, Source'Last in
+ -- Positive.
+
+ if Source = "" then
+ return 0;
+ end if;
+
-- Check for null pointer in case checks are off
if Mapping = null then
@@ -152,23 +178,28 @@ package body Ada.Strings.Search is
end if;
Num := 0;
- Ind := Source'First;
- while Ind <= Source'Last - PL1 loop
- Cur := Ind;
+ Ind := Source'First - 1;
+ while Ind < Source'Last - PL1 loop
+ Ind := Ind + 1;
for K in Pattern'Range loop
- if Pattern (K) /= Mapping (Source (Cur)) then
- Ind := Ind + 1;
+ if Pattern (K) /= Mapping (Source (Ind + (K - Pattern'First))) then
+ pragma Assert (not (Match (Source, Pattern, Mapping, Ind)));
goto Cont;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Mapping (Source (Ind + (J - Pattern'First))));
end loop;
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
Num := Num + 1;
- Ind := Ind + Pattern'Length;
+ Ind := Ind + PL1;
<<Cont>>
null;
+ pragma Loop_Invariant (Num <= Ind - (Source'First - 1));
+ pragma Loop_Invariant (Ind >= Source'First);
end loop;
return Num;
@@ -182,6 +213,7 @@ package body Ada.Strings.Search is
begin
for J in Source'Range loop
+ pragma Loop_Invariant (N <= J - Source'First);
if Is_In (Source (J), Set) then
N := N + 1;
end if;
@@ -217,12 +249,18 @@ package body Ada.Strings.Search is
if Belongs (Source (J), Set, Test) then
First := J;
- for K in J + 1 .. Source'Last loop
- if not Belongs (Source (K), Set, Test) then
- Last := K - 1;
- return;
- end if;
- end loop;
+ if J < Source'Last then
+ for K in J + 1 .. Source'Last loop
+ if not Belongs (Source (K), Set, Test) then
+ Last := K - 1;
+ return;
+ end if;
+
+ pragma Loop_Invariant
+ (for all L in J .. K =>
+ Belongs (Source (L), Set, Test));
+ end loop;
+ end if;
-- Here if J indexes first char of token, and all chars after J
-- are in the token.
@@ -230,6 +268,10 @@ package body Ada.Strings.Search is
Last := Source'Last;
return;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Integer'Max (From, Source'First) .. J =>
+ not (Belongs (Source (K), Set, Test)));
end loop;
-- Here if no token found
@@ -250,12 +292,18 @@ package body Ada.Strings.Search is
if Belongs (Source (J), Set, Test) then
First := J;
- for K in J + 1 .. Source'Last loop
- if not Belongs (Source (K), Set, Test) then
- Last := K - 1;
- return;
- end if;
- end loop;
+ if J < Source'Last then
+ for K in J + 1 .. Source'Last loop
+ if not Belongs (Source (K), Set, Test) then
+ Last := K - 1;
+ return;
+ end if;
+
+ pragma Loop_Invariant
+ (for all L in J .. K =>
+ Belongs (Source (L), Set, Test));
+ end loop;
+ end if;
-- Here if J indexes first char of token, and all chars after J
-- are in the token.
@@ -263,6 +311,10 @@ package body Ada.Strings.Search is
Last := Source'Last;
return;
end if;
+
+ pragma Loop_Invariant
+ (for all K in Source'First .. J =>
+ not (Belongs (Source (K), Set, Test)));
end loop;
-- Here if no token found
@@ -292,53 +344,61 @@ package body Ada.Strings.Search is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
PL1 : constant Integer := Pattern'Length - 1;
- Cur : Natural;
-
- Ind : Integer;
- -- Index for start of match check. This can be negative if the pattern
- -- length is greater than the string length, which is why this variable
- -- is Integer instead of Natural. In this case, the search loops do not
- -- execute at all, so this Ind value is never used.
begin
if Pattern = "" then
raise Pattern_Error;
end if;
+ -- If Pattern is longer than Source, it can't be found
+
+ if Pattern'Length > Source'Length then
+ return 0;
+ end if;
+
-- Forwards case
if Going = Forward then
- Ind := Source'First;
-- Unmapped forward case
- if Mapping'Address = Maps.Identity'Address then
- for J in 1 .. Source'Length - PL1 loop
+ if Is_Identity (Mapping) then
+ for Ind in Source'First .. Source'Last - PL1 loop
if Pattern = Source (Ind .. Ind + PL1) then
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
return Ind;
- else
- Ind := Ind + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Source'First .. Ind =>
+ not (Match (Source, Pattern, Mapping, J)));
end loop;
-- Mapped forward case
else
- for J in 1 .. Source'Length - PL1 loop
- Cur := Ind;
-
+ for Ind in Source'First .. Source'Last - PL1 loop
for K in Pattern'Range loop
- if Pattern (K) /= Value (Mapping, Source (Cur)) then
+ if Pattern (K) /= Value (Mapping,
+ Source (Ind + (K - Pattern'First)))
+ then
goto Cont1;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Value (Mapping,
+ Source (Ind + (J - Pattern'First))));
end loop;
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
return Ind;
- <<Cont1>>
- Ind := Ind + 1;
+ <<Cont1>>
+ pragma Loop_Invariant
+ (for all J in Source'First .. Ind =>
+ not (Match (Source, Pattern, Mapping, J)));
+ null;
end loop;
end if;
@@ -347,35 +407,43 @@ package body Ada.Strings.Search is
else
-- Unmapped backward case
- Ind := Source'Last - PL1;
-
- if Mapping'Address = Maps.Identity'Address then
- for J in reverse 1 .. Source'Length - PL1 loop
+ if Is_Identity (Mapping) then
+ for Ind in reverse Source'First .. Source'Last - PL1 loop
if Pattern = Source (Ind .. Ind + PL1) then
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
return Ind;
- else
- Ind := Ind - 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Ind .. Source'Last - PL1 =>
+ not (Match (Source, Pattern, Mapping, J)));
end loop;
-- Mapped backward case
else
- for J in reverse 1 .. Source'Length - PL1 loop
- Cur := Ind;
-
+ for Ind in reverse Source'First .. Source'Last - PL1 loop
for K in Pattern'Range loop
- if Pattern (K) /= Value (Mapping, Source (Cur)) then
+ if Pattern (K) /= Value (Mapping,
+ Source (Ind + (K - Pattern'First)))
+ then
goto Cont2;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Value (Mapping,
+ Source (Ind + (J - Pattern'First))));
end loop;
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
return Ind;
- <<Cont2>>
- Ind := Ind - 1;
+ <<Cont2>>
+ pragma Loop_Invariant
+ (for all J in Ind .. Source'Last - PL1 =>
+ not (Match (Source, Pattern, Mapping, J)));
+ null;
end loop;
end if;
end if;
@@ -393,9 +461,6 @@ package body Ada.Strings.Search is
Mapping : Maps.Character_Mapping_Function) return Natural
is
PL1 : constant Integer := Pattern'Length - 1;
- Ind : Natural;
- Cur : Natural;
-
begin
if Pattern = "" then
raise Pattern_Error;
@@ -416,43 +481,52 @@ package body Ada.Strings.Search is
-- Forwards case
if Going = Forward then
- Ind := Source'First;
- for J in 1 .. Source'Length - PL1 loop
- Cur := Ind;
-
+ for Ind in Source'First .. Source'Last - PL1 loop
for K in Pattern'Range loop
- if Pattern (K) /= Mapping.all (Source (Cur)) then
+ if Pattern (K) /= Mapping.all
+ (Source (Ind + (K - Pattern'First)))
+ then
goto Cont1;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Mapping (Source (Ind + (J - Pattern'First))));
end loop;
+ pragma Assert (Match (Source, Pattern, Mapping, Ind));
return Ind;
- <<Cont1>>
- Ind := Ind + 1;
+ <<Cont1>>
+ pragma Loop_Invariant
+ (for all J in Source'First .. Ind =>
+ not (Match (Source, Pattern, Mapping, J)));
+ null;
end loop;
-- Backwards case
else
- Ind := Source'Last - PL1;
- for J in reverse 1 .. Source'Length - PL1 loop
- Cur := Ind;
-
+ for Ind in reverse Source'First .. Source'Last - PL1 loop
for K in Pattern'Range loop
- if Pattern (K) /= Mapping.all (Source (Cur)) then
+ if Pattern (K) /= Mapping.all
+ (Source (Ind + (K - Pattern'First)))
+ then
goto Cont2;
- else
- Cur := Cur + 1;
end if;
+
+ pragma Loop_Invariant
+ (for all J in Pattern'First .. K =>
+ Pattern (J) = Mapping (Source (Ind + (J - Pattern'First))));
end loop;
return Ind;
- <<Cont2>>
- Ind := Ind - 1;
+ <<Cont2>>
+ pragma Loop_Invariant
+ (for all J in Ind .. (Source'Last - PL1) =>
+ not (Match (Source, Pattern, Mapping, J)));
+ null;
end loop;
end if;
@@ -476,6 +550,10 @@ package body Ada.Strings.Search is
if Belongs (Source (J), Set, Test) then
return J;
end if;
+
+ pragma Loop_Invariant
+ (for all C of Source (Source'First .. J) =>
+ not (Belongs (C, Set, Test)));
end loop;
-- Backwards case
@@ -485,6 +563,10 @@ package body Ada.Strings.Search is
if Belongs (Source (J), Set, Test) then
return J;
end if;
+
+ pragma Loop_Invariant
+ (for all C of Source (J .. Source'Last) =>
+ not (Belongs (C, Set, Test)));
end loop;
end if;
@@ -500,6 +582,8 @@ package body Ada.Strings.Search is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
+ Result : Natural;
+ PL1 : constant Integer := Pattern'Length - 1;
begin
-- AI05-056: If source is empty result is always zero
@@ -512,17 +596,29 @@ package body Ada.Strings.Search is
raise Index_Error;
end if;
- return
+ Result :=
Index (Source (From .. Source'Last), Pattern, Forward, Mapping);
+ pragma Assert
+ (if (for some J in From .. Source'Last - PL1 =>
+ Match (Source, Pattern, Mapping, J))
+ then Result in From .. Source'Last - PL1
+ else Result = 0);
else
if From > Source'Last then
raise Index_Error;
end if;
- return
+ Result :=
Index (Source (Source'First .. From), Pattern, Backward, Mapping);
+ pragma Assert
+ (if (for some J in Source'First .. From - PL1 =>
+ Match (Source, Pattern, Mapping, J))
+ then Result in Source'First .. From - PL1
+ else Result = 0);
end if;
+
+ return Result;
end Index;
function Index
@@ -603,6 +699,9 @@ package body Ada.Strings.Search is
if Source (J) /= ' ' then
return J;
end if;
+
+ pragma Loop_Invariant
+ (for all C of Source (Source'First .. J) => C = ' ');
end loop;
else -- Going = Backward
@@ -610,6 +709,9 @@ package body Ada.Strings.Search is
if Source (J) /= ' ' then
return J;
end if;
+
+ pragma Loop_Invariant
+ (for all C of Source (J .. Source'Last) => C = ' ');
end loop;
end if;
@@ -624,6 +726,13 @@ package body Ada.Strings.Search is
Going : Direction := Forward) return Natural
is
begin
+
+ -- For equivalence with Index, if Source is empty the result is 0
+
+ if Source'Length = 0 then
+ return 0;
+ end if;
+
if Going = Forward then
if From < Source'First then
raise Index_Error;
@@ -642,4 +751,12 @@ package body Ada.Strings.Search is
end if;
end Index_Non_Blank;
+ function Is_Identity
+ (Mapping : Maps.Character_Mapping) return Boolean
+ with SPARK_Mode => Off
+ is
+ begin
+ return Mapping'Address = Maps.Identity'Address;
+ end Is_Identity;
+
end Ada.Strings.Search;
diff --git a/gcc/ada/libgnat/a-strsea.ads b/gcc/ada/libgnat/a-strsea.ads
index 623c0f4..f4e7d36 100644
--- a/gcc/ada/libgnat/a-strsea.ads
+++ b/gcc/ada/libgnat/a-strsea.ads
@@ -32,76 +32,489 @@
-- This package contains the search functions from Ada.Strings.Fixed. They
-- are separated out because they are shared by Ada.Strings.Bounded and
-- Ada.Strings.Unbounded, and we don't want to drag in other irrelevant stuff
--- from Ada.Strings.Fixed when using the other two packages. We make this a
--- private package, since user programs should access these subprograms via
--- one of the standard string packages.
+-- from Ada.Strings.Fixed when using the other two packages. Although user
+-- programs should access these subprograms via one of the standard string
+-- packages, we do not make this a private package, since ghost function
+-- Match is used in the contracts of the standard string packages.
-with Ada.Strings.Maps;
+-- 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. Postconditions,
+-- contract cases and ghost code should not be executed at runtime as well,
+-- in order not to slow down the execution of these functions.
-private package Ada.Strings.Search is
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
+
+package Ada.Strings.Search with SPARK_Mode is
pragma Preelaborate;
+ -- The ghost function Match tells whether the slice of Source starting at
+ -- From and of length Pattern'Length matches with Pattern with respect to
+ -- Mapping. Pattern should be non-empty and the considered slice should be
+ -- fully included in Source'Range.
+
+ function Match
+ (Source : String;
+ Pattern : String;
+ Mapping : Maps.Character_Mapping_Function;
+ From : Integer) return Boolean
+ is
+ (for all K in Pattern'Range =>
+ Pattern (K) = Mapping (Source (From + (K - Pattern'First))))
+ with
+ Ghost,
+ Pre => Mapping /= null
+ and then Pattern'Length > 0
+ and then Source'Length > 0
+ and then From in Source'First .. Source'Last - (Pattern'Length - 1),
+ Global => null;
+
+ function Match
+ (Source : String;
+ Pattern : String;
+ Mapping : Maps.Character_Mapping;
+ From : Integer) return Boolean
+ is
+ (for all K in Pattern'Range =>
+ Pattern (K) =
+ Ada.Strings.Maps.Value
+ (Mapping, Source (From + (K - Pattern'First))))
+ with
+ Ghost,
+ Pre => Pattern'Length > 0
+ and then Source'Length > 0
+ and then From in Source'First .. Source'Last - (Pattern'Length - 1),
+ Global => null;
+
+ function Is_Identity
+ (Mapping : Maps.Character_Mapping) return Boolean
+ with
+ Post => (if Is_Identity'Result then
+ (for all K in Character =>
+ Ada.Strings.Maps.Value (Mapping, K) = K)),
+ Global => null;
+
function Index
(Source : String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0,
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Source'Length = 0 => Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Source'Length > 0
+ and then
+ (for some J in
+ Source'First .. Source'Last - (Pattern'Length - 1) =>
+ Match (Source, Pattern, Mapping, J))
+ =>
+
+ -- 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 Match (Source, Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ 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 not (Match (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others => Index'Result = 0),
+ Global => null;
function Index
(Source : String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length > 0 and then Mapping /= null,
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the null string, then 0 is returned
+
+ (Source'Length = 0 => Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Source'Length > 0 and then
+ (for some J in Source'First .. Source'Last - (Pattern'Length - 1) =>
+ Match (Source, Pattern, Mapping, J))
+ =>
+
+ -- 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 Match (Source, Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ 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 not (Match (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others => Index'Result = 0),
+ Global => null;
function Index
(Source : String;
Set : Maps.Character_Set;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ 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, an 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 =
+ -- Backward.
+
+ 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;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0
+ and then (if Source'Length > 0 then From in Source'Range),
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Source'Length = 0 => Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Source'Length > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1) =>
+ Match (Source, Pattern, Mapping, J))
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Match (Source, Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ 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 not (Match (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others => Index'Result = 0),
+ Global => null;
function Index
(Source : String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length > 0
+ and then Mapping /= null
+ and then (if Source'Length > 0 then From in Source'Range),
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Source'Length = 0 => Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Source'Length > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1) =>
+ Match (Source, Pattern, Mapping, J))
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else Source'First)
+ .. (if Going = Forward then Source'Last else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Match (Source, Pattern, Mapping, Index'Result)
+
+ -- 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 not (Match (Source, Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others => Index'Result = 0),
+ Global => null;
function Index
(Source : String;
Set : Maps.Character_Set;
From : Positive;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre => (if Source'Length > 0 then From in Source'Range),
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Source'Length = 0
+ or else
+ (for all J in Source'Range =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (Source (J), Set)))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the considered 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 =
+ -- Backward.
+
+ 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;
function Index_Non_Blank
(Source : String;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ 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 = Backward.
+
+ 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;
function Index_Non_Blank
(Source : String;
From : Positive;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre => (if Source'Length /= 0 then From in Source'Range),
+ Post => Index_Non_Blank'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is the null string, or all characters in the considered
+ -- slice of Source are Space characters, then 0 is returned.
+
+ (Source'Length = 0
+ or else
+ (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 = Backward.
+
+ 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;
function Count
(Source : String;
Pattern : String;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0,
+ Global => null;
function Count
(Source : String;
Pattern : String;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length > 0 and then Mapping /= null,
+ Global => null;
function Count
(Source : String;
- Set : Maps.Character_Set) return Natural;
+ Set : Maps.Character_Set) return Natural
+ with
+ Global => null;
procedure Find_Token
(Source : String;
@@ -109,13 +522,104 @@ private package Ada.Strings.Search is
From : Positive;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ 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;
procedure Find_Token
(Source : String;
Set : Maps.Character_Set;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Pre => Source'First > 0,
+ 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;
end Ada.Strings.Search;
diff --git a/gcc/ada/libgnat/a-strsup.adb b/gcc/ada/libgnat/a-strsup.adb
index 1e85cc2..a94d6ca 100644
--- a/gcc/ada/libgnat/a-strsup.adb
+++ b/gcc/ada/libgnat/a-strsup.adb
@@ -29,10 +29,17 @@
-- --
------------------------------------------------------------------------------
-with Ada.Strings.Maps; use Ada.Strings.Maps;
-with Ada.Strings.Search;
+-- Ghost code, loop invariants and assertions in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
-package body Ada.Strings.Superbounded is
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+with Ada.Strings.Maps; use Ada.Strings.Maps;
+
+package body Ada.Strings.Superbounded with SPARK_Mode is
------------
-- Concat --
@@ -53,9 +60,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -74,9 +85,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
+
+ if Right'Length > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -97,9 +112,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
end;
end return;
end Concat;
@@ -117,9 +136,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Result.Current_Length) := Right;
+ Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
end;
end return;
end Concat;
@@ -137,10 +156,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
- Result.Data (2 .. Result.Current_Length) :=
- Right.Data (1 .. Rlen);
+ Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
end;
end return;
end Concat;
@@ -154,9 +172,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Current_Length = Right.Current_Length
- and then Left.Data (1 .. Left.Current_Length) =
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) = Super_To_String (Right);
end "=";
function Equal
@@ -164,8 +180,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Current_Length = Right'Length
- and then Left.Data (1 .. Left.Current_Length) = Right;
+ return Super_To_String (Left) = Right;
end Equal;
function Equal
@@ -173,8 +188,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left'Length = Right.Current_Length
- and then Left = Right.Data (1 .. Right.Current_Length);
+ return Left = Super_To_String (Right);
end Equal;
-------------
@@ -186,8 +200,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) > Super_To_String (Right);
end Greater;
function Greater
@@ -195,7 +208,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) > Right;
+ return Super_To_String (Left) > Right;
end Greater;
function Greater
@@ -203,7 +216,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left > Right.Data (1 .. Right.Current_Length);
+ return Left > Super_To_String (Right);
end Greater;
----------------------
@@ -215,8 +228,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) >= Super_To_String (Right);
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -224,7 +236,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >= Right;
+ return Super_To_String (Left) >= Right;
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -232,7 +244,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left >= Right.Data (1 .. Right.Current_Length);
+ return Left >= Super_To_String (Right);
end Greater_Or_Equal;
----------
@@ -244,8 +256,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) < Super_To_String (Right);
end Less;
function Less
@@ -253,7 +264,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) < Right;
+ return Super_To_String (Left) < Right;
end Less;
function Less
@@ -261,7 +272,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left < Right.Data (1 .. Right.Current_Length);
+ return Left < Super_To_String (Right);
end Less;
-------------------
@@ -273,8 +284,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) <= Super_To_String (Right);
end Less_Or_Equal;
function Less_Or_Equal
@@ -282,7 +292,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <= Right;
+ return Super_To_String (Left) <= Right;
end Less_Or_Equal;
function Less_Or_Equal
@@ -290,7 +300,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left <= Right.Data (1 .. Right.Current_Length);
+ return Left <= Super_To_String (Right);
end Less_Or_Equal;
----------------------
@@ -307,20 +317,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Target.Data (1 .. Slen) := Super_String_Data (Source);
Target.Current_Length := Slen;
- Target.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
@@ -343,17 +353,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -379,6 +390,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -392,16 +405,15 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) := New_Item.Data (1 .. Rlen);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
@@ -423,6 +435,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -438,17 +452,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -456,27 +471,29 @@ package body Ada.Strings.Superbounded is
else
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Max_Length) :=
- Right (Right'First .. Right'First - 1 +
- Max_Length - Llen);
+ Result.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (Right
+ (Right'First .. Right'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Right (Right'Last - (Max_Length - 1) .. Right'Last);
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Right (Right'Last - (Max_Length - 1) .. Right'Last));
else
Result.Data (1 .. Max_Length - Rlen) :=
Left.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- Right;
+ Super_String_Data (Right);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -490,40 +507,42 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item;
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
- Source.Data (Llen + 1 .. Max_Length) :=
- New_Item (New_Item'First ..
- New_Item'First - 1 + Max_Length - Llen);
+ Source.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First ..
+ New_Item'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - (Max_Length - 1) ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - 1) ..
+ New_Item'Last));
else
Source.Data (1 .. Max_Length - Rlen) :=
Source.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -539,25 +558,25 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left'Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Left (Left'First .. Left'First + (Max_Length - 1));
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Left (Left'First .. Left'First + (Max_Length - 1)));
else
- Result.Data (1 .. Llen) := Left;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
Result.Data (Llen + 1 .. Max_Length) :=
Right.Data (1 .. Max_Length - Llen);
end if;
@@ -568,8 +587,8 @@ package body Ada.Strings.Superbounded is
Right.Data (Rlen - (Max_Length - 1) .. Rlen);
else
- Result.Data (1 .. Max_Length - Rlen) :=
- Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last);
+ Result.Data (1 .. Max_Length - Rlen) := Super_String_Data
+ (Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last));
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
Right.Data (1 .. Rlen);
end if;
@@ -577,6 +596,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -595,9 +616,9 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
return Result;
else
@@ -606,10 +627,10 @@ package body Ada.Strings.Superbounded is
return Left;
when Strings.Left =>
- Result.Current_Length := Max_Length;
Result.Data (1 .. Max_Length - 1) :=
Left.Data (2 .. Max_Length);
Result.Data (Max_Length) := Right;
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Error =>
@@ -628,12 +649,10 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Source.Current_Length := Llen + 1;
Source.Data (Llen + 1) := New_Item;
+ Source.Current_Length := Llen + 1;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
null;
@@ -663,18 +682,18 @@ package body Ada.Strings.Superbounded is
begin
if Rlen < Max_Length then
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
return Result;
else
case Drop is
when Strings.Right =>
- Result.Current_Length := Max_Length;
Result.Data (1) := Left;
Result.Data (2 .. Max_Length) :=
Right.Data (1 .. Max_Length - 1);
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Left =>
@@ -696,9 +715,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -707,9 +724,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -717,7 +732,7 @@ package body Ada.Strings.Superbounded is
Set : Maps.Character_Set) return Natural
is
begin
- return Search.Count (Source.Data (1 .. Source.Current_Length), Set);
+ return Search.Count (Super_To_String (Source), Set);
end Super_Count;
------------------
@@ -737,19 +752,19 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return Source;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
- Result.Current_Length := From - 1;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
+ Result.Current_Length := From - 1;
return Result;
else
- Result.Current_Length := Slen - Num_Delete;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
- Result.Data (From .. Result.Current_Length) :=
+ Result.Data (From .. Slen - Num_Delete) :=
Source.Data (Through + 1 .. Slen);
+ Result.Current_Length := Slen - Num_Delete;
return Result;
end if;
end Super_Delete;
@@ -766,7 +781,7 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
@@ -779,22 +794,6 @@ package body Ada.Strings.Superbounded is
end if;
end Super_Delete;
- -------------------
- -- Super_Element --
- -------------------
-
- function Super_Element
- (Source : Super_String;
- Index : Positive) return Character
- is
- begin
- if Index <= Source.Current_Length then
- return Source.Data (Index);
- else
- raise Strings.Index_Error;
- end if;
- end Super_Element;
-
----------------------
-- Super_Find_Token --
----------------------
@@ -809,7 +808,7 @@ package body Ada.Strings.Superbounded is
is
begin
Search.Find_Token
- (Source.Data (From .. Source.Current_Length), Set, Test, First, Last);
+ (Super_To_String (Source), Set, From, Test, First, Last);
end Super_Find_Token;
procedure Super_Find_Token
@@ -820,8 +819,7 @@ package body Ada.Strings.Superbounded is
Last : out Natural)
is
begin
- Search.Find_Token
- (Source.Data (1 .. Source.Current_Length), Set, Test, First, Last);
+ Search.Find_Token (Super_To_String (Source), Set, Test, First, Last);
end Super_Find_Token;
----------------
@@ -841,21 +839,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
Result.Data (1 .. Count) := Source.Data (1 .. Count);
+ Result.Current_Length := Count;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
Result.Data (Slen + 1 .. Count) := (others => Pad);
+ Result.Current_Length := Count;
else
- Result.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+
+ if Slen < Max_Length then
+ Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad >= Max_Length then
@@ -871,6 +870,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -885,22 +886,22 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : String (1 .. Max_Length);
+ Temp : Super_String_Data (1 .. Max_Length);
begin
if Npad <= 0 then
Source.Current_Length := Count;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Current_Length := Count;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ if Slen < Max_Length then
+ Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad > Max_Length then
@@ -910,15 +911,15 @@ package body Ada.Strings.Superbounded is
Temp := Source.Data;
Source.Data (1 .. Max_Length - Npad) :=
Temp (Count - Max_Length + 1 .. Slen);
-
- for J in Max_Length - Npad + 1 .. Max_Length loop
- Source.Data (J) := Pad;
- end loop;
+ Source.Data (Max_Length - Npad + 1 .. Max_Length) :=
+ (others => Pad);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Head;
@@ -933,8 +934,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -944,8 +944,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -955,8 +954,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, Test, Going);
+ return Search.Index (Super_To_String (Source), Set, Test, Going);
end Super_Index;
function Super_Index
@@ -968,8 +966,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -981,8 +978,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -993,8 +989,15 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, From, Test, Going);
+ return Result : Natural do
+ Result :=
+ Search.Index (Super_To_String (Source), Set, From, Test, Going);
+ pragma Assert
+ (if (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Source.Data (J), Set)))
+ then Result = 0);
+ end return;
end Super_Index;
---------------------------
@@ -1006,9 +1009,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), Going);
end Super_Index_Non_Blank;
function Super_Index_Non_Blank
@@ -1017,9 +1018,7 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), From, Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), From, Going);
end Super_Index_Non_Blank;
------------------
@@ -1031,60 +1030,71 @@ package body Ada.Strings.Superbounded is
Before : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
Slen : constant Natural := Source.Current_Length;
Nlen : constant Natural := New_Item'Length;
- Tlen : constant Natural := Slen + Nlen;
Blen : constant Natural := Before - 1;
Alen : constant Integer := Slen - Blen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Slen - Max_Length + Nlen;
- -- Tlen is the length of the total string before possible truncation.
-- Blen, Alen are the lengths of the before and after pieces of the
- -- source string.
+ -- source string. The number of dropped characters is Natural'Max (0,
+ -- Droplen).
begin
if Alen < 0 then
raise Ada.Strings.Index_Error;
elsif Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
- Result.Data (Before + Nlen .. Tlen) :=
- Source.Data (Before .. Slen);
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
- else
- Result.Current_Length := Max_Length;
+ if Before <= Slen then
+ Result.Data (Before + Nlen .. Slen + Nlen) :=
+ Source.Data (Before .. Slen);
+ end if;
+ Result.Current_Length := Slen + Nlen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Before .. Max_Length) :=
- New_Item (New_Item'First
- .. New_Item'First + Max_Length - Before);
+ if Droplen >= Alen then
+ Result.Data (Before .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
+ pragma Assert
+ (String (Result.Data (Before .. Max_Length)) =
+ New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
else
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
Result.Data (Before + Nlen .. Max_Length) :=
Source.Data (Before .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (Before .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (Before .. Slen);
+ end if;
- if Droplen >= Blen then
- Result.Data (1 .. Max_Length - Alen) :=
- New_Item (New_Item'Last - (Max_Length - Alen) + 1
- .. New_Item'Last);
+ if Droplen > Blen then
+ if Alen < Max_Length then
+ Result.Data (1 .. Max_Length - Alen) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - Alen) + 1
+ .. New_Item'Last));
+ end if;
else
- Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) :=
- New_Item;
+ Result.Data (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (New_Item);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1092,6 +1102,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1111,15 +1123,6 @@ package body Ada.Strings.Superbounded is
Source := Super_Insert (Source, Before, New_Item, Drop);
end Super_Insert;
- ------------------
- -- Super_Length --
- ------------------
-
- function Super_Length (Source : Super_String) return Natural is
- begin
- return Source.Current_Length;
- end Super_Length;
-
---------------------
-- Super_Overwrite --
---------------------
@@ -1132,61 +1135,61 @@ package body Ada.Strings.Superbounded is
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
- Endpos : constant Natural := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif New_Item'Length = 0 then
return Source;
- elsif Endpos <= Slen then
- Result.Current_Length := Source.Current_Length;
+ elsif Position - 1 <= Slen - New_Item'Length then
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Source.Current_Length;
return Result;
- elsif Endpos <= Max_Length then
- Result.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Position - 1 + New_Item'Length;
return Result;
else
- Result.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
Result.Data (1 .. Position - 1) :=
Source.Data (1 .. Position - 1);
- Result.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
- return Result;
+ Result.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
- return Result;
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - Max_Length + 1 ..
+ New_Item'Last));
else
Result.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
Result.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
- return Result;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
+ return Result;
end if;
end Super_Overwrite;
@@ -1195,50 +1198,52 @@ package body Ada.Strings.Superbounded is
Position : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error)
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
- Endpos : constant Positive := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
- elsif Endpos <= Slen then
- Source.Data (Position .. Endpos) := New_Item;
+ elsif Position - 1 <= Slen - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
- elsif Endpos <= Max_Length then
- Source.Data (Position .. Endpos) := New_Item;
- Source.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Position - 1 + New_Item'Length;
else
- Source.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
- Source.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
+ Source.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length > Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last));
else
Source.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
-
Source.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Overwrite;
@@ -1269,12 +1274,13 @@ package body Ada.Strings.Superbounded is
High : Natural;
By : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
begin
- if Low > Slen + 1 then
+ if Low - 1 > Slen then
raise Strings.Index_Error;
elsif High < Low then
@@ -1282,51 +1288,58 @@ package body Ada.Strings.Superbounded is
else
declare
- Blen : constant Natural := Natural'Max (0, Low - 1);
+ Blen : constant Natural := Low - 1;
Alen : constant Natural := Natural'Max (0, Slen - High);
- Tlen : constant Natural := Blen + By'Length + Alen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Blen + Alen - Max_Length + By'Length;
Result : Super_String (Max_Length);
- -- Tlen is the total length of the result string before any
- -- truncation. Blen and Alen are the lengths of the pieces
- -- of the original string that end up in the result string
- -- before and after the replaced slice.
+ -- Blen and Alen are the lengths of the pieces of the original
+ -- string that end up in the result string before and after the
+ -- replaced slice. The number of dropped characters is Natural'Max
+ -- (0, Droplen).
begin
if Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Low .. Low + By'Length - 1) := By;
- Result.Data (Low + By'Length .. Tlen) :=
- Source.Data (High + 1 .. Slen);
+ Result.Data (Low .. Blen + By'Length) :=
+ Super_String_Data (By);
- else
- Result.Current_Length := Max_Length;
+ if Alen > 0 then
+ Result.Data (Low + By'Length .. Blen + By'Length + Alen) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
+ Result.Current_Length := Blen + By'Length + Alen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Low .. Max_Length) :=
- By (By'First .. By'First + Max_Length - Low);
+ if Droplen >= Alen then
+ Result.Data (Low .. Max_Length) := Super_String_Data
+ (By (By'First .. By'First - Low + Max_Length));
else
- Result.Data (Low .. Low + By'Length - 1) := By;
+ Result.Data (Low .. Low - 1 + By'Length) :=
+ Super_String_Data (By);
Result.Data (Low + By'Length .. Max_Length) :=
Source.Data (High + 1 .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (High + 1 .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
if Droplen >= Blen then
Result.Data (1 .. Max_Length - Alen) :=
- By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
+ Super_String_Data (By
+ (By'Last - (Max_Length - Alen) + 1 .. By'Last));
else
Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) := By;
+ (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (By);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1334,6 +1347,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1370,16 +1385,17 @@ package body Ada.Strings.Superbounded is
begin
if Count <= Max_Length then
+ Result.Data (1 .. Count) := (others => Item);
Result.Current_Length := Count;
elsif Drop = Strings.Error then
raise Ada.Strings.Length_Error;
else
+ Result.Data (1 .. Max_Length) := (others => Item);
Result.Current_Length := Max_Length;
end if;
- Result.Data (1 .. Result.Current_Length) := (others => Item);
return Result;
end Super_Replicate;
@@ -1389,52 +1405,203 @@ package body Ada.Strings.Superbounded is
Drop : Truncation := Error;
Max_Length : Positive) return Super_String
is
- Length : constant Integer := Count * Item'Length;
Result : Super_String (Max_Length);
- Indx : Positive;
+ Indx : Natural;
+ Ilen : constant Natural := Item'Length;
+
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then Q mod Ilen = 0
+ and then K - Q in 0 .. Ilen - 1,
+ Post => K mod Ilen = K - Q;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Item'Length.
+
+ procedure Lemma_Mod_Zero (X : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then X mod Ilen = 0
+ and then X <= Natural'Last - Ilen,
+ Post => (X + Ilen) mod Ilen = 0;
+ -- Lemma_Mod_Zero is applied to prove that the length of the range
+ -- of indexes considered in the loop, when dropping on the Left, is
+ -- a multiple of Item'Length.
+
+ procedure Lemma_Split (Going : Direction) with
+ Ghost,
+ Pre =>
+ Ilen /= 0
+ and then Indx in 0 .. Max_Length - Ilen
+ and then
+ (if Going = Forward
+ then Indx mod Ilen = 0
+ else (Max_Length - Indx - Ilen) mod Ilen = 0)
+ and then Result.Data (Indx + 1 .. Indx + Ilen)'Initialized
+ and then String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item,
+ Post =>
+ (if Going = Forward then
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen))
+ else
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen)));
+ -- Lemma_Split is used after Result.Data (Indx + 1 .. Indx + Ilen) is
+ -- updated to Item and concludes that the characters match for each
+ -- index when taken modulo Item'Length, as the considered slice starts
+ -- at index 1 (or ends at index Max_Length, if Going = Backward) modulo
+ -- Item'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) is null;
+
+ --------------------
+ -- Lemma_Mod_Zero --
+ --------------------
+
+ procedure Lemma_Mod_Zero (X : Natural) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split (Going : Direction) is
+ begin
+ if Going = Forward then
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (K - 1, Indx);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen));
+ end loop;
+ else
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (Max_Length - K, Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen));
+ end loop;
+ end if;
+ end Lemma_Split;
begin
- if Length <= Max_Length then
- Result.Current_Length := Length;
-
- if Length > 0 then
- Indx := 1;
+ if Count = 0 or else Ilen <= Max_Length / Count then
+ if Count * Ilen > 0 then
+ Indx := 0;
for J in 1 .. Count loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx = J * Ilen);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
end if;
- else
- Result.Current_Length := Max_Length;
+ Result.Current_Length := Count * Ilen;
+ else
case Drop is
when Strings.Right =>
- Indx := 1;
-
- while Indx + Item'Length <= Max_Length + 1 loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Indx := 0;
+
+ while Indx < Max_Length - Ilen loop
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 0 .. Max_Length - 1);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
- Result.Data (Indx .. Max_Length) :=
- Item (Item'First .. Item'First + Max_Length - Indx);
+ Result.Data (Indx + 1 .. Max_Length) := Super_String_Data
+ (Item (Item'First .. Item'First + (Max_Length - Indx - 1)));
+ pragma Assert
+ (for all J in Indx + 1 .. Max_Length =>
+ Result.Data (J) = Item (Item'First - 1 - Indx + J));
+
+ for J in Indx + 1 .. Max_Length loop
+ Lemma_Mod (J - 1, Indx);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
+ end loop;
when Strings.Left =>
Indx := Max_Length;
- while Indx - Item'Length >= 1 loop
- Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
- Indx := Indx - Item'Length;
+ while Indx > Ilen loop
+ Indx := Indx - Ilen;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Backward);
+ Lemma_Mod_Zero (Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ ((Max_Length - Indx) mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 1 .. Max_Length);
+ pragma Loop_Invariant
+ (Result.Data (Indx + 1 .. Max_Length)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Indx + 1 .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
end loop;
Result.Data (1 .. Indx) :=
- Item (Item'Last - Indx + 1 .. Item'Last);
+ Super_String_Data (Item (Item'Last - Indx + 1 .. Item'Last));
+ pragma Assert
+ (for all J in 1 .. Indx =>
+ Result.Data (J) = Item (Item'Last - Indx + J));
+
+ for J in reverse 1 .. Indx loop
+ Lemma_Mod (Max_Length - J, Max_Length - Indx);
+ pragma Loop_Invariant
+ (for all K in J .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
+ end loop;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1447,11 +1614,7 @@ package body Ada.Strings.Superbounded is
is
begin
return
- Super_Replicate
- (Count,
- Item.Data (1 .. Item.Current_Length),
- Drop,
- Item.Max_Length);
+ Super_Replicate (Count, Super_To_String (Item), Drop, Item.Max_Length);
end Super_Replicate;
-----------------
@@ -1461,42 +1624,20 @@ package body Ada.Strings.Superbounded is
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String
- is
- begin
- -- Note: test of High > Length is in accordance with AI95-00128
-
- return R : String (Low .. High) do
- if Low > Source.Current_Length + 1
- or else High > Source.Current_Length
- then
- raise Index_Error;
- end if;
-
- -- Note: in this case, superflat bounds are not a problem, we just
- -- get the null string in accordance with normal Ada slice rules.
-
- R := Source.Data (Low .. High);
- end return;
- end Super_Slice;
-
- function Super_Slice
- (Source : Super_String;
- Low : Positive;
High : Natural) return Super_String
is
begin
return Result : Super_String (Source.Max_Length) do
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Result.Current_Length := Integer'Max (0, High - Low + 1);
- Result.Data (1 .. Result.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
end return;
end Super_Slice;
@@ -1507,16 +1648,18 @@ package body Ada.Strings.Superbounded is
High : Natural)
is
begin
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Target.Current_Length := Integer'Max (0, High - Low + 1);
- Target.Data (1 .. Target.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Target.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Target.Current_Length := High - Low + 1;
+ else
+ Target.Current_Length := 0;
+ end if;
end Super_Slice;
----------------
@@ -1536,18 +1679,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
- Result.Data (1 .. Count) :=
- Source.Data (Slen - (Count - 1) .. Slen);
+ if Count > 0 then
+ Result.Data (1 .. Count) :=
+ Source.Data (Slen - (Count - 1) .. Slen);
+ Result.Current_Length := Count;
+ end if;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Npad) := (others => Pad);
- Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
- else
- Result.Current_Length := Max_Length;
+ if Slen > 0 then
+ Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
+ end if;
+
+ Result.Current_Length := Count;
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1567,6 +1714,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1582,22 +1731,27 @@ package body Ada.Strings.Superbounded is
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : constant String (1 .. Max_Length) := Source.Data;
+ Temp : constant Super_String_Data (1 .. Max_Length) := Source.Data;
begin
if Npad <= 0 then
Source.Current_Length := Count;
- Source.Data (1 .. Count) :=
- Temp (Slen - (Count - 1) .. Slen);
+
+ if Count > 0 then
+ Source.Data (1 .. Count) :=
+ Temp (Slen - (Count - 1) .. Slen);
+ end if;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (1 .. Npad) := (others => Pad);
- Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
- else
- Source.Current_Length := Max_Length;
+ if Slen > 0 then
+ Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
+ end if;
+ Source.Current_Length := Count;
+
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1610,31 +1764,19 @@ package body Ada.Strings.Superbounded is
end if;
when Strings.Left =>
- for J in 1 .. Max_Length - Slen loop
- Source.Data (J) := Pad;
- end loop;
-
+ Source.Data (1 .. Max_Length - Slen) := (others => Pad);
Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
Temp (1 .. Slen);
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Tail;
---------------------
- -- Super_To_String --
- ---------------------
-
- function Super_To_String (Source : Super_String) return String is
- begin
- return R : String (1 .. Source.Current_Length) do
- R := Source.Data (1 .. Source.Current_Length);
- end return;
- end Super_To_String;
-
- ---------------------
-- Super_Translate --
---------------------
@@ -1645,12 +1787,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Value (Mapping, Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1661,6 +1806,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Value (Mapping, Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1671,12 +1819,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Mapping (Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1687,6 +1838,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Mapping (Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1699,24 +1853,62 @@ package body Ada.Strings.Superbounded is
Side : Trim_End) return Super_String
is
Result : Super_String (Source.Max_Length);
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
+ Last : constant Natural := Source.Current_Length;
begin
- if Side = Left or else Side = Both then
- while First <= Last and then Source.Data (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Source.Data (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
+ if Low = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. Last - Low + 1) := Source.Data (Low .. Last);
+ Result.Current_Length := Last - Low + 1;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ -- All blanks case
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. High) := Source.Data (1 .. High);
+ Result.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Result.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end;
+ end;
+ end case;
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) := Source.Data (First .. Last);
return Result;
end Super_Trim;
@@ -1724,28 +1916,54 @@ package body Ada.Strings.Superbounded is
(Source : in out Super_String;
Side : Trim_End)
is
- Max_Length : constant Positive := Source.Max_Length;
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
- Temp : String (1 .. Max_Length);
-
+ Last : constant Natural := Source.Current_Length;
begin
- Temp (1 .. Last) := Source.Data (1 .. Last);
-
- if Side = Left or else Side = Both then
- while First <= Last and then Temp (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Temp (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
-
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) := Temp (First .. Last);
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ Source.Data (1 .. Last - Low + 1) :=
+ Source.Data (Low .. Last);
+ Source.Current_Length := Last - Low + 1;
+ end if;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end;
+ end if;
+ end;
+ end case;
end Super_Trim;
function Super_Trim
@@ -1754,22 +1972,31 @@ package body Ada.Strings.Superbounded is
Right : Maps.Character_Set) return Super_String
is
Result : Super_String (Source.Max_Length);
+ Low : Natural;
+ High : Natural;
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) :=
- Source.Data (First .. Last);
- return Result;
- end if;
- end loop;
- end if;
- end loop;
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ High := Super_Index (Source, Right, Outside, Backward);
+
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
- Result.Current_Length := 0;
return Result;
end Super_Trim;
@@ -1778,29 +2005,39 @@ package body Ada.Strings.Superbounded is
Left : Maps.Character_Set;
Right : Maps.Character_Set)
is
+ Last : constant Natural := Source.Current_Length;
+ Temp : Super_String_Data (1 .. Last);
+ Low : Natural;
+ High : Natural;
+
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- if First = 1 then
- Source.Current_Length := Last;
- return;
- else
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) :=
- Source.Data (First .. Last);
- return;
- end if;
- end if;
- end loop;
+ Temp := Source.Data (1 .. Last);
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+
+ else
+ High := Super_Index (Source, Right, Outside, Backward);
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
Source.Current_Length := 0;
- return;
- end if;
- end loop;
- Source.Current_Length := 0;
+ elsif Low = 1 then
+ Source.Current_Length := High;
+
+ elsif High < Low then
+ Source.Current_Length := 0;
+
+ else
+ Source.Data (1 .. High - Low + 1) := Temp (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end if;
+ end if;
end Super_Trim;
-----------
@@ -1819,11 +2056,14 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Left;
-
for J in 1 .. Left loop
Result.Data (J) := Right;
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result.Data (K) = Right);
end loop;
+
+ Result.Current_Length := Left;
end if;
return Result;
@@ -1835,23 +2075,88 @@ package body Ada.Strings.Superbounded is
Max_Length : Positive) return Super_String
is
Result : Super_String (Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right'Length;
Nlen : constant Natural := Left * Rlen;
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Integer) with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then K in Pos .. Pos + Rlen - 1,
+ Post => K mod Rlen = K - Pos;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Right'Length.
+
+ procedure Lemma_Split with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then Result.Data (1 .. Pos + Rlen)'Initialized
+ and then String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right,
+ Post =>
+ (for all K in Pos + 1 .. Pos + Rlen =>
+ Result.Data (K) = Right (Right'First + (K - 1) mod Rlen));
+ -- Lemma_Split is used after Result.Data (Pos + 1 .. Pos + Rlen) is
+ -- updated to Right and concludes that the characters match for each
+ -- index when taken modulo Right'Length, as the considered slice starts
+ -- at index 1 modulo Right'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Integer) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split is
+ begin
+ for K in Pos + 1 .. Pos + Rlen loop
+ Lemma_Mod (K - 1);
+ pragma Loop_Invariant
+ (for all J in Pos + 1 .. K =>
+ Result.Data (J) = Right (Right'First + (J - 1) mod Rlen));
+ end loop;
+ end Lemma_Split;
+
begin
if Nlen > Max_Length then
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) := Right;
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
+ Super_String_Data (Right);
+ pragma Assert
+ (for all K in 1 .. Rlen => Result.Data (Pos + K) =
+ Right (Right'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right);
+ Lemma_Split;
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right (Right'First + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1862,7 +2167,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Super_String
is
Result : Super_String (Right.Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right.Current_Length;
Nlen : constant Natural := Left * Rlen;
@@ -1871,15 +2176,21 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) :=
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
Right.Data (1 .. Rlen);
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right.Data (1 + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1891,7 +2202,7 @@ package body Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
+ Max_Length : Positive;
Drop : Truncation := Error) return Super_String
is
Result : Super_String (Max_Length);
@@ -1899,20 +2210,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Result.Data (1 .. Slen) := Super_String_Data (Source);
Result.Current_Length := Slen;
- Result.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
diff --git a/gcc/ada/libgnat/a-strsup.ads b/gcc/ada/libgnat/a-strsup.ads
index 9e568a8..7428e9c 100644
--- a/gcc/ada/libgnat/a-strsup.ads
+++ b/gcc/ada/libgnat/a-strsup.ads
@@ -36,28 +36,47 @@
-- length as the discriminant. Individual instantiations of Strings.Bounded
-- use this type with an appropriate discriminant value set.
-with Ada.Strings.Maps;
+-- 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. Postconditions and
+-- contract cases should not be executed at runtime as well, in order not to
+-- slow down the execution of these functions.
-package Ada.Strings.Superbounded is
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
+with Ada.Strings.Search;
+
+package Ada.Strings.Superbounded with SPARK_Mode is
pragma Preelaborate;
-- Type Bounded_String in Ada.Strings.Bounded.Generic_Bounded_Length is
-- derived from Super_String, with the constraint of the maximum length.
+ type Super_String_Data is new String with Relaxed_Initialization;
+
type Super_String (Max_Length : Positive) is record
Current_Length : Natural := 0;
- Data : String (1 .. Max_Length);
+ Data : Super_String_Data (1 .. Max_Length);
-- A previous version had a default initial value for Data, which is
-- no longer necessary, because we now special-case this type in the
-- compiler, so "=" composes properly for descendants of this type.
-- Leaving it out is more efficient.
- end record;
+ end record
+ with
+ Predicate =>
+ Current_Length <= Max_Length
+ and then Data (1 .. Current_Length)'Initialized;
-- The subprograms defined for Super_String are similar to those
-- defined for Bounded_String, except that they have different names, so
-- that they can be renamed in Ada.Strings.Bounded.Generic_Bounded_Length.
- function Super_Length (Source : Super_String) return Natural;
+ function Super_Length (Source : Super_String) return Natural
+ is (Source.Current_Length);
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -65,109 +84,606 @@ package Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
- Drop : Truncation := Error) return Super_String;
+ Max_Length : Positive;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Post => To_Super_String'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ Super_To_String (To_Super_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length)),
+ Global => null;
-- Note the additional parameter Max_Length, which specifies the maximum
-- length setting of the resulting Super_String value.
-- The following procedures have declarations (and semantics) that are
-- exactly analogous to those declared in Ada.Strings.Bounded.
- function Super_To_String (Source : Super_String) return String;
+ function Super_To_String (Source : Super_String) return String
+ is (String (Source.Data (1 .. Source.Current_Length)));
procedure Set_Super_String
(Target : out Super_String;
Source : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Source'Length > Target.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Target.Max_Length
+ =>
+ Super_To_String (Target) = Source,
+
+ Source'Length > Target.Max_Length and then Drop = Left
+ =>
+ Super_To_String (Target) =
+ Source (Source'Last - Target.Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Target.Max_Length)),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Left.Max_Length = Right.Max_Length
+ and then
+ (if Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Super_Length (Right) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Super_Length (Right))) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length
+ + Super_Length (Right) + 1,
+ Super_Length (Left)))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Super_Length (Right) + 1, Left.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length)) =
+ Super_Slice (Right,
+ 1, Left.Max_Length - Super_Length (Left)))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Right'Length > Left.Max_Length - Super_Length (Left)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Right'Length
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Right),
+
+ Super_Length (Left) > Left.Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Right'Length < Left.Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Right'Length)) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length + Right'Length
+ + 1,
+ Super_Length (Left))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Right'Length + 1, Left.Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ Super_To_String (Super_Append'Result) =
+ Right (Right'Last - Left.Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length) =
+ Right (Right'First
+ .. Left.Max_Length - Super_Length (Left)
+ - 1 + Right'First))),
+ Global => null;
function Super_Append
(Left : String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Left'Length > Right.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Left'Length <= Right.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Left'Length + Super_Length (Right)
+ and then Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Left'Length + 1, Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Left'Length > Right.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Super_Length (Right) < Right.Max_Length then
+ Super_Slice (Super_Append'Result,
+ 1, Right.Max_Length - Super_Length (Right)) =
+ Left
+ (Left'Last - Right.Max_Length + Super_Length (Right) + 1
+ .. Left'Last))
+ and then
+ Super_Slice (Super_Append'Result,
+ Right.Max_Length - Super_Length (Right) + 1,
+ Right.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Left'Length < Right.Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ Left'Length + 1, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ Super_To_String (Super_Append'Result) =
+ Left (Left'First .. Right.Max_Length - 1 + Left'First))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Character;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Left) = Left.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) < Left.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ Super_Element (Super_Append'Result, Super_Length (Left) + 1) =
+ Right,
+
+ Super_Length (Left) = Left.Max_Length and then Drop = Strings.Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - 1)) =
+ Super_Slice (Left, 2, Left.Max_Length)
+ and then
+ Super_Element (Super_Append'Result, Left.Max_Length) = Right),
+ Global => null;
function Super_Append
(Left : Character;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Right) = Right.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Right) < Right.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Right) + 1
+ and then
+ Super_Slice (Super_Append'Result, 2, Super_Length (Right) + 1) =
+ Super_To_String (Right)
+ and then Super_Element (Super_Append'Result, 1) = Left,
+
+ Super_Length (Right) = Right.Max_Length and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result, 2, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - 1)
+ and then Super_Element (Super_Append'Result, 1) = Left),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Super_String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Source.Max_Length = New_Item.Max_Length
+ and then
+ (if Super_Length (Source) >
+ Source.Max_Length - Super_Length (New_Item)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - Super_Length (New_Item)
+ =>
+ Super_Length (Source) =
+ Super_Length (Source'Old) + Super_Length (New_Item)
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (New_Item) > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ Super_To_String (New_Item)),
+
+ Super_Length (Source) > Source.Max_Length - Super_Length (New_Item)
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Super_Length (New_Item) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (New_Item))) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + Super_Length (New_Item) + 1,
+ Super_Length (Source'Old)))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (New_Item) + 1,
+ Source.Max_Length) =
+ Super_To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (New_Item,
+ 1, Source.Max_Length - Super_Length (Source'Old)))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ New_Item),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if New_Item'Length < Source.Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + New_Item'Length + 1,
+ Super_Length (Source'Old))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ Super_To_String (Source) = New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Super_Length (Source'Old) - 1
+ + New_Item'First))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Character;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Super_Length (Source) = Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) < Source.Max_Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + 1
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ Super_Element (Source, Super_Length (Source'Old) + 1) = New_Item,
+
+ Super_Length (Source) = Source.Max_Length and then Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then Super_To_String (Source) = Super_To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Source.Max_Length - 1)) =
+ Super_Slice (Source'Old, 2, Source.Max_Length)
+ and then Super_Element (Source, Source.Max_Length) = New_Item),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left.Max_Length = Right.Max_Length
+ and then Super_Length (Left) <= Left.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : String) return Super_String;
+ Right : String) return Super_String
+ with
+ Pre => Right'Length <= Left.Max_Length - Super_Length (Left),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) = Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Right),
+ Global => null;
function Concat
(Left : String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left'Length <= Right.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then
+ Super_Length (Concat'Result) = Left'Length + Super_Length (Right)
+ and then Super_Slice (Concat'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Left'Length + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Character) return Super_String;
+ Right : Character) return Super_String
+ with
+ Pre => Super_Length (Left) < Left.Max_Length,
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then Super_Length (Concat'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then Super_Element (Concat'Result, Super_Length (Left) + 1) = Right,
+ Global => null;
function Concat
(Left : Character;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Super_Length (Right) < Right.Max_Length,
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Concat'Result) = 1 + Super_Length (Right)
+ and then Super_Element (Concat'Result, 1) = Left
+ and then
+ Super_Slice (Concat'Result, 2, Super_Length (Concat'Result)) =
+ Super_To_String (Right),
+ Global => null;
function Super_Element
(Source : Super_String;
- Index : Positive) return Character;
+ Index : Positive) return Character
+ is (if Index <= Source.Current_Length
+ then Source.Data (Index)
+ else raise Index_Error)
+ with Pre => Index <= Super_Length (Source);
procedure Super_Replace_Element
(Source : in out Super_String;
Index : Positive;
- By : Character);
+ By : Character)
+ with
+ Pre => Index <= Super_Length (Source),
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ (if K = Index then By else Super_Element (Source'Old, K))),
+ Global => null;
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String;
+ High : Natural) return String
+ is (if Low - 1 > Source.Current_Length or else High > Source.Current_Length
+
+ -- Note: test of High > Length is in accordance with AI95-00128
+
+ then raise Index_Error
+ else
+ -- Note: in this case, superflat bounds are not a problem, we just
+ -- get the null string in accordance with normal Ada slice rules.
+
+ String (Source.Data (Low .. High)))
+ with Pre => Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source);
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return Super_String;
+ High : Natural) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source) and then High <= Super_Length (Source),
+ Post => Super_Slice'Result.Max_Length = Source.Max_Length
+ and then
+ Super_To_String (Super_Slice'Result) =
+ Super_Slice (Source, Low, High),
+ Global => null;
procedure Super_Slice
(Source : Super_String;
Target : out Super_String;
Low : Positive;
- High : Natural);
+ High : Natural)
+ with
+ Pre => Source.Max_Length = Target.Max_Length
+ and then Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source),
+ Post => Super_To_String (Target) = Super_Slice (Source, Low, High),
+ Global => null;
function "="
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post => "="'Result = (Super_To_String (Left) = Super_To_String (Right)),
+ Global => null;
function Equal
(Left : Super_String;
@@ -175,59 +691,111 @@ package Ada.Strings.Superbounded is
function Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Equal'Result = (Super_To_String (Left) = Right),
+ Global => null;
function Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Equal'Result = (Left = Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less'Result = (Super_To_String (Left) < Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less'Result = (Super_To_String (Left) < Right),
+ Global => null;
function Less
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less'Result = (Left < Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less_Or_Equal'Result =
+ (Super_To_String (Left) <= Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Super_To_String (Left) <= Right),
+ Global => null;
function Less_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Left <= Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater'Result = (Super_To_String (Left) > Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater'Result = (Super_To_String (Left) > Right),
+ Global => null;
function Greater
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater'Result = (Left > Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater_Or_Equal'Result =
+ (Super_To_String (Left) >= Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Super_To_String (Left) >= Right),
+ Global => null;
function Greater_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Left >= Super_To_String (Right)),
+ Global => null;
----------------------
-- Search Functions --
@@ -237,63 +805,449 @@ package Ada.Strings.Superbounded is
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of Super_To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
From : Positive;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set)))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index'Result = From
+ or else (Super_Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
From : Positive;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Super_Element (Source, J) = ' '))
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index_Non_Blank'Result = From
+ or else
+ (Super_Index_Non_Blank'Result > From) = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length /= 0,
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Global => null;
function Super_Count
(Source : Super_String;
- Set : Maps.Character_Set) return Natural;
+ Set : Maps.Character_Set) return Natural
+ with
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
@@ -301,14 +1255,112 @@ package Ada.Strings.Superbounded is
From : Positive;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ 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.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in From .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), 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 .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), 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 < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ 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 1 and Last is set to 0.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), Set))
+ =>
+ First = 1 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 1 .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between 1 and First satisfies the property Test on
+ -- Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), 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 < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
@@ -316,19 +1368,51 @@ package Ada.Strings.Superbounded is
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping) return Super_String;
+ Mapping : Maps.Character_Mapping) return Super_String
+ with
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping);
+ Mapping : Maps.Character_Mapping)
+ with
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source'Old, K))),
+ Global => null;
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping_Function) return Super_String;
+ Mapping : Maps.Character_Mapping_Function) return Super_String
+ with
+ Pre => Mapping /= null,
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Mapping (Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping_Function);
+ Mapping : Maps.Character_Mapping_Function)
+ with
+ Pre => Mapping /= null,
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Mapping (Super_Element (Source'Old, K))),
+ Global => null;
---------------------------------------
-- String Transformation Subprograms --
@@ -339,48 +1423,756 @@ package Ada.Strings.Superbounded is
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Integer'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Post =>
+ Super_Replace_Slice'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Super_Replace_Slice'Result) =
+ Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+ and then
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source) then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length,
+ Super_Length (Super_Replace_Slice'Result))) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Super_Replace_Slice'Result,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source,
+ Low - Source.Max_Length
+ + Final_Super_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
procedure Super_Replace_Slice
(Source : in out Super_String;
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Natural'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+ and then Super_Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Low + By'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max (0,
+ Super_Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0
+ then
+ -- The first characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source'Old,
+ Low - Source.Max_Length + Final_Super_Slice
+ + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Source, Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
function Super_Insert
(Source : Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Post => Super_Insert'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Super_Insert'Result) =
+ Super_Length (Source) + New_Item'Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+ and then
+ Super_Slice (Super_Insert'Result,
+ Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length,
+ Super_Length (Super_Insert'Result))) =
+ Super_Slice (Source, Before, Super_Length (Source))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source, Before, Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Super_Insert'Result, 1,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) - New_Item'Length
+ + Before,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ 1, Source.Max_Length - Super_Length (Source)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source,
+ Super_Length (Source) - Source.Max_Length
+ + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Super_Insert'Result, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Super_Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
procedure Super_Insert
(Source : in out Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+ and then
+ Super_Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source'Old) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old)
+ - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source'Old) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length + Before,
+ Source.Max_Length - Super_Length (Source'Old) - 1 + Before)
+ = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old)
+ - Source.Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Source, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
function Super_Overwrite
(Source : Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Post => Super_Overwrite'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Super_Overwrite'Result) =
+ Integer'Max (Super_Length (Source), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Super_Overwrite'Result,
+ Position + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Super_Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Super_Overwrite'Result,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Super_Overwrite'Result,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
procedure Super_Overwrite
(Source : in out Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Source) = Integer'Max
+ (Super_Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+ and then Super_Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source'Old)
+ then
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Position + New_Item'Length, Super_Length (Source'Old))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Source) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Super_Slice (Source, Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
function Super_Delete
(Source : Super_String;
From : Positive;
- Through : Natural) return Super_String;
+ Through : Natural) return Super_String
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Post => Super_Delete'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Super_Delete'Result) =
+ From - 1 + Natural'Max (Super_Length (Source) - Through, 0)
+ and then
+ String'(Super_Slice (Super_Delete'Result, 1, From - 1)) =
+ Super_Slice (Source, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Super_Delete'Result,
+ From, Super_Length (Super_Delete'Result))) =
+ Super_Slice (Source, Through + 1, Super_Length (Source))),
+ others =>
+ Super_Delete'Result = Source),
+ Global => null;
procedure Super_Delete
(Source : in out Super_String;
From : Positive;
- Through : Natural);
+ Through : Natural)
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Source) =
+ From - 1 + Natural'Max (Super_Length (Source'Old) - Through, 0)
+ and then
+ String'(Super_Slice (Source, 1, From - 1)) =
+ Super_Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Source, From, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Through + 1, Super_Length (Source'Old))),
+ others =>
+ Source = Source'Old),
+ Global => null;
---------------------------------
-- String Selector Subprograms --
@@ -388,45 +2180,376 @@ package Ada.Strings.Superbounded is
function Super_Trim
(Source : Super_String;
- Side : Trim_End) return Super_String;
+ Side : Trim_End) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source)
+ else Super_Index_Non_Blank (Source, Backward));
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
- Side : Trim_End);
+ Side : Trim_End)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source'Old)
+ else Super_Index_Non_Blank (Source'Old, Backward));
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Trim
(Source : Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set) return Super_String;
+ Right : Maps.Character_Set) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source, Right, Outside, Backward);
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set);
+ Right : Maps.Character_Set)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source'Old, Right, Outside, Backward);
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Head
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Head'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Super_Head'Result) = Super_Slice (Source, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Count
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Count)) =
+ (1 .. Count - Super_Length (Source) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Super_Head'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ 1, Source.Max_Length - Count + Super_Length (Source))) =
+ Super_Slice (Source,
+ Count - Source.Max_Length + 1, Super_Length (Source))
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Source.Max_Length - Count + Super_Length (Source) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source) => Pad)),
+ Global => null;
procedure Super_Head
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Source) = Super_Slice (Source'Old, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Count)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Count - Source.Max_Length + 1, Super_Length (Source'Old))
+ and then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Count + Super_Length (Source'Old) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)),
+ Global => null;
function Super_Tail
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Tail'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Super_Tail'Result) =
+ Super_Slice (Source,
+ Super_Length (Source) - Count + 1, Super_Length (Source))
+ else Super_Length (Super_Tail'Result) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Count
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Count) =
+ Super_To_String (Source),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Source.Max_Length - Super_Length (Source))) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad)
+ and then
+ (if Super_Length (Source) > 0 then
+ Super_Slice (Super_Tail'Result,
+ Source.Max_Length - Super_Length (Source) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Super_Tail'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Source.Max_Length)) =
+ Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source))),
+ Global => null;
procedure Super_Tail
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Source) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Count + 1,
+ Super_Length (Source'Old))
+ else Super_Length (Source) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Count) =
+ Super_To_String (Source'Old),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old))) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad)
+ and then
+ (if Super_Length (Source'Old) > 0 then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source'Old)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ String'(Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))),
+ Global => null;
------------------------------------
-- String Constructor Subprograms --
@@ -439,37 +2562,135 @@ package Ada.Strings.Superbounded is
function Times
(Left : Natural;
Right : Character;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => Left <= Max_Length,
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_To_String (Times'Result) = (1 .. Left => Right),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
Right : String;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_Length (Times'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Super_Element (Times'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre =>
+ (if Left /= 0 then Super_Length (Right) <= Right.Max_Length / Left),
+ Post => Times'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Times'Result) = Left * Super_Length (Right)
+ and then
+ (if Super_Length (Right) > 0 then
+ (for all K in 1 .. Left * Super_Length (Right) =>
+ Super_Element (Times'Result, K) =
+ Super_Element (Right, 1 + (K - 1) mod Super_Length (Right)))),
+ Global => null;
function Super_Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length
+ and then Super_To_String (Super_Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Item.Max_Length,
+ Contract_Cases =>
+ ((if Count /= 0 then Super_Length (Item) <= Item.Max_Length / Count)
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Super_Length (Item)
+ and then
+ (if Super_Length (Item) > 0 then
+ (for all K in 1 .. Count * Super_Length (Item) =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ 1 + (K - 1) mod Super_Length (Item)))),
+ Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item, 1 + (K - 1) mod Super_Length (Item))),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ Super_Length (Item)
+ - (Item.Max_Length - K) mod Super_Length (Item)))),
+ Global => null;
private
-- Pragma Inline declarations
diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads
index 13c7612..b3050fd 100644
--- a/gcc/ada/libgnat/a-strunb.ads
+++ b/gcc/ada/libgnat/a-strunb.ads
@@ -53,11 +53,13 @@ private with Ada.Strings.Text_Buffers;
-- and selector operations are provided.
package Ada.Strings.Unbounded with
+ SPARK_Mode,
Initial_Condition => Length (Null_Unbounded_String) = 0
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
@@ -73,7 +75,7 @@ is
-- Provides a (nonprivate) access type for explicit processing of
-- unbounded-length strings.
- procedure Free (X : in out String_Access);
+ procedure Free (X : in out String_Access) with SPARK_Mode => Off;
-- Performs an unchecked deallocation of an object of type String_Access
--------------------------------------------------------
@@ -732,6 +734,8 @@ is
-- strings applied to the string represented by Source's original value.
private
+ pragma SPARK_Mode (Off); -- Controlled types are not in SPARK
+
pragma Inline (Length);
package AF renames Ada.Finalization;
diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads
index 2091bde..2cf6780 100644
--- a/gcc/ada/libgnat/a-strunb__shared.ads
+++ b/gcc/ada/libgnat/a-strunb__shared.ads
@@ -85,7 +85,8 @@ package Ada.Strings.Unbounded with
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
diff --git a/gcc/ada/libgnat/a-tags.adb b/gcc/ada/libgnat/a-tags.adb
index c6a9d25..170d16a 100644
--- a/gcc/ada/libgnat/a-tags.adb
+++ b/gcc/ada/libgnat/a-tags.adb
@@ -1032,7 +1032,7 @@ package body Ada.Tags is
-- Wide_Expanded_Name --
------------------------
- WC_Encoding : Character;
+ WC_Encoding : constant Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
-- Encoding method for source, as exported by binder
diff --git a/gcc/ada/libgnat/a-textio.adb b/gcc/ada/libgnat/a-textio.adb
index 717f529..1bdab6e 100644
--- a/gcc/ada/libgnat/a-textio.adb
+++ b/gcc/ada/libgnat/a-textio.adb
@@ -44,6 +44,7 @@ pragma Elaborate_All (System.File_IO);
-- Needed because of calls to Chain_File in package body elaboration
package body Ada.Text_IO with
+ SPARK_Mode => Off,
Refined_State => (File_System => (Standard_In,
Standard_Out,
Standard_Err,
@@ -66,7 +67,7 @@ is
use type System.CRTL.size_t;
- WC_Encoding : Character;
+ WC_Encoding : constant Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
-- Default wide character encoding
diff --git a/gcc/ada/libgnat/a-textio.ads b/gcc/ada/libgnat/a-textio.ads
index a06a35c..f94c92d 100644
--- a/gcc/ada/libgnat/a-textio.ads
+++ b/gcc/ada/libgnat/a-textio.ads
@@ -56,8 +56,9 @@ with System.File_Control_Block;
with System.WCh_Con;
package Ada.Text_IO with
- Abstract_State => (File_System),
- Initializes => (File_System),
+ SPARK_Mode,
+ Abstract_State => File_System,
+ Initializes => File_System,
Initial_Condition => Line_Length = 0 and Page_Length = 0
is
pragma Elaborate_Body;
@@ -547,6 +548,7 @@ is
Layout_Error : exception renames IO_Exceptions.Layout_Error;
private
+ pragma SPARK_Mode (Off);
-- The following procedures have a File_Type formal of mode IN OUT because
-- they may close the original file. The Close operation may raise an
diff --git a/gcc/ada/libgnat/a-witeio.adb b/gcc/ada/libgnat/a-witeio.adb
index 7dbd3b3..dbc0f2a 100644
--- a/gcc/ada/libgnat/a-witeio.adb
+++ b/gcc/ada/libgnat/a-witeio.adb
@@ -55,7 +55,7 @@ package body Ada.Wide_Text_IO is
use type System.CRTL.size_t;
- WC_Encoding : Character;
+ WC_Encoding : constant Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
-- Default wide character encoding
diff --git a/gcc/ada/libgnat/a-zchhan.adb b/gcc/ada/libgnat/a-zchhan.adb
index 3f2a91b..61405f7 100644
--- a/gcc/ada/libgnat/a-zchhan.adb
+++ b/gcc/ada/libgnat/a-zchhan.adb
@@ -33,6 +33,15 @@ with Ada.Wide_Wide_Characters.Unicode; use Ada.Wide_Wide_Characters.Unicode;
package body Ada.Wide_Wide_Characters.Handling is
+ ---------------------------
+ -- Character_Set_Version --
+ ---------------------------
+
+ function Character_Set_Version return String is
+ begin
+ return "Unicode 4.0";
+ end Character_Set_Version;
+
---------------------
-- Is_Alphanumeric --
---------------------
@@ -42,6 +51,13 @@ package body Ada.Wide_Wide_Characters.Handling is
return Is_Letter (Item) or else Is_Digit (Item);
end Is_Alphanumeric;
+ --------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean
+ renames Ada.Wide_Wide_Characters.Unicode.Is_Basic;
+
----------------
-- Is_Control --
----------------
@@ -191,4 +207,22 @@ package body Ada.Wide_Wide_Characters.Handling is
return Result;
end To_Upper;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character
+ renames Ada.Wide_Wide_Characters.Unicode.To_Basic;
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String is
+ Result : Wide_Wide_String (Item'Range);
+
+ begin
+ for J in Result'Range loop
+ Result (J) := To_Basic (Item (J));
+ end loop;
+
+ return Result;
+ end To_Basic;
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchhan.ads b/gcc/ada/libgnat/a-zchhan.ads
index 74fab2a..6ebd1a8 100644
--- a/gcc/ada/libgnat/a-zchhan.ads
+++ b/gcc/ada/libgnat/a-zchhan.ads
@@ -15,10 +15,12 @@
package Ada.Wide_Wide_Characters.Handling is
pragma Pure;
- -- This package is clearly intended to be Pure, by analogy with the
- -- base Ada.Characters.Handling package. The version in the RM does
- -- not yet have this pragma, but that is a clear omission. This will
- -- be fixed in a future version of AI05-0266-1.
+
+ function Character_Set_Version return String;
+ pragma Inline (Character_Set_Version);
+ -- Returns an implementation-defined identifier that identifies the version
+ -- of the character set standard that is used for categorizing characters
+ -- by the implementation. For GNAT this is "Unicode v.v".
function Is_Control (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Control);
@@ -42,6 +44,12 @@ package Ada.Wide_Wide_Characters.Handling is
-- Returns True if the Wide_Wide_Character designated by Item is
-- categorized as letter_uppercase, otherwise returns false.
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
function Is_Digit (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Digit);
-- Returns True if the Wide_Wide_Character designated by Item is
@@ -135,4 +143,17 @@ package Ada.Wide_Wide_Characters.Handling is
-- designated by Item. The result is the null Wide_Wide_String if the value
-- of the formal parameter is the null Wide_Wide_String.
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given
+ -- by the first value of its Decomposition Mapping in the code charts
+ -- of ISO/IEC 10646:2017 if any, returns Item otherwise.
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String;
+ -- Returns the result of applying the To_Basic conversion to each
+ -- Wide_Wide_Character element of the Wide_Wide_String designated by Item.
+ -- The result is the null Wide_Wide_String if the value of the formal
+ -- parameter is the null Wide_Wide_String. The lower bound of the result
+ -- Wide_Wide_String is 1.
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchuni.adb b/gcc/ada/libgnat/a-zchuni.adb
index 2bbe584..3c6e720 100644
--- a/gcc/ada/libgnat/a-zchuni.adb
+++ b/gcc/ada/libgnat/a-zchuni.adb
@@ -43,6 +43,15 @@ package body Ada.Wide_Wide_Characters.Unicode is
end Get_Category;
--------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (U : Wide_Wide_Character) return Boolean is
+ begin
+ return G.Is_UTF_32_Basic (Wide_Wide_Character'Pos (U));
+ end Is_Basic;
+
+ --------------
-- Is_Digit --
--------------
@@ -158,6 +167,16 @@ package body Ada.Wide_Wide_Characters.Unicode is
return G.Is_UTF_32_Space (G.Category (C));
end Is_Space;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character is
+ begin
+ return Wide_Wide_Character'Val
+ (G.UTF_32_To_Basic (Wide_Wide_Character'Pos (U)));
+ end To_Basic;
+
-------------------
-- To_Lower_Case --
-------------------
diff --git a/gcc/ada/libgnat/a-zchuni.ads b/gcc/ada/libgnat/a-zchuni.ads
index 51f7c92..0030fd1 100644
--- a/gcc/ada/libgnat/a-zchuni.ads
+++ b/gcc/ada/libgnat/a-zchuni.ads
@@ -177,6 +177,18 @@ package Ada.Wide_Wide_Characters.Unicode is
-- in the list of categories above. This means that these characters can
-- be included in character and string literals.
+ function Is_Basic (U : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given by the first
+ -- value of its Decomposition Mapping in the code charts of
+ -- ISO/IEC 10646:2017 if any, returns Item otherwise.
+
-- The following function is used to fold to upper case, as required by
-- the Ada 2005 standard rules for identifier case folding. Two
-- identifiers are equivalent if they are identical after folding all
diff --git a/gcc/ada/libgnat/a-ztexio.adb b/gcc/ada/libgnat/a-ztexio.adb
index 71d733e..b72a1d4 100644
--- a/gcc/ada/libgnat/a-ztexio.adb
+++ b/gcc/ada/libgnat/a-ztexio.adb
@@ -55,7 +55,7 @@ package body Ada.Wide_Wide_Text_IO is
use type System.CRTL.size_t;
- WC_Encoding : Character;
+ WC_Encoding : constant Character;
pragma Import (C, WC_Encoding, "__gl_wc_encoding");
-- Default wide character encoding
diff --git a/gcc/ada/libgnat/g-binenv.adb b/gcc/ada/libgnat/g-binenv.adb
index e10fb96..4bf39cd 100644
--- a/gcc/ada/libgnat/g-binenv.adb
+++ b/gcc/ada/libgnat/g-binenv.adb
@@ -40,7 +40,7 @@ package body GNAT.Bind_Environment is
function Get (Key : String) return String is
use type System.Address;
- Bind_Env_Addr : System.Address;
+ Bind_Env_Addr : constant System.Address;
pragma Import (C, Bind_Env_Addr, "__gl_bind_env_addr");
-- Variable provided by init.c/s-init.ads, and initialized by
-- the binder generated file.
diff --git a/gcc/ada/libgnat/g-forstr.adb b/gcc/ada/libgnat/g-forstr.adb
index 64c4cb6..04539be 100644
--- a/gcc/ada/libgnat/g-forstr.adb
+++ b/gcc/ada/libgnat/g-forstr.adb
@@ -420,11 +420,11 @@ package body GNAT.Formatted_String is
-- Zero padding if required and possible
- if F_Spec.Left_Justify = False
+ if not F_Spec.Left_Justify
and then F_Spec.Zero_Pad
and then F_Spec.Width > Len + Value'First - S
then
- Append (Res, String'((F_Spec.Width - Len + Value'First - S) * '0'));
+ Append (Res, String'((F_Spec.Width - (Len + Value'First - S)) * '0'));
end if;
-- Add the value now
@@ -519,7 +519,7 @@ package body GNAT.Formatted_String is
J := J + 1;
end loop;
- if F (J) /= '%' or else J = F'Last then
+ if J >= F'Last or else F (J) /= '%' then
raise Format_Error with "no format specifier found for parameter"
& Positive'Image (Format.D.Current);
end if;
diff --git a/gcc/ada/libgnat/i-vxwork.ads b/gcc/ada/libgnat/i-vxwork.ads
index c5686bb..0ba1e6e 100644
--- a/gcc/ada/libgnat/i-vxwork.ads
+++ b/gcc/ada/libgnat/i-vxwork.ads
@@ -133,6 +133,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -145,9 +148,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/i-vxwork__x86.ads b/gcc/ada/libgnat/i-vxwork__x86.ads
index ed9bb42..659167f 100644
--- a/gcc/ada/libgnat/i-vxwork__x86.ads
+++ b/gcc/ada/libgnat/i-vxwork__x86.ads
@@ -128,6 +128,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -140,9 +143,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/memtrack.adb b/gcc/ada/libgnat/memtrack.adb
index e622fec..b34ac04 100644
--- a/gcc/ada/libgnat/memtrack.adb
+++ b/gcc/ada/libgnat/memtrack.adb
@@ -69,10 +69,13 @@
pragma Source_File_Name (System.Memory, Body_File_Name => "memtrack.adb");
with Ada.Exceptions;
+with GNAT.IO;
+
with System.Soft_Links;
with System.Traceback;
with System.Traceback_Entries;
-with GNAT.IO;
+with System.CRTL;
+with System.OS_Lib;
with System.OS_Primitives;
package body System.Memory is
@@ -93,30 +96,14 @@ package body System.Memory is
(Ptr : System.Address; Size : size_t) return System.Address;
pragma Import (C, c_realloc, "realloc");
- subtype File_Ptr is System.Address;
-
- function fopen (Path : String; Mode : String) return File_Ptr;
- pragma Import (C, fopen);
-
- procedure OS_Exit (Status : Integer);
- 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;
- Nmemb : size_t;
- Stream : File_Ptr);
- pragma Import (C, fwrite);
+ subtype File_Ptr is CRTL.FILEs;
- procedure fputc (C : Integer; Stream : File_Ptr);
- pragma Import (C, fputc);
+ procedure Write (Ptr : System.Address; Size : size_t);
- procedure fclose (Stream : File_Ptr);
- pragma Import (C, fclose);
+ procedure Putc (Char : Character);
procedure Finalize;
pragma Export (C, Finalize, "__gnat_finalize");
@@ -210,20 +197,17 @@ package body System.Memory is
Timestamp := System.OS_Primitives.Clock;
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -246,8 +230,8 @@ package body System.Memory is
procedure Finalize is
begin
- if not Needs_Init then
- fclose (Gmemfile);
+ if not Needs_Init and then CRTL.fclose (Gmemfile) /= 0 then
+ Put_Line ("gmem close error: " & OS_Lib.Errno_Message);
end if;
end Finalize;
@@ -275,18 +259,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -304,29 +286,41 @@ package body System.Memory is
procedure Gmem_Initialize is
Timestamp : aliased Duration;
-
+ File_Mode : constant String := "wb" & ASCII.NUL;
begin
if Needs_Init then
Needs_Init := False;
System.OS_Primitives.Initialize;
Timestamp := System.OS_Primitives.Clock;
- Gmemfile := fopen (Gmemfname, "wb" & ASCII.NUL);
+ Gmemfile := CRTL.fopen (Gmemfname'Address, File_Mode'Address);
if Gmemfile = System.Null_Address then
Put_Line ("Couldn't open gnatmem log file for writing");
- OS_Exit (255);
+ OS_Lib.OS_Exit (255);
end if;
declare
S : constant String := "GMEM DUMP" & ASCII.LF;
begin
- fwrite (S'Address, S'Length, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements,
- 1, Gmemfile);
+ Write (S'Address, S'Length);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
end;
end if;
end Gmem_Initialize;
+ ----------
+ -- Putc --
+ ----------
+
+ procedure Putc (Char : Character) is
+ C : constant Integer := Character'Pos (Char);
+
+ begin
+ if CRTL.fputc (C, Gmemfile) /= C then
+ Put_Line ("gmem fputc error: " & OS_Lib.Errno_Message);
+ end if;
+ end Putc;
+
-------------
-- Realloc --
-------------
@@ -360,18 +354,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -381,20 +373,17 @@ package body System.Memory is
-- Log allocation call using the same backtrace
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -411,4 +400,22 @@ package body System.Memory is
return Result;
end Realloc;
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write (Ptr : System.Address; Size : size_t) is
+ function fwrite
+ (buffer : System.Address;
+ size : size_t;
+ count : size_t;
+ stream : File_Ptr) return size_t;
+ pragma Import (C, fwrite);
+
+ begin
+ if fwrite (Ptr, Size, 1, Gmemfile) /= 1 then
+ Put_Line ("gmem fwrite error: " & OS_Lib.Errno_Message);
+ end if;
+ end Write;
+
end System.Memory;
diff --git a/gcc/ada/libgnat/s-aoinar.adb b/gcc/ada/libgnat/s-aoinar.adb
index df12b16..2f430ed 100644
--- a/gcc/ada/libgnat/s-aoinar.adb
+++ b/gcc/ada/libgnat/s-aoinar.adb
@@ -203,7 +203,7 @@ package body System.Atomic_Operations.Integer_Arithmetic is
pragma Unreferenced (Item);
use type Interfaces.C.size_t;
begin
- return Boolean (Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8));
+ return Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8);
end Is_Lock_Free;
end System.Atomic_Operations.Integer_Arithmetic;
diff --git a/gcc/ada/libgnat/s-aomoar.adb b/gcc/ada/libgnat/s-aomoar.adb
index c955623..a6f4b0e 100644
--- a/gcc/ada/libgnat/s-aomoar.adb
+++ b/gcc/ada/libgnat/s-aomoar.adb
@@ -209,7 +209,7 @@ package body System.Atomic_Operations.Modular_Arithmetic is
pragma Unreferenced (Item);
use type Interfaces.C.size_t;
begin
- return Boolean (Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8));
+ return Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8);
end Is_Lock_Free;
end System.Atomic_Operations.Modular_Arithmetic;
diff --git a/gcc/ada/libgnat/s-aotase.adb b/gcc/ada/libgnat/s-aotase.adb
index 5317889..94b28df 100644
--- a/gcc/ada/libgnat/s-aotase.adb
+++ b/gcc/ada/libgnat/s-aotase.adb
@@ -40,7 +40,7 @@ package body System.Atomic_Operations.Test_And_Set is
function Atomic_Test_And_Set
(Item : aliased in out Test_And_Set_Flag) return Boolean is
begin
- return Boolean (Atomic_Test_And_Set (Item'Address));
+ return Atomic_Test_And_Set (Item'Address);
end Atomic_Test_And_Set;
------------------
diff --git a/gcc/ada/libgnat/s-arit128.ads b/gcc/ada/libgnat/s-arit128.ads
index 6213cfb..fa6fedc 100644
--- a/gcc/ada/libgnat/s-arit128.ads
+++ b/gcc/ada/libgnat/s-arit128.ads
@@ -81,4 +81,11 @@ package System.Arith_128 is
-- then Q is the rounded quotient. The remainder R is not affected by the
-- setting of the Round flag.
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check128,
+ "strub", "callable");
+
end System.Arith_128;
diff --git a/gcc/ada/libgnat/s-arit64.ads b/gcc/ada/libgnat/s-arit64.ads
index c9141f5..68d2149 100644
--- a/gcc/ada/libgnat/s-arit64.ads
+++ b/gcc/ada/libgnat/s-arit64.ads
@@ -93,4 +93,11 @@ package System.Arith_64 is
Round : Boolean) renames Double_Divide64;
-- Renamed procedure to preserve compatibility with earlier versions
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check64,
+ "strub", "callable");
+
end System.Arith_64;
diff --git a/gcc/ada/libgnat/s-atopex.adb b/gcc/ada/libgnat/s-atopex.adb
index 501254e..b0aa9e5 100644
--- a/gcc/ada/libgnat/s-atopex.adb
+++ b/gcc/ada/libgnat/s-atopex.adb
@@ -89,36 +89,36 @@ package body System.Atomic_Operations.Exchange is
(Ptr : System.Address;
Expected : System.Address;
Desired : Atomic_Type;
- Weak : bool := False;
+ Weak : Boolean := False;
Success_Model : Mem_Model := Seq_Cst;
- Failure_Model : Mem_Model := Seq_Cst) return bool;
+ Failure_Model : Mem_Model := Seq_Cst) return Boolean;
pragma Import
(Intrinsic, Atomic_Compare_Exchange_1, "__atomic_compare_exchange_1");
function Atomic_Compare_Exchange_2
(Ptr : System.Address;
Expected : System.Address;
Desired : Atomic_Type;
- Weak : bool := False;
+ Weak : Boolean := False;
Success_Model : Mem_Model := Seq_Cst;
- Failure_Model : Mem_Model := Seq_Cst) return bool;
+ Failure_Model : Mem_Model := Seq_Cst) return Boolean;
pragma Import
(Intrinsic, Atomic_Compare_Exchange_2, "__atomic_compare_exchange_2");
function Atomic_Compare_Exchange_4
(Ptr : System.Address;
Expected : System.Address;
Desired : Atomic_Type;
- Weak : bool := False;
+ Weak : Boolean := False;
Success_Model : Mem_Model := Seq_Cst;
- Failure_Model : Mem_Model := Seq_Cst) return bool;
+ Failure_Model : Mem_Model := Seq_Cst) return Boolean;
pragma Import
(Intrinsic, Atomic_Compare_Exchange_4, "__atomic_compare_exchange_4");
function Atomic_Compare_Exchange_8
(Ptr : System.Address;
Expected : System.Address;
Desired : Atomic_Type;
- Weak : bool := False;
+ Weak : Boolean := False;
Success_Model : Mem_Model := Seq_Cst;
- Failure_Model : Mem_Model := Seq_Cst) return bool;
+ Failure_Model : Mem_Model := Seq_Cst) return Boolean;
pragma Import
(Intrinsic, Atomic_Compare_Exchange_8, "__atomic_compare_exchange_8");
pragma Warnings (On);
@@ -126,21 +126,17 @@ package body System.Atomic_Operations.Exchange is
begin
case Atomic_Type'Object_Size is
when 8 =>
- return Boolean
- (Atomic_Compare_Exchange_1
- (Item'Address, Prior'Address, Desired));
+ return
+ Atomic_Compare_Exchange_1 (Item'Address, Prior'Address, Desired);
when 16 =>
- return Boolean
- (Atomic_Compare_Exchange_2
- (Item'Address, Prior'Address, Desired));
+ return
+ Atomic_Compare_Exchange_2 (Item'Address, Prior'Address, Desired);
when 32 =>
- return Boolean
- (Atomic_Compare_Exchange_4
- (Item'Address, Prior'Address, Desired));
+ return
+ Atomic_Compare_Exchange_4 (Item'Address, Prior'Address, Desired);
when 64 =>
- return Boolean
- (Atomic_Compare_Exchange_8
- (Item'Address, Prior'Address, Desired));
+ return
+ Atomic_Compare_Exchange_8 (Item'Address, Prior'Address, Desired);
when others =>
raise Program_Error;
end case;
@@ -154,7 +150,7 @@ package body System.Atomic_Operations.Exchange is
pragma Unreferenced (Item);
use type Interfaces.C.size_t;
begin
- return Boolean (Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8));
+ return Atomic_Always_Lock_Free (Atomic_Type'Object_Size / 8);
end Is_Lock_Free;
end System.Atomic_Operations.Exchange;
diff --git a/gcc/ada/libgnat/s-atopri.ads b/gcc/ada/libgnat/s-atopri.ads
index 2a5ffe5..891b2ed 100644
--- a/gcc/ada/libgnat/s-atopri.ads
+++ b/gcc/ada/libgnat/s-atopri.ads
@@ -62,9 +62,6 @@ package System.Atomic_Primitives is
subtype Mem_Model is Integer range Relaxed .. Last;
- type bool is new Boolean;
- pragma Convention (C, bool);
-
------------------------------------
-- GCC built-in atomic primitives --
------------------------------------
@@ -137,7 +134,7 @@ package System.Atomic_Primitives is
function Atomic_Test_And_Set
(Ptr : System.Address;
- Model : Mem_Model := Seq_Cst) return bool;
+ Model : Mem_Model := Seq_Cst) return Boolean;
pragma Import (Intrinsic, Atomic_Test_And_Set, "__atomic_test_and_set");
procedure Atomic_Clear
@@ -147,7 +144,7 @@ package System.Atomic_Primitives is
function Atomic_Always_Lock_Free
(Size : Interfaces.C.size_t;
- Ptr : System.Address := System.Null_Address) return bool;
+ Ptr : System.Address := System.Null_Address) return Boolean;
pragma Import
(Intrinsic, Atomic_Always_Lock_Free, "__atomic_always_lock_free");
diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb
index 4a9d538..e02b0fd 100644
--- a/gcc/ada/libgnat/s-dwalin.adb
+++ b/gcc/ada/libgnat/s-dwalin.adb
@@ -31,7 +31,6 @@
with Ada.Characters.Handling;
with Ada.Containers.Generic_Array_Sort;
-with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
with Ada.Unchecked_Deallocation;
with Interfaces; use Interfaces;
@@ -42,13 +41,16 @@ with System.Bounded_Strings; use System.Bounded_Strings;
with System.IO; use System.IO;
with System.Mmap; use System.Mmap;
with System.Object_Reader; use System.Object_Reader;
-with System.Traceback_Entries; use System.Traceback_Entries;
with System.Storage_Elements; use System.Storage_Elements;
package body System.Dwarf_Lines is
SSU : constant := System.Storage_Unit;
+ function Get_Load_Displacement (C : Dwarf_Context) return Storage_Offset;
+ -- Return the displacement between the load address present in the binary
+ -- and the run-time address at which it is loaded (i.e. non-zero for PIE).
+
function String_Length (Str : Str_Access) return Natural;
-- Return the length of the C string Str
@@ -76,7 +78,7 @@ package body System.Dwarf_Lines is
procedure Read_Aranges_Entry
(C : in out Dwarf_Context;
- Start : out Storage_Offset;
+ Start : out Address;
Len : out Storage_Count);
-- Read a single .debug_aranges pair
@@ -88,7 +90,7 @@ package body System.Dwarf_Lines is
procedure Aranges_Lookup
(C : in out Dwarf_Context;
- Addr : Storage_Offset;
+ Addr : Address;
Info_Offset : out Offset;
Success : out Boolean);
-- Search for Addr in .debug_aranges and return offset Info_Offset in
@@ -153,7 +155,7 @@ package body System.Dwarf_Lines is
procedure Symbolic_Address
(C : in out Dwarf_Context;
- Addr : Storage_Offset;
+ Addr : Address;
Dir_Name : out Str_Access;
File_Name : out Str_Access;
Subprg_Name : out String_Ptr_Len;
@@ -370,6 +372,19 @@ package body System.Dwarf_Lines is
end loop;
end For_Each_Row;
+ ---------------------------
+ -- Get_Load_Displacement --
+ ---------------------------
+
+ function Get_Load_Displacement (C : Dwarf_Context) return Storage_Offset is
+ begin
+ if C.Load_Address /= Null_Address then
+ return C.Load_Address - Address (Get_Load_Address (C.Obj.all));
+ else
+ return 0;
+ end if;
+ end Get_Load_Displacement;
+
---------------------
-- Initialize_Pass --
---------------------
@@ -405,18 +420,19 @@ package body System.Dwarf_Lines is
---------------
function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean is
+ Disp : constant Storage_Offset := Get_Load_Displacement (C);
+
begin
- return (Addr >= C.Low + C.Load_Address
- and then Addr <= C.High + C.Load_Address);
+ return Addr >= C.Low + Disp and then Addr <= C.High + Disp;
end Is_Inside;
-----------------
-- Low_Address --
-----------------
- function Low_Address (C : Dwarf_Context) return System.Address is
+ function Low_Address (C : Dwarf_Context) return Address is
begin
- return C.Load_Address + C.Low;
+ return C.Low + Get_Load_Displacement (C);
end Low_Address;
----------
@@ -450,12 +466,12 @@ package body System.Dwarf_Lines is
Success := True;
- -- Get memory bounds for executable code. Note that such code
+ -- Get address bounds for executable code. Note that such code
-- might come from multiple sections.
Get_Xcode_Bounds (C.Obj.all, Lo, Hi);
- C.Low := Storage_Offset (Lo);
- C.High := Storage_Offset (Hi);
+ C.Low := Address (Lo);
+ C.High := Address (Hi);
-- Create a stream for debug sections
@@ -568,10 +584,10 @@ package body System.Dwarf_Lines is
Standard_Opcode_Lengths (J) := Read (C.Lines);
end loop;
- -- The directories table follows. Up to DWARF 4, this is a list of null
+ -- The Directories table follows. Up to DWARF 4, this is a list of null
-- terminated strings terminated by a null byte. In DWARF 5, this is a
- -- sequence of Directories_Count entries encoded as described by the
- -- Directory_Entry_Format field. We store its offset for later decoding.
+ -- sequence of Directories_Count entries which are encoded as described
+ -- by the Directory_Entry_Format field. We store its offset for later.
if Header.Version <= 4 then
Tell (C.Lines, Header.Directories);
@@ -603,12 +619,12 @@ package body System.Dwarf_Lines is
end loop;
end if;
- -- The file_names table is next. Up to DWARF 4, this is a list of record
+ -- The File_Names table is next. Up to DWARF 4, this is a list of record
-- containing a null terminated string for the file name, an unsigned
-- LEB128 directory index in the Directories table, an unsigned LEB128
-- modification time, and an unsigned LEB128 for the file length; the
-- table is terminated by a null byte. In DWARF 5, this is a sequence
- -- of File_Names_Count entries encoded as described by the
+ -- of File_Names_Count entries which are encoded as described by the
-- File_Name_Entry_Format field. We store its offset for later decoding.
if Header.Version <= 4 then
@@ -941,8 +957,10 @@ package body System.Dwarf_Lines is
when DW_FORM_line_strp =>
Read_Section_Offset (C.Lines, Off, C.Header.Is64);
- Seek (C.Line_Str, Off);
- Read_C_String (C.Line_Str, Buf);
+ if J = File then
+ Seek (C.Line_Str, Off);
+ Read_C_String (C.Line_Str, Buf);
+ end if;
when others =>
raise Dwarf_Error with "DWARF form not implemented";
@@ -1027,7 +1045,7 @@ package body System.Dwarf_Lines is
case C_Type is
when DW_LNCT_path .. DW_LNCT_MD5 =>
if N not in A'Range then
- raise Dwarf_Error with "DWARF duplicate content type";
+ raise Dwarf_Error with "duplicate DWARF content type";
end if;
A (N) := (C_Type, Form);
@@ -1048,7 +1066,7 @@ package body System.Dwarf_Lines is
procedure Aranges_Lookup
(C : in out Dwarf_Context;
- Addr : Storage_Offset;
+ Addr : Address;
Info_Offset : out Offset;
Success : out Boolean)
is
@@ -1062,7 +1080,7 @@ package body System.Dwarf_Lines is
loop
declare
- Start : Storage_Offset;
+ Start : Address;
Len : Storage_Count;
begin
Read_Aranges_Entry (C, Start, Len);
@@ -1098,8 +1116,6 @@ package body System.Dwarf_Lines is
case Form is
when DW_FORM_addr =>
Skip := Offset (Ptr_Sz);
- when DW_FORM_addrx =>
- Skip := Offset (uint32'(Read_LEB128 (S)));
when DW_FORM_block1 =>
Skip := Offset (uint8'(Read (S)));
when DW_FORM_block2 =>
@@ -1145,11 +1161,12 @@ package body System.Dwarf_Lines is
begin
return;
end;
- when DW_FORM_udata
- | DW_FORM_ref_udata
+ when DW_FORM_addrx
| DW_FORM_loclistx
+ | DW_FORM_ref_udata
| DW_FORM_rnglistx
| DW_FORM_strx
+ | DW_FORM_udata
=>
declare
Val : constant uint32 := Read_LEB128 (S);
@@ -1157,7 +1174,7 @@ package body System.Dwarf_Lines is
begin
return;
end;
- when DW_FORM_flag_present =>
+ when DW_FORM_flag_present | DW_FORM_implicit_const =>
return;
when DW_FORM_ref_addr
| DW_FORM_sec_offset
@@ -1171,10 +1188,10 @@ package body System.Dwarf_Lines is
null;
end loop;
return;
- when DW_FORM_implicit_const | DW_FORM_indirect =>
- raise Constraint_Error;
+ when DW_FORM_indirect =>
+ raise Dwarf_Error with "DW_FORM_indirect not implemented";
when others =>
- raise Constraint_Error;
+ raise Dwarf_Error with "DWARF form not implemented";
end case;
Seek (S, Tell (S) + Skip);
@@ -1393,7 +1410,7 @@ package body System.Dwarf_Lines is
procedure Read_Aranges_Entry
(C : in out Dwarf_Context;
- Start : out Storage_Offset;
+ Start : out Address;
Len : out Storage_Count)
is
begin
@@ -1405,7 +1422,7 @@ package body System.Dwarf_Lines is
begin
S := Read (C.Aranges);
L := Read (C.Aranges);
- Start := Storage_Offset (S);
+ Start := Address (S);
Len := Storage_Count (L);
end;
@@ -1415,7 +1432,7 @@ package body System.Dwarf_Lines is
begin
S := Read (C.Aranges);
L := Read (C.Aranges);
- Start := Storage_Offset (S);
+ Start := Address (S);
Len := Storage_Count (L);
end;
@@ -1505,11 +1522,12 @@ package body System.Dwarf_Lines is
Info_Offset : Offset;
Line_Offset : Offset;
Success : Boolean;
- Ar_Start : Storage_Offset;
+ Ar_Start : Address;
Ar_Len : Storage_Count;
Start, Len : uint32;
First, Last : Natural;
Mid : Natural;
+
begin
Seek (C.Aranges, 0);
@@ -1524,7 +1542,7 @@ package body System.Dwarf_Lines is
loop
Read_Aranges_Entry (C, Ar_Start, Ar_Len);
- exit when Ar_Start = 0 and Ar_Len = 0;
+ exit when Ar_Start = Null_Address and Ar_Len = 0;
Len := uint32 (Ar_Len);
Start := uint32 (Ar_Start - C.Low);
@@ -1580,7 +1598,7 @@ package body System.Dwarf_Lines is
procedure Symbolic_Address
(C : in out Dwarf_Context;
- Addr : Storage_Offset;
+ Addr : Address;
Dir_Name : out Str_Access;
File_Name : out Str_Access;
Subprg_Name : out String_Ptr_Len;
@@ -1658,8 +1676,10 @@ package body System.Dwarf_Lines is
when DW_FORM_line_strp =>
Read_Section_Offset (C.Lines, Off, C.Header.Is64);
- Seek (C.Line_Str, Off);
- File_Name := Read_C_String (C.Line_Str);
+ if J = Match.File then
+ Seek (C.Line_Str, Off);
+ File_Name := Read_C_String (C.Line_Str);
+ end if;
when others =>
raise Dwarf_Error with "DWARF form not implemented";
@@ -1678,7 +1698,8 @@ package body System.Dwarf_Lines is
Dir_Idx := Read_LEB128 (C.Lines);
when others =>
- raise Dwarf_Error with "invalid DWARF";
+ raise Dwarf_Error with
+ "invalid DWARF form for DW_LNCT_directory_index";
end case;
else
@@ -1702,8 +1723,10 @@ package body System.Dwarf_Lines is
when DW_FORM_line_strp =>
Read_Section_Offset (C.Lines, Off, C.Header.Is64);
- Seek (C.Line_Str, Off);
- Dir_Name := Read_C_String (C.Line_Str);
+ if J = Dir_Idx then
+ Seek (C.Line_Str, Off);
+ Dir_Name := Read_C_String (C.Line_Str);
+ end if;
when others =>
raise Dwarf_Error with "DWARF form not implemented";
@@ -1864,7 +1887,7 @@ package body System.Dwarf_Lines is
procedure Symbolic_Traceback
(Cin : Dwarf_Context;
- Traceback : AET.Tracebacks_Array;
+ Traceback : STE.Tracebacks_Array;
Suppress_Hex : Boolean;
Symbol_Found : out Boolean;
Res : in out System.Bounded_Strings.Bounded_String)
@@ -1873,7 +1896,6 @@ package body System.Dwarf_Lines is
C : Dwarf_Context := Cin;
Addr_In_Traceback : Address;
- Offset_To_Lookup : Storage_Offset;
Dir_Name : Str_Access;
File_Name : Str_Access;
@@ -1893,13 +1915,11 @@ package body System.Dwarf_Lines is
-- If the buffer is full, no need to do any useless work
exit when Is_Full (Res);
- Addr_In_Traceback := PC_For (Traceback (J));
-
- Offset_To_Lookup := Addr_In_Traceback - C.Load_Address;
+ Addr_In_Traceback := STE.PC_For (Traceback (J));
Symbolic_Address
(C,
- Offset_To_Lookup,
+ Addr_In_Traceback - Get_Load_Displacement (C),
Dir_Name,
File_Name,
Subprg_Name,
diff --git a/gcc/ada/libgnat/s-dwalin.ads b/gcc/ada/libgnat/s-dwalin.ads
index 132d3e1..bd86e5e 100644
--- a/gcc/ada/libgnat/s-dwalin.ads
+++ b/gcc/ada/libgnat/s-dwalin.ads
@@ -35,15 +35,13 @@
--
-- Files must be compiled with at least minimal debugging information (-g1).
-with Ada.Exceptions.Traceback;
-
-with System.Object_Reader;
-with System.Storage_Elements;
with System.Bounded_Strings;
+with System.Object_Reader;
+with System.Traceback_Entries;
package System.Dwarf_Lines is
- package AET renames Ada.Exceptions.Traceback;
+ package STE renames System.Traceback_Entries;
package SOR renames System.Object_Reader;
type Dwarf_Context (In_Exception : Boolean := False) is private;
@@ -58,19 +56,19 @@ package System.Dwarf_Lines is
C : out Dwarf_Context;
Success : out Boolean);
procedure Close (C : in out Dwarf_Context);
- -- Open and close files
+ -- Open and close a file
procedure Set_Load_Address (C : in out Dwarf_Context; Addr : Address);
- -- Set the load address of a file. This is used to rebase PIE (Position
+ -- Set the run-time load address of a file. Used to rebase PIE (Position
-- Independent Executable) binaries.
function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean;
pragma Inline (Is_Inside);
- -- Return true iff a run-time address Addr is within the module
+ -- Return whether a run-time address Addr lies within the file
- function Low_Address (C : Dwarf_Context) return System.Address;
+ function Low_Address (C : Dwarf_Context) return Address;
pragma Inline (Low_Address);
- -- Return the lowest address of C, accounting for the module load address
+ -- Return the lowest run-time address of the file
procedure Dump (C : in out Dwarf_Context);
-- Dump each row found in the object's .debug_lines section to standard out
@@ -83,7 +81,7 @@ package System.Dwarf_Lines is
procedure Symbolic_Traceback
(Cin : Dwarf_Context;
- Traceback : AET.Tracebacks_Array;
+ Traceback : STE.Tracebacks_Array;
Suppress_Hex : Boolean;
Symbol_Found : out Boolean;
Res : in out System.Bounded_Strings.Bounded_String);
@@ -175,13 +173,13 @@ private
type Search_Array_Access is access Search_Array;
type Dwarf_Context (In_Exception : Boolean := False) is record
- Low, High : System.Storage_Elements.Storage_Offset;
- -- Bounds of the module, per the module object file
+ Low, High : Address;
+ -- Address bounds for executable code
Obj : SOR.Object_File_Access;
-- The object file containing dwarf sections
- Load_Address : System.Address := System.Null_Address;
+ Load_Address : Address := Null_Address;
-- The address at which the object file was loaded at run time
Has_Debug : Boolean;
diff --git a/gcc/ada/libgnat/s-ficobl.ads b/gcc/ada/libgnat/s-ficobl.ads
index 6fff2da..4e97079 100644
--- a/gcc/ada/libgnat/s-ficobl.ads
+++ b/gcc/ada/libgnat/s-ficobl.ads
@@ -39,7 +39,7 @@ with Ada.Streams;
with Interfaces.C_Streams;
with System.CRTL;
-package System.File_Control_Block is
+package System.File_Control_Block with SPARK_Mode => Off is
pragma Preelaborate;
----------------------------
diff --git a/gcc/ada/libgnat/s-imenne.adb b/gcc/ada/libgnat/s-imenne.adb
deleted file mode 100644
index 4ca7a12..0000000
--- a/gcc/ada/libgnat/s-imenne.adb
+++ /dev/null
@@ -1,170 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- B o d y --
--- --
--- Copyright (C) 2000-2021, 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. --
--- --
-------------------------------------------------------------------------------
-
-pragma Compiler_Unit_Warning;
-
-with Ada.Unchecked_Conversion;
-
-package body System.Img_Enum_New is
-
- -------------------------
- -- Image_Enumeration_8 --
- -------------------------
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_8 is range 0 .. 2 ** 7 - 1;
- subtype Names_Index is
- Natural_8 range Natural_8 (Names'First)
- .. Natural_8 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_8;
-
- --------------------------
- -- Image_Enumeration_16 --
- --------------------------
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_16 is range 0 .. 2 ** 15 - 1;
- subtype Names_Index is
- Natural_16 range Natural_16 (Names'First)
- .. Natural_16 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_16;
-
- --------------------------
- -- Image_Enumeration_32 --
- --------------------------
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_32 is range 0 .. 2 ** 31 - 1;
- subtype Names_Index is
- Natural_32 range Natural_32 (Names'First)
- .. Natural_32 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_32;
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imenne.ads b/gcc/ada/libgnat/s-imenne.ads
deleted file mode 100644
index eba31c2..0000000
--- a/gcc/ada/libgnat/s-imenne.ads
+++ /dev/null
@@ -1,85 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- S p e c --
--- --
--- Copyright (C) 2000-2021, 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. --
--- --
-------------------------------------------------------------------------------
-
--- Enumeration_Type'Image for all enumeration types except those in package
--- Standard (where we have no opportunity to build image tables), and in
--- package System (where it is too early to start building image tables).
--- Special routines exist for the enumeration types in these packages.
-
--- Note: this is an obsolete package replaced by instantiations of the generic
--- package System.Image_N. The reason we maintain this package is that when
--- bootstrapping with an old compiler, the old compiler will search for this
--- unit, expecting to find these functions. The new compiler will search for
--- procedures in the instances of System.Image_N instead.
-
-pragma Compiler_Unit_Warning;
-
-package System.Img_Enum_New is
- pragma Pure;
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Used to compute Enum'Image (Str) where Enum is some enumeration type
- -- other than those defined in package Standard. Names is a string with
- -- a lower bound of 1 containing the characters of all the enumeration
- -- literals concatenated together in sequence. Indexes is the address of
- -- an array of type array (0 .. N) of Natural_8, where N is the number of
- -- enumeration literals in the type. The Indexes values are the starting
- -- subscript of each enumeration literal, indexed by Pos values, with an
- -- extra entry at the end containing Names'Length + 1. The reason that
- -- Indexes is passed by address is that the actual type is created on the
- -- fly by the expander. The desired 'Image value is stored in S (1 .. P)
- -- and P is set on return. The caller guarantees that S is long enough to
- -- hold the result and that the lower bound is 1.
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_16 for the Indexes table.
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_32 for the Indexes table.
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imglli.ads b/gcc/ada/libgnat/s-imglli.ads
index 2e0b42c..e6e3efc 100644
--- a/gcc/ada/libgnat/s-imglli.ads
+++ b/gcc/ada/libgnat/s-imglli.ads
@@ -30,8 +30,8 @@
------------------------------------------------------------------------------
-- This package contains the routines for supporting the Image attribute for
--- signed integer types larger Integer, and also for conversion operations
--- required in Text_IO.Integer_IO for such types.
+-- signed integer types larger than Integer, and also for conversion
+-- operations required in Text_IO.Integer_IO for such types.
with System.Image_I;
diff --git a/gcc/ada/libgnat/s-objrea.adb b/gcc/ada/libgnat/s-objrea.adb
index 9dd8c1f..e1bc677 100644
--- a/gcc/ada/libgnat/s-objrea.adb
+++ b/gcc/ada/libgnat/s-objrea.adb
@@ -36,6 +36,7 @@ with Interfaces.C;
with System.CRTL;
package body System.Object_Reader is
+
use Interfaces;
use Interfaces.C;
use System.Mmap;
@@ -220,7 +221,6 @@ package body System.Object_Reader is
Characteristics : uint16;
Variant : uint16;
end record;
-
pragma Pack (Header);
type Optional_Header_PE32 is record
@@ -306,7 +306,6 @@ package body System.Object_Reader is
NumberOfLinenumbers : uint16;
Characteristics : uint32;
end record;
-
pragma Pack (Section_Header);
IMAGE_SCN_CNT_CODE : constant := 16#0020#;
@@ -319,7 +318,6 @@ package body System.Object_Reader is
StorageClass : uint8;
NumberOfAuxSymbols : uint8;
end record;
-
pragma Pack (Symtab_Entry);
type Auxent_Section is record
@@ -435,7 +433,6 @@ package body System.Object_Reader is
s_nlnno : uint16;
s_flags : uint32;
end record;
-
pragma Pack (Section_Header);
STYP_TEXT : constant := 16#0020#;
@@ -460,7 +457,6 @@ package body System.Object_Reader is
x_snstab : uint16;
end record;
for Aux_Entry'Size use 18 * 8;
-
pragma Pack (Aux_Entry);
C_EXT : constant := 2;
@@ -549,6 +545,7 @@ package body System.Object_Reader is
Shnum : uint32) return Object_Section
is
SHdr : constant Section_Header := Read_Section_Header (Obj, Shnum);
+
begin
return (Shnum,
Offset (SHdr.Sh_Offset),
@@ -680,6 +677,7 @@ package body System.Object_Reader is
function Read_Header (F : in out Mapped_Stream) return Header is
Hdr : Header;
+
begin
Seek (F, 0);
Read_Raw (F, Hdr'Address, uint32 (Hdr'Size / SSU));
@@ -695,6 +693,7 @@ package body System.Object_Reader is
Shnum : uint32) return Section_Header
is
Shdr : Section_Header;
+
begin
Seek (Obj.Sectab_Stream, Offset (Shnum * Section_Header'Size / SSU));
Read_Raw (Obj.Sectab_Stream, Shdr'Address, Section_Header'Size / SSU);
@@ -749,6 +748,7 @@ package body System.Object_Reader is
Sec : Object_Section) return String
is
SHdr : Section_Header;
+
begin
SHdr := Read_Section_Header (Obj, Sec.Num);
return Offset_To_String (Obj.Secstr_Stream, Offset (SHdr.Sh_Name));
@@ -861,7 +861,8 @@ package body System.Object_Reader is
------------------
function First_Symbol
- (Obj : in out PECOFF_Object_File) return Object_Symbol is
+ (Obj : in out PECOFF_Object_File) return Object_Symbol
+ is
begin
-- Return Null_Symbol in the case that the symbol table is empty
@@ -881,6 +882,7 @@ package body System.Object_Reader is
Index : uint32) return Object_Section
is
Sec : constant Section_Header := Read_Section_Header (Obj, Index);
+
begin
-- Use VirtualSize instead of SizeOfRawData. The latter is rounded to
-- the page size, so it may add garbage to the content. On the other
@@ -938,6 +940,7 @@ package body System.Object_Reader is
Hdr_Offset : Offset;
Opt_Offset : File_Size;
Opt_Stream : Mapped_Stream;
+
begin
Res.MF := F;
Res.In_Exception := In_Exception;
@@ -1180,7 +1183,8 @@ package body System.Object_Reader is
function String_Table
(Obj : in out PECOFF_Object_File;
- Index : Offset) return String is
+ Index : Offset) return String
+ is
begin
-- An index of zero is used to represent an empty string, as the
-- first word of the string table is specified to contain the length
@@ -1361,6 +1365,7 @@ package body System.Object_Reader is
is
Res : XCOFF32_Object_File (Format => XCOFF32);
Strtab_Sz : uint32;
+
begin
Res.Mf := F;
Res.In_Exception := In_Exception;
@@ -1401,6 +1406,7 @@ package body System.Object_Reader is
Index : uint32) return Object_Section
is
Sec : constant Section_Header := Read_Section_Header (Obj, Index);
+
begin
return (Index, Offset (Sec.s_scnptr),
uint64 (Sec.s_vaddr),
@@ -1414,6 +1420,7 @@ package body System.Object_Reader is
function Read_Header (F : in out Mapped_Stream) return Header is
Hdr : Header;
+
begin
Seek (F, 0);
Read_Raw (F, Hdr'Address, uint32 (Hdr'Size / SSU));
@@ -1428,7 +1435,7 @@ package body System.Object_Reader is
(Obj : in out XCOFF32_Object_File;
Index : uint32) return Section_Header
is
- Sec : Section_Header;
+ Sec : Section_Header;
begin
-- Seek to the end of the object header
@@ -1451,6 +1458,7 @@ package body System.Object_Reader is
Sec : Object_Section) return String
is
Hdr : Section_Header;
+
begin
Hdr := Read_Section_Header (Obj, Sec.Num);
return Trim_Trailing_Nuls (Hdr.s_name);
@@ -1520,7 +1528,8 @@ package body System.Object_Reader is
function Create_Stream
(Obj : Object_File;
- Sec : Object_Section) return Mapped_Stream is
+ Sec : Object_Section) return Mapped_Stream
+ is
begin
return Create_Stream (Obj.Mf, File_Size (Sec.Off), File_Size (Sec.Size));
end Create_Stream;
@@ -1573,7 +1582,8 @@ package body System.Object_Reader is
function Strip_Leading_Char
(Obj : in out Object_File;
- Sym : String_Ptr_Len) return Positive is
+ Sym : String_Ptr_Len) return Positive
+ is
begin
if (Obj.Format = PECOFF and then Sym.Ptr (1) = '_')
or else
@@ -1605,6 +1615,7 @@ package body System.Object_Reader is
String (Sym.Ptr (1 .. Sym.Len)) & ASCII.NUL;
Decoded : char_array (0 .. size_t (Sym.Len) * 2 + 60);
Off : Natural;
+
begin
-- In the PECOFF case most but not all symbol table entries have an
-- extra leading underscore. In this case we trim it.
@@ -1645,8 +1656,11 @@ package body System.Object_Reader is
function Get_Load_Address (Obj : Object_File) return uint64 is
begin
- raise Format_Error with "Get_Load_Address not implemented";
- return 0;
+ case Obj.Format is
+ when ELF => return 0;
+ when Any_PECOFF => return Obj.ImageBase;
+ when XCOFF32 => raise Format_Error;
+ end case;
end Get_Load_Address;
-----------------
@@ -1655,7 +1669,8 @@ package body System.Object_Reader is
function Get_Section
(Obj : in out Object_File;
- Shnum : uint32) return Object_Section is
+ Shnum : uint32) return Object_Section
+ is
begin
case Obj.Format is
when ELF32 => return ELF32_Ops.Get_Section (Obj, Shnum);
@@ -1692,9 +1707,11 @@ package body System.Object_Reader is
----------------------
procedure Get_Xcode_Bounds
- (Obj : in out Object_File;
- Low, High : out uint64) is
+ (Obj : in out Object_File;
+ Low, High : out uint64)
+ is
Sec : Object_Section;
+
begin
-- First set as an empty range
Low := uint64'Last;
@@ -1721,7 +1738,8 @@ package body System.Object_Reader is
function Name
(Obj : in out Object_File;
- Sec : Object_Section) return String is
+ Sec : Object_Section) return String
+ is
begin
case Obj.Format is
when ELF32 => return ELF32_Ops.Name (Obj, Sec);
@@ -1733,7 +1751,8 @@ package body System.Object_Reader is
function Name
(Obj : in out Object_File;
- Sym : Object_Symbol) return String_Ptr_Len is
+ Sym : Object_Symbol) return String_Ptr_Len
+ is
begin
case Obj.Format is
when ELF32 => return ELF32_Ops.Name (Obj, Sym);
@@ -1749,7 +1768,8 @@ package body System.Object_Reader is
function Next_Symbol
(Obj : in out Object_File;
- Prev : Object_Symbol) return Object_Symbol is
+ Prev : Object_Symbol) return Object_Symbol
+ is
begin
-- Test whether we've reached the end of the symbol table
@@ -1801,6 +1821,7 @@ package body System.Object_Reader is
Off : Offset) return String
is
Buf : Buffer;
+
begin
Seek (S, Off);
Read_C_String (S, Buf);
@@ -1922,10 +1943,10 @@ package body System.Object_Reader is
-- Read --
----------
- function Read (S : in out Mapped_Stream) return Mmap.Str_Access
- is
+ function Read (S : in out Mapped_Stream) return Mmap.Str_Access is
function To_Str_Access is
new Ada.Unchecked_Conversion (Address, Str_Access);
+
begin
return To_Str_Access (Data (S.Region) (Natural (S.Off + 1))'Address);
end Read;
@@ -1949,8 +1970,8 @@ package body System.Object_Reader is
is
function To_Str_Access is
new Ada.Unchecked_Conversion (Address, Str_Access);
-
Sz : constant Offset := Offset (Size);
+
begin
-- Check size
@@ -2027,7 +2048,8 @@ package body System.Object_Reader is
------------------
function Read_Address
- (Obj : Object_File; S : in out Mapped_Stream) return uint64 is
+ (Obj : Object_File; S : in out Mapped_Stream) return uint64
+ is
Address_32 : uint32;
Address_64 : uint64;
@@ -2147,7 +2169,8 @@ package body System.Object_Reader is
function Read_Symbol
(Obj : in out Object_File;
- Off : Offset) return Object_Symbol is
+ Off : Offset) return Object_Symbol
+ is
begin
case Obj.Format is
when ELF32 => return ELF32_Ops.Read_Symbol (Obj, Off);
@@ -2221,7 +2244,8 @@ package body System.Object_Reader is
function To_String_Ptr_Len
(Ptr : Mmap.Str_Access;
- Max_Len : Natural := Natural'Last) return String_Ptr_Len is
+ Max_Len : Natural := Natural'Last) return String_Ptr_Len
+ is
begin
for I in 1 .. Max_Len loop
if Ptr (I) = ASCII.NUL then
diff --git a/gcc/ada/libgnat/s-objrea.ads b/gcc/ada/libgnat/s-objrea.ads
index a83ca53..d20a53d 100644
--- a/gcc/ada/libgnat/s-objrea.ads
+++ b/gcc/ada/libgnat/s-objrea.ads
@@ -287,7 +287,7 @@ package System.Object_Reader is
(Obj : in out Object_File;
Low, High : out uint64);
-- Return the low and high addresses of the code for the object file. Can
- -- be used to check if an address in within this object file. This
+ -- be used to check if an address lies within this object file. This
-- procedure is not efficient and the result should be saved to avoid
-- recomputation.
@@ -381,9 +381,8 @@ private
subtype Any_PECOFF is Object_Format range PECOFF .. PECOFF_PLUS;
type Object_File (Format : Object_Format) is record
- Mf : System.Mmap.Mapped_File :=
- System.Mmap.Invalid_Mapped_File;
- Arch : Object_Arch := Unknown;
+ Mf : System.Mmap.Mapped_File := System.Mmap.Invalid_Mapped_File;
+ Arch : Object_Arch := Unknown;
Num_Sections : uint32 := 0;
-- Number of sections
@@ -406,6 +405,7 @@ private
when ELF =>
Secstr_Stream : Mapped_Stream;
-- Section strings
+
when Any_PECOFF =>
ImageBase : uint64; -- ImageBase value from header
@@ -413,19 +413,20 @@ private
GSVA_Sec : uint32 := uint32'Last;
GSVA_Addr : uint64;
+
when XCOFF32 =>
null;
end case;
end record;
- subtype ELF_Object_File is Object_File; -- with
- -- Predicate => ELF_Object_File.Format in ELF;
- subtype PECOFF_Object_File is Object_File; -- with
- -- Predicate => PECOFF_Object_File.Format in Any_PECOFF;
- subtype XCOFF32_Object_File is Object_File; -- with
- -- Predicate => XCOFF32_Object_File.Format in XCOFF32;
- -- ???Above predicates cause the compiler to crash when instantiating
- -- ELF64_Ops (see package body).
+ subtype ELF_Object_File is Object_File
+ with Predicate => ELF_Object_File.Format in ELF;
+
+ subtype PECOFF_Object_File is Object_File
+ with Predicate => PECOFF_Object_File.Format in Any_PECOFF;
+
+ subtype XCOFF32_Object_File is Object_File
+ with Predicate => XCOFF32_Object_File.Format in XCOFF32;
type Object_Section is record
Num : uint32 := 0;
diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads
index 2049e38..139d2e0 100644
--- a/gcc/ada/libgnat/s-os_lib.ads
+++ b/gcc/ada/libgnat/s-os_lib.ads
@@ -169,16 +169,15 @@ package System.OS_Lib is
------------------
-- Note: Do not use time_t in the compiler and host-based tools; instead
- -- use OS_Time. These 3 declarations are intended for use only by consumers
- -- of the GNAT.OS_Lib renaming of this package.
+ -- use OS_Time.
subtype time_t is Long_Long_Integer;
- -- C time_t can be either long or long long, but this is a subtype not used
- -- in the compiler or tools, but only for user applications, so we choose
- -- the Ada equivalent of the latter because eventually that will be the
+ -- C time_t can be either long or long long, so we choose the Ada
+ -- equivalent of the latter because eventually that will be the
-- type used out of necessity. This may affect some user code on 32-bit
-- targets that have not yet migrated to the Posix 2008 standard,
- -- particularly pre version 5 32-bit Linux.
+ -- particularly pre version 5 32-bit Linux. Do not change this
+ -- declaration without coordinating it with conversions in Ada.Calendar.
function To_C (Time : OS_Time) return time_t;
-- Convert OS_Time to C time_t type
diff --git a/gcc/ada/libgnat/s-osprim__vxworks.adb b/gcc/ada/libgnat/s-osprim__vxworks.adb
deleted file mode 100644
index ad2ac40..0000000
--- a/gcc/ada/libgnat/s-osprim__vxworks.adb
+++ /dev/null
@@ -1,162 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
--- --
--- S Y S T E M . O S _ P R I M I T I V E S --
--- --
--- B o d y --
--- --
--- Copyright (C) 1998-2021, Free Software Foundation, Inc. --
--- --
--- GNARL 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/>. --
--- --
--- GNARL was developed by the GNARL team at Florida State University. --
--- Extensive contributions were provided by Ada Core Technologies, Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This version is for VxWorks targets
-
-with System.OS_Interface;
--- Since the thread library is part of the VxWorks kernel, using OS_Interface
--- is not a problem here, as long as we only use System.OS_Interface as a
--- set of C imported routines: using Ada routines from this package would
--- create a dependency on libgnarl in libgnat, which is not desirable.
-
-with System.OS_Constants;
-with Interfaces.C;
-
-package body System.OS_Primitives is
-
- use System.OS_Interface;
- use type Interfaces.C.int;
-
- package OSC renames System.OS_Constants;
-
- ------------------------
- -- Internal functions --
- ------------------------
-
- function To_Clock_Ticks (D : Duration) return int;
- -- Convert a duration value (in seconds) into clock ticks.
- -- Note that this routine is duplicated from System.OS_Interface since
- -- as explained above, we do not want to depend on libgnarl
-
- function To_Clock_Ticks (D : Duration) return int is
- Ticks : Long_Long_Integer;
- Rate_Duration : Duration;
- Ticks_Duration : Duration;
-
- begin
- if D < 0.0 then
- return -1;
- end if;
-
- -- Ensure that the duration can be converted to ticks
- -- at the current clock tick rate without overflowing.
-
- Rate_Duration := Duration (sysClkRateGet);
-
- if D > (Duration'Last / Rate_Duration) then
- Ticks := Long_Long_Integer (int'Last);
- else
- Ticks_Duration := D * Rate_Duration;
- Ticks := Long_Long_Integer (Ticks_Duration);
-
- if Ticks_Duration > Duration (Ticks) then
- Ticks := Ticks + 1;
- end if;
-
- if Ticks > Long_Long_Integer (int'Last) then
- Ticks := Long_Long_Integer (int'Last);
- end if;
- end if;
-
- return int (Ticks);
- end To_Clock_Ticks;
-
- -----------
- -- Clock --
- -----------
-
- function Clock return Duration is
- TS : aliased timespec;
- Result : int;
- begin
- Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
- pragma Assert (Result = 0);
- return Duration (TS.ts_sec) + Duration (TS.ts_nsec) / 10#1#E9;
- end Clock;
-
- -----------------
- -- Timed_Delay --
- -----------------
-
- procedure Timed_Delay
- (Time : Duration;
- Mode : Integer)
- is
- Rel_Time : Duration;
- Abs_Time : Duration;
- Base_Time : constant Duration := Clock;
- Check_Time : Duration := Base_Time;
- Ticks : int;
-
- Result : int;
- pragma Unreferenced (Result);
-
- begin
- if Mode = Relative then
- Rel_Time := Time;
- Abs_Time := Time + Check_Time;
- else
- Rel_Time := Time - Check_Time;
- Abs_Time := Time;
- end if;
-
- if Rel_Time > 0.0 then
- loop
- Ticks := To_Clock_Ticks (Rel_Time);
-
- if Mode = Relative and then Ticks < int'Last then
- -- The first tick will delay anytime between 0 and
- -- 1 / sysClkRateGet seconds, so we need to add one to
- -- be on the safe side.
-
- Ticks := Ticks + 1;
- end if;
-
- Result := taskDelay (Ticks);
- Check_Time := Clock;
-
- exit when Abs_Time <= Check_Time or else Check_Time < Base_Time;
-
- Rel_Time := Abs_Time - Check_Time;
- end loop;
- end if;
- end Timed_Delay;
-
- ----------------
- -- Initialize --
- ----------------
-
- procedure Initialize is
- begin
- null;
- end Initialize;
-
-end System.OS_Primitives;
diff --git a/gcc/ada/libgnat/s-osvers__vxworks-653.ads b/gcc/ada/libgnat/s-osvers__vxworks-653.ads
deleted file mode 100644
index e180e7c..0000000
--- a/gcc/ada/libgnat/s-osvers__vxworks-653.ads
+++ /dev/null
@@ -1,38 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME LIBRARY COMPONENTS --
--- --
--- S Y S T E M . O S _ V E R S I O N --
--- --
--- S p e c --
--- --
--- Copyright (C) 2010-2021, AdaCore --
--- --
--- 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/>. --
--- --
-------------------------------------------------------------------------------
-
--- This is the VxWorks 653 Partition OS version of this file. If you add an OS
--- variant please be sure to update type OS_Version in all variants of this
--- file, which is part of the Level A certified run-time libraries.
-
-package System.OS_Versions is
- pragma Pure (System.OS_Versions);
- type OS_Version is
- (LynxOS_178, VxWorks_Cert, VxWorks_Cert_RTP, VxWorks_653, VxWorks_MILS);
- OS : constant OS_Version := VxWorks_653;
-end System.OS_Versions;
diff --git a/gcc/ada/libgnat/s-parame.adb b/gcc/ada/libgnat/s-parame.adb
index 9001626..09a65ee 100644
--- a/gcc/ada/libgnat/s-parame.adb
+++ b/gcc/ada/libgnat/s-parame.adb
@@ -55,7 +55,7 @@ package body System.Parameters is
------------------------
function Default_Stack_Size return Size_Type is
- Default_Stack_Size : Integer;
+ Default_Stack_Size : constant Integer;
pragma Import (C, Default_Stack_Size, "__gl_default_stack_size");
begin
if Default_Stack_Size = -1 then
diff --git a/gcc/ada/libgnat/s-parame__ae653.ads b/gcc/ada/libgnat/s-parame__ae653.ads
index f838b41..a3e2351 100644
--- a/gcc/ada/libgnat/s-parame__ae653.ads
+++ b/gcc/ada/libgnat/s-parame__ae653.ads
@@ -104,8 +104,12 @@ package System.Parameters is
-- Characteristics of time_t type --
------------------------------------
- time_t_bits : constant := Long_Integer'Size;
- -- Number of bits in type time_t
+ -- IMPORTANT NOTE:
+ -- time_t_bits must match the size specified in the VSB.
+
+ time_t_bits : constant := Long_Long_Integer'Size;
+ -- Number of bits in type time_t for SR0660 and newer,
+ -- with the default configuration of the VSB.
----------------------------------------------
-- Characteristics of types in Interfaces.C --
diff --git a/gcc/ada/libgnat/s-parame__rtems.adb b/gcc/ada/libgnat/s-parame__rtems.adb
index 1a6d577..ae88a2c 100644
--- a/gcc/ada/libgnat/s-parame__rtems.adb
+++ b/gcc/ada/libgnat/s-parame__rtems.adb
@@ -35,10 +35,6 @@ with Interfaces.C;
package body System.Parameters is
- function ada_pthread_minimum_stack_size return Interfaces.C.size_t;
- pragma Import (C, ada_pthread_minimum_stack_size,
- "_ada_pthread_minimum_stack_size");
-
-------------------------
-- Adjust_Storage_Size --
-------------------------
@@ -61,8 +57,15 @@ package body System.Parameters is
------------------------
function Default_Stack_Size return Size_Type is
+ Default_Stack_Size : constant Integer
+ with Import, Convention => C,
+ External_Name => "__gl_default_stack_size";
begin
- return Size_Type (ada_pthread_minimum_stack_size);
+ if Default_Stack_Size = -1 then
+ return 32 * 1024;
+ else
+ return Size_Type (Default_Stack_Size);
+ end if;
end Default_Stack_Size;
------------------------
@@ -70,9 +73,11 @@ package body System.Parameters is
------------------------
function Minimum_Stack_Size return Size_Type is
-
+ POSIX_Threads_Minimum_stack_size : constant Interfaces.C.size_t
+ with Import, Convention => C,
+ External_Name => "_POSIX_Threads_Minimum_stack_size";
begin
- return Size_Type (ada_pthread_minimum_stack_size);
+ return Size_Type (POSIX_Threads_Minimum_stack_size);
end Minimum_Stack_Size;
end System.Parameters;
diff --git a/gcc/ada/libgnat/s-parame__vxworks.adb b/gcc/ada/libgnat/s-parame__vxworks.adb
index 5970eb0..45ee0a9 100644
--- a/gcc/ada/libgnat/s-parame__vxworks.adb
+++ b/gcc/ada/libgnat/s-parame__vxworks.adb
@@ -53,7 +53,7 @@ package body System.Parameters is
------------------------
function Default_Stack_Size return Size_Type is
- Default_Stack_Size : Integer;
+ Default_Stack_Size : constant Integer;
pragma Import (C, Default_Stack_Size, "__gl_default_stack_size");
begin
if Default_Stack_Size = -1 then
diff --git a/gcc/ada/libgnat/s-parame__vxworks.ads b/gcc/ada/libgnat/s-parame__vxworks.ads
index 11b408b..b22d858 100644
--- a/gcc/ada/libgnat/s-parame__vxworks.ads
+++ b/gcc/ada/libgnat/s-parame__vxworks.ads
@@ -108,11 +108,11 @@ package System.Parameters is
-- Select the appropriate time_t_bits for the VSB in use, then rebuild
-- the runtime using instructions in adainclude/libada.gpr.
- time_t_bits : constant := Long_Integer'Size;
+ -- time_t_bits : constant := Long_Integer'Size;
-- Number of bits in type time_t for SR0650 and before and SR0660 with
-- non-default configuration.
- -- time_t_bits : constant := Long_Long_Integer'Size;
+ time_t_bits : constant := Long_Long_Integer'Size;
-- Number of bits in type time_t for SR0660 with default configuration.
----------------------------------------------
diff --git a/gcc/ada/libgnat/s-regpat.adb b/gcc/ada/libgnat/s-regpat.adb
index 7e33067..b40f682 100644
--- a/gcc/ada/libgnat/s-regpat.adb
+++ b/gcc/ada/libgnat/s-regpat.adb
@@ -3463,18 +3463,58 @@ package body System.Regpat is
end;
elsif Self.First /= ASCII.NUL then
- -- We know what char it must start with
+ -- We know what char (modulo casing) it must start with
- declare
- Next_Try : Natural := Index (First_In_Data, Self.First);
+ if (Self.Flags and Case_Insensitive) = 0
+ or else Self.First not in 'a' .. 'z'
+ then
+ declare
+ Next_Try : Natural := Index (First_In_Data, Self.First);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Index (Next_Try + 1, Self.First);
+ end loop;
+ end;
+ else
+ declare
+ Uc_First : constant Character := To_Upper (Self.First);
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural;
+ -- Search for both Self.First and To_Upper (Self.First).
+ -- If both are nonzero, return the smaller one; if exactly
+ -- one is nonzero, return it; if both are zero, return zero.
+
+ ---------------------------
+ -- Case_Insenstive_Index --
+ ---------------------------
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural
+ is
+ Lc_Index : constant Natural := Index (Start, Self.First);
+ Uc_Index : constant Natural := Index (Start, Uc_First);
+ begin
+ if Lc_Index = 0 then
+ return Uc_Index;
+ elsif Uc_Index = 0 then
+ return Lc_Index;
+ else
+ return Natural'Min (Lc_Index, Uc_Index);
+ end if;
+ end Case_Insensitive_Index;
- begin
- while Next_Try /= 0 loop
- Matched := Try (Next_Try);
- exit when Matched;
- Next_Try := Index (Next_Try + 1, Self.First);
- end loop;
- end;
+ Next_Try : Natural := Case_Insensitive_Index (First_In_Data);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Case_Insensitive_Index (Next_Try + 1);
+ end loop;
+ end;
+ end if;
else
-- Messy cases: try all locations (including for the empty string)
@@ -3634,6 +3674,9 @@ package body System.Regpat is
if Program (Scan) = EXACT then
Self.First := Program (String_Operand (Scan));
+ elsif Program (Scan) = EXACTF then
+ Self.First := To_Lower (Program (String_Operand (Scan)));
+
elsif Program (Scan) = BOL
or else Program (Scan) = SBOL
or else Program (Scan) = MBOL
diff --git a/gcc/ada/libgnat/s-regpat.ads b/gcc/ada/libgnat/s-regpat.ads
index b1a1366f..8fac30a 100644
--- a/gcc/ada/libgnat/s-regpat.ads
+++ b/gcc/ada/libgnat/s-regpat.ads
@@ -482,18 +482,17 @@ package System.Regpat is
-- Data_First is the lower bound for the match, i.e. Data (Data_First)
-- will be the first character to be examined. If Data_First is set to
-- the special value of -1 (the default), then the first character to
- -- be examined is Data (Data_First). However, the regular expression
- -- character ^ (start of string) still refers to the first character
+ -- be examined is Data (Data'First). However, the regular expression
+ -- character ^ (start of string) always refers to the first character
-- of the full string (Data (Data'First)), which is why there is a
-- separate mechanism for specifying Data_First.
-- Data_Last is the upper bound for the match, i.e. Data (Data_Last)
-- will be the last character to be examined. If Data_Last is set to
-- the special value of Positive'Last (the default), then the last
- -- character to be examined is Data (Data_Last). However, the regular
- -- expression character $ (end of string) still refers to the last
- -- character of the full string (Data (Data'Last)), which is why there
- -- is a separate mechanism for specifying Data_Last.
+ -- character to be examined is Data (Data'Last). However, the regular
+ -- expression character $ (end of string) always refers to the last
+ -- character of the full string (Data (Data'Last)).
-- Note: the use of Data_First and Data_Last is not equivalent to
-- simply passing a slice as Expression because of the handling of
diff --git a/gcc/ada/libgnat/s-secsta.ads b/gcc/ada/libgnat/s-secsta.ads
index 7d6b1b9..6648c23 100644
--- a/gcc/ada/libgnat/s-secsta.ads
+++ b/gcc/ada/libgnat/s-secsta.ads
@@ -440,4 +440,9 @@ private
function Get_Stack_Info (Stack : SS_Stack_Ptr) return Stack_Info;
-- Obtain the information attributes of secondary stack Stack
+ pragma Machine_Attribute (SS_Allocate, "strub", "callable");
+ pragma Machine_Attribute (SS_Mark, "strub", "callable");
+ pragma Machine_Attribute (SS_Release, "strub", "callable");
+ -- Enable these to be called from within strub contexts.
+
end System.Secondary_Stack;
diff --git a/gcc/ada/libgnat/s-stchop__rtems.adb b/gcc/ada/libgnat/s-stchop__rtems.adb
deleted file mode 100644
index f273f29..0000000
--- a/gcc/ada/libgnat/s-stchop__rtems.adb
+++ /dev/null
@@ -1,113 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
--- --
--- S Y S T E M . S T A C K _ C H E C K I N G . O P E R A T I O N S --
--- --
--- B o d y --
--- --
--- Copyright (C) 1999-2021, Free Software Foundation, Inc. --
--- --
--- GNARL 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/>. --
--- --
--- GNARL was developed by the GNARL team at Florida State University. --
--- Extensive contributions were provided by Ada Core Technologies, Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This is the RTEMS version of this package.
--- This file should be kept synchronized with the general implementation
--- provided by s-stchop.adb.
-
-pragma Restrictions (No_Elaboration_Code);
--- We want to guarantee the absence of elaboration code because the
--- binder does not handle references to this package.
-
-with Ada.Exceptions;
-
-with Interfaces.C; use Interfaces.C;
-
-package body System.Stack_Checking.Operations is
-
- ----------------------------
- -- Invalidate_Stack_Cache --
- ----------------------------
-
- procedure Invalidate_Stack_Cache (Any_Stack : Stack_Access) is
- pragma Warnings (Off, Any_Stack);
- begin
- Cache := Null_Stack;
- end Invalidate_Stack_Cache;
-
- -----------------------------
- -- Notify_Stack_Attributes --
- -----------------------------
-
- procedure Notify_Stack_Attributes
- (Initial_SP : System.Address;
- Size : System.Storage_Elements.Storage_Offset)
- is
-
- -- RTEMS keeps all the information we need.
-
- pragma Unreferenced (Size);
- pragma Unreferenced (Initial_SP);
-
- begin
- null;
- end Notify_Stack_Attributes;
-
- -----------------
- -- Stack_Check --
- -----------------
-
- function Stack_Check
- (Stack_Address : System.Address) return Stack_Access
- is
- pragma Unreferenced (Stack_Address);
-
- -- RTEMS has a routine to check if the stack is blown.
- -- It returns a C99 bool.
- function rtems_stack_checker_is_blown return Interfaces.C.unsigned_char;
- pragma Import (C,
- rtems_stack_checker_is_blown, "rtems_stack_checker_is_blown");
-
- begin
- -- RTEMS has a routine to check this. So use it.
-
- if rtems_stack_checker_is_blown /= 0 then
- Ada.Exceptions.Raise_Exception
- (E => Storage_Error'Identity,
- Message => "stack overflow detected");
- end if;
-
- return null;
-
- end Stack_Check;
-
- ------------------------
- -- Update_Stack_Cache --
- ------------------------
-
- procedure Update_Stack_Cache (Stack : Stack_Access) is
- begin
- if not Multi_Processor then
- Cache := Stack;
- end if;
- end Update_Stack_Cache;
-
-end System.Stack_Checking.Operations;
diff --git a/gcc/ada/libgnat/s-stratt.adb b/gcc/ada/libgnat/s-stratt.adb
index 5f04153..d7f572e 100644
--- a/gcc/ada/libgnat/s-stratt.adb
+++ b/gcc/ada/libgnat/s-stratt.adb
@@ -36,13 +36,13 @@ with System.Stream_Attributes.XDR;
package body System.Stream_Attributes is
- XDR_Flag : Integer;
- pragma Import (C, XDR_Flag, "__gl_xdr_stream");
+ XDR_Stream : constant Integer;
+ pragma Import (C, XDR_Stream, "__gl_xdr_stream");
-- This imported value is used to determine whether the build had the
-- binder switch "-xdr" present which enables XDR streaming and sets this
-- flag to 1.
- function XDR_Support return Boolean;
+ function XDR_Support return Boolean is (XDR_Stream = 1);
pragma Inline (XDR_Support);
-- 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.
@@ -142,15 +142,6 @@ package body System.Stream_Attributes is
function To_WWC is new UC (S_WWC, Wide_Wide_Character);
-----------------
- -- XDR_Support --
- -----------------
-
- function XDR_Support return Boolean is
- begin
- return XDR_Flag = 1;
- end XDR_Support;
-
- -----------------
-- Block_IO_OK --
-----------------
diff --git a/gcc/ada/libgnat/s-thread.ads b/gcc/ada/libgnat/s-thread.ads
index 5d0a3c1..6508df5 100644
--- a/gcc/ada/libgnat/s-thread.ads
+++ b/gcc/ada/libgnat/s-thread.ads
@@ -34,16 +34,13 @@
-- This package is currently implemented for:
--- VxWorks AE653 rts-cert
--- VxWorks AE653 rts-full (not rts-kernel)
+-- VxWorks7r2Cert Light
-with Ada.Exceptions;
with Ada.Unchecked_Conversion;
with Interfaces.C;
with System.Secondary_Stack;
-with System.Soft_Links;
package System.Threads is
@@ -81,12 +78,15 @@ package System.Threads is
procedure Thread_Body_Leave;
-- Leave thread body (normally), see above for details
- procedure Thread_Body_Exceptional_Exit
- (EO : Ada.Exceptions.Exception_Occurrence);
+ procedure Thread_Body_Exceptional_Exit;
-- Leave thread body (abnormally on exception), see above for details
private
- type ATSD is new System.Soft_Links.TSD;
+ type ATSD is record
+ Sec_Stack_Ptr : SST.SS_Stack_Ptr;
+ -- Pointer of the allocated secondary stack
+
+ end record;
end System.Threads;
diff --git a/gcc/ada/libgnat/s-thread__ae653.adb b/gcc/ada/libgnat/s-thread__ae653.adb
index ecbd415..2282a66 100644
--- a/gcc/ada/libgnat/s-thread__ae653.adb
+++ b/gcc/ada/libgnat/s-thread__ae653.adb
@@ -29,22 +29,19 @@
-- --
------------------------------------------------------------------------------
--- This is the VxWorks 653 version of this package
+-- This is the VxWorks7r2Cert Light version of this package
pragma Restrictions (No_Tasking);
--- The VxWorks 653 version of this package is intended only for programs
--- which do not use Ada tasking. This restriction ensures that this
--- will be checked by the binder.
+-- The VxWorks7r2Cert Light version of this package is intended only
+-- for programs which do not use Ada tasking. This restriction ensures
+-- that this will be checked by the binder.
with System.Storage_Elements; use System.Storage_Elements;
-with System.OS_Versions; use System.OS_Versions;
package body System.Threads is
use Interfaces.C;
- package SSL renames System.Soft_Links;
-
Main_ATSD : aliased ATSD;
-- TSD for environment task
@@ -52,21 +49,7 @@ package body System.Threads is
pragma Thread_Local_Storage (Current_ATSD);
-- pragma TLS needed since TaskVarAdd no longer available
- -- Assume guard pages for Helix APEX partitions, but leave
- -- checking mechanism in for now, in case of surprises. ???
- Stack_Limit : Address;
- pragma Import (C, Stack_Limit, "__gnat_stack_limit");
-
- type Set_Stack_Limit_Proc_Acc is access procedure;
- pragma Convention (C, Set_Stack_Limit_Proc_Acc);
-
- Set_Stack_Limit_Hook : Set_Stack_Limit_Proc_Acc;
- pragma Import (C, Set_Stack_Limit_Hook, "__gnat_set_stack_limit_hook");
- -- Procedure to be called when a task is created to set stack limit if
- -- limit checking is used.
-
-- VxWorks specific API
-
ERROR : constant STATUS := Interfaces.C.int (-1);
OK : constant STATUS := Interfaces.C.int (0);
@@ -85,13 +68,8 @@ package body System.Threads is
-- It installs System.Threads versions of certain operations of the
-- run-time lib.
- procedure Install_Handler;
- pragma Import (C, Install_Handler, "__gnat_install_handler");
-
function Get_Sec_Stack return SST.SS_Stack_Ptr;
- procedure Set_Sec_Stack (Stack : SST.SS_Stack_Ptr);
-
-----------------------
-- Thread_Body_Enter --
-----------------------
@@ -108,27 +86,14 @@ package body System.Threads is
ATSD.Sec_Stack_Ptr := Sec_Stack_Ptr;
SST.SS_Init (ATSD.Sec_Stack_Ptr);
Current_ATSD := Process_ATSD_Address;
- Install_Handler;
-
- -- Assume guard pages for Helix/Vx7, but leave in for now ???
- -- Initialize stack limit if needed.
- if Current_ATSD /= Main_ATSD'Address
- and then Set_Stack_Limit_Hook /= null
- then
- Set_Stack_Limit_Hook.all;
- end if;
end Thread_Body_Enter;
----------------------------------
-- Thread_Body_Exceptional_Exit --
----------------------------------
- procedure Thread_Body_Exceptional_Exit
- (EO : Ada.Exceptions.Exception_Occurrence)
- is
- pragma Unreferenced (EO);
-
+ procedure Thread_Body_Exceptional_Exit is
begin
-- No action for this target
@@ -156,11 +121,8 @@ package body System.Threads is
pragma Assert (Result /= ERROR);
begin
- Main_ATSD.Sec_Stack_Ptr := SSL.Get_Sec_Stack_NT;
+ Main_ATSD.Sec_Stack_Ptr := Get_Sec_Stack;
Current_ATSD := Main_ATSD'Address;
- Install_Handler;
- SSL.Get_Sec_Stack := Get_Sec_Stack'Access;
- SSL.Set_Sec_Stack := Set_Sec_Stack'Access;
end Init_RTS;
-------------------
@@ -190,38 +152,12 @@ package body System.Threads is
Current_ATSD := To_Address (Integer_Address (T));
- -- The same issue applies to the task variable that contains the stack
- -- limit when that overflow checking mechanism is used instead of
- -- probing. If stack checking is enabled and limit checking is used,
- -- allocate the limit for this task. The environment task has this
- -- initialized by the binder-generated main when
- -- System.Stack_Check_Limits = True.
-
- pragma Warnings (Off);
-
- -- OS is a constant
- if OS /= VxWorks_653 and then Set_Stack_Limit_Hook /= null then
- -- Check that this is correct if limit checking left in. ???
- Stack_Limit := To_Address (Integer_Address (T));
- end if;
- pragma Warnings (On);
-
return OK;
end Register;
- -------------------
- -- Set_Sec_Stack --
- -------------------
-
- procedure Set_Sec_Stack (Stack : SST.SS_Stack_Ptr) is
- CTSD : constant ATSD_Access := From_Address (Current_ATSD);
- begin
- pragma Assert (CTSD /= null);
- CTSD.Sec_Stack_Ptr := Stack;
- end Set_Sec_Stack;
-
begin
-- Initialize run-time library
Init_RTS;
+
end System.Threads;
diff --git a/gcc/ada/libgnat/s-trasym__dwarf.adb b/gcc/ada/libgnat/s-trasym__dwarf.adb
index 61e7a1c..fb26d77 100644
--- a/gcc/ada/libgnat/s-trasym__dwarf.adb
+++ b/gcc/ada/libgnat/s-trasym__dwarf.adb
@@ -691,7 +691,7 @@ package body System.Traceback.Symbolic is
return Symbolic_Traceback (E, Suppress_Hex => True);
end Symbolic_Traceback_No_Hex;
- Exception_Tracebacks_Symbolic : Integer;
+ Exception_Tracebacks_Symbolic : constant Integer;
pragma Import
(C,
Exception_Tracebacks_Symbolic,
diff --git a/gcc/ada/libgnat/system-vxworks-e500-vthread.ads b/gcc/ada/libgnat/system-vxworks-e500-vthread.ads
deleted file mode 100644
index 0857c67..0000000
--- a/gcc/ada/libgnat/system-vxworks-e500-vthread.ads
+++ /dev/null
@@ -1,162 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M --
--- --
--- S p e c --
--- (VxWorks e500 AE653 vThreads) --
--- --
--- Copyright (C) 1992-2021, 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 version is for the AE653/e500v2 vThreads full run-time
-
-package System is
- pragma Pure;
- -- Note that we take advantage of the implementation permission to make
- -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada
- -- 2005, this is Pure in any case (AI-362).
-
- pragma No_Elaboration_Code_All;
- -- Allow the use of that restriction in units that WITH this unit
-
- type Name is (SYSTEM_NAME_GNAT);
- System_Name : constant Name := SYSTEM_NAME_GNAT;
-
- -- System-Dependent Named Numbers
-
- Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1);
- Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1;
-
- Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size;
- Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1;
-
- Max_Base_Digits : constant := Long_Long_Float'Digits;
- Max_Digits : constant := Long_Long_Float'Digits;
-
- Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
- Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
-
- Tick : constant := 1.0 / 60.0;
-
- -- Storage-related Declarations
-
- type Address is private;
- pragma Preelaborable_Initialization (Address);
- Null_Address : constant Address;
-
- Storage_Unit : constant := 8;
- Word_Size : constant := 32;
- Memory_Size : constant := 2 ** 32;
-
- -- Address comparison
-
- function "<" (Left, Right : Address) return Boolean;
- function "<=" (Left, Right : Address) return Boolean;
- function ">" (Left, Right : Address) return Boolean;
- function ">=" (Left, Right : Address) return Boolean;
- function "=" (Left, Right : Address) return Boolean;
-
- pragma Import (Intrinsic, "<");
- pragma Import (Intrinsic, "<=");
- pragma Import (Intrinsic, ">");
- pragma Import (Intrinsic, ">=");
- pragma Import (Intrinsic, "=");
-
- -- Other System-Dependent Declarations
-
- type Bit_Order is (High_Order_First, Low_Order_First);
- Default_Bit_Order : constant Bit_Order := High_Order_First;
- pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning
-
- -- Priority-related Declarations (RM D.1)
-
- -- Ada priorities are mapped to VxWorks priorities using the following
- -- transformation: 255 - Ada Priority
-
- -- Ada priorities are used as follows:
-
- -- 256 is reserved for the VxWorks kernel
- -- 248 - 255 correspond to hardware interrupt levels 0 .. 7
- -- 247 is a catchall default "interrupt" priority for signals,
- -- allowing higher priority than normal tasks, but lower than
- -- hardware priority levels. Protected Object ceilings can
- -- override these values.
- -- 246 is used by the Interrupt_Manager task
-
- Max_Priority : constant Positive := 245;
- Max_Interrupt_Priority : constant Positive := 255;
-
- subtype Any_Priority is Integer range 0 .. 255;
- subtype Priority is Any_Priority range 0 .. 245;
- subtype Interrupt_Priority is Any_Priority range 246 .. 255;
-
- Default_Priority : constant Priority := 122;
-
-private
-
- type Address is mod Memory_Size;
- Null_Address : constant Address := 0;
-
- --------------------------------------
- -- System Implementation Parameters --
- --------------------------------------
-
- -- These parameters provide information about the target that is used
- -- by the compiler. They are in the private part of System, where they
- -- can be accessed using the special circuitry in the Targparm unit
- -- whose source should be consulted for more detailed descriptions
- -- of the individual switch values.
-
- Backend_Divide_Checks : constant Boolean := False;
- Backend_Overflow_Checks : constant Boolean := True;
- Command_Line_Args : constant Boolean := False;
- Configurable_Run_Time : constant Boolean := False;
- Denorm : constant Boolean := True;
- Duration_32_Bits : constant Boolean := False;
- Exit_Status_Supported : constant Boolean := True;
- Machine_Overflows : constant Boolean := False;
- Machine_Rounds : constant Boolean := True;
- Preallocated_Stacks : constant Boolean := False;
- Signed_Zeros : constant Boolean := True;
- Stack_Check_Default : constant Boolean := False;
- Stack_Check_Probes : constant Boolean := True;
- Stack_Check_Limits : constant Boolean := False;
- Support_Aggregates : constant Boolean := True;
- Support_Composite_Assign : constant Boolean := True;
- Support_Composite_Compare : constant Boolean := True;
- Support_Long_Shifts : constant Boolean := True;
- Always_Compatible_Rep : constant Boolean := False;
- Suppress_Standard_Library : constant Boolean := False;
- Use_Ada_Main_Program_Name : constant Boolean := True;
- Frontend_Exceptions : constant Boolean := False;
- ZCX_By_Default : constant Boolean := False;
-
- Executable_Extension : constant String := ".out";
-
-end System;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads b/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads
deleted file mode 100644
index 64f1303..0000000
--- a/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads
+++ /dev/null
@@ -1,162 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M --
--- --
--- S p e c --
--- (VxWorks PPC AE653 vThreads) --
--- --
--- Copyright (C) 1992-2021, 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 version is for the AE653 vThreads full run-time
-
-package System is
- pragma Pure;
- -- Note that we take advantage of the implementation permission to make
- -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada
- -- 2005, this is Pure in any case (AI-362).
-
- pragma No_Elaboration_Code_All;
- -- Allow the use of that restriction in units that WITH this unit
-
- type Name is (SYSTEM_NAME_GNAT);
- System_Name : constant Name := SYSTEM_NAME_GNAT;
-
- -- System-Dependent Named Numbers
-
- Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1);
- Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1;
-
- Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size;
- Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1;
-
- Max_Base_Digits : constant := Long_Long_Float'Digits;
- Max_Digits : constant := Long_Long_Float'Digits;
-
- Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
- Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
-
- Tick : constant := 1.0 / 60.0;
-
- -- Storage-related Declarations
-
- type Address is private;
- pragma Preelaborable_Initialization (Address);
- Null_Address : constant Address;
-
- Storage_Unit : constant := 8;
- Word_Size : constant := 32;
- Memory_Size : constant := 2 ** 32;
-
- -- Address comparison
-
- function "<" (Left, Right : Address) return Boolean;
- function "<=" (Left, Right : Address) return Boolean;
- function ">" (Left, Right : Address) return Boolean;
- function ">=" (Left, Right : Address) return Boolean;
- function "=" (Left, Right : Address) return Boolean;
-
- pragma Import (Intrinsic, "<");
- pragma Import (Intrinsic, "<=");
- pragma Import (Intrinsic, ">");
- pragma Import (Intrinsic, ">=");
- pragma Import (Intrinsic, "=");
-
- -- Other System-Dependent Declarations
-
- type Bit_Order is (High_Order_First, Low_Order_First);
- Default_Bit_Order : constant Bit_Order := High_Order_First;
- pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning
-
- -- Priority-related Declarations (RM D.1)
-
- -- Ada priorities are mapped to VxWorks priorities using the following
- -- transformation: 255 - Ada Priority
-
- -- Ada priorities are used as follows:
-
- -- 256 is reserved for the VxWorks kernel
- -- 248 - 255 correspond to hardware interrupt levels 0 .. 7
- -- 247 is a catchall default "interrupt" priority for signals,
- -- allowing higher priority than normal tasks, but lower than
- -- hardware priority levels. Protected Object ceilings can
- -- override these values.
- -- 246 is used by the Interrupt_Manager task
-
- Max_Priority : constant Positive := 245;
- Max_Interrupt_Priority : constant Positive := 255;
-
- subtype Any_Priority is Integer range 0 .. 255;
- subtype Priority is Any_Priority range 0 .. 245;
- subtype Interrupt_Priority is Any_Priority range 246 .. 255;
-
- Default_Priority : constant Priority := 122;
-
-private
-
- type Address is mod Memory_Size;
- Null_Address : constant Address := 0;
-
- --------------------------------------
- -- System Implementation Parameters --
- --------------------------------------
-
- -- These parameters provide information about the target that is used
- -- by the compiler. They are in the private part of System, where they
- -- can be accessed using the special circuitry in the Targparm unit
- -- whose source should be consulted for more detailed descriptions
- -- of the individual switch values.
-
- Backend_Divide_Checks : constant Boolean := False;
- Backend_Overflow_Checks : constant Boolean := True;
- Command_Line_Args : constant Boolean := False;
- Configurable_Run_Time : constant Boolean := False;
- Denorm : constant Boolean := True;
- Duration_32_Bits : constant Boolean := False;
- Exit_Status_Supported : constant Boolean := True;
- Machine_Overflows : constant Boolean := True;
- Machine_Rounds : constant Boolean := True;
- Preallocated_Stacks : constant Boolean := False;
- Signed_Zeros : constant Boolean := True;
- Stack_Check_Default : constant Boolean := False;
- Stack_Check_Probes : constant Boolean := True;
- Stack_Check_Limits : constant Boolean := False;
- Support_Aggregates : constant Boolean := True;
- Support_Composite_Assign : constant Boolean := True;
- Support_Composite_Compare : constant Boolean := True;
- Support_Long_Shifts : constant Boolean := True;
- Always_Compatible_Rep : constant Boolean := False;
- Suppress_Standard_Library : constant Boolean := False;
- Use_Ada_Main_Program_Name : constant Boolean := True;
- Frontend_Exceptions : constant Boolean := False;
- ZCX_By_Default : constant Boolean := False;
-
- Executable_Extension : constant String := ".out";
-
-end System;
diff --git a/gcc/ada/libgnat/system-vxworks-x86-vthread.ads b/gcc/ada/libgnat/system-vxworks-x86-vthread.ads
deleted file mode 100644
index 3b78e7e..0000000
--- a/gcc/ada/libgnat/system-vxworks-x86-vthread.ads
+++ /dev/null
@@ -1,163 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M --
--- --
--- S p e c --
--- (VxWorks 653 x86 vThreads) --
--- --
--- Copyright (C) 1992-2021, 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 version is for the AE653 vThreads full run-time
-
-package System is
- pragma Pure;
- -- Note that we take advantage of the implementation permission to make
- -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada
- -- 2005, this is Pure in any case (AI-362).
-
- pragma No_Elaboration_Code_All;
- -- Allow the use of that restriction in units that WITH this unit
-
- type Name is (SYSTEM_NAME_GNAT);
- System_Name : constant Name := SYSTEM_NAME_GNAT;
-
- -- System-Dependent Named Numbers
-
- Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1);
- Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1;
-
- Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size;
- Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1;
-
- Max_Base_Digits : constant := Long_Long_Float'Digits;
- Max_Digits : constant := Long_Long_Float'Digits;
-
- Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
- Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
-
- Tick : constant := 1.0 / 60.0;
-
- -- Storage-related Declarations
-
- type Address is private;
- pragma Preelaborable_Initialization (Address);
- Null_Address : constant Address;
-
- Storage_Unit : constant := 8;
- Word_Size : constant := 32;
- Memory_Size : constant := 2 ** 32;
-
- -- Address comparison
-
- function "<" (Left, Right : Address) return Boolean;
- function "<=" (Left, Right : Address) return Boolean;
- function ">" (Left, Right : Address) return Boolean;
- function ">=" (Left, Right : Address) return Boolean;
- function "=" (Left, Right : Address) return Boolean;
-
- pragma Import (Intrinsic, "<");
- pragma Import (Intrinsic, "<=");
- pragma Import (Intrinsic, ">");
- pragma Import (Intrinsic, ">=");
- pragma Import (Intrinsic, "=");
-
- -- Other System-Dependent Declarations
-
- type Bit_Order is (High_Order_First, Low_Order_First);
- Default_Bit_Order : constant Bit_Order := Low_Order_First;
- pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning
-
- -- Priority-related Declarations (RM D.1)
-
- -- Ada priorities are mapped to VxWorks priorities using the following
- -- transformation: 255 - Ada Priority
-
- -- Ada priorities are used as follows:
-
- -- 256 is reserved for the VxWorks kernel
- -- 248 - 255 correspond to hardware interrupt levels 0 .. 7
- -- 247 is a catchall default "interrupt" priority for signals,
- -- allowing higher priority than normal tasks, but lower than
- -- hardware priority levels. Protected Object ceilings can
- -- override these values.
- -- 246 is used by the Interrupt_Manager task
-
- Max_Priority : constant Positive := 245;
- Max_Interrupt_Priority : constant Positive := 255;
-
- subtype Any_Priority is Integer range 0 .. 255;
- subtype Priority is Any_Priority range 0 .. 245;
- subtype Interrupt_Priority is Any_Priority range 246 .. 255;
-
- Default_Priority : constant Priority := 122;
-
-private
-
- type Address is mod Memory_Size;
- Null_Address : constant Address := 0;
-
- --------------------------------------
- -- System Implementation Parameters --
- --------------------------------------
-
- -- These parameters provide information about the target that is used
- -- by the compiler. They are in the private part of System, where they
- -- can be accessed using the special circuitry in the Targparm unit
- -- whose source should be consulted for more detailed descriptions
- -- of the individual switch values.
-
- Backend_Divide_Checks : constant Boolean := False;
- Backend_Overflow_Checks : constant Boolean := True;
- Command_Line_Args : constant Boolean := False;
- Configurable_Run_Time : constant Boolean := False;
- Denorm : constant Boolean := True;
- Duration_32_Bits : constant Boolean := False;
- Exit_Status_Supported : constant Boolean := True;
- Machine_Overflows : constant Boolean := True;
- Machine_Rounds : constant Boolean := True;
- Preallocated_Stacks : constant Boolean := False;
- Signed_Zeros : constant Boolean := True;
- Stack_Check_Default : constant Boolean := False;
- Stack_Check_Probes : constant Boolean := True;
- Stack_Check_Limits : constant Boolean := False;
- Support_Aggregates : constant Boolean := True;
- Support_Atomic_Primitives : constant Boolean := True;
- Support_Composite_Assign : constant Boolean := True;
- Support_Composite_Compare : constant Boolean := True;
- Support_Long_Shifts : constant Boolean := True;
- Always_Compatible_Rep : constant Boolean := False;
- Suppress_Standard_Library : constant Boolean := False;
- Use_Ada_Main_Program_Name : constant Boolean := True;
- Frontend_Exceptions : constant Boolean := False;
- ZCX_By_Default : constant Boolean := False;
-
- Executable_Extension : constant String := ".out";
-
-end System;
diff --git a/gcc/ada/live.adb b/gcc/ada/live.adb
index 5a74f8b..db0a5f2 100644
--- a/gcc/ada/live.adb
+++ b/gcc/ada/live.adb
@@ -45,7 +45,8 @@ package body Live is
-- any valuable per-node space and possibly results in better locality and
-- cache usage.
- type Name_Set is array (Node_Id range <>) of Boolean;
+ type Name_Set is array (Node_Id'Base range <>) of Boolean;
+ -- We use 'Base here, in case we want to add a predicate to Node_Id
pragma Pack (Name_Set);
function Marked (Marks : Name_Set; Name : Node_Id) return Boolean;
diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb
index 6e74e90..10276fa 100644
--- a/gcc/ada/make.adb
+++ b/gcc/ada/make.adb
@@ -1168,7 +1168,7 @@ package body Make is
end if;
else
- ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
+ ALI := Scan_ALI (Lib_File, Text, Err => True);
Free (Text);
if ALI = No_ALI_Id then
@@ -2647,7 +2647,7 @@ package body Make is
if Text /= null then
ALI :=
Scan_ALI
- (Data.Lib_File, Text, Ignore_ED => False, Err => True);
+ (Data.Lib_File, Text, Err => True);
if ALI = No_ALI_Id then
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 3786d2c..3ccd630 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -1031,22 +1031,6 @@ package Opt is
-- GNATBIND
-- Set to True to enable XDR in s-stratt.adb. Set by -xdr.
- type Create_Repinfo_File_Proc is access procedure (Src : String);
- type Write_Repinfo_Line_Proc is access procedure (Info : String);
- type Close_Repinfo_File_Proc is access procedure;
- -- Types used for procedure addresses below
-
- Create_Repinfo_File_Access : Create_Repinfo_File_Proc := null;
- Write_Repinfo_Line_Access : Write_Repinfo_Line_Proc := null;
- Close_Repinfo_File_Access : Close_Repinfo_File_Proc := null;
- -- GNAT
- -- These three locations are left null when operating in non-compiler (e.g.
- -- ASIS mode), but when operating in compiler mode, they are set to point
- -- to the three corresponding procedures in Osint-C. The reason for this
- -- slightly strange interface is to stop Repinfo from dragging in Osint in
- -- ASIS mode, which would include lots of unwanted units in the ASIS build.
- -- ??? Revisit this now that ASIS mode is gone.
-
type Create_List_File_Proc is access procedure (S : String);
type Write_List_Info_Proc is access procedure (S : String);
type Close_List_File_Proc is access procedure;
diff --git a/gcc/ada/osint-c.adb b/gcc/ada/osint-c.adb
index 14c6993..d08b082 100644
--- a/gcc/ada/osint-c.adb
+++ b/gcc/ada/osint-c.adb
@@ -520,10 +520,6 @@ package body Osint.C is
begin
Adjust_OS_Resource_Limits;
- Opt.Create_Repinfo_File_Access := Create_Repinfo_File'Access;
- Opt.Write_Repinfo_Line_Access := Write_Repinfo_Line'Access;
- Opt.Close_Repinfo_File_Access := Close_Repinfo_File'Access;
-
Opt.Create_List_File_Access := Create_List_File'Access;
Opt.Write_List_Info_Access := Write_List_Info'Access;
Opt.Close_List_File_Access := Close_List_File'Access;
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index 4ee6aa8..cf39128 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -2373,14 +2373,12 @@ package body Osint is
Nb_Relative_Dir := 0;
for J in 1 .. Len loop
- -- Treat any control character as a path separator. Note that we do
+ -- Treat any EOL character as a path separator. Note that we do
-- not treat space as a path separator (we used to treat space as a
-- path separator in an earlier version). That way space can appear
-- as a legitimate character in a path name.
- -- Why do we treat all control characters as path separators???
-
- if S (J) in ASCII.NUL .. ASCII.US then
+ if S (J) = ASCII.LF or else S (J) = ASCII.CR then
S (J) := Path_Separator;
end if;
diff --git a/gcc/ada/output.adb b/gcc/ada/output.adb
index e886b92..00202fd 100644
--- a/gcc/ada/output.adb
+++ b/gcc/ada/output.adb
@@ -467,6 +467,32 @@ package body Output is
end if;
end Write_Int;
+ ------------------
+ -- Write_Int_64 --
+ ------------------
+
+ procedure Write_Int_64 (Val : Int_64) is
+ subtype Nonpositive is Int_64 range Int_64'First .. 0;
+ procedure Write_Abs (Val : Nonpositive);
+
+ procedure Write_Abs (Val : Nonpositive) is
+ begin
+ if Val < -9 then
+ Write_Abs (Val / 10);
+ end if;
+
+ Write_Char (Character'Val (-(Val rem 10) + Character'Pos ('0')));
+ end Write_Abs;
+
+ begin
+ if Val < 0 then
+ Write_Char ('-');
+ Write_Abs (Val);
+ else
+ Write_Abs (-Val);
+ end if;
+ end Write_Int_64;
+
----------------
-- Write_Line --
----------------
diff --git a/gcc/ada/output.ads b/gcc/ada/output.ads
index 6a36533..5058d6d 100644
--- a/gcc/ada/output.ads
+++ b/gcc/ada/output.ads
@@ -124,6 +124,7 @@ package Output is
-- Similar as Write_Eol, except that trailing spaces are not removed
procedure Write_Int (Val : Int);
+ procedure Write_Int_64 (Val : Int_64);
-- Write an integer value with no leading blanks or zeroes. Negative values
-- are preceded by a minus sign).
diff --git a/gcc/ada/par-ch10.adb b/gcc/ada/par-ch10.adb
index f02934a..76f0edd 100644
--- a/gcc/ada/par-ch10.adb
+++ b/gcc/ada/par-ch10.adb
@@ -532,13 +532,14 @@ package body Ch10 is
| N_Subprogram_Body
| N_Subprogram_Renaming_Declaration
then
- Unit_Node := Specification (Unit_Node);
-
- elsif Nkind (Unit_Node) = N_Subprogram_Renaming_Declaration then
- if Ada_Version = Ada_83 then
+ if Nkind (Unit_Node) = N_Subprogram_Renaming_Declaration
+ and then Ada_Version = Ada_83
+ then
Error_Msg_N
("(Ada 83) library unit renaming not allowed", Unit_Node);
end if;
+
+ Unit_Node := Specification (Unit_Node);
end if;
if Nkind (Unit_Node) in N_Task_Body
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 20f8dd1..b6cc1a0 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -3518,62 +3518,62 @@ package body Ch4 is
Assoc_Node :=
New_Node (N_Iterated_Component_Association, Prev_Token_Ptr);
- if Token = Tok_In then
- Set_Defining_Identifier (Assoc_Node, Id);
- T_In;
- Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
+ case Token is
+ when Tok_In =>
+ 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;
+ if Token = Tok_When then
+ Scan; -- past WHEN
+ Filter := P_Condition;
+ end if;
- if Token = Tok_Use then
+ if Token = Tok_Use then
- -- Ada 2022 Key-expression is present, rewrite node as an
- -- Iterated_Element_Association.
+ -- Ada 2022 Key-expression is present, rewrite node as an
+ -- Iterated_Element_Association.
- Scan; -- past USE
- Build_Iterated_Element_Association;
- Set_Key_Expression (Assoc_Node, P_Expression);
+ 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 2022
- -- construct, in contrast with a subtype indication used in
- -- array aggregates.
+ elsif Present (Filter) then
+ -- A loop_parameter_specification also indicates an Ada 2022
+ -- construct, in contrast with a subtype indication used in
+ -- array aggregates.
- Build_Iterated_Element_Association;
- end if;
+ Build_Iterated_Element_Association;
+ end if;
- TF_Arrow;
- Set_Expression (Assoc_Node, P_Expression);
+ TF_Arrow;
+ Set_Expression (Assoc_Node, P_Expression);
- elsif Ada_Version >= Ada_2022
- and then Token = Tok_Of
- then
- Restore_Scan_State (State);
- Scan; -- past OF
- Set_Defining_Identifier (Assoc_Node, Id);
- Iter_Spec := P_Iterator_Specification (Id);
- Set_Iterator_Specification (Assoc_Node, Iter_Spec);
-
- if Token = Tok_Use then
- Scan; -- past USE
- -- This is an iterated_element_association
-
- Assoc_Node :=
- New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
+ when Tok_Of =>
+ Restore_Scan_State (State);
+ Scan; -- past OF
+ Set_Defining_Identifier (Assoc_Node, Id);
+ Iter_Spec := P_Iterator_Specification (Id);
Set_Iterator_Specification (Assoc_Node, Iter_Spec);
- Set_Key_Expression (Assoc_Node, P_Expression);
- end if;
- TF_Arrow;
- Set_Expression (Assoc_Node, P_Expression);
- end if;
+ if Token = Tok_Use then
+ Scan; -- past USE
+ -- This is an iterated_element_association
- Error_Msg_Ada_2022_Feature ("iterated component", Token_Ptr);
+ Assoc_Node :=
+ New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
+ Set_Iterator_Specification (Assoc_Node, Iter_Spec);
+ Set_Key_Expression (Assoc_Node, P_Expression);
+ end if;
+
+ TF_Arrow;
+ Set_Expression (Assoc_Node, P_Expression);
+
+ when others =>
+ Error_Msg_AP ("missing IN or OF");
+ end case;
return Assoc_Node;
end P_Iterated_Component_Association;
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 06c7d87..e1258e0 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1338,6 +1338,7 @@ begin
| Pragma_CPP_Virtual
| Pragma_CPP_Vtable
| Pragma_CPU
+ | Pragma_CUDA_Device
| Pragma_CUDA_Execute
| Pragma_CUDA_Global
| Pragma_C_Pass_By_Copy
diff --git a/gcc/ada/par_sco.adb b/gcc/ada/par_sco.adb
index b4f7609..09e4d50 100644
--- a/gcc/ada/par_sco.adb
+++ b/gcc/ada/par_sco.adb
@@ -216,9 +216,6 @@ package body Par_SCO is
-- Parameter D, when present, indicates the dominant of the first
-- declaration or statement within N.
- -- Why is Traverse_Sync_Definition commented specifically, whereas
- -- the others are not???
-
procedure Traverse_Generic_Package_Declaration (N : Node_Id);
procedure Traverse_Handled_Statement_Sequence
@@ -235,8 +232,7 @@ package body Par_SCO is
(N : Node_Id;
D : Dominant_Info := No_Dominant);
- procedure Traverse_Sync_Definition (N : Node_Id);
- -- Traverse a protected definition or task definition
+ procedure Traverse_Protected_Or_Task_Definition (N : Node_Id);
-- Note regarding traversals: In a few cases where an Alternatives list is
-- involved, pragmas such as "pragma Page" may show up before the first
@@ -690,9 +686,6 @@ package body Par_SCO is
-- fully equivalent to the "To" sloc computed by
-- Sloc_Range (Guard, To, From).
- -- Doesn't this requirement of using First_Sloc need to be
- -- documented in the spec ???
-
if Nkind (Parent (N)) in N_Accept_Alternative
| N_Delay_Alternative
| N_Terminate_Alternative
@@ -834,6 +827,14 @@ package body Par_SCO is
return Skip;
end;
+ when N_Quantified_Expression =>
+ declare
+ Cond : constant Node_Id := Condition (N);
+ begin
+ Process_Decisions (Cond, 'W', Pragma_Sloc);
+ return Skip;
+ end;
+
-- All other cases, continue scan
when others =>
@@ -2248,6 +2249,8 @@ package body Par_SCO is
| Name_Loop_Invariant
| Name_Postcondition
| Name_Precondition
+ | Name_Type_Invariant
+ | Name_Invariant
=>
-- For Assert/Check/Precondition/Postcondition, we
-- must generate a P entry for the decision. Note
@@ -2256,7 +2259,10 @@ package body Par_SCO is
-- on when we output the decision line in Put_SCOs,
-- depending on setting by Set_SCO_Pragma_Enabled.
- if Nam = Name_Check then
+ if Nam = Name_Check
+ or else Nam = Name_Type_Invariant
+ or else Nam = Name_Invariant
+ then
Next (Arg);
end if;
@@ -2285,8 +2291,7 @@ package body Par_SCO is
-- never disabled.
-- Should generate P decisions (not X) for assertion
- -- related pragmas: [Type_]Invariant,
- -- [{Static,Dynamic}_]Predicate???
+ -- related pragmas: [{Static,Dynamic}_]Predicate???
when others =>
Process_Decisions_Defer (N, 'X');
@@ -2327,7 +2332,7 @@ package body Par_SCO is
Process_Decisions_Defer (Discriminant_Specifications (N), 'X');
Set_Statement_Entry;
- Traverse_Sync_Definition (N);
+ Traverse_Protected_Or_Task_Definition (N);
when N_Single_Protected_Declaration
| N_Single_Task_Declaration
@@ -2335,7 +2340,7 @@ package body Par_SCO is
Extend_Statement_Sequence (N, 'o');
Set_Statement_Entry;
- Traverse_Sync_Definition (N);
+ Traverse_Protected_Or_Task_Definition (N);
when others =>
@@ -2513,11 +2518,11 @@ package body Par_SCO is
Traverse_Declarations_Or_Statements (Private_Declarations (Spec), Dom);
end Traverse_Package_Declaration;
- ------------------------------
- -- Traverse_Sync_Definition --
- ------------------------------
+ -------------------------------------------
+ -- Traverse_Protected_Or_Task_Definition --
+ -------------------------------------------
- procedure Traverse_Sync_Definition (N : Node_Id) is
+ procedure Traverse_Protected_Or_Task_Definition (N : Node_Id) is
Dom_Info : Dominant_Info := ('S', N);
-- The first declaration is dominated by the protected or task [type]
-- declaration.
@@ -2566,7 +2571,7 @@ package body Par_SCO is
Traverse_Declarations_Or_Statements
(L => Priv_Decl,
D => Dom_Info);
- end Traverse_Sync_Definition;
+ end Traverse_Protected_Or_Task_Definition;
--------------------------------------
-- Traverse_Subprogram_Or_Task_Body --
diff --git a/gcc/ada/pprint.adb b/gcc/ada/pprint.adb
index f7717bf..b76bd91 100644
--- a/gcc/ada/pprint.adb
+++ b/gcc/ada/pprint.adb
@@ -100,7 +100,7 @@ package body Pprint is
Add_Space : Boolean := True;
Add_Paren : Boolean := True;
Num : Natural := 1) return String;
- -- ??? what does this do
+ -- Created for purposes of recursing on embedded lists
------------------------
-- Internal_List_Name --
@@ -113,30 +113,6 @@ package body Pprint is
Add_Paren : Boolean := True;
Num : Natural := 1) return String
is
- function Prepend (S : String) return String;
- -- ??? what does this do
-
- -------------
- -- Prepend --
- -------------
-
- function Prepend (S : String) return String is
- begin
- if Add_Space then
- if Add_Paren then
- return " (" & S;
- else
- return ' ' & S;
- end if;
- elsif Add_Paren then
- return '(' & S;
- else
- return S;
- end if;
- end Prepend;
-
- -- Start of processing for Internal_List_Name
-
begin
if not Present (List) then
if First or else not Add_Paren then
@@ -152,23 +128,22 @@ package body Pprint is
end if;
end if;
- -- ??? the Internal_List_Name calls can be factored out
-
- if First then
- return Prepend (Expr_Name (List)
- & Internal_List_Name
- (List => Next (List),
- First => False,
- Add_Paren => Add_Paren,
- Num => Num + 1));
- else
- return ", " & Expr_Name (List)
- & Internal_List_Name
- (List => Next (List),
- First => False,
- Add_Paren => Add_Paren,
- Num => Num + 1);
- end if;
+ -- Continue recursing on the list - handling the first element
+ -- in a special way.
+
+ return
+ (if First then
+ (if Add_Space and Add_Paren then " ("
+ elsif Add_Paren then "("
+ elsif Add_Space then " "
+ else "")
+ else ", ")
+ & Expr_Name (List)
+ & Internal_List_Name
+ (List => Next (List),
+ First => False,
+ Add_Paren => Add_Paren,
+ Num => Num + 1);
end Internal_List_Name;
-- Start of processing for List_Name
diff --git a/gcc/ada/prep.adb b/gcc/ada/prep.adb
index 37556d5..e01161c 100644
--- a/gcc/ada/prep.adb
+++ b/gcc/ada/prep.adb
@@ -1410,7 +1410,12 @@ package body Prep is
Scan.all;
- if Token /= Tok_If then
+ -- Ignore all recoverable errors if Relaxed_RM_Semantics
+
+ if Relaxed_RM_Semantics then
+ null;
+
+ elsif Token /= Tok_If then
Error_Msg -- CODEFIX
("IF expected", Token_Ptr);
No_Error_Found := False;
@@ -1453,21 +1458,31 @@ package body Prep is
-- Illegal preprocessor line
when others =>
- No_Error_Found := False;
-
if Pp_States.Last = 0 then
Error_Msg -- CODEFIX
("IF expected", Token_Ptr);
+ No_Error_Found := False;
- elsif
- Pp_States.Table (Pp_States.Last).Else_Ptr = 0
+ elsif Relaxed_RM_Semantics
+ and then Get_Name_String (Token_Name) = "endif"
then
+ -- In relaxed mode, accept "endif" instead of
+ -- "end if".
+
+ -- Decrement the depth of the #if stack
+
+ if Pp_States.Last > 0 then
+ Pp_States.Decrement_Last;
+ end if;
+ elsif Pp_States.Table (Pp_States.Last).Else_Ptr = 0 then
Error_Msg
("IF, ELSIF, ELSE, or `END IF` expected",
Token_Ptr);
+ No_Error_Found := False;
else
Error_Msg ("IF or `END IF` expected", Token_Ptr);
+ No_Error_Found := False;
end if;
-- Skip to the end of this illegal line
diff --git a/gcc/ada/repinfo-input.adb b/gcc/ada/repinfo-input.adb
index 5d85040..7e250a4 100644
--- a/gcc/ada/repinfo-input.adb
+++ b/gcc/ada/repinfo-input.adb
@@ -776,7 +776,7 @@ package body Repinfo.Input is
-- Compute Component_Bit_Offset from Position and First_Bit,
-- either symbolically or literally depending on Position.
- if Position = No_Uint or else First_Bit = No_Uint then
+ if No (Position) or else No (First_Bit) then
Error ("bit offset expected");
end if;
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
index 148de53..084ca91 100644
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -35,6 +35,7 @@ with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
with Output; use Output;
+with Osint.C; use Osint.C;
with Sem_Aux; use Sem_Aux;
with Sem_Eval; use Sem_Eval;
with Sinfo; use Sinfo;
@@ -422,7 +423,8 @@ package body Repinfo is
Write_Line (";");
end if;
- -- Alignment is not always set for task and protected types
+ -- Alignment is not always set for task, protected, and class-wide
+ -- types.
else
pragma Assert
@@ -807,7 +809,7 @@ package body Repinfo is
-- Start of processing for List_GCC_Expression
begin
- if U = No_Uint then
+ if No (U) then
Write_Unknown_Val;
else
Print_Expr (U);
@@ -1188,13 +1190,7 @@ package body Repinfo is
Write_Str (" .. ");
end if;
- -- Allowing Uint_0 here is an annoying special case. Really this
- -- should be a fine Esize value but currently it means unknown,
- -- except that we know after gigi has back annotated that a size
- -- of zero is real, since otherwise gigi back annotates using
- -- No_Uint as the value to indicate unknown.
-
- if (Esize (Ent) = Uint_0 or else Known_Static_Esize (Ent))
+ if Known_Static_Esize (Ent)
and then Known_Static_Normalized_First_Bit (Ent)
then
Lbit := Sbit + Esiz - 1;
@@ -1209,14 +1205,7 @@ package body Repinfo is
UI_Write (Lbit, Decimal);
end if;
- -- The test for Esize (Ent) not Uint_0 here is an annoying special
- -- case. Officially a value of zero for Esize means unknown, but
- -- here we use the fact that we know that gigi annotates Esize with
- -- No_Uint, not Uint_0. Really everyone should use No_Uint???
-
- elsif List_Representation_Info < 3
- or else (Esize (Ent) /= Uint_0 and then not Known_Esize (Ent))
- then
+ elsif List_Representation_Info < 3 or else not Known_Esize (Ent) then
Write_Unknown_Val;
-- List_Representation >= 3 and Known_Esize (Ent)
@@ -1736,7 +1725,7 @@ package body Repinfo is
-- List representation information to file
else
- Create_Repinfo_File_Access.all
+ Create_Repinfo_File
(Get_Name_String (File_Name (Source_Index (U))));
Set_Special_Output (Write_Info_Line'Access);
if List_Representation_Info_To_JSON then
@@ -1748,7 +1737,7 @@ package body Repinfo is
Write_Line ("]");
end if;
Cancel_Special_Output;
- Close_Repinfo_File_Access.all;
+ Close_Repinfo_File;
end if;
end if;
end loop;
@@ -2116,7 +2105,7 @@ package body Repinfo is
function Rep_Not_Constant (Val : Node_Ref_Or_Val) return Boolean is
begin
- if Val = No_Uint or else Val < 0 then
+ if No (Val) or else Val < 0 then
return True;
else
return False;
@@ -2315,7 +2304,7 @@ package body Repinfo is
-- Start of processing for Rep_Value
begin
- if Val = No_Uint then
+ if No (Val) then
return No_Uint;
else
@@ -2340,7 +2329,7 @@ package body Repinfo is
procedure Write_Info_Line (S : String) is
begin
- Write_Repinfo_Line_Access.all (S (S'First .. S'Last - 1));
+ Write_Repinfo_Line (S (S'First .. S'Last - 1));
end Write_Info_Line;
---------------------
@@ -2401,7 +2390,7 @@ package body Repinfo is
procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False) is
begin
if Rep_Not_Constant (Val) then
- if List_Representation_Info < 3 or else Val = No_Uint then
+ if List_Representation_Info < 3 or else No (Val) then
Write_Unknown_Val;
else
diff --git a/gcc/ada/restrict.ads b/gcc/ada/restrict.ads
index eec85c2..183973b 100644
--- a/gcc/ada/restrict.ads
+++ b/gcc/ada/restrict.ads
@@ -402,6 +402,8 @@ package Restrict is
-- Test to see if current restrictions settings specify that no
-- exception propagation is activated.
+ -- WARNING: There is a matching C declaration of this subprogram in fe.h
+
function Process_Restriction_Synonyms (N : Node_Id) return Name_Id;
-- Id is a node whose Chars field contains the name of a restriction.
-- If it is one of synonyms that we allow for historical purposes (for
diff --git a/gcc/ada/scn.adb b/gcc/ada/scn.adb
index ad53279..e81985f 100644
--- a/gcc/ada/scn.adb
+++ b/gcc/ada/scn.adb
@@ -159,7 +159,7 @@ package body Scn is
-- Int_Literal_Value can be No_Uint in some cases in syntax-only
-- mode (see Scng.Scan.Nlit).
- if Int_Literal_Value /= No_Uint then
+ if Present (Int_Literal_Value) then
Set_Intval (Token_Node, Int_Literal_Value);
end if;
diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb
index bf1307c..fb42e30b 100644
--- a/gcc/ada/scng.adb
+++ b/gcc/ada/scng.adb
@@ -1743,13 +1743,13 @@ package body Scng is
Code := Character'Pos (' ');
-- In Ada 95 mode we allow any wide character in a character
- -- literal, but in Ada 2005, the set of characters allowed
- -- is restricted to graphic characters.
+ -- literal, but in later versions, the set of characters
+ -- allowed is restricted to graphic characters.
elsif Ada_Version >= Ada_2005
and then Is_UTF_32_Non_Graphic (UTF_32 (Code))
then
- Error_Msg -- CODEFIX????
+ Error_Msg -- CODEFIX
("(Ada 2005) non-graphic character not permitted " &
"in character literal", Wptr);
end if;
diff --git a/gcc/ada/scos.ads b/gcc/ada/scos.ads
index d8e88dd..cdac552 100644
--- a/gcc/ada/scos.ads
+++ b/gcc/ada/scos.ads
@@ -257,7 +257,7 @@ package SCOs is
-- I decision in IF statement or if expression
-- P decision in pragma Assert / Check / Pre/Post_Condition
-- A[name] decision in aspect Pre/Post (aspect name optional)
- -- W decision in WHILE iteration scheme
+ -- W decision in WHILE iteration scheme or quantified expression
-- X decision in some other expression context
-- For E, G, I, P, W, sloc is the source location of the EXIT, ENTRY, IF,
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index 783c94aa..3eee2ee 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -1402,7 +1402,9 @@ package body Sem is
procedure Do_Analyze is
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
- -- Save the Ghost-related attributes to restore on exit
+ Saved_ISMP : constant Boolean :=
+ Ignore_SPARK_Mode_Pragmas_In_Instance;
+ -- Save Ghost and SPARK mode-related data to restore on exit
-- Generally style checks are preserved across compilations, with
-- one exception: s-oscons.ads, which allows arbitrary long lines
@@ -1421,6 +1423,7 @@ package body Sem is
-- Set up a clean environment before analyzing
Install_Ghost_Region (None, Empty);
+ Ignore_SPARK_Mode_Pragmas_In_Instance := False;
Outer_Generic_Scope := Empty;
Scope_Suppress := Suppress_Options;
@@ -1443,9 +1446,11 @@ package body Sem is
Pop_Scope;
Restore_Scope_Stack (List);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
Style_Max_Line_Length := Saved_ML;
Style_Check_Max_Line_Length := Saved_CML;
+
+ Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
end Do_Analyze;
-- Local variables
diff --git a/gcc/ada/sem.ads b/gcc/ada/sem.ads
index 2fdccf7..699f685 100644
--- a/gcc/ada/sem.ads
+++ b/gcc/ada/sem.ads
@@ -291,6 +291,10 @@ package Sem is
-- freezing nodes can modify the status of this flag, any other client
-- should regard it as read-only.
+ Inside_Class_Condition_Preanalysis : Boolean := False;
+ -- Flag indicating whether we are preanalyzing a class-wide precondition
+ -- or postcondition.
+
Inside_Preanalysis_Without_Freezing : Nat := 0;
-- Flag indicating whether we are preanalyzing an expression performing no
-- freezing. Non-zero means we are inside (it is actually a level counter
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 9ad9629..527342f 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -365,7 +365,7 @@ package body Sem_Aggr is
-- to the expansion phase. As an optimization, if the discrete choice
-- specifies a single value we do not delay resolution.
- function Array_Aggr_Subtype (N : Node_Id; Typ : Node_Id) return Entity_Id;
+ function Array_Aggr_Subtype (N : Node_Id; Typ : Entity_Id) return Entity_Id;
-- This routine returns the type or subtype of an array aggregate.
--
-- N is the array aggregate node whose type we return.
@@ -545,6 +545,14 @@ package body Sem_Aggr is
-- Make sure that the list of index constraints is properly attached to
-- the tree, and then collect the aggregate bounds.
+ -- If no aggregaate bounds have been set, this is an aggregate with
+ -- iterator specifications and a dynamic size to be determined by
+ -- first pass of expanded code.
+
+ if No (Aggregate_Bounds (N)) then
+ return Typ;
+ end if;
+
Set_Parent (Index_Constraints, N);
Collect_Aggr_Bounds (N, 1);
@@ -1597,6 +1605,8 @@ package body Sem_Aggr is
Loc : constant Source_Ptr := Sloc (N);
Id : constant Entity_Id := Defining_Identifier (N);
+ Id_Typ : Entity_Id := Any_Type;
+
-----------------------
-- Remove_References --
-----------------------
@@ -1630,42 +1640,65 @@ package body Sem_Aggr is
-- Start of processing for Resolve_Iterated_Component_Association
begin
- -- An element iterator specification cannot appear in
- -- an array aggregate because it does not provide index
- -- values for the association. This must be a semantic
- -- check because the parser cannot tell whether this is
- -- an array aggregate or a container aggregate.
+ Error_Msg_Ada_2022_Feature ("iterated component", Loc);
if Present (Iterator_Specification (N)) then
- Error_Msg_N ("container element Iterator cannot appear "
- & "in an array aggregate", N);
- return;
- end if;
+ Analyze (Name (Iterator_Specification (N)));
- Choice := First (Discrete_Choices (N));
+ -- We assume that the domain of iteration cannot be overloaded.
- while Present (Choice) loop
- if Nkind (Choice) = N_Others_Choice then
- Others_Present := True;
+ declare
+ Domain : constant Node_Id := Name (Iterator_Specification (N));
+ D_Type : constant Entity_Id := Etype (Domain);
+ Elt : Entity_Id;
+ begin
+ if Is_Array_Type (D_Type) then
+ Id_Typ := Component_Type (D_Type);
- else
- Analyze (Choice);
+ else
+ if Has_Aspect (D_Type, Aspect_Iterable) then
+ Elt :=
+ Get_Iterable_Type_Primitive (D_Type, Name_Element);
+ if No (Elt) then
+ Error_Msg_N
+ ("missing Element primitive for iteration", Domain);
+ else
+ Id_Typ := Etype (Elt);
+ end if;
+ else
+ Error_Msg_N ("cannot iterate over", Domain);
+ end if;
+ end if;
+ end;
- -- Choice can be a subtype name, a range, or an expression
+ else
+ Id_Typ := Index_Typ;
+ Choice := First (Discrete_Choices (N));
- if Is_Entity_Name (Choice)
- and then Is_Type (Entity (Choice))
- and then Base_Type (Entity (Choice)) = Base_Type (Index_Typ)
- then
- null;
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Others_Choice then
+ Others_Present := True;
else
- Analyze_And_Resolve (Choice, Index_Typ);
+ Analyze (Choice);
+
+ -- Choice can be a subtype name, a range, or an expression
+
+ if Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ and then
+ Base_Type (Entity (Choice)) = Base_Type (Index_Typ)
+ then
+ null;
+
+ else
+ Analyze_And_Resolve (Choice, Index_Typ);
+ end if;
end if;
- end if;
- Next (Choice);
- end loop;
+ Next (Choice);
+ end loop;
+ end if;
-- Create a scope in which to introduce an index, which is usually
-- visible in the expression for the component, and needed for its
@@ -1681,7 +1714,7 @@ package body Sem_Aggr is
-- directly visible.
Enter_Name (Id);
- Set_Etype (Id, Index_Typ);
+ Set_Etype (Id, Id_Typ);
Mutate_Ekind (Id, E_Variable);
Set_Scope (Id, Ent);
@@ -1735,6 +1768,12 @@ package body Sem_Aggr is
Delete_Choice : Boolean;
-- Used when replacing a subtype choice with predicate by a list
+ Has_Iterator_Specifications : Boolean := False;
+ -- Flag to indicate that all named associations are iterated component
+ -- associations with iterator specifications, in which case the
+ -- expansion will create two loops: one to evaluate the size and one
+ -- to generate the elements (4.3.3 (20.2/5)).
+
Nb_Elements : Uint := Uint_0;
-- The number of elements in a positional aggregate
@@ -1756,6 +1795,54 @@ package body Sem_Aggr is
-- STEP 1: make sure the aggregate is correctly formatted
if Present (Component_Associations (N)) then
+
+ -- Verify that all or none of the component associations
+ -- include an iterator specification.
+
+ Assoc := First (Component_Associations (N));
+ if Nkind (Assoc) = N_Iterated_Component_Association
+ and then Present (Iterator_Specification (Assoc))
+ then
+ -- All other component associations must have an iterator spec.
+
+ Next (Assoc);
+ while Present (Assoc) loop
+ if Nkind (Assoc) /= N_Iterated_Component_Association
+ or else No (Iterator_Specification (Assoc))
+ then
+ Error_Msg_N ("mixed iterated component association"
+ & " (RM 4.4.3 (17.1/5))",
+ Assoc);
+ return False;
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ Has_Iterator_Specifications := True;
+
+ else
+ -- or none of them do.
+
+ Next (Assoc);
+ while Present (Assoc) loop
+ if Nkind (Assoc) = N_Iterated_Component_Association
+ and then Present (Iterator_Specification (Assoc))
+ then
+ Error_Msg_N ("mixed iterated component association"
+ & " (RM 4.4.3 (17.1/5))",
+ Assoc);
+ return False;
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ while Present (Assoc) loop
+ Next (Assoc);
+ end loop;
+ end if;
+
Assoc := First (Component_Associations (N));
while Present (Assoc) loop
if Nkind (Assoc) = N_Iterated_Component_Association then
@@ -1867,7 +1954,7 @@ package body Sem_Aggr is
or else (Nb_Choices = 1 and then not Others_Present))
then
Error_Msg_N
- ("named association cannot follow positional association",
+ ("cannot mix named and positional associations in array aggregate",
First (Choice_List (First (Component_Associations (N)))));
return Failure;
end if;
@@ -1948,9 +2035,12 @@ package body Sem_Aggr is
begin
-- STEP 2 (A): Check discrete choices validity
+ -- No need if this is an element iteration.
Assoc := First (Component_Associations (N));
- while Present (Assoc) loop
+ while Present (Assoc)
+ and then Present (Choice_List (Assoc))
+ loop
Prev_Nb_Discrete_Choices := Nb_Discrete_Choices;
Choice := First (Choice_List (Assoc));
@@ -2391,6 +2481,12 @@ package body Sem_Aggr is
end Check_Choices;
end if;
+ if Has_Iterator_Specifications then
+ -- Bounds will be determined dynamically.
+
+ return Success;
+ end if;
+
-- STEP 2 (B): Compute aggregate bounds and min/max choices values
if Nb_Discrete_Choices > 0 then
@@ -2706,7 +2802,10 @@ package body Sem_Aggr is
-- Exp_Aggr.Convert_To_Positional, so we don't want to change those
-- bounds.
- if Present (Aggregate_Bounds (N)) and then not Others_Allowed then
+ if Present (Aggregate_Bounds (N))
+ and then not Others_Allowed
+ and then not Comes_From_Source (N)
+ then
Aggr_Low := Low_Bound (Aggregate_Bounds (N));
Aggr_High := High_Bound (Aggregate_Bounds (N));
end if;
@@ -2770,6 +2869,7 @@ package body Sem_Aggr is
Key_Type : Entity_Id;
Elmt_Type : Entity_Id)
is
+ Loc : constant Source_Ptr := Sloc (N);
Choice : Node_Id;
Ent : Entity_Id;
Expr : Node_Id;
@@ -2780,6 +2880,8 @@ package body Sem_Aggr is
Typ : Entity_Id := Empty;
begin
+ Error_Msg_Ada_2022_Feature ("iterated component", Loc);
+
-- If this is an Iterated_Element_Association then either a
-- an Iterator_Specification or a Loop_Parameter specification
-- is present. In both cases a Key_Expression is present.
@@ -5205,8 +5307,8 @@ package body Sem_Aggr is
Add_Association
(Component => Component,
- Expr => Empty,
- Assoc_List => New_Assoc_List,
+ Expr => Empty,
+ Assoc_List => New_Assoc_List,
Is_Box_Present => True);
elsif Present (Parent (Component))
@@ -5285,74 +5387,12 @@ package body Sem_Aggr is
Assoc_List => New_Assoc_List);
Set_Has_Self_Reference (N);
- -- A box-defaulted access component gets the value null. Also
- -- included are components of private types whose underlying
- -- type is an access type. In either case set the type of the
- -- literal, for subsequent use in semantic checks.
-
- elsif Present (Underlying_Type (Ctyp))
- and then Is_Access_Type (Underlying_Type (Ctyp))
- then
- -- If the component's type is private with an access type as
- -- its underlying type then we have to create an unchecked
- -- conversion to satisfy type checking.
-
- if Is_Private_Type (Ctyp) then
- declare
- Qual_Null : constant Node_Id :=
- Make_Qualified_Expression (Sloc (N),
- Subtype_Mark =>
- New_Occurrence_Of
- (Underlying_Type (Ctyp), Sloc (N)),
- Expression => Make_Null (Sloc (N)));
-
- Convert_Null : constant Node_Id :=
- Unchecked_Convert_To
- (Ctyp, Qual_Null);
-
- begin
- Analyze_And_Resolve (Convert_Null, Ctyp);
- Add_Association
- (Component => Component,
- Expr => Convert_Null,
- Assoc_List => New_Assoc_List);
- end;
-
- -- Otherwise the component type is non-private
-
- else
- Expr := Make_Null (Sloc (N));
- Set_Etype (Expr, Ctyp);
-
- Add_Association
- (Component => Component,
- Expr => Expr,
- Assoc_List => New_Assoc_List);
- end if;
-
- -- Ada 2012: If component is scalar with default value, use it
- -- by converting it to Ctyp, so that subtype constraints are
- -- checked.
-
- elsif Is_Scalar_Type (Ctyp)
- and then Has_Default_Aspect (Ctyp)
- then
- declare
- Conv : constant Node_Id :=
- Convert_To
- (Typ => Ctyp,
- Expr =>
- New_Copy_Tree
- (Default_Aspect_Value
- (First_Subtype (Underlying_Type (Ctyp)))));
-
- begin
- Analyze_And_Resolve (Conv, Ctyp);
- Add_Association
- (Component => Component,
- Expr => Conv,
- Assoc_List => New_Assoc_List);
- end;
+ elsif Needs_Simple_Initialization (Ctyp) then
+ Add_Association
+ (Component => Component,
+ Expr => Empty,
+ Assoc_List => New_Assoc_List,
+ Is_Box_Present => True);
elsif Has_Non_Null_Base_Init_Proc (Ctyp)
or else not Expander_Active
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index d1a91d8..32c5d37 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -175,6 +175,7 @@ package body Sem_Attr is
Attribute_22 : constant Attribute_Class_Array := Attribute_Class_Array'(
Attribute_Enum_Rep |
Attribute_Enum_Val => True,
+ Attribute_Preelaborable_Initialization => True,
others => False);
-- The following array contains all attributes that imply a modification
@@ -1338,6 +1339,16 @@ package body Sem_Attr is
Legal := False;
Spec_Id := Empty;
+ -- Skip processing during preanalysis of class-wide preconditions and
+ -- postconditions since at this stage the expression is not installed
+ -- yet on its definite context.
+
+ if Inside_Class_Condition_Preanalysis then
+ Legal := True;
+ Spec_Id := Current_Scope;
+ return;
+ end if;
+
-- Traverse the parent chain to find the aspect or pragma where the
-- attribute resides.
@@ -1402,6 +1413,15 @@ package body Sem_Attr is
return;
end if;
+ -- 'Old attribute reference ok in a _Postconditions procedure
+
+ elsif Nkind (Prag) = N_Subprogram_Body
+ and then not Comes_From_Source (Prag)
+ and then Nkind (Corresponding_Spec (Prag)) = N_Defining_Identifier
+ and then Chars (Corresponding_Spec (Prag)) = Name_uPostconditions
+ then
+ null;
+
-- Otherwise the placement of the attribute is illegal
else
@@ -1413,6 +1433,15 @@ package body Sem_Attr is
if Nkind (Prag) = N_Aspect_Specification then
Subp_Decl := Parent (Prag);
+ elsif Nkind (Prag) = N_Subprogram_Body then
+ declare
+ Enclosing_Scope : constant Node_Id :=
+ Scope (Corresponding_Spec (Prag));
+ begin
+ pragma Assert (Postconditions_Proc (Enclosing_Scope)
+ = Corresponding_Spec (Prag));
+ Subp_Decl := Parent (Parent (Enclosing_Scope));
+ end;
else
Subp_Decl := Find_Related_Declaration_Or_Body (Prag);
end if;
@@ -1518,14 +1547,6 @@ package body Sem_Attr is
Check_E1;
Set_Etype (N, Str_Typ);
- -- ???It's not clear why 'Img should behave any differently than
- -- 'Image.
-
- if Attr_Id = Attribute_Img then
- Error_Attr_P
- ("prefix of % attribute must be a scalar object name");
- end if;
-
pragma Assert (Is_Entity_Name (P) and then Is_Type (Entity (P)));
if Ekind (Entity (P)) = E_Incomplete_Type
@@ -5408,6 +5429,45 @@ package body Sem_Attr is
end if;
end if;
+ ----------------------------------
+ -- Preelaborable_Initialization --
+ ----------------------------------
+
+ when Attribute_Preelaborable_Initialization =>
+ Check_E0;
+ Check_Type;
+
+ -- If we're in an instance, we know that the legality of the
+ -- attribute prefix type was already checked in the generic.
+
+ if not In_Instance then
+
+ -- If the prefix type is a generic formal type, then it must be
+ -- either a formal private type or a formal derived type.
+
+ if Is_Generic_Type (P_Type) then
+ if not Is_Private_Type (P_Type)
+ and then not Is_Derived_Type (P_Type)
+ then
+ Error_Attr_P ("formal type prefix of % attribute must be "
+ & "formal private or formal derived type");
+ end if;
+
+ -- Otherwise, the prefix type must be a nonformal composite
+ -- type declared within the visible part of a package or
+ -- generic package.
+
+ elsif not Is_Composite_Type (P_Type)
+ or else not Original_View_In_Visible_Part (P_Type)
+ then
+ Error_Attr_P
+ ("prefix of % attribute must be composite type declared "
+ & "in visible part of a package or generic package");
+ end if;
+ end if;
+
+ Set_Etype (N, Standard_Boolean);
+
--------------
-- Priority --
--------------
@@ -6601,7 +6661,9 @@ package body Sem_Attr is
Initialize (CRC);
Compute_Type_Key (Entity (P));
- if not Is_Frozen (Entity (P)) then
+ if not Is_Frozen (Entity (P))
+ and then not Is_Generic_Type (Entity (P))
+ then
Error_Msg_N ("premature usage of Type_Key?", N);
end if;
@@ -8084,13 +8146,13 @@ package body Sem_Attr is
end if;
-- If we are asked to evaluate an attribute where the prefix is a
- -- non-frozen generic actual type whose RM_Size is still set to zero,
+ -- non-frozen generic actual type whose RM_Size has not been set,
-- then abandon the effort.
if Is_Type (P_Entity)
and then (not Is_Frozen (P_Entity)
and then Is_Generic_Actual_Type (P_Entity)
- and then RM_Size (P_Entity) = 0)
+ and then not Known_RM_Size (P_Entity))
-- However, the attribute Unconstrained_Array must be evaluated,
-- since it is documented to be a static attribute (and can for
@@ -8182,15 +8244,16 @@ package body Sem_Attr is
-- is to say if we are within an instantiation. Same processing applies
-- to selected GNAT attributes.
- elsif (Id = Attribute_Atomic_Always_Lock_Free or else
- Id = Attribute_Definite or else
- Id = Attribute_Descriptor_Size or else
- Id = Attribute_Has_Access_Values or else
- Id = Attribute_Has_Discriminants or else
- Id = Attribute_Has_Tagged_Values or else
- Id = Attribute_Lock_Free or else
- Id = Attribute_Type_Class or else
- Id = Attribute_Unconstrained_Array or else
+ elsif (Id = Attribute_Atomic_Always_Lock_Free or else
+ Id = Attribute_Definite or else
+ Id = Attribute_Descriptor_Size or else
+ Id = Attribute_Has_Access_Values or else
+ Id = Attribute_Has_Discriminants or else
+ Id = Attribute_Has_Tagged_Values or else
+ Id = Attribute_Lock_Free or else
+ Id = Attribute_Preelaborable_Initialization or else
+ Id = Attribute_Type_Class or else
+ Id = Attribute_Unconstrained_Array or else
Id = Attribute_Max_Alignment_For_Allocation)
and then not Is_Generic_Type (P_Entity)
then
@@ -8315,15 +8378,20 @@ package body Sem_Attr is
-- unconstrained arrays. Furthermore, it is essential to fold this
-- in the packed case, since otherwise the value will be incorrect.
- elsif Id = Attribute_Atomic_Always_Lock_Free or else
- Id = Attribute_Definite or else
- Id = Attribute_Descriptor_Size or else
- Id = Attribute_Has_Access_Values or else
- Id = Attribute_Has_Discriminants or else
- Id = Attribute_Has_Tagged_Values or else
- Id = Attribute_Lock_Free or else
- Id = Attribute_Type_Class or else
- Id = Attribute_Unconstrained_Array or else
+ -- Folding can also be done for Preelaborable_Initialization based on
+ -- whether the prefix type has preelaborable initialization, even though
+ -- the attribute is nonstatic.
+
+ elsif Id = Attribute_Atomic_Always_Lock_Free or else
+ Id = Attribute_Definite or else
+ Id = Attribute_Descriptor_Size or else
+ Id = Attribute_Has_Access_Values or else
+ Id = Attribute_Has_Discriminants or else
+ Id = Attribute_Has_Tagged_Values or else
+ Id = Attribute_Lock_Free or else
+ Id = Attribute_Preelaborable_Initialization or else
+ Id = Attribute_Type_Class or else
+ Id = Attribute_Unconstrained_Array or else
Id = Attribute_Component_Size
then
Static := False;
@@ -9085,12 +9153,26 @@ package body Sem_Attr is
-- Leading_Part --
------------------
- when Attribute_Leading_Part =>
+ when Attribute_Leading_Part => Leading_Part : declare
+ Radix_Digits : constant Uint := Expr_Value (E2);
+
+ begin
+ if UI_Le (Radix_Digits, Uint_0) then
+ Apply_Compile_Time_Constraint_Error
+ (N, "Radix_Digits in Leading_Part is zero or negative",
+ CE_Explicit_Raise,
+ Warn => not Static);
+
+ Check_Expressions;
+ return;
+ end if;
+
Fold_Ureal
(N,
Eval_Fat.Leading_Part
- (P_Base_Type, Expr_Value_R (E1), Expr_Value (E2)),
+ (P_Base_Type, Expr_Value_R (E1), Radix_Digits),
Static);
+ end Leading_Part;
------------
-- Length --
@@ -9143,7 +9225,7 @@ package body Sem_Attr is
Fold_Uint (N, Uint_0, Static);
when LT =>
- if Diff /= No_Uint then
+ if Present (Diff) then
Fold_Uint (N, Diff + 1, Static);
end if;
@@ -9609,6 +9691,17 @@ package body Sem_Attr is
Fold_Uint (N, Expr_Value (E1) - 1, Static);
end if;
+ ----------------------------------
+ -- Preelaborable_Initialization --
+ ----------------------------------
+
+ when Attribute_Preelaborable_Initialization =>
+ Fold_Uint
+ (N,
+ UI_From_Int
+ (Boolean'Pos (Has_Preelaborable_Initialization (P_Type))),
+ Static);
+
-----------
-- Range --
-----------
@@ -9653,7 +9746,7 @@ package body Sem_Attr is
Fold_Uint (N, Uint_0, Static);
when LT =>
- if Diff /= No_Uint then
+ if Present (Diff) then
Fold_Uint (N, Diff + 1, Static);
end if;
@@ -9824,9 +9917,9 @@ package body Sem_Attr is
P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
begin
- if Is_Scalar_Type (P_TypeA)
- or else RM_Size (P_TypeA) /= Uint_0
- then
+ pragma Assert
+ (if Is_Scalar_Type (P_TypeA) then Known_RM_Size (P_TypeA));
+ if Known_RM_Size (P_TypeA) then
-- VADS_Size case
if Id = Attribute_VADS_Size or else Use_VADS_Size then
@@ -10102,7 +10195,9 @@ package body Sem_Attr is
P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
begin
- if Is_Scalar_Type (P_TypeA) or else RM_Size (P_TypeA) /= Uint_0 then
+ pragma Assert
+ (if Is_Scalar_Type (P_TypeA) then Known_RM_Size (P_TypeA));
+ if Known_RM_Size (P_TypeA) then
Fold_Uint (N, RM_Size (P_TypeA), Static);
end if;
end Value_Size;
@@ -11429,28 +11524,45 @@ package body Sem_Attr is
-- in such a context - unless the restriction
-- No_Dynamic_Accessibility_Checks is active.
- if Attr_Id /= Attribute_Unchecked_Access
- and then
- (Ekind (Btyp) = E_General_Access_Type
- or else No_Dynamic_Accessibility_Checks_Enabled (Btyp))
-
- -- Call Accessibility_Level directly to avoid returning zero
- -- on cases where the prefix is an explicitly aliased
- -- parameter in a return statement, instead of using the
- -- normal Static_Accessibility_Level function.
-
- -- Shouldn't this be handled somehow in
- -- Static_Accessibility_Level ???
+ declare
+ No_Dynamic_Acc_Checks : constant Boolean :=
+ No_Dynamic_Accessibility_Checks_Enabled (Btyp);
- and then Nkind (Accessibility_Level (P, Dynamic_Level))
- = N_Integer_Literal
- and then
- Intval (Accessibility_Level (P, Dynamic_Level))
- > Deepest_Type_Access_Level (Btyp)
- then
- Accessibility_Message;
- return;
- end if;
+ Compatible_Alt_Checks : constant Boolean :=
+ No_Dynamic_Acc_Checks and then not Debug_Flag_Underscore_B;
+ begin
+ if Attr_Id /= Attribute_Unchecked_Access
+ and then (Ekind (Btyp) = E_General_Access_Type
+ or else No_Dynamic_Acc_Checks)
+
+ -- In the case of the alternate "compatibility"
+ -- accessibility model we do not perform a static
+ -- accessibility check on actuals for anonymous access
+ -- types - so exclude them here.
+
+ and then not (Compatible_Alt_Checks
+ and then Is_Actual_Parameter (N)
+ and then Ekind (Btyp)
+ = E_Anonymous_Access_Type)
+
+ -- Call Accessibility_Level directly to avoid returning
+ -- zero on cases where the prefix is an explicitly aliased
+ -- parameter in a return statement, instead of using the
+ -- normal Static_Accessibility_Level function.
+
+ -- Shouldn't this be handled somehow in
+ -- Static_Accessibility_Level ???
+
+ and then Nkind (Accessibility_Level (P, Dynamic_Level))
+ = N_Integer_Literal
+ and then
+ Intval (Accessibility_Level (P, Dynamic_Level))
+ > Deepest_Type_Access_Level (Btyp)
+ then
+ Accessibility_Message;
+ return;
+ end if;
+ end;
end if;
if Ekind (Btyp) in E_Access_Protected_Subprogram_Type
@@ -12418,7 +12530,7 @@ package body Sem_Attr is
function Stream_Attribute_Available
(Typ : Entity_Id;
Nam : TSS_Name_Type;
- Partial_View : Node_Id := Empty) return Boolean
+ Partial_View : Entity_Id := Empty) return Boolean
is
Etyp : Entity_Id := Typ;
diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
index ea3b59c..dcced7e 100644
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -846,10 +846,7 @@ package body Sem_Aux is
Btype : constant Entity_Id := Base_Type (Ent);
begin
- if Error_Posted (Ent) or else Error_Posted (Btype) then
- return False;
-
- elsif Is_Private_Type (Btype) then
+ if Is_Private_Type (Btype) then
declare
Utyp : constant Entity_Id := Underlying_Type (Btype);
begin
@@ -1405,6 +1402,31 @@ package body Sem_Aux is
end Object_Type_Has_Constrained_Partial_View;
------------------
+ -- Package_Body --
+ ------------------
+
+ function Package_Body (E : Entity_Id) return Node_Id is
+ Body_Decl : Node_Id;
+ Body_Id : constant Opt_E_Package_Body_Id :=
+ Corresponding_Body (Package_Spec (E));
+
+ begin
+ if Present (Body_Id) then
+ Body_Decl := Parent (Body_Id);
+
+ if Nkind (Body_Decl) = N_Defining_Program_Unit_Name then
+ Body_Decl := Parent (Body_Decl);
+ end if;
+
+ pragma Assert (Nkind (Body_Decl) = N_Package_Body);
+
+ return Body_Decl;
+ else
+ return Empty;
+ end if;
+ end Package_Body;
+
+ ------------------
-- Package_Spec --
------------------
diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads
index 810e2d8..3adaee4 100644
--- a/gcc/ada/sem_aux.ads
+++ b/gcc/ada/sem_aux.ads
@@ -377,6 +377,10 @@ 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, 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_case.adb b/gcc/ada/sem_case.adb
index 7d08da5..31f14d5 100644
--- a/gcc/ada/sem_case.adb
+++ b/gcc/ada/sem_case.adb
@@ -44,6 +44,7 @@ with Stand; use Stand;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
+with Stringt; use Stringt;
with Table;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
@@ -105,25 +106,70 @@ package body Sem_Case is
package Composite_Case_Ops is
+ function Choice_Count (Alternatives : List_Id) return Nat;
+ -- The sum of the number of choices for each alternative in the given
+ -- list.
+
function Scalar_Part_Count (Subtyp : Entity_Id) return Nat;
-- Given the composite type Subtyp of a case selector, returns the
-- number of scalar parts in an object of this type. This is the
-- dimensionality of the associated Cartesian product space.
- function Choice_Count (Alternatives : List_Id) return Nat;
- -- The sum of the number of choices for each alternative in the given
- -- list.
+ package Array_Case_Ops is
+ function Array_Choice_Length (Choice : Node_Id) return Nat;
+ -- Given a choice expression of an array type, returns its length.
+
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id;
+ -- Usually returns the Etype of the selector expression of the
+ -- case statement. However, in the case of a constrained array
+ -- subtype with a nonstatic constraint, returns the unconstrained
+ -- array base type.
+
+ function Unconstrained_Array_Effective_Length
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat;
+ -- If the nominal subtype of the case selector is unconstrained,
+ -- then use the length of the longest choice of the case statement.
+ -- Components beyond that index value will not influence the case
+ -- selection decision.
+
+ function Unconstrained_Array_Scalar_Part_Count
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat;
+ -- Same as Scalar_Part_Count except that the value used for the
+ -- "length" of the array subtype being cased on is determined by
+ -- calling Unconstrained_Array_Effective_Length.
+ end Array_Case_Ops;
generic
Case_Statement : Node_Id;
package Choice_Analysis is
+ use Array_Case_Ops;
+
type Alternative_Id is
new Int range 1 .. List_Length (Alternatives (Case_Statement));
type Choice_Id is
new Int range 1 .. Choice_Count (Alternatives (Case_Statement));
+
+ Case_Expr_Type : constant Entity_Id :=
+ Normalized_Case_Expr_Type (Case_Statement);
+
+ Unconstrained_Array_Case : constant Boolean :=
+ Is_Array_Type (Case_Expr_Type)
+ and then not Is_Constrained (Case_Expr_Type);
+
+ -- If Unconstrained_Array_Case is True, choice lengths may differ:
+ -- when "Aaa" | "Bb" | "C" | "" =>
+ --
+ -- Strictly speaking, the name "Unconstrained_Array_Case" is
+ -- slightly imprecise; a subtype with a nonstatic constraint is
+ -- also treated as unconstrained (see Normalize_Case_Expr_Type).
+
type Part_Id is new Int range
- 1 .. Scalar_Part_Count (Etype (Expression (Case_Statement)));
+ 1 .. (if Unconstrained_Array_Case
+ then Unconstrained_Array_Scalar_Part_Count
+ (Case_Expr_Type, Case_Statement)
+ else Scalar_Part_Count (Case_Expr_Type));
type Discrete_Range_Info is
record
@@ -1118,6 +1164,21 @@ package body Sem_Case is
return UI_To_Int (Len);
end Static_Array_Length;
+ ------------------
+ -- Choice_Count --
+ ------------------
+
+ function Choice_Count (Alternatives : List_Id) return Nat is
+ Result : Nat := 0;
+ Alt : Node_Id := First (Alternatives);
+ begin
+ while Present (Alt) loop
+ Result := Result + List_Length (Discrete_Choices (Alt));
+ Next (Alt);
+ end loop;
+ return Result;
+ end Choice_Count;
+
-----------------------
-- Scalar_Part_Count --
-----------------------
@@ -1147,20 +1208,118 @@ package body Sem_Case is
end if;
end Scalar_Part_Count;
- ------------------
- -- Choice_Count --
- ------------------
+ package body Array_Case_Ops is
- function Choice_Count (Alternatives : List_Id) return Nat is
- Result : Nat := 0;
- Alt : Node_Id := First (Alternatives);
- begin
- while Present (Alt) loop
- Result := Result + List_Length (Discrete_Choices (Alt));
- Next (Alt);
- end loop;
- return Result;
- end Choice_Count;
+ -------------------------
+ -- Array_Choice_Length --
+ -------------------------
+
+ function Array_Choice_Length (Choice : Node_Id) return Nat is
+ begin
+ case Nkind (Choice) is
+ when N_String_Literal =>
+ return String_Length (Strval (Choice));
+ when N_Aggregate =>
+ declare
+ Bounds : constant Node_Id :=
+ Aggregate_Bounds (Choice);
+ pragma Assert (Is_OK_Static_Range (Bounds));
+ Lo : constant Uint :=
+ Expr_Value (Low_Bound (Bounds));
+ Hi : constant Uint :=
+ Expr_Value (High_Bound (Bounds));
+ Len : constant Uint := (Hi - Lo) + 1;
+ begin
+ return UI_To_Int (Len);
+ end;
+ when N_Has_Entity =>
+ if Present (Entity (Choice))
+ and then Ekind (Entity (Choice)) = E_Constant
+ then
+ return Array_Choice_Length
+ (Expression (Parent (Entity (Choice))));
+ end if;
+ when N_Others_Choice =>
+ return 0;
+ when others =>
+ null;
+ end case;
+
+ if Nkind (Original_Node (Choice))
+ in N_String_Literal | N_Aggregate
+ then
+ return Array_Choice_Length (Original_Node (Choice));
+ end if;
+
+ Error_Msg_N ("Unsupported case choice", Choice);
+ return 0;
+ end Array_Choice_Length;
+
+ -------------------------------
+ -- Normalized_Case_Expr_Type --
+ -------------------------------
+
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id
+ is
+ Unnormalized : constant Entity_Id :=
+ Etype (Expression (Case_Statement));
+ begin
+ if Is_Array_Type (Unnormalized)
+ and then Is_Constrained (Unnormalized)
+ and then not Has_Static_Array_Bounds (Unnormalized)
+ then
+ return Base_Type (Unnormalized);
+ else
+ return Unnormalized;
+ end if;
+ end Normalized_Case_Expr_Type;
+
+ ------------------------------------------
+ -- Unconstrained_Array_Effective_Length --
+ ------------------------------------------
+
+ function Unconstrained_Array_Effective_Length
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat
+ is
+ pragma Assert (Is_Array_Type (Array_Type));
+ -- Array_Type is otherwise unreferenced for now.
+
+ Result : Nat := 0;
+ Alt : Node_Id := First (Alternatives (Case_Statement));
+ begin
+ while Present (Alt) loop
+ declare
+ Choice : Node_Id := First (Discrete_Choices (Alt));
+ begin
+ while Present (Choice) loop
+ Result := Nat'Max (Result, Array_Choice_Length (Choice));
+ Next (Choice);
+ end loop;
+ end;
+ Next (Alt);
+ end loop;
+
+ return Result;
+ end Unconstrained_Array_Effective_Length;
+
+ -------------------------------------------
+ -- Unconstrained_Array_Scalar_Part_Count --
+ -------------------------------------------
+
+ function Unconstrained_Array_Scalar_Part_Count
+ (Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat
+ is
+ begin
+ -- Add one for the length, which is treated like a discriminant
+
+ return 1 + (Unconstrained_Array_Effective_Length
+ (Array_Type => Array_Type,
+ Case_Statement => Case_Statement)
+ * Scalar_Part_Count (Component_Type (Array_Type)));
+ end Unconstrained_Array_Scalar_Part_Count;
+
+ end Array_Case_Ops;
package body Choice_Analysis is
@@ -1220,9 +1379,32 @@ package body Sem_Case is
((Low => Expr_Value (Type_Low_Bound (Subtyp)),
High => Expr_Value (Type_High_Bound (Subtyp))));
elsif Is_Array_Type (Subtyp) then
- for I in 1 .. Static_Array_Length (Subtyp) loop
- Traverse_Discrete_Parts (Component_Type (Subtyp));
- end loop;
+ declare
+ Len : Nat;
+ begin
+ if Is_Constrained (Subtyp) then
+ Len := Static_Array_Length (Subtyp);
+ else
+ -- Length will be treated like a discriminant;
+ -- We could compute High more precisely as
+ -- 1 + Index_Subtype'Last - Index_Subtype'First
+ -- (we currently require that those bounds be
+ -- static, so this is an option), but only downside of
+ -- overshooting is if somebody wants to omit a
+ -- "when others" choice and exhaustively cover all
+ -- possibilities explicitly.
+ Update_Result
+ ((Low => Uint_0,
+ High => Uint_2 ** Uint_32));
+
+ Len := Unconstrained_Array_Effective_Length
+ (Array_Type => Subtyp,
+ Case_Statement => Case_Statement);
+ end if;
+ for I in 1 .. Len loop
+ Traverse_Discrete_Parts (Component_Type (Subtyp));
+ end loop;
+ end;
elsif Is_Record_Type (Subtyp) then
if Has_Static_Discriminant_Constraint (Subtyp) then
@@ -1274,7 +1456,7 @@ package body Sem_Case is
end Traverse_Discrete_Parts;
begin
- Traverse_Discrete_Parts (Etype (Expression (Case_Statement)));
+ Traverse_Discrete_Parts (Case_Expr_Type);
pragma Assert (Done or else Serious_Errors_Detected > 0);
return Result;
end Component_Bounds_Info;
@@ -1531,6 +1713,19 @@ package body Sem_Case is
& "choice not implemented", Expr);
end if;
+ if not Unconstrained_Array_Case
+ and then List_Length (Expressions (Expr))
+ /= Nat (Part_Id'Last)
+ then
+ Error_Msg_Uint_1 := UI_From_Int
+ (List_Length (Expressions (Expr)));
+ Error_Msg_Uint_2 := UI_From_Int (Int (Part_Id'Last));
+ Error_Msg_N
+ ("array aggregate length ^ does not match length " &
+ "of statically constrained case selector ^", Expr);
+ return;
+ end if;
+
declare
Subexpr : Node_Id := First (Expressions (Expr));
begin
@@ -1542,9 +1737,51 @@ package body Sem_Case is
else
raise Program_Error;
end if;
+ elsif Nkind (Expr) = N_String_Literal then
+ if not Is_Array_Type (Etype (Expr)) then
+ Error_Msg_N
+ ("User-defined string literal not allowed as/within"
+ & "case choice", Expr);
+ else
+ declare
+ Char_Type : constant Entity_Id :=
+ Root_Type (Component_Type (Etype (Expr)));
+
+ -- If the component type is not a standard character
+ -- type then this string lit should have already been
+ -- transformed into an aggregate in
+ -- Resolve_String_Literal.
+ --
+ pragma Assert (Is_Standard_Character_Type (Char_Type));
+
+ Str : constant String_Id := Strval (Expr);
+ Strlen : constant Nat := String_Length (Str);
+ Char_Val : Uint;
+ begin
+ if not Unconstrained_Array_Case
+ and then Strlen /= Nat (Part_Id'Last)
+ then
+ Error_Msg_Uint_1 := UI_From_Int (Strlen);
+ Error_Msg_Uint_2 := UI_From_Int
+ (Int (Part_Id'Last));
+ Error_Msg_N
+ ("String literal length ^ does not match length" &
+ " of statically constrained case selector ^",
+ Expr);
+ return;
+ end if;
+
+ for Idx in 1 .. Strlen loop
+ Char_Val :=
+ UI_From_CC (Get_String_Char (Str, Idx));
+ Update_Result ((Low | High => Char_Val));
+ end loop;
+ end;
+ end if;
elsif Is_Discrete_Type (Etype (Expr)) then
- if Nkind (Expr) in N_Has_Entity and then
- Is_Type (Entity (Expr))
+ if Nkind (Expr) in N_Has_Entity
+ and then Present (Entity (Expr))
+ and then Is_Type (Entity (Expr))
then
declare
Low : constant Node_Id :=
@@ -1559,10 +1796,20 @@ package body Sem_Case is
pragma Assert (Compile_Time_Known_Value (Expr));
Update_Result ((Low | High => Expr_Value (Expr)));
end if;
+ elsif Nkind (Expr) in N_Has_Entity
+ and then Present (Entity (Expr))
+ and then Ekind (Entity (Expr)) = E_Constant
+ then
+ Traverse_Choice (Expression (Parent (Entity (Expr))));
+ elsif Nkind (Original_Node (Expr))
+ in N_Aggregate | N_String_Literal
+ then
+ Traverse_Choice (Original_Node (Expr));
else
Error_Msg_N
- ("non-aggregate case choice subexpression which is not"
- & " of a discrete type not implemented", Expr);
+ ("non-aggregate case choice (or subexpression thereof)"
+ & " that is not of a discrete type not implemented",
+ Expr);
end if;
end Traverse_Choice;
@@ -1572,8 +1819,26 @@ package body Sem_Case is
if Nkind (Choice) = N_Others_Choice then
return (Is_Others => True);
end if;
+
+ if Unconstrained_Array_Case then
+ -- Treat length like a discriminant
+ Update_Result ((Low | High =>
+ UI_From_Int (Array_Choice_Length (Choice))));
+ end if;
+
Traverse_Choice (Choice);
+ if Unconstrained_Array_Case then
+ -- This is somewhat tricky. Suppose we are casing on String,
+ -- the longest choice in the case statement is length 10, and
+ -- the choice we are looking at now is of length 6. We fill
+ -- in the trailing 4 slots here.
+ while Next_Part <= Part_Id'Last loop
+ Update_Result_For_Full_Coverage
+ (Comp_Type => Component_Type (Case_Expr_Type));
+ end loop;
+ end if;
+
-- Avoid returning uninitialized garbage in error case
if Next_Part /= Part_Id'Last + 1 then
pragma Assert (Serious_Errors_Detected > 0);
@@ -2098,6 +2363,12 @@ package body Sem_Case is
Result := Result * Value_Index_Base (Uint_Sets.Size (Set));
end loop;
return Result;
+ exception
+ when Constraint_Error =>
+ Error_Msg_N
+ ("Capacity exceeded in compiling case statement with"
+ & " composite selector type", Case_Statement);
+ raise;
end Value_Index_Count;
Max_Value_Index : constant Value_Index_Base := Value_Index_Count;
@@ -3014,12 +3285,20 @@ package body Sem_Case is
"an enumeration representation clause", N);
end if;
elsif Is_Array_Type (Subtyp) then
- pragma Assert (Is_Constrained (Subtyp));
-
if Number_Dimensions (Subtyp) /= 1 then
Error_Msg_N
("dimensionality of array type of case selector (or " &
"subcomponent thereof) is greater than 1", N);
+
+ elsif not Is_Constrained (Subtyp) then
+ if not Is_Static_Subtype
+ (Etype (First_Index (Subtyp)))
+ then
+ Error_Msg_N
+ ("Unconstrained array subtype of case selector" &
+ " has nonstatic index subtype", N);
+ end if;
+
elsif not Is_OK_Static_Range (First_Index (Subtyp)) then
Error_Msg_N
("array subtype of case selector (or " &
@@ -3077,10 +3356,6 @@ package body Sem_Case is
elsif Needs_Finalization (Subtyp) then
Error_Msg_N ("case selector type requires finalization", N);
- elsif Is_Array_Type (Subtyp) and not Is_Constrained (Subtyp) then
- Error_Msg_N
- ("case selector subtype is unconstrained array subtype", N);
-
else
Check_Component_Subtype (Subtyp);
end if;
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 1e7b93c..5b54e7d 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -4162,8 +4162,7 @@ package body Sem_Ch10 is
end if;
if Ekind (P_Name) = E_Generic_Package
- and then Nkind (Lib_Unit) not in N_Generic_Subprogram_Declaration
- | N_Generic_Package_Declaration
+ and then Nkind (Lib_Unit) not in N_Generic_Declaration
| N_Generic_Renaming_Declaration
then
Error_Msg_N
@@ -5610,9 +5609,8 @@ package body Sem_Ch10 is
-- demand, at the point of instantiation (see ch12).
procedure Load_Needed_Body
- (N : Node_Id;
- OK : out Boolean;
- Do_Analyze : Boolean := True)
+ (N : Node_Id;
+ OK : out Boolean)
is
Body_Name : Unit_Name_Type;
Unum : Unit_Number_Type;
@@ -5646,9 +5644,8 @@ package body Sem_Ch10 is
Write_Eol;
end if;
- if Do_Analyze then
- Semantics (Cunit (Unum));
- end if;
+ -- We always perform analyses
+ Semantics (Cunit (Unum));
end if;
OK := True;
@@ -5825,7 +5822,7 @@ package body Sem_Ch10 is
Set_Is_First_Subtype (Ent);
Set_Scope (Ent, Scop);
Set_Stored_Constraint (Ent, No_Elist);
- Init_Size_Align (Ent);
+ Reinit_Size_Align (Ent);
if From_Limited_With (Ent) then
Set_Private_Dependents (Ent, New_Elmt_List);
@@ -5865,7 +5862,7 @@ package body Sem_Ch10 is
Set_Is_Tagged_Type (CW_Typ);
Set_Materialize_Entity (CW_Typ, Materialize);
Set_Scope (CW_Typ, Scop);
- Init_Size_Align (CW_Typ);
+ Reinit_Size_Align (CW_Typ);
end if;
end Decorate_Type;
@@ -6195,9 +6192,7 @@ package body Sem_Ch10 is
("subprogram not allowed in `LIMITED WITH` clause", N);
return;
- when N_Generic_Package_Declaration
- | N_Generic_Subprogram_Declaration
- =>
+ when N_Generic_Declaration =>
Error_Msg_N ("generic not allowed in `LIMITED WITH` clause", N);
return;
diff --git a/gcc/ada/sem_ch10.ads b/gcc/ada/sem_ch10.ads
index fbaf3ca..ecf3151a5 100644
--- a/gcc/ada/sem_ch10.ads
+++ b/gcc/ada/sem_ch10.ads
@@ -59,16 +59,13 @@ package Sem_Ch10 is
-- reported on Error_Node (if present); otherwise no error is reported.
procedure Load_Needed_Body
- (N : Node_Id;
- OK : out Boolean;
- Do_Analyze : Boolean := True);
+ (N : Node_Id;
+ OK : out Boolean);
-- Load and analyze the body of a context unit that is generic, or that
-- contains generic units or inlined units. The body becomes part of the
-- semantic dependency set of the unit that needs it. The returned result
-- in OK is True if the load is successful, and False if the requested file
- -- cannot be found. If the flag Do_Analyze is false, the unit is loaded and
- -- parsed only. This allows a selective analysis in some inlining cases
- -- where a full analysis would lead so circularities in the back-end.
+ -- cannot be found.
procedure Remove_Context (N : Node_Id);
-- Removes the entities from the context clause of the given compilation
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 85c854f..e4cb7e3 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -2495,7 +2495,7 @@ package body Sem_Ch12 is
Mutate_Ekind (T, E_Enumeration_Subtype);
Set_Etype (T, Base);
Init_Size (T, 8);
- Init_Alignment (T);
+ Reinit_Alignment (T);
Set_Is_Generic_Type (T);
Set_Is_Constrained (T);
@@ -2524,7 +2524,7 @@ package body Sem_Ch12 is
Mutate_Ekind (Base, E_Enumeration_Type);
Set_Etype (Base, Base);
Init_Size (Base, 8);
- Init_Alignment (Base);
+ Reinit_Alignment (Base);
Set_Is_Generic_Type (Base);
Set_Scalar_Range (Base, Scalar_Range (T));
Set_Parent (Base, Parent (Def));
@@ -7112,8 +7112,8 @@ package body Sem_Ch12 is
Astype := First_Subtype (E);
end if;
- Set_Size_Info (E, (Astype));
- Set_RM_Size (E, RM_Size (Astype));
+ Set_Size_Info (E, (Astype));
+ Copy_RM_Size (To => E, From => Astype);
Set_First_Rep_Item (E, First_Rep_Item (Astype));
if Is_Discrete_Or_Fixed_Point_Type (E) then
@@ -13047,7 +13047,7 @@ package body Sem_Ch12 is
while Present (Index) loop
Num := Num + 1;
- Next_Index (Index);
+ Next (Index);
end loop;
return Num;
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 76859c5..c60dd97 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -26,6 +26,7 @@
with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
+with Contracts; use Contracts;
with Debug; use Debug;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
@@ -261,6 +262,19 @@ package body Sem_Ch13 is
-- Check legality of functions given in the Ada 2022 Stable_Properties
-- (or Stable_Properties'Class) aspect.
+ procedure Validate_Storage_Model_Type_Aspect
+ (Typ : Entity_Id; ASN : Node_Id);
+ -- Check legality and completeness of the aggregate associations given in
+ -- the Storage_Model_Type aspect associated with Typ.
+
+ procedure Resolve_Storage_Model_Type_Argument
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Addr_Type : in out Entity_Id;
+ Nam : Name_Id);
+ -- Resolve argument N to be of the proper kind (when a type or constant)
+ -- or to have the proper profile (when a subprogram).
+
procedure Resolve_Aspect_Stable_Properties
(Typ_Or_Subp : Entity_Id;
Expr : Node_Id;
@@ -860,9 +874,10 @@ package body Sem_Ch13 is
if Known_Alignment (Typ)
and then not Has_Alignment_Clause (Typ)
+ and then Present (Size)
and then Size mod (Alignment (Typ) * SSU) /= 0
then
- Init_Alignment (Typ);
+ Reinit_Alignment (Typ);
end if;
end Alignment_Check_For_Size_Change;
@@ -1455,9 +1470,17 @@ package body Sem_Ch13 is
-- Aspect Full_Access_Only must be analyzed last so that
-- aspects Volatile and Atomic, if any, are analyzed.
+ -- Skip creation of pragma Preelaborable_Initialization
+ -- in the case where the aspect has an expression,
+ -- because the pragma is only needed for setting flag
+ -- Known_To_Have_Preelab_Init, which is set by other
+ -- means following resolution of the aspect expression.
+
if A_Id not in Aspect_Export
| Aspect_Full_Access_Only
| Aspect_Import
+ and then (A_Id /= Aspect_Preelaborable_Initialization
+ or else not Present (Expression (ASN)))
then
Make_Pragma_From_Boolean_Aspect (ASN);
end if;
@@ -1507,6 +1530,32 @@ package body Sem_Ch13 is
when Aspect_Iterable =>
Validate_Iterable_Aspect (E, ASN);
+ when Aspect_Designated_Storage_Model =>
+ Analyze_And_Resolve (Expression (ASN));
+
+ if not Is_Entity_Name (Expression (ASN))
+ or else not Is_Object (Entity (Expression (ASN)))
+ or else
+ not Present (Find_Aspect (Etype (Expression (ASN)),
+ Aspect_Storage_Model_Type))
+ then
+ Error_Msg_N
+ ("must specify name of stand-alone object of type "
+ & "with aspect Storage_Model_Type",
+ Expression (ASN));
+
+ -- Set access type's Associated_Storage_Pool to denote
+ -- the Storage_Model_Type object given for the aspect
+ -- (even though that isn't actually an Ada storage pool).
+
+ else
+ Set_Associated_Storage_Pool
+ (E, Entity (Expression (ASN)));
+ end if;
+
+ when Aspect_Storage_Model_Type =>
+ Validate_Storage_Model_Type_Aspect (E, ASN);
+
when Aspect_Aggregate =>
null;
@@ -1876,6 +1925,11 @@ package body Sem_Ch13 is
-- expression is allowed. Includes checking that the expression
-- does not raise Constraint_Error.
+ function Directly_Specified
+ (Id : Entity_Id; A : Aspect_Id) return Boolean;
+ -- Returns True if the given aspect is directly (as opposed to
+ -- via any form of inheritance) specified for the given entity.
+
function Make_Aitem_Pragma
(Pragma_Argument_Associations : List_Id;
Pragma_Name : Name_Id) return Node_Id;
@@ -2769,6 +2823,18 @@ package body Sem_Ch13 is
end if;
end Check_Expr_Is_OK_Static_Expression;
+ ------------------------
+ -- Directly_Specified --
+ ------------------------
+
+ function Directly_Specified
+ (Id : Entity_Id; A : Aspect_Id) return Boolean
+ is
+ Aspect_Spec : constant Node_Id := Find_Aspect (Id, A);
+ begin
+ return Present (Aspect_Spec) and then Entity (Aspect_Spec) = Id;
+ end Directly_Specified;
+
-----------------------
-- Make_Aitem_Pragma --
-----------------------
@@ -2915,6 +2981,7 @@ package body Sem_Ch13 is
| Aspect_Async_Writers
| Aspect_Effective_Reads
| Aspect_Effective_Writes
+ | Aspect_Preelaborable_Initialization
then
Error_Msg_Name_1 := Nam;
@@ -2951,6 +3018,7 @@ package body Sem_Ch13 is
| Aspect_Async_Writers
| Aspect_Effective_Reads
| Aspect_Effective_Writes
+ | Aspect_Preelaborable_Initialization
then
Error_Msg_N
("aspect % not allowed for formal type declaration",
@@ -2962,7 +3030,15 @@ package body Sem_Ch13 is
-- Copy expression for later processing by the procedures
-- Check_Aspect_At_[Freeze_Point | End_Of_Declarations]
- Set_Entity (Id, New_Copy_Tree (Expr));
+ -- The expression may be a subprogram name, and can
+ -- be an operator name that appears as a string, but
+ -- requires its own analysis procedure (see sem_ch6).
+
+ if Nkind (Expr) = N_Operator_Symbol then
+ Set_Entity (Id, Expr);
+ else
+ Set_Entity (Id, New_Copy_Tree (Expr));
+ end if;
-- Set Delay_Required as appropriate to aspect
@@ -3028,10 +3104,11 @@ package body Sem_Ch13 is
if Delay_Required
- and then A_Id = Aspect_Stable_Properties
+ and then (A_Id = Aspect_Stable_Properties
+ or else A_Id = Aspect_Designated_Storage_Model
+ or else A_Id = Aspect_Storage_Model_Type)
-- ??? It seems like we should do this for all aspects, not
- -- just Stable_Properties, but that causes as-yet-undiagnosed
- -- regressions.
+ -- just these, but that causes as-yet-undiagnosed regressions.
then
Set_Has_Delayed_Aspects (E);
@@ -3332,6 +3409,15 @@ package body Sem_Ch13 is
("Predicate_Failure requires previous predicate" &
" specification", Aspect);
goto Continue;
+
+ elsif not (Directly_Specified (E, Aspect_Dynamic_Predicate)
+ or else Directly_Specified (E, Aspect_Static_Predicate)
+ or else Directly_Specified (E, Aspect_Predicate))
+ then
+ Error_Msg_N
+ ("Predicate_Failure requires accompanying" &
+ " noninherited predicate specification", Aspect);
+ goto Continue;
end if;
-- Construct the pragma
@@ -4322,6 +4408,44 @@ package body Sem_Ch13 is
Record_Rep_Item (E, Aspect);
goto Continue;
+ when Aspect_Designated_Storage_Model =>
+ if not Extensions_Allowed then
+ Error_Msg_N
+ ("aspect only allowed if extensions enabled",
+ Aspect);
+ Error_Msg_N
+ ("\unit must be compiled with -gnatX switch", Aspect);
+
+ elsif not Is_Type (E)
+ or else Ekind (E) /= E_Access_Type
+ then
+ Error_Msg_N
+ ("can only be specified for pool-specific access type",
+ Aspect);
+ end if;
+
+ Record_Rep_Item (E, Aspect);
+ goto Continue;
+
+ when Aspect_Storage_Model_Type =>
+ if not Extensions_Allowed then
+ Error_Msg_N
+ ("aspect only allowed if extensions enabled",
+ Aspect);
+ Error_Msg_N
+ ("\unit must be compiled with -gnatX switch", Aspect);
+
+ elsif not Is_Type (E)
+ or else not Is_Immutably_Limited_Type (E)
+ then
+ Error_Msg_N
+ ("can only be specified for immutably limited type",
+ Aspect);
+ end if;
+
+ Record_Rep_Item (E, Aspect);
+ goto Continue;
+
when Aspect_Integer_Literal
| Aspect_Real_Literal
| Aspect_String_Literal
@@ -4409,6 +4533,38 @@ package body Sem_Ch13 is
goto Continue;
end if;
+ -- Remember class-wide conditions; they will be merged
+ -- with inherited conditions.
+
+ if Class_Present (Aspect)
+ and then A_Id in Aspect_Pre | Aspect_Post
+ and then Is_Subprogram (E)
+ and then not Is_Ignored_Ghost_Entity (E)
+ then
+ if A_Id = Aspect_Pre then
+ if Is_Ignored (Aspect) then
+ Set_Ignored_Class_Preconditions (E,
+ New_Copy_Tree (Expr));
+ else
+ Set_Class_Preconditions (E, New_Copy_Tree (Expr));
+ end if;
+
+ -- Postconditions may split into separate aspects, and we
+ -- remember the expression before such split (i.e. when
+ -- the first postcondition is processed).
+
+ elsif No (Class_Postconditions (E))
+ and then No (Ignored_Class_Postconditions (E))
+ then
+ if Is_Ignored (Aspect) then
+ Set_Ignored_Class_Postconditions (E,
+ New_Copy_Tree (Expr));
+ else
+ Set_Class_Postconditions (E, New_Copy_Tree (Expr));
+ end if;
+ end if;
+ end if;
+
-- If the expressions is of the form A and then B, then
-- we generate separate Pre/Post aspects for the separate
-- clauses. Since we allow multiple pragmas, there is no
@@ -6621,7 +6777,7 @@ package body Sem_Ch13 is
elsif Duplicate_Clause then
null;
- elsif Align /= No_Uint then
+ elsif Present (Align) then
Set_Has_Alignment_Clause (U_Ent);
-- Tagged type case, check for attempt to set alignment to a
@@ -6711,7 +6867,7 @@ package body Sem_Ch13 is
elsif Rep_Item_Too_Early (Btype, N) then
null;
- elsif Csize /= No_Uint then
+ elsif Present (Csize) then
Check_Size (Expr, Ctyp, Csize, Biased);
-- For the biased case, build a declaration for a subtype that
@@ -6736,9 +6892,9 @@ package body Sem_Ch13 is
Analyze (Decl, Suppress => All_Checks);
Set_Has_Delayed_Freeze (New_Ctyp, False);
- Init_Esize (New_Ctyp);
+ Reinit_Esize (New_Ctyp);
Set_RM_Size (New_Ctyp, Csize);
- Init_Alignment (New_Ctyp);
+ Reinit_Alignment (New_Ctyp);
Set_Is_Itype (New_Ctyp, True);
Set_Associated_Node_For_Itype (New_Ctyp, U_Ent);
@@ -7051,7 +7207,7 @@ package body Sem_Ch13 is
elsif Duplicate_Clause then
null;
- elsif Radix /= No_Uint then
+ elsif Present (Radix) then
Set_Has_Machine_Radix_Clause (U_Ent);
Set_Has_Non_Standard_Rep (Base_Type (U_Ent));
@@ -7089,7 +7245,7 @@ package body Sem_Ch13 is
else
Check_Size (Expr, U_Ent, Size, Biased);
- if Size <= 0 then
+ if No (Size) or else Size <= 0 then
Error_Msg_N ("Object_Size must be positive", Expr);
elsif Is_Scalar_Type (U_Ent) then
@@ -7264,7 +7420,7 @@ package body Sem_Ch13 is
Error_Msg_N
(Attr_Name & " cannot be given for unconstrained array", Nam);
- elsif Size /= No_Uint then
+ elsif Present (Size) then
declare
Etyp : constant Entity_Id :=
(if Is_Type (U_Ent) then U_Ent else Etype (U_Ent));
@@ -7312,13 +7468,14 @@ package body Sem_Ch13 is
if Is_First_Subtype (U_Ent) then
if Is_Elementary_Type (U_Ent) then
if Size <= System_Storage_Unit then
- Init_Esize (U_Ent, System_Storage_Unit);
+ Set_Esize
+ (U_Ent, UI_From_Int (System_Storage_Unit));
elsif Size <= 16 then
- Init_Esize (U_Ent, 16);
+ Set_Esize (U_Ent, Uint_16);
elsif Size <= 32 then
- Init_Esize (U_Ent, 32);
+ Set_Esize (U_Ent, Uint_32);
else
- Set_Esize (U_Ent, (Size + 63) / 64 * 64);
+ Set_Esize (U_Ent, (Size + 63) / 64 * 64);
end if;
Alignment_Check_For_Size_Change
@@ -7788,11 +7945,16 @@ package body Sem_Ch13 is
null;
elsif Is_Elementary_Type (U_Ent) then
- if Size /= System_Storage_Unit
- and then Size /= System_Storage_Unit * 2
- and then Size /= System_Storage_Unit * 3
- and then Size /= System_Storage_Unit * 4
- and then Size /= System_Storage_Unit * 8
+ -- Size will be empty if we already detected an error
+ -- (e.g. Expr is of the wrong type); we might as well
+ -- give the useful hint below even in that case.
+
+ if No (Size) or else
+ (Size /= System_Storage_Unit
+ and then Size /= System_Storage_Unit * 2
+ and then Size /= System_Storage_Unit * 3
+ and then Size /= System_Storage_Unit * 4
+ and then Size /= System_Storage_Unit * 8)
then
Error_Msg_N
("stream size for elementary type must be 8, 16, 24, " &
@@ -8095,7 +8257,7 @@ package body Sem_Ch13 is
-- the list. The final checks for completeness and ordering are
-- skipped in this case.
- if Val = No_Uint then
+ if No (Val) then
Err := True;
elsif Val < Lo or else Hi < Val then
@@ -8174,7 +8336,7 @@ package body Sem_Ch13 is
Expr := Expression (Assoc);
Val := Static_Integer (Expr);
- if Val = No_Uint then
+ if No (Val) then
Err := True;
elsif Val < Lo or else Hi < Val then
@@ -8209,12 +8371,12 @@ package body Sem_Ch13 is
else
Val := Enumeration_Rep (Elit);
- if Min = No_Uint then
+ if No (Min) then
Min := Val;
end if;
- if Val /= No_Uint then
- if Max /= No_Uint and then Val <= Max then
+ if Present (Val) then
+ if Present (Max) and then Val <= Max then
Error_Msg_NE
("enumeration value for& not ordered!",
Enumeration_Rep_Expr (Elit), Elit);
@@ -8499,9 +8661,9 @@ package body Sem_Ch13 is
Fbit := Static_Integer (First_Bit (CC));
Lbit := Static_Integer (Last_Bit (CC));
- if Posit /= No_Uint
- and then Fbit /= No_Uint
- and then Lbit /= No_Uint
+ if Present (Posit)
+ and then Present (Fbit)
+ and then Present (Lbit)
then
if Posit < 0 then
Error_Msg_N ("position cannot be negative", Position (CC));
@@ -8642,9 +8804,6 @@ package body Sem_Ch13 is
Set_Normalized_First_Bit (Comp, Fbit mod SSU);
Set_Normalized_Position (Comp, Fbit / SSU);
- Set_Normalized_Position_Max
- (Comp, Normalized_Position (Comp));
-
if Warn_On_Overridden_Size
and then Has_Size_Clause (Etype (Comp))
and then RM_Size (Etype (Comp)) /= Esize (Comp)
@@ -8676,9 +8835,6 @@ package body Sem_Ch13 is
Set_Normalized_First_Bit (Ocomp, Fbit mod SSU);
Set_Normalized_Position (Ocomp, Fbit / SSU);
- Set_Normalized_Position_Max
- (Ocomp, Normalized_Position (Ocomp));
-
-- Note: we don't use Set_Biased here, because we
-- already gave a warning above if needed, and we
-- would get a duplicate for the same name here.
@@ -10067,7 +10223,10 @@ package body Sem_Ch13 is
-- If the type is private, check whether full view has inherited
-- predicates.
- if Is_Private_Type (Typ) and then No (Ritem) then
+ if Is_Private_Type (Typ)
+ and then No (Ritem)
+ and then Present (Full_View (Typ))
+ then
Ritem := First_Rep_Item (Full_View (Typ));
end if;
@@ -10155,6 +10314,9 @@ package body Sem_Ch13 is
or else
(Is_Itype (Typ)
and then not Comes_From_Source (Typ)
+ and then Ekind (Typ) in E_Array_Subtype
+ | E_Record_Subtype
+ | E_Record_Subtype_With_Private
and then Present (Predicated_Parent (Typ)))
then
return;
@@ -11145,6 +11307,34 @@ package body Sem_Ch13 is
-- Here is the list of aspects that don't require delay analysis
+ when Aspect_Designated_Storage_Model =>
+ return;
+
+ when Aspect_Storage_Model_Type =>
+ T := Entity (ASN);
+
+ declare
+ Assoc : Node_Id;
+ Expr : Node_Id;
+ Addr_Type : Entity_Id := Empty;
+
+ begin
+ Assoc := First (Component_Associations (Expression (ASN)));
+ while Present (Assoc) loop
+ Expr := Expression (Assoc);
+ Analyze (Expr);
+
+ if not Error_Posted (Expr) then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, T, Addr_Type, Chars (First (Choices (Assoc))));
+ end if;
+
+ Next (Assoc);
+ end loop;
+ end;
+
+ return;
+
when Aspect_Abstract_State
| Aspect_Annotate
| Aspect_Async_Readers
@@ -11872,9 +12062,23 @@ package body Sem_Ch13 is
--------
function Lt (Op1, Op2 : Natural) return Boolean is
+ K1 : constant Boolean :=
+ Known_Component_Bit_Offset (Comps (Op1));
+ K2 : constant Boolean :=
+ Known_Component_Bit_Offset (Comps (Op2));
+ -- Record representation clauses can be incomplete, so the
+ -- Component_Bit_Offsets can be unknown.
begin
- return Component_Bit_Offset (Comps (Op1))
- < Component_Bit_Offset (Comps (Op2));
+ if K1 then
+ if K2 then
+ return Component_Bit_Offset (Comps (Op1))
+ < Component_Bit_Offset (Comps (Op2));
+ else
+ return True;
+ end if;
+ else
+ return K2;
+ end if;
end Lt;
----------
@@ -11938,7 +12142,7 @@ package body Sem_Ch13 is
begin
-- Skip components with unknown offsets
- if CBO /= No_Uint and then CBO >= 0 then
+ if Present (CBO) and then CBO >= 0 then
Error_Msg_Uint_1 := CBO - Nbit;
if Warn and then Error_Msg_Uint_1 > 0 then
@@ -12053,7 +12257,7 @@ package body Sem_Ch13 is
Pcomp := First_Entity (Tagged_Parent);
while Present (Pcomp) loop
if Ekind (Pcomp) in E_Discriminant | E_Component then
- if Component_Bit_Offset (Pcomp) /= No_Uint
+ if Present (Component_Bit_Offset (Pcomp))
and then Known_Static_Esize (Pcomp)
then
Parent_Last_Bit :=
@@ -12094,8 +12298,7 @@ package body Sem_Ch13 is
Set_Component_Bit_Offset (Fent, Uint_0);
Set_Normalized_Position (Fent, Uint_0);
Set_Normalized_First_Bit (Fent, Uint_0);
- Set_Normalized_Position_Max (Fent, Uint_0);
- Init_Esize (Fent, System_Address_Size);
+ Set_Esize (Fent, UI_From_Int (System_Address_Size));
Set_Component_Clause (Fent,
Make_Component_Clause (Loc,
@@ -12312,8 +12515,8 @@ package body Sem_Ch13 is
end if;
-- Outer level of record definition, check discriminants
- -- but be careful not to flag a non-girder discriminant
- -- and the girder discriminant it renames as overlapping.
+ -- but be careful not to flag a non-stored discriminant
+ -- and the stored discriminant it renames as overlapping.
if Nkind (Clist) in N_Full_Type_Declaration
| N_Private_Type_Declaration
@@ -13113,6 +13316,13 @@ package body Sem_Ch13 is
end if;
end Check_Variant_Part;
end if;
+
+ if not In_Generic_Scope (E)
+ and then Ekind (E) = E_Record_Type
+ and then Is_Tagged_Type (E)
+ then
+ Process_Class_Conditions_At_Freeze_Point (E);
+ end if;
end Freeze_Entity_Checks;
-------------------------
@@ -13123,7 +13333,7 @@ package body Sem_Ch13 is
Align : constant Uint := Static_Integer (Expr);
begin
- if Align = No_Uint then
+ if No (Align) then
return No_Uint;
elsif Align < 0 then
@@ -13700,6 +13910,7 @@ package body Sem_Ch13 is
| Attribute_Iterable
| Attribute_Iterator_Element
| Attribute_Output
+ | Attribute_Put_Image
| Attribute_Read
| Attribute_Variable_Indexing
| Attribute_Write;
@@ -13979,7 +14190,7 @@ package body Sem_Ch13 is
function Minimum_Size
(T : Entity_Id;
- Biased : Boolean := False) return Nat
+ Biased : Boolean := False) return Int
is
Lo : Uint := No_Uint;
Hi : Uint := No_Uint;
@@ -13993,17 +14204,17 @@ package body Sem_Ch13 is
R_Typ : constant Entity_Id := Root_Type (T);
begin
- -- If bad type, return 0
+ -- Bad type
if T = Any_Type then
- return 0;
+ return Unknown_Minimum_Size;
- -- For generic types, just return zero. There cannot be any legitimate
- -- need to know such a size, but this routine may be called with a
- -- generic type as part of normal processing.
+ -- For generic types, just return unknown. There cannot be any
+ -- legitimate need to know such a size, but this routine may be
+ -- called with a generic type as part of normal processing.
elsif Is_Generic_Type (R_Typ) or else R_Typ = Any_Type then
- return 0;
+ return Unknown_Minimum_Size;
-- Access types (cannot have size smaller than System.Address)
@@ -14026,7 +14237,7 @@ package body Sem_Ch13 is
Ancest := T;
loop
if Ancest = Any_Type or else Etype (Ancest) = Any_Type then
- return 0;
+ return Unknown_Minimum_Size;
end if;
if not LoSet then
@@ -14051,7 +14262,7 @@ package body Sem_Ch13 is
Ancest := Base_Type (T);
if Is_Generic_Type (Ancest) then
- return 0;
+ return Unknown_Minimum_Size;
end if;
end if;
end loop;
@@ -14072,7 +14283,7 @@ package body Sem_Ch13 is
Ancest := T;
loop
if Ancest = Any_Type or else Etype (Ancest) = Any_Type then
- return 0;
+ return Unknown_Minimum_Size;
end if;
-- Note: In the following two tests for LoSet and HiSet, it may
@@ -14112,7 +14323,7 @@ package body Sem_Ch13 is
Ancest := Base_Type (T);
if Is_Generic_Type (Ancest) then
- return 0;
+ return Unknown_Minimum_Size;
end if;
end if;
end loop;
@@ -14142,7 +14353,7 @@ package body Sem_Ch13 is
-- type case, since that's the odd case that came up. Probably we should
-- also do this in the fixed-point case, but doing so causes peculiar
-- gigi failures, and it is not worth worrying about this incredibly
- -- marginal case (explicit null-range fixed-point type declarations)???
+ -- marginal case (explicit null-range fixed-point type declarations).
if Lo > Hi and then Is_Discrete_Type (T) then
S := 0;
@@ -15681,18 +15892,17 @@ package body Sem_Ch13 is
------------------------------
procedure Resolve_Aspect_Aggregate
- (Typ : Entity_Id;
+ (Typ : Entity_Id;
Expr : Node_Id)
is
+ function Valid_Empty (E : Entity_Id) return Boolean;
+ function Valid_Add_Named (E : Entity_Id) return Boolean;
+ function Valid_Add_Unnamed (E : Entity_Id) return Boolean;
+ function Valid_New_Indexed (E : Entity_Id) return Boolean;
+ function Valid_Assign_Indexed (E : Entity_Id) return Boolean;
-- Predicates that establish the legality of each possible operation in
-- an Aggregate aspect.
- function Valid_Empty (E : Entity_Id) return Boolean;
- function Valid_Add_Named (E : Entity_Id) return Boolean;
- function Valid_Add_Unnamed (E : Entity_Id) return Boolean;
- function Valid_New_Indexed (E : Entity_Id) return Boolean;
- function Valid_Assign_Indexed (E : Entity_Id) return Boolean;
-
generic
with function Pred (Id : Node_Id) return Boolean;
procedure Resolve_Operation (Subp_Id : Node_Id);
@@ -15715,7 +15925,7 @@ package body Sem_Ch13 is
end Valid_Assign_Indexed;
-----------------
- -- Valid_Emoty --
+ -- Valid_Empty --
-----------------
function Valid_Empty (E : Entity_Id) return Boolean is
@@ -15740,7 +15950,7 @@ package body Sem_Ch13 is
-- Valid_Add_Named --
---------------------
- function Valid_Add_Named (E : Entity_Id) return Boolean is
+ function Valid_Add_Named (E : Entity_Id) return Boolean is
F2, F3 : Entity_Id;
begin
if Ekind (E) = E_Procedure
@@ -15839,6 +16049,9 @@ package body Sem_Ch13 is
procedure Resolve_Assign_Indexed
is new Resolve_Operation
(Valid_Assign_Indexed);
+
+ -- Start of processing for Resolve_Aspect_Aggregate
+
begin
Assoc := First (Component_Associations (Expr));
@@ -16092,6 +16305,334 @@ package body Sem_Ch13 is
Set_Analyzed (Expr);
end Resolve_Aspect_Stable_Properties;
+ -----------------------------------------
+ -- Resolve_Storage_Model_Type_Argument --
+ -----------------------------------------
+
+ procedure Resolve_Storage_Model_Type_Argument
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Addr_Type : in out Entity_Id;
+ Nam : Name_Id)
+ is
+
+ type Formal_Profile is record
+ Subt : Entity_Id;
+ Mode : Formal_Kind;
+ end record;
+
+ type Formal_Profiles is array (Positive range <>) of Formal_Profile;
+
+ function Aspect_Argument_Profile_Matches
+ (Subp : Entity_Id;
+ Profiles : Formal_Profiles;
+ Result_Subt : Entity_Id;
+ Err_On_Mismatch : Boolean) return Boolean;
+ -- Checks that the formal parameters of subprogram Subp conform to the
+ -- subtypes and modes specified by Profiles, as well as to the result
+ -- subtype Result_Subt when that is nonempty.
+
+ function Aspect_Argument_Profile_Matches
+ (Subp : Entity_Id;
+ Profiles : Formal_Profiles;
+ Result_Subt : Entity_Id;
+ Err_On_Mismatch : Boolean) return Boolean
+ is
+
+ procedure Report_Argument_Error
+ (Msg : String;
+ Formal : Entity_Id := Empty;
+ Subt : Entity_Id := Empty);
+ -- If Err_On_Mismatch is True, reports an argument error given by Msg
+ -- associated with Formal and/or Subt.
+
+ procedure Report_Argument_Error
+ (Msg : String;
+ Formal : Entity_Id := Empty;
+ Subt : Entity_Id := Empty)
+ is
+ begin
+ if Err_On_Mismatch then
+ if Present (Formal) then
+ if Present (Subt) then
+ Error_Msg_Node_2 := Subt;
+ end if;
+ Error_Msg_NE (Msg, N, Formal);
+
+ elsif Present (Subt) then
+ Error_Msg_NE (Msg, N, Subt);
+
+ else
+ Error_Msg_N (Msg, N);
+ end if;
+ end if;
+ end Report_Argument_Error;
+
+ -- Local variables
+
+ Formal : Entity_Id := First_Formal (Subp);
+ Is_Error : Boolean := False;
+
+ -- Start of processing for Aspect_Argument_Profile_Matches
+
+ begin
+ for FP of Profiles loop
+ if not Present (Formal) then
+ Is_Error := True;
+ Report_Argument_Error ("missing formal of }", Subt => FP.Subt);
+ exit;
+
+ elsif not Subtypes_Statically_Match
+ (Etype (Formal), FP.Subt)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("formal& must be of subtype&",
+ Formal => Formal, Subt => FP.Subt);
+ exit;
+
+ elsif Ekind (Formal) /= FP.Mode then
+ Is_Error := True;
+ Report_Argument_Error
+ ("formal& has wrong mode", Formal => Formal);
+ exit;
+ end if;
+
+ Formal := Next_Formal (Formal);
+ end loop;
+
+ if not Is_Error
+ and then Present (Formal)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("too many formals for subprogram in aspect");
+ end if;
+
+ if not Is_Error
+ and then Present (Result_Subt)
+ and then not Subtypes_Statically_Match (Etype (Subp), Result_Subt)
+ then
+ Is_Error := True;
+ Report_Argument_Error
+ ("subprogram must have result}", Subt => Result_Subt);
+ end if;
+
+ return not Is_Error;
+ end Aspect_Argument_Profile_Matches;
+
+ -- Local variables
+
+ Ent : Entity_Id;
+
+ Storage_Count_Type : constant Entity_Id := RTE (RE_Storage_Count);
+ System_Address_Type : constant Entity_Id := RTE (RE_Address);
+
+ -- Start of processing for Resolve_Storage_Model_Type_Argument
+
+ begin
+ if Nam = Name_Address_Type then
+ if not Is_Entity_Name (N)
+ or else not Is_Type (Entity (N))
+ or else (Root_Type (Entity (N)) /= System_Address_Type
+ and then not Is_Integer_Type (Entity (N)))
+ then
+ Error_Msg_N ("named entity must be a descendant of System.Address "
+ & "or an integer type", N);
+ end if;
+
+ Addr_Type := Entity (N);
+
+ return;
+
+ elsif not Present (Addr_Type) then
+ Error_Msg_N ("argument association for Address_Type missing; "
+ & "must be specified as first aspect argument", N);
+ return;
+
+ elsif Nam = Name_Null_Address then
+ if not Is_Entity_Name (N)
+ or else not Is_Constant_Object (Entity (N))
+ or else
+ not Subtypes_Statically_Match (Etype (Entity (N)), Addr_Type)
+ then
+ Error_Msg_NE
+ ("named entity must be constant of subtype}", N, Addr_Type);
+ end if;
+
+ return;
+
+ elsif not Is_Overloaded (N) then
+ if not Is_Entity_Name (N)
+ or else Ekind (Entity (N)) not in E_Function | E_Procedure
+ or else Scope (Entity (N)) /= Scope (Typ)
+ then
+ Error_Msg_N ("argument must be local subprogram name", N);
+ return;
+ end if;
+
+ Ent := Entity (N);
+
+ if Nam = Name_Allocate then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_Out_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Allocate operation", N);
+ end if;
+
+ elsif Nam = Name_Deallocate then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Deallocate operation", N);
+ end if;
+
+ elsif Nam = Name_Copy_From then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Copy_From operation", N);
+ end if;
+
+ elsif Nam = Name_Copy_To then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Copy_To operation", N);
+ end if;
+
+ elsif Nam = Name_Storage_Size then
+ if not Aspect_Argument_Profile_Matches
+ (Ent,
+ Profiles => (1 => (Typ, E_In_Parameter)),
+ Result_Subt => Storage_Count_Type,
+ Err_On_Mismatch => True)
+ then
+ Error_Msg_N ("no match for Storage_Size operation", N);
+ end if;
+
+ else
+ null; -- Error will be caught in Validate_Storage_Model_Type_Aspect
+ end if;
+
+ else
+ -- Overloaded case: find subprogram with proper signature
+
+ declare
+ I : Interp_Index;
+ It : Interp;
+ Found_Match : Boolean := False;
+
+ begin
+ Get_First_Interp (N, I, It);
+ while Present (It.Typ) loop
+ if Ekind (It.Nam) in E_Function | E_Procedure
+ and then Scope (It.Nam) = Scope (Typ)
+ then
+ if Nam = Name_Allocate then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_Out_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Deallocate then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Copy_From then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Copy_To then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles =>
+ ((Typ, E_In_Out_Parameter),
+ (Addr_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter),
+ (System_Address_Type, E_In_Parameter),
+ (Storage_Count_Type, E_In_Parameter)),
+ Result_Subt => Empty,
+ Err_On_Mismatch => False);
+
+ elsif Nam = Name_Storage_Size then
+ Found_Match :=
+ Aspect_Argument_Profile_Matches
+ (It.Nam,
+ Profiles => (1 => (Typ, E_In_Parameter)),
+ Result_Subt => Storage_Count_Type,
+ Err_On_Mismatch => False);
+ end if;
+
+ if Found_Match then
+ Set_Entity (N, It.Nam);
+ exit;
+ end if;
+ end if;
+
+ Get_Next_Interp (I, It);
+ end loop;
+
+ if not Found_Match then
+ Error_Msg_N
+ ("no match found for Storage_Model_Type operation", N);
+ end if;
+ end;
+ end if;
+ end Resolve_Storage_Model_Type_Argument;
+
----------------
-- Set_Biased --
----------------
@@ -16120,10 +16661,10 @@ package body Sem_Ch13 is
procedure Set_Enum_Esize (T : Entity_Id) is
Lo : Uint;
Hi : Uint;
- Sz : Nat;
+ Sz : Unat;
begin
- Init_Alignment (T);
+ Reinit_Alignment (T);
-- Find the minimum standard size (8,16,32,64,128) that fits
@@ -16131,37 +16672,38 @@ package body Sem_Ch13 is
Hi := Enumeration_Rep (Entity (Type_High_Bound (T)));
if Lo < 0 then
- if Lo >= -Uint_2**07 and then Hi < Uint_2**07 then
- Sz := Standard_Character_Size; -- May be > 8 on some targets
+ if Lo >= -Uint_2**7 and then Hi < Uint_2**7 then
+ Sz := UI_From_Int (Standard_Character_Size);
+ -- Might be > 8 on some targets
elsif Lo >= -Uint_2**15 and then Hi < Uint_2**15 then
- Sz := 16;
+ Sz := Uint_16;
elsif Lo >= -Uint_2**31 and then Hi < Uint_2**31 then
- Sz := 32;
+ Sz := Uint_32;
elsif Lo >= -Uint_2**63 and then Hi < Uint_2**63 then
- Sz := 64;
+ Sz := Uint_64;
else pragma Assert (Lo >= -Uint_2**127 and then Hi < Uint_2**127);
- Sz := 128;
+ Sz := Uint_128;
end if;
else
- if Hi < Uint_2**08 then
- Sz := Standard_Character_Size; -- May be > 8 on some targets
+ if Hi < Uint_2**8 then
+ Sz := UI_From_Int (Standard_Character_Size);
elsif Hi < Uint_2**16 then
- Sz := 16;
+ Sz := Uint_16;
elsif Hi < Uint_2**32 then
- Sz := 32;
+ Sz := Uint_32;
elsif Hi < Uint_2**64 then
- Sz := 64;
+ Sz := Uint_64;
else pragma Assert (Hi < Uint_2**128);
- Sz := 128;
+ Sz := Uint_128;
end if;
end if;
@@ -16177,9 +16719,9 @@ package body Sem_Ch13 is
and then not Target_Short_Enums
then
- Init_Esize (T, Standard_Integer_Size);
+ Set_Esize (T, UI_From_Int (Standard_Integer_Size));
else
- Init_Esize (T, Sz);
+ Set_Esize (T, Sz);
end if;
end Set_Enum_Esize;
@@ -16262,7 +16804,7 @@ package body Sem_Ch13 is
elsif Nkind (N) = N_Selected_Component then
Off := Component_Bit_Offset (Entity (Selector_Name (N)));
- if Off /= No_Uint and then Off >= Uint_0 then
+ if Present (Off) and then Off >= Uint_0 then
Val := Val + Off;
N := Prefix (N);
else
@@ -16271,7 +16813,7 @@ package body Sem_Ch13 is
elsif Nkind (N) = N_Indexed_Component then
Off := Indexed_Component_Bit_Offset (N);
- if Off /= No_Uint then
+ if Present (Off) then
Val := Val + Off;
N := Prefix (N);
else
@@ -16319,7 +16861,8 @@ package body Sem_Ch13 is
if Present (ACCR.Y) then
Y_Alignment := Alignment (ACCR.Y);
- Y_Size := Esize (ACCR.Y);
+ Y_Size :=
+ (if Known_Esize (ACCR.Y) then Esize (ACCR.Y) else Uint_0);
end if;
if ACCR.Off
@@ -16567,7 +17110,15 @@ package body Sem_Ch13 is
end if;
if not Overloaded and then not Present (Entity (Func_Name)) then
- Analyze (Func_Name);
+ -- The aspect is specified by a subprogram name, which
+ -- may be an operator name given originally by a string.
+
+ if Is_Operator_Name (Chars (Func_Name)) then
+ Analyze_Operator_Symbol (Func_Name);
+ else
+ Analyze (Func_Name);
+ end if;
+
Overloaded := Is_Overloaded (Func_Name);
end if;
@@ -16664,6 +17215,116 @@ package body Sem_Ch13 is
end if;
end Validate_Literal_Aspect;
+ ----------------------------------------
+ -- Validate_Storage_Model_Type_Aspect --
+ ----------------------------------------
+
+ procedure Validate_Storage_Model_Type_Aspect
+ (Typ : Entity_Id; ASN : Node_Id)
+ is
+ Assoc : Node_Id;
+ Choice : Entity_Id;
+ Expr : Node_Id;
+
+ Address_Type_Id : Entity_Id := Empty;
+ Null_Address_Id : Entity_Id := Empty;
+ Allocate_Id : Entity_Id := Empty;
+ Deallocate_Id : Entity_Id := Empty;
+ Copy_From_Id : Entity_Id := Empty;
+ Copy_To_Id : Entity_Id := Empty;
+ Storage_Size_Id : Entity_Id := Empty;
+
+ begin
+ -- Each expression must resolve to an entity of the right kind or proper
+ -- profile.
+
+ Assoc := First (Component_Associations (Expression (ASN)));
+ while Present (Assoc) loop
+ Expr := Expression (Assoc);
+ Analyze (Expr);
+
+ Choice := First (Choices (Assoc));
+
+ if Nkind (Choice) /= N_Identifier or else Present (Next (Choice)) then
+ Error_Msg_N ("illegal name in association", Choice);
+
+ elsif Chars (Choice) = Name_Address_Type then
+ if Assoc /= First (Component_Associations (Expression (ASN))) then
+ Error_Msg_N ("Address_Type must be first association", Choice);
+ end if;
+
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Address_Type);
+ Address_Type_Id := Entity (Expr);
+
+ -- Shouldn't we check for duplicates of the same subaspect name,
+ -- and issue an error in such cases???
+
+ elsif not Present (Address_Type_Id) then
+ Error_Msg_N
+ ("Address_Type missing, must be first association", Choice);
+
+ elsif Chars (Choice) = Name_Null_Address then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Null_Address);
+ Null_Address_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Allocate then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Allocate);
+ Allocate_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Deallocate then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Deallocate);
+ Deallocate_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Copy_From then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Copy_From);
+ Copy_From_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Copy_To then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Copy_To);
+ Copy_To_Id := Entity (Expr);
+
+ elsif Chars (Choice) = Name_Storage_Size then
+ Resolve_Storage_Model_Type_Argument
+ (Expr, Typ, Address_Type_Id, Name_Storage_Size);
+ Storage_Size_Id := Entity (Expr);
+
+ else
+ Error_Msg_N
+ ("invalid name for Storage_Model_Type argument", Choice);
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ if No (Address_Type_Id) then
+ Error_Msg_N ("match for Address_Type not found", ASN);
+
+ elsif No (Null_Address_Id) then
+ Error_Msg_N ("match for Null_Address primitive not found", ASN);
+
+ elsif No (Allocate_Id) then
+ Error_Msg_N ("match for Allocate primitive not found", ASN);
+
+ elsif No (Deallocate_Id) then
+ Error_Msg_N ("match for Deallocate primitive not found", ASN);
+
+ elsif No (Copy_From_Id) then
+ Error_Msg_N ("match for Copy_From primitive not found", ASN);
+
+ elsif No (Copy_To_Id) then
+ Error_Msg_N ("match for Copy_To primitive not found", ASN);
+
+ elsif No (Storage_Size_Id) then
+ Error_Msg_N ("match for Storage_Size primitive not found", ASN);
+ end if;
+ end Validate_Storage_Model_Type_Aspect;
+
-----------------------------------
-- Validate_Unchecked_Conversion --
-----------------------------------
@@ -16674,8 +17335,32 @@ package body Sem_Ch13 is
is
Source : Entity_Id;
Target : Entity_Id;
+
+ procedure Warn_Nonportable (RE : RE_Id);
+ -- Warn if either source or target of the conversion is a predefined
+ -- private type, whose representation might differ between releases and
+ -- targets of the compiler.
+
+ ----------------------
+ -- Warn_Nonportable --
+ ----------------------
+
+ procedure Warn_Nonportable (RE : RE_Id) is
+ begin
+ if Is_RTE (Source, RE) or else Is_RTE (Target, RE) then
+ pragma Assert (Is_Private_Type (RTE (RE)));
+ Error_Msg_NE
+ ("?z?representation of & values may change between "
+ & "'G'N'A'T versions", N, RTE (RE));
+ end if;
+ end Warn_Nonportable;
+
+ -- Local variables
+
Vnode : Node_Id;
+ -- Start of processing for Validate_Unchecked_Conversion
+
begin
-- Obtain source and target types. Note that we call Ancestor_Subtype
-- here because the processing for generic instantiation always makes
@@ -16692,6 +17377,18 @@ package body Sem_Ch13 is
return;
end if;
+ -- Warn if one of the operands is a private type declared in
+ -- Ada.Calendar or Ada.Real_Time. Do not emit a warning when compiling
+ -- GNAT-related sources.
+
+ if Warn_On_Unchecked_Conversion
+ and then not In_Predefined_Unit (N)
+ then
+ Warn_Nonportable (RO_CA_Time);
+ Warn_Nonportable (RO_RT_Time);
+ Warn_Nonportable (RE_Time_Span);
+ end if;
+
-- If we are dealing with private types, then do the check on their
-- fully declared counterparts if the full declarations have been
-- encountered (they don't have to be visible, but they must exist).
@@ -16738,32 +17435,6 @@ package body Sem_Ch13 is
end if;
end if;
- -- Warn if one of the operands is Ada.Calendar.Time. Do not emit a
- -- warning when compiling GNAT-related sources.
-
- if Warn_On_Unchecked_Conversion
- and then not In_Predefined_Unit (N)
- and then RTU_Loaded (Ada_Calendar)
- and then (Chars (Source) = Name_Time
- or else
- Chars (Target) = Name_Time)
- then
- -- If Ada.Calendar is loaded and the name of one of the operands is
- -- Time, there is a good chance that this is Ada.Calendar.Time.
-
- declare
- Calendar_Time : constant Entity_Id := Full_View (RTE (RO_CA_Time));
- begin
- pragma Assert (Present (Calendar_Time));
-
- if Source = Calendar_Time or else Target = Calendar_Time then
- Error_Msg_N
- ("?z?representation of 'Time values may change between "
- & "'G'N'A'T versions", N);
- end if;
- end;
- end if;
-
-- Make entry in unchecked conversion table for later processing by
-- Validate_Unchecked_Conversions, which will check sizes and alignments
-- (using values set by the back end where possible). This is only done
diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads
index 3b21484..0d3b041 100644
--- a/gcc/ada/sem_ch13.ads
+++ b/gcc/ada/sem_ch13.ads
@@ -81,9 +81,11 @@ package Sem_Ch13 is
-- the setting of the RM_Size field is not affected. This routine also
-- initializes the alignment field to zero.
+ Unknown_Minimum_Size : constant Nonzero_Int := -1;
+
function Minimum_Size
(T : Entity_Id;
- Biased : Boolean := False) return Nat;
+ Biased : Boolean := False) return Int;
-- Given an elementary type, determines the minimum number of bits required
-- to represent all values of the type. This function may not be called
-- with any other types. If the flag Biased is set True, then the minimum
@@ -96,7 +98,7 @@ package Sem_Ch13 is
-- the type is already biased, then Minimum_Size returns the biased size,
-- regardless of the setting of Biased. Also, fixed-point types are never
-- biased in the current implementation. If the size is not known at
- -- compile time, this function returns 0.
+ -- compile time, this function returns Unknown_Minimum_Size.
procedure Check_Constant_Address_Clause (Expr : Node_Id; U_Ent : Entity_Id);
-- Expr is an expression for an address clause. This procedure checks
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index e9b4456..57db637 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -696,8 +696,8 @@ package body Sem_Ch3 is
-- copy will leave the references to the ancestor discriminants unchanged
-- in the declaration tree and they need to be fixed up. If the derived
-- type has a known discriminant part, then the remapping done during the
- -- copy will only create references to the girder discriminants and they
- -- need to be replaced with references to the non-girder discriminants.
+ -- copy will only create references to the stored discriminants and they
+ -- need to be replaced with references to the non-stored discriminants.
procedure Set_Fixed_Range
(E : Entity_Id;
@@ -1299,7 +1299,7 @@ package body Sem_Ch3 is
Set_Can_Use_Internal_Rep (T_Name,
not Always_Compatible_Rep_On_Target);
Set_Etype (T_Name, T_Name);
- Init_Size_Align (T_Name);
+ Reinit_Size_Align (T_Name);
Set_Directly_Designated_Type (T_Name, Desig_Type);
-- If the access_to_subprogram is not declared at the library level,
@@ -1465,7 +1465,7 @@ package body Sem_Ch3 is
-- and the pointer size is already set. Else, initialize.
if not From_Limited_With (T) then
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
end if;
-- Note that Has_Task is always false, since the access type itself
@@ -1551,7 +1551,7 @@ package body Sem_Ch3 is
Set_Is_Aliased (Tag);
Set_Is_Independent (Tag);
Set_Related_Type (Tag, Iface);
- Init_Component_Location (Tag);
+ Reinit_Component_Location (Tag);
pragma Assert (Is_Frozen (Iface));
@@ -1591,7 +1591,7 @@ package body Sem_Ch3 is
Set_Is_Aliased (Offset);
Set_Is_Independent (Offset);
Set_Related_Type (Offset, Iface);
- Init_Component_Location (Offset);
+ Reinit_Component_Location (Offset);
Insert_After (Last_Tag, Decl);
Last_Tag := Decl;
end if;
@@ -2648,6 +2648,48 @@ package body Sem_Ch3 is
E := First_Entity (Current_Scope);
while Present (E) loop
Resolve_Aspect_Expressions (E);
+
+ -- Now that the aspect expressions have been resolved, if this is
+ -- at the end of the visible declarations, we can set the flag
+ -- Known_To_Have_Preelab_Init properly on types declared in the
+ -- visible part, which is needed for checking whether full types
+ -- in the private part satisfy the Preelaborable_Initialization
+ -- aspect of the partial view. We can't wait for the creation of
+ -- the pragma by Analyze_Aspects_At_Freeze_Point, because the
+ -- freeze point may occur after the end of the package declaration
+ -- (in the case of nested packages).
+
+ if Is_Type (E)
+ and then L = Visible_Declarations (Parent (L))
+ and then Has_Aspect (E, Aspect_Preelaborable_Initialization)
+ then
+ declare
+ ASN : constant Node_Id :=
+ Find_Aspect (E, Aspect_Preelaborable_Initialization);
+ Expr : constant Node_Id := Expression (ASN);
+ begin
+ -- Set Known_To_Have_Preelab_Init to True if aspect has no
+ -- expression, or if the expression is True (or was folded
+ -- to True), or if the expression is a conjunction of one or
+ -- more Preelaborable_Initialization attributes applied to
+ -- formal types and wasn't folded to False. (Note that
+ -- Is_Conjunction_Of_Formal_Preelab_Init_Attributes goes to
+ -- Original_Node if needed, hence test for Standard_False.)
+
+ if not Present (Expr)
+ or else (Is_Entity_Name (Expr)
+ and then Entity (Expr) = Standard_True)
+ or else
+ (Is_Conjunction_Of_Formal_Preelab_Init_Attributes (Expr)
+ and then
+ not (Is_Entity_Name (Expr)
+ and then Entity (Expr) = Standard_False))
+ then
+ Set_Known_To_Have_Preelab_Init (E);
+ end if;
+ end;
+ end if;
+
Next_Entity (E);
end loop;
end Resolve_Aspects;
@@ -3450,7 +3492,7 @@ package body Sem_Ch3 is
Mutate_Ekind (T, E_Incomplete_Type);
Set_Etype (T, T);
Set_Is_First_Subtype (T);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
-- Set the SPARK mode from the current context
@@ -4463,7 +4505,7 @@ package body Sem_Ch3 is
-- default initial value (including via a Default_Value or
-- Default_Component_Value aspect, see AI12-0301) and then this is not
-- an internal declaration whose initialization comes later (as for an
- -- aggregate expansion).
+ -- aggregate expansion) or a deferred constant.
-- If expression is an aggregate it may be expanded into assignments
-- and the declaration itself is marked with No_Initialization, but
-- the predicate still applies.
@@ -4477,6 +4519,7 @@ package body Sem_Ch3 is
(Present (E)
or else
Is_Partially_Initialized_Type (T, Include_Implicit => False))
+ and then not (Constant_Present (N) and then No (E))
then
-- If the type has a static predicate and the expression is known at
-- compile time, see if the expression satisfies the predicate.
@@ -4849,8 +4892,8 @@ package body Sem_Ch3 is
-- Initialize alignment and size and capture alignment setting
- Init_Alignment (Id);
- Init_Esize (Id);
+ Reinit_Alignment (Id);
+ Reinit_Esize (Id);
Set_Optimize_Alignment_Flags (Id);
-- Deal with aliased case
@@ -5183,7 +5226,7 @@ package body Sem_Ch3 is
Set_Is_Pure (T, Is_Pure (Current_Scope));
Set_Scope (T, Current_Scope);
Mutate_Ekind (T, E_Record_Type_With_Private);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Default_SSO (T);
Set_No_Reordering (T, No_Component_Reordering);
@@ -5348,7 +5391,7 @@ package body Sem_Ch3 is
begin
Generate_Definition (Id);
Set_Is_Pure (Id, Is_Pure (Current_Scope));
- Init_Size_Align (Id);
+ Reinit_Size_Align (Id);
-- The following guard condition on Enter_Name is to handle cases where
-- the defining identifier has already been entered into the scope but
@@ -5466,7 +5509,7 @@ package body Sem_Ch3 is
Set_Machine_Radix_10 (Id, Machine_Radix_10 (T));
Set_Is_Constrained (Id, Is_Constrained (T));
Set_Is_Known_Valid (Id, Is_Known_Valid (T));
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
when Enumeration_Kind =>
Mutate_Ekind (Id, E_Enumeration_Subtype);
@@ -5475,7 +5518,7 @@ package body Sem_Ch3 is
Set_Is_Character_Type (Id, Is_Character_Type (T));
Set_Is_Constrained (Id, Is_Constrained (T));
Set_Is_Known_Valid (Id, Is_Known_Valid (T));
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
when Ordinary_Fixed_Point_Kind =>
Mutate_Ekind (Id, E_Ordinary_Fixed_Point_Subtype);
@@ -5484,7 +5527,7 @@ package body Sem_Ch3 is
Set_Delta_Value (Id, Delta_Value (T));
Set_Is_Constrained (Id, Is_Constrained (T));
Set_Is_Known_Valid (Id, Is_Known_Valid (T));
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
when Float_Kind =>
Mutate_Ekind (Id, E_Floating_Point_Subtype);
@@ -5500,14 +5543,14 @@ package body Sem_Ch3 is
Set_Scalar_Range (Id, Scalar_Range (T));
Set_Is_Constrained (Id, Is_Constrained (T));
Set_Is_Known_Valid (Id, Is_Known_Valid (T));
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
when Modular_Integer_Kind =>
Mutate_Ekind (Id, E_Modular_Integer_Subtype);
Set_Scalar_Range (Id, Scalar_Range (T));
Set_Is_Constrained (Id, Is_Constrained (T));
Set_Is_Known_Valid (Id, Is_Known_Valid (T));
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
when Class_Wide_Kind =>
Mutate_Ekind (Id, E_Class_Wide_Subtype);
@@ -5534,7 +5577,7 @@ package body Sem_Ch3 is
-- the type they rename.
if Present (Generic_Parent_Type (N)) then
- Set_RM_Size (Id, RM_Size (T));
+ Copy_RM_Size (To => Id, From => T);
end if;
if Ekind (T) = E_Record_Subtype
@@ -6211,7 +6254,7 @@ package body Sem_Ch3 is
-- Move to next index
- Next_Index (Index);
+ Next (Index);
Nb_Index := Nb_Index + 1;
end loop;
@@ -6290,7 +6333,7 @@ package body Sem_Ch3 is
-- The constrained array type is a subtype of the unconstrained one
Mutate_Ekind (T, E_Array_Subtype);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Etype (T, Implicit_Base);
Set_Scope (T, Current_Scope);
Set_Is_Constrained (T);
@@ -6326,7 +6369,7 @@ package body Sem_Ch3 is
end if;
Mutate_Ekind (T, E_Array_Type);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Etype (T, T);
Set_Scope (T, Current_Scope);
Set_Component_Size (T, Uint_0);
@@ -6724,6 +6767,7 @@ package body Sem_Ch3 is
Make_Procedure_Specification (Loc,
Defining_Unit_Name => Subp,
Parameter_Specifications => Profile);
+ Mutate_Ekind (Subp, E_Procedure);
else
Spec :=
Make_Function_Specification (Loc,
@@ -6732,13 +6776,32 @@ package body Sem_Ch3 is
Result_Definition =>
New_Copy_Tree
(Result_Definition (Type_Definition (Decl))));
+ Mutate_Ekind (Subp, E_Function);
end if;
New_Decl :=
Make_Subprogram_Declaration (Loc, Specification => Spec);
Set_Aspect_Specifications (New_Decl, Contracts);
+ Set_Is_Wrapper (Subp);
+
+ -- The wrapper is declared in the freezing actions to facilitate its
+ -- identification and thus avoid handling it as a primitive operation
+ -- of a tagged type (see Is_Access_To_Subprogram_Wrapper); otherwise it
+ -- may be handled as a dispatching operation and erroneously registered
+ -- in a dispatch table.
+
+ if not GNATprove_Mode then
+ Ensure_Freeze_Node (Id);
+ Append_Freeze_Actions (Id, New_List (New_Decl));
+
+ -- Under GNATprove mode there is no such problem but we do not declare
+ -- it in the freezing actions since they are not analyzed under this
+ -- mode.
+
+ else
+ Insert_After (Decl, New_Decl);
+ end if;
- Insert_After (Decl, New_Decl);
Set_Access_Subprogram_Wrapper (Designated_Type (Id), Subp);
Build_Access_Subprogram_Wrapper_Body (Decl, New_Decl);
end Build_Access_Subprogram_Wrapper;
@@ -6813,8 +6876,8 @@ package body Sem_Ch3 is
Set_Is_Constrained (Derived_Type, Is_Constrained (Subt));
Set_Is_Access_Constant (Derived_Type, Is_Access_Constant (Parent_Type));
- Set_Size_Info (Derived_Type, Parent_Type);
- Set_RM_Size (Derived_Type, RM_Size (Parent_Type));
+ Set_Size_Info (Derived_Type, Parent_Type);
+ Copy_RM_Size (To => Derived_Type, From => Parent_Type);
Set_Depends_On_Private (Derived_Type,
Has_Private_Component (Derived_Type));
Conditional_Delay (Derived_Type, Subt);
@@ -8433,11 +8496,11 @@ package body Sem_Ch3 is
-- discriminants in R and T1 through T4:
-- Type Discrim Stored Discrim Comment
- -- R (D1, D2, D3) (D1, D2, D3) Girder discrims implicit in R
- -- T1 (D1, D2, D3) (D1, D2, D3) Girder discrims implicit in T1
- -- T2 (X1, X2) (D1, D2, D3) Girder discrims EXPLICIT in T2
- -- T3 (X1, X2) (D1, D2, D3) Girder discrims EXPLICIT in T3
- -- T4 (Y) (D1, D2, D3) Girder discrims EXPLICIT in T4
+ -- R (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in R
+ -- T1 (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in T1
+ -- T2 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T2
+ -- T3 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T3
+ -- T4 (Y) (D1, D2, D3) Stored discrims EXPLICIT in T4
-- Field Corresponding_Discriminant (abbreviated CD below) allows us to
-- find the corresponding discriminant in the parent type, while
@@ -8945,7 +9008,7 @@ package body Sem_Ch3 is
if Is_Tagged then
Set_Is_Tagged_Type (Derived_Type);
- Init_Size_Align (Derived_Type);
+ Reinit_Size_Align (Derived_Type);
end if;
-- STEP 0a: figure out what kind of derived type declaration we have
@@ -9854,8 +9917,8 @@ package body Sem_Ch3 is
Mutate_Ekind (Derived_Type, Ekind (Parent_Base));
Propagate_Concurrent_Flags (Derived_Type, Parent_Base);
- Set_Size_Info (Derived_Type, Parent_Type);
- Set_RM_Size (Derived_Type, RM_Size (Parent_Type));
+ Set_Size_Info (Derived_Type, Parent_Type);
+ Copy_RM_Size (To => Derived_Type, From => Parent_Type);
Set_Is_Controlled_Active
(Derived_Type, Is_Controlled_Active (Parent_Type));
@@ -10392,6 +10455,7 @@ package body Sem_Ch3 is
(Discr_Expr (J), Check_Concurrent => True)
then
Discrim_Present := True;
+ exit;
end if;
end loop;
@@ -10449,7 +10513,43 @@ package body Sem_Ch3 is
Apply_Range_Check (Discr_Expr (J), Etype (Discr));
end if;
- Force_Evaluation (Discr_Expr (J));
+ -- If the value of the discriminant may be visible in
+ -- another unit or child unit, create an external name
+ -- for it. We use the name of the object or component
+ -- that carries the discriminated subtype. The code
+ -- below may generate external symbols for the discriminant
+ -- expression when not strictly needed, which is harmless.
+
+ if Expander_Active
+ and then Comes_From_Source (Def)
+ and then not Is_Subprogram (Current_Scope)
+ then
+ declare
+ Id : Entity_Id := Empty;
+ begin
+ if Nkind (Parent (Def)) = N_Object_Declaration then
+ Id := Defining_Identifier (Parent (Def));
+
+ elsif Nkind (Parent (Def)) = N_Component_Definition
+ and then
+ Nkind (Parent (Parent (Def)))
+ = N_Component_Declaration
+ then
+ Id := Defining_Identifier (Parent (Parent (Def)));
+ end if;
+
+ if Present (Id) then
+ Force_Evaluation (
+ Discr_Expr (J),
+ Related_Id => Id,
+ Discr_Number => J);
+ else
+ Force_Evaluation (Discr_Expr (J));
+ end if;
+ end;
+ else
+ Force_Evaluation (Discr_Expr (J));
+ end if;
end if;
-- Check that the designated type of an access discriminant's
@@ -10554,7 +10654,7 @@ package body Sem_Ch3 is
end if;
Set_Etype (Def_Id, T);
- Init_Size_Align (Def_Id);
+ Reinit_Size_Align (Def_Id);
Set_Has_Discriminants (Def_Id, Has_Discrs);
Set_Is_Constrained (Def_Id, Constrained);
@@ -12689,7 +12789,7 @@ package body Sem_Ch3 is
Set_Is_First_Subtype (Full, False);
Set_Scope (Full, Scope (Priv));
Set_Size_Info (Full, Full_Base);
- Set_RM_Size (Full, RM_Size (Full_Base));
+ Copy_RM_Size (To => Full, From => Full_Base);
Set_Is_Itype (Full);
-- A subtype of a private-type-without-discriminants, whose full-view
@@ -14516,7 +14616,7 @@ package body Sem_Ch3 is
end if;
Set_Size_Info (Def_Id, (T));
- Set_RM_Size (Def_Id, RM_Size (T));
+ Copy_RM_Size (To => Def_Id, From => T);
Set_First_Rep_Item (Def_Id, First_Rep_Item (T));
-- If this is a range for a fixed-lower-bound subtype, then set the
@@ -15054,7 +15154,7 @@ package body Sem_Ch3 is
Add_Discriminants : declare
Num_Disc : Nat;
- Num_Gird : Nat;
+ Num_Stor : Nat;
begin
Num_Disc := 0;
@@ -15075,7 +15175,7 @@ package body Sem_Ch3 is
-- the GCC 4.x back-end decides to break apart assignments between
-- objects using the parent view into member-wise assignments.
- Num_Gird := 0;
+ Num_Stor := 0;
if Is_Derived_Type (Typ)
and then not Is_Tagged_Type (Typ)
@@ -15083,12 +15183,12 @@ package body Sem_Ch3 is
Old_C := First_Stored_Discriminant (Typ);
while Present (Old_C) loop
- Num_Gird := Num_Gird + 1;
+ Num_Stor := Num_Stor + 1;
Next_Stored_Discriminant (Old_C);
end loop;
end if;
- if Num_Gird > Num_Disc then
+ if Num_Stor > Num_Disc then
-- Find out multiple uses of new discriminants, and add hidden
-- components for the extra renamed discriminants. We recognize
@@ -15320,12 +15420,12 @@ package body Sem_Ch3 is
Set_Fixed_Range (Implicit_Base, Loc, -Bound_Val, Bound_Val);
- -- Note: We leave size as zero for now, size will be set at freeze
+ -- Note: We leave Esize unset for now, size will be set at freeze
-- time. We have to do this for ordinary fixed-point, because the size
-- depends on the specified small, and we might as well do the same for
-- decimal fixed-point.
- pragma Assert (Esize (Implicit_Base) = Uint_0);
+ pragma Assert (not Known_Esize (Implicit_Base));
-- If there are bounds given in the declaration use them as the
-- bounds of the first named subtype.
@@ -15676,7 +15776,7 @@ package body Sem_Ch3 is
-- Set remaining characterstics of anonymous access type
- Init_Alignment (Acc_Type);
+ Reinit_Alignment (Acc_Type);
Set_Directly_Designated_Type (Acc_Type, Derived_Type);
Set_Etype (New_Id, Acc_Type);
@@ -16011,6 +16111,14 @@ package body Sem_Ch3 is
Set_No_Return (New_Subp, No_Return (Parent_Subp));
+ -- If the parent subprogram is marked as Ghost, then so is the derived
+ -- subprogram. The ghost policy for the derived subprogram is set from
+ -- the effective ghost policy at the point of derived type declaration.
+
+ if Is_Ghost_Entity (Parent_Subp) then
+ Set_Is_Ghost_Entity (New_Subp);
+ end if;
+
-- A derived function with a controlling result is abstract. If the
-- Derived_Type is a nonabstract formal generic derived type, then
-- inherited operations are not abstract: the required check is done at
@@ -19714,6 +19822,8 @@ package body Sem_Ch3 is
Set_Is_Non_Static_Subtype (Def_Id);
end if;
end if;
+
+ Set_Parent (Def_Id, N);
end if;
-- Final step is to label the index with this constructed type
@@ -19750,10 +19860,10 @@ package body Sem_Ch3 is
Siz := Siz * 2;
end loop;
- Init_Esize (T, Siz);
+ Set_Esize (T, UI_From_Int (Siz));
else
- Init_Esize (T, System_Max_Binary_Modulus_Power);
+ Set_Esize (T, UI_From_Int (System_Max_Binary_Modulus_Power));
end if;
if not Non_Binary_Modulus (T) and then Esize (T) = RM_Size (T) then
@@ -19788,7 +19898,7 @@ package body Sem_Ch3 is
Set_Etype (T, T);
Mutate_Ekind (T, E_Modular_Integer_Type);
- Init_Alignment (T);
+ Reinit_Alignment (T);
Set_Is_Constrained (T);
if not Is_OK_Static_Expression (Mod_Expr) then
@@ -19867,7 +19977,7 @@ package body Sem_Ch3 is
Error_Msg_F ("modulus exceeds limit (2 '*'*^)", Mod_Expr);
Set_Modular_Size (System_Max_Binary_Modulus_Power);
- Init_Alignment (T);
+ Reinit_Alignment (T);
end Modular_Type_Declaration;
@@ -20189,7 +20299,7 @@ package body Sem_Ch3 is
Mutate_Ekind (T, E_Ordinary_Fixed_Point_Subtype);
Set_Etype (T, Implicit_Base);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Inherit_Rep_Item_Chain (T, Implicit_Base);
Set_Small_Value (T, Small_Val);
Set_Delta_Value (T, Delta_Val);
@@ -20591,8 +20701,8 @@ package body Sem_Ch3 is
end if;
Mutate_Ekind (Id, E_Discriminant);
- Init_Component_Location (Id);
- Init_Esize (Id);
+ Reinit_Component_Location (Id);
+ Reinit_Esize (Id);
Set_Discriminant_Number (Id, Discr_Number);
-- Make sure this is always set, even in illegal programs
@@ -21531,11 +21641,10 @@ package body Sem_Ch3 is
--------------------------------
procedure Process_Range_Expr_In_Decl
- (R : Node_Id;
- T : Entity_Id;
- Subtyp : Entity_Id := Empty;
- Check_List : List_Id := No_List;
- R_Check_Off : Boolean := False)
+ (R : Node_Id;
+ T : Entity_Id;
+ Subtyp : Entity_Id := Empty;
+ Check_List : List_Id := No_List)
is
Lo, Hi : Node_Id;
R_Checks : Check_Result;
@@ -21638,13 +21747,8 @@ package body Sem_Ch3 is
-- represent the null range the Constraint_Error exception should
-- not be raised.
- -- ??? The following code should be cleaned up as follows
-
- -- 1. The Is_Null_Range (Lo, Hi) test should disappear since it
- -- is done in the call to Range_Check (R, T); below
-
- -- 2. The use of R_Check_Off should be investigated and possibly
- -- removed, this would clean up things a bit.
+ -- ??? The Is_Null_Range (Lo, Hi) test should disappear since it
+ -- is done in the call to Range_Check (R, T); below.
if Is_Null_Range (Lo, Hi) then
null;
@@ -21661,8 +21765,8 @@ package body Sem_Ch3 is
if Expander_Active or GNATprove_Mode then
- -- Call Force_Evaluation to create declarations as needed to
- -- deal with side effects, and also create typ_FIRST/LAST
+ -- Call Force_Evaluation to create declarations as needed
+ -- to deal with side effects, and also create typ_FIRST/LAST
-- entities for bounds if we have a subtype name.
-- Note: we do this transformation even if expansion is not
@@ -21680,106 +21784,103 @@ package body Sem_Ch3 is
-- because the type we check against isn't necessarily the place
-- where we put the check.
- if not R_Check_Off then
- R_Checks := Get_Range_Checks (R, T);
-
- -- Look up tree to find an appropriate insertion point. We
- -- can't just use insert_actions because later processing
- -- depends on the insertion node. Prior to Ada 2012 the
- -- insertion point could only be a declaration or a loop, but
- -- quantified expressions can appear within any context in an
- -- expression, and the insertion point can be any statement,
- -- pragma, or declaration.
-
- Insert_Node := Parent (R);
- while Present (Insert_Node) loop
- exit when
- Nkind (Insert_Node) in N_Declaration
- and then
- Nkind (Insert_Node) not in N_Component_Declaration
- | N_Loop_Parameter_Specification
- | N_Function_Specification
- | N_Procedure_Specification;
-
- exit when Nkind (Insert_Node) in
- N_Later_Decl_Item |
- N_Statement_Other_Than_Procedure_Call |
- N_Procedure_Call_Statement |
- N_Pragma;
-
- Insert_Node := Parent (Insert_Node);
- end loop;
+ R_Checks := Get_Range_Checks (R, T);
- -- Why would Type_Decl not be present??? Without this test,
- -- short regression tests fail.
+ -- Look up tree to find an appropriate insertion point. We can't
+ -- just use insert_actions because later processing depends on
+ -- the insertion node. Prior to Ada 2012 the insertion point could
+ -- only be a declaration or a loop, but quantified expressions can
+ -- appear within any context in an expression, and the insertion
+ -- point can be any statement, pragma, or declaration.
- if Present (Insert_Node) then
+ Insert_Node := Parent (R);
+ while Present (Insert_Node) loop
+ exit when
+ Nkind (Insert_Node) in N_Declaration
+ and then
+ Nkind (Insert_Node) not in N_Component_Declaration
+ | N_Loop_Parameter_Specification
+ | N_Function_Specification
+ | N_Procedure_Specification;
+
+ exit when Nkind (Insert_Node) in
+ N_Later_Decl_Item |
+ N_Statement_Other_Than_Procedure_Call |
+ N_Procedure_Call_Statement |
+ N_Pragma;
+
+ Insert_Node := Parent (Insert_Node);
+ end loop;
- -- Case of loop statement. Verify that the range is part
- -- of the subtype indication of the iteration scheme.
+ -- Why would Type_Decl not be present??? Without this test,
+ -- short regression tests fail.
- if Nkind (Insert_Node) = N_Loop_Statement then
- declare
- Indic : Node_Id;
+ if Present (Insert_Node) then
- begin
- Indic := Parent (R);
- while Present (Indic)
- and then Nkind (Indic) /= N_Subtype_Indication
- loop
- Indic := Parent (Indic);
- end loop;
+ -- Case of loop statement. Verify that the range is part of the
+ -- subtype indication of the iteration scheme.
- if Present (Indic) then
- Def_Id := Etype (Subtype_Mark (Indic));
+ if Nkind (Insert_Node) = N_Loop_Statement then
+ declare
+ Indic : Node_Id;
- Insert_Range_Checks
- (R_Checks,
- Insert_Node,
- Def_Id,
- Sloc (Insert_Node),
- Do_Before => True);
- end if;
- end;
+ begin
+ Indic := Parent (R);
+ while Present (Indic)
+ and then Nkind (Indic) /= N_Subtype_Indication
+ loop
+ Indic := Parent (Indic);
+ end loop;
- -- Case of declarations. If the declaration is for a type
- -- and involves discriminants, the checks are premature at
- -- the declaration point and need to wait for the expansion
- -- of the initialization procedure, which will pass in the
- -- list to put them on; otherwise, the checks are done at
- -- the declaration point and there is no need to do them
- -- again in the initialization procedure.
+ if Present (Indic) then
+ Def_Id := Etype (Subtype_Mark (Indic));
- elsif Nkind (Insert_Node) in N_Declaration then
- Def_Id := Defining_Identifier (Insert_Node);
+ Insert_Range_Checks
+ (R_Checks,
+ Insert_Node,
+ Def_Id,
+ Sloc (Insert_Node),
+ Do_Before => True);
+ end if;
+ end;
- if (Ekind (Def_Id) = E_Record_Type
- and then Depends_On_Discriminant (R))
- or else
- (Ekind (Def_Id) = E_Protected_Type
- and then Has_Discriminants (Def_Id))
- then
- if Present (Check_List) then
- Append_Range_Checks
- (R_Checks,
- Check_List, Def_Id, Sloc (Insert_Node));
- end if;
+ -- Case of declarations. If the declaration is for a type and
+ -- involves discriminants, the checks are premature at the
+ -- declaration point and need to wait for the expansion of the
+ -- initialization procedure, which will pass in the list to put
+ -- them on; otherwise, the checks are done at the declaration
+ -- point and there is no need to do them again in the
+ -- initialization procedure.
- else
- if No (Check_List) then
- Insert_Range_Checks
- (R_Checks,
- Insert_Node, Def_Id, Sloc (Insert_Node));
- end if;
- end if;
+ elsif Nkind (Insert_Node) in N_Declaration then
+ Def_Id := Defining_Identifier (Insert_Node);
- -- Case of statements. Drop the checks, as the range appears
- -- in the context of a quantified expression. Insertion will
- -- take place when expression is expanded.
+ if (Ekind (Def_Id) = E_Record_Type
+ and then Depends_On_Discriminant (R))
+ or else
+ (Ekind (Def_Id) = E_Protected_Type
+ and then Has_Discriminants (Def_Id))
+ then
+ if Present (Check_List) then
+ Append_Range_Checks
+ (R_Checks,
+ Check_List, Def_Id, Sloc (Insert_Node));
+ end if;
else
- null;
+ if No (Check_List) then
+ Insert_Range_Checks
+ (R_Checks,
+ Insert_Node, Def_Id, Sloc (Insert_Node));
+ end if;
end if;
+
+ -- Case of statements. Drop the checks, as the range appears in
+ -- the context of a quantified expression. Insertion will take
+ -- place when expression is expanded.
+
+ else
+ null;
end if;
end if;
end if;
@@ -22260,7 +22361,7 @@ package body Sem_Ch3 is
Mutate_Ekind (T, E_Record_Type);
Set_Etype (T, T);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Interfaces (T, No_Elist);
Set_Stored_Constraint (T, No_Elist);
Set_Default_SSO (T);
@@ -22369,7 +22470,7 @@ package body Sem_Ch3 is
Set_Etype (Tag_Comp, RTE (RE_Tag));
Set_DT_Entry_Count (Tag_Comp, No_Uint);
Set_Original_Record_Component (Tag_Comp, Tag_Comp);
- Init_Component_Location (Tag_Comp);
+ Reinit_Component_Location (Tag_Comp);
-- Ada 2005 (AI-251): Addition of the Tag corresponding to all the
-- implemented interfaces.
@@ -22473,7 +22574,7 @@ package body Sem_Ch3 is
and then not Is_Itype (Component)
then
Mutate_Ekind (Component, E_Component);
- Init_Component_Location (Component);
+ Reinit_Component_Location (Component);
end if;
Propagate_Concurrent_Flags (T, Etype (Component));
diff --git a/gcc/ada/sem_ch3.ads b/gcc/ada/sem_ch3.ads
index eedb98c..f3722a0 100644
--- a/gcc/ada/sem_ch3.ads
+++ b/gcc/ada/sem_ch3.ads
@@ -257,11 +257,10 @@ package Sem_Ch3 is
-- Priv_T is the private view of the type whose full declaration is in N.
procedure Process_Range_Expr_In_Decl
- (R : Node_Id;
- T : Entity_Id;
- Subtyp : Entity_Id := Empty;
- Check_List : List_Id := No_List;
- R_Check_Off : Boolean := False);
+ (R : Node_Id;
+ T : Entity_Id;
+ Subtyp : Entity_Id := Empty;
+ Check_List : List_Id := No_List);
-- Process a range expression that appears in a declaration context. The
-- range is analyzed and resolved with the base type of the given type, and
-- an appropriate check for expressions in non-static contexts made on the
@@ -271,8 +270,7 @@ package Sem_Ch3 is
-- pointer of R so that the types get properly frozen. Check_List is used
-- when the subprogram is called from Build_Record_Init_Proc and is used to
-- return a set of constraint checking statements generated by the Checks
- -- package. R_Check_Off is set to True when the call to Range_Check is to
- -- be skipped.
+ -- package.
--
-- If Subtyp is given, then the range is for the named subtype Subtyp, and
-- in this case the bounds are captured if necessary using this name.
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index c052022..169b01b 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -2534,6 +2534,7 @@ package body Sem_Ch4 is
and then Is_Entity_Name (Actual)
and then Is_Type (Entity (Actual))
and then Is_Discrete_Type (Entity (Actual))
+ and then not Is_Current_Instance (Actual)
then
Replace (N,
Make_Slice (Loc,
@@ -2956,47 +2957,23 @@ package body Sem_Ch4 is
I_F : Interp_Index;
T_F : Entity_Id;
+ procedure Analyze_Set_Membership;
+ -- If a set of alternatives is present, analyze each and find the
+ -- common type to which they must all resolve.
+
+ procedure Find_Interpretation;
+ function Find_Interpretation return Boolean;
+ -- Routine and wrapper to find a matching interpretation in case
+ -- of overloading. The wrapper returns True iff a matching
+ -- interpretation is found. Beware, in absence of overloading,
+ -- using this function will break gnat's bootstrapping.
+
procedure Try_One_Interp (T1 : Entity_Id);
-- Routine to try one proposed interpretation. Note that the context
-- of the operation plays no role in resolving the arguments, so that
-- if there is more than one interpretation of the operands that is
-- compatible with a membership test, the operation is ambiguous.
- --------------------
- -- Try_One_Interp --
- --------------------
-
- procedure Try_One_Interp (T1 : Entity_Id) is
- begin
- if Has_Compatible_Type (R, T1) then
- if Found
- and then Base_Type (T1) /= Base_Type (T_F)
- then
- It := Disambiguate (L, I_F, Index, Any_Type);
-
- if It = No_Interp then
- Ambiguous_Operands (N);
- Set_Etype (L, Any_Type);
- return;
-
- else
- T_F := It.Typ;
- end if;
-
- else
- Found := True;
- T_F := T1;
- I_F := Index;
- end if;
-
- Set_Etype (L, T_F);
- end if;
- end Try_One_Interp;
-
- procedure Analyze_Set_Membership;
- -- If a set of alternatives is present, analyze each and find the
- -- common type to which they must all resolve.
-
----------------------------
-- Analyze_Set_Membership --
----------------------------
@@ -3095,6 +3072,57 @@ package body Sem_Ch4 is
end if;
end Analyze_Set_Membership;
+ -------------------------
+ -- Find_Interpretation --
+ -------------------------
+
+ procedure Find_Interpretation is
+ begin
+ Get_First_Interp (L, Index, It);
+ while Present (It.Typ) loop
+ Try_One_Interp (It.Typ);
+ Get_Next_Interp (Index, It);
+ end loop;
+ end Find_Interpretation;
+
+ function Find_Interpretation return Boolean is
+ begin
+ Find_Interpretation;
+
+ return Found;
+ end Find_Interpretation;
+
+ --------------------
+ -- Try_One_Interp --
+ --------------------
+
+ procedure Try_One_Interp (T1 : Entity_Id) is
+ begin
+ if Has_Compatible_Type (R, T1) then
+ if Found
+ and then Base_Type (T1) /= Base_Type (T_F)
+ then
+ It := Disambiguate (L, I_F, Index, Any_Type);
+
+ if It = No_Interp then
+ Ambiguous_Operands (N);
+ Set_Etype (L, Any_Type);
+ return;
+
+ else
+ T_F := It.Typ;
+ end if;
+
+ else
+ Found := True;
+ T_F := T1;
+ I_F := Index;
+ end if;
+
+ Set_Etype (L, T_F);
+ end if;
+ end Try_One_Interp;
+
Op : Node_Id;
-- Start of processing for Analyze_Membership_Op
@@ -3119,11 +3147,7 @@ package body Sem_Ch4 is
Try_One_Interp (Etype (L));
else
- Get_First_Interp (L, Index, It);
- while Present (It.Typ) loop
- Try_One_Interp (It.Typ);
- Get_Next_Interp (Index, It);
- end loop;
+ Find_Interpretation;
end if;
-- If not a range, it can be a subtype mark, or else it is a degenerate
@@ -3139,13 +3163,14 @@ package body Sem_Ch4 is
Find_Type (R);
Check_Fully_Declared (Entity (R), R);
- elsif Ada_Version >= Ada_2012
- and then Has_Compatible_Type (R, Etype (L))
+ elsif Ada_Version >= Ada_2012 and then
+ ((Is_Overloaded (L) and then Find_Interpretation) or else
+ (not Is_Overloaded (L) and then Has_Compatible_Type (R, Etype (L))))
then
if Nkind (N) = N_In then
- Op := Make_Op_Eq (Loc, Left_Opnd => L, Right_Opnd => R);
+ Op := Make_Op_Eq (Loc, Left_Opnd => L, Right_Opnd => R);
else
- Op := Make_Op_Ne (Loc, Left_Opnd => L, Right_Opnd => R);
+ Op := Make_Op_Ne (Loc, Left_Opnd => L, Right_Opnd => R);
end if;
if Is_Record_Or_Limited_Type (Etype (L)) then
@@ -6626,7 +6651,7 @@ package body Sem_Ch4 is
Get_Next_Interp (Index, It);
end loop;
end if;
- else
+ elsif Has_Compatible_Type (R, T1) or else Covers (Etype (R), T1) then
Add_One_Interp (N, Op_Id, Standard_Boolean, Base_Type (T1));
end if;
end Find_Non_Universal_Interpretations;
@@ -8029,6 +8054,7 @@ package body Sem_Ch4 is
while Present (It.Nam) loop
if Is_Numeric_Type (It.Typ)
and then Scope (It.Typ) = Standard_Standard
+ and then Ekind (It.Nam) = E_Operator
then
Set_Abstract_Op (I, Abstract_Op);
end if;
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 7a8d0cc..45d2457 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -1681,6 +1681,13 @@ package body Sem_Ch5 is
Error_Msg_N
("(Ada 83) case expression cannot be of a generic type", Exp);
return;
+
+ elsif not Extensions_Allowed
+ and then not Is_Discrete_Type (Exp_Type)
+ then
+ Error_Msg_N
+ ("expression in case statement must be of a discrete_Type", Exp);
+ return;
end if;
-- If the case expression is a formal object of mode in out, then treat
@@ -3028,6 +3035,10 @@ package body Sem_Ch5 is
then
Analyze_And_Resolve (Original_Bound, Typ);
return Original_Bound;
+
+ elsif Inside_Class_Condition_Preanalysis then
+ Analyze_And_Resolve (Original_Bound, Typ);
+ return Original_Bound;
end if;
-- Normally, the best approach is simply to generate a constant
@@ -3333,11 +3344,17 @@ package body Sem_Ch5 is
-- or post-condition has been expanded. Update the type of the loop
-- variable to reflect the proper itype at each stage of analysis.
+ -- Loop_Nod might not be present when we are preanalyzing a class-wide
+ -- pre/postcondition since preanalysis occurs in a place unrelated to
+ -- the actual code and the quantified expression may be the outermost
+ -- expression of the class-wide condition.
+
if No (Etype (Id))
or else Etype (Id) = Any_Type
or else
(Present (Etype (Id))
and then Is_Itype (Etype (Id))
+ and then Present (Loop_Nod)
and then Nkind (Parent (Loop_Nod)) = N_Expression_With_Actions
and then Nkind (Original_Node (Parent (Loop_Nod))) =
N_Quantified_Expression)
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 304dc19..e32c4ad 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -385,15 +385,9 @@ package body Sem_Ch6 is
Analyze (New_Body);
Set_Is_Inlined (Prev);
- -- If the expression function is a completion, the previous declaration
- -- must come from source. We know already that it appears in the current
- -- scope. The entity itself may be internally created if within a body
- -- to be inlined.
-
elsif Present (Prev)
and then Is_Overloadable (Prev)
and then not Is_Formal_Subprogram (Prev)
- and then Comes_From_Source (Parent (Prev))
then
Set_Has_Completion (Prev, False);
Set_Is_Inlined (Prev);
@@ -2132,8 +2126,15 @@ package body Sem_Ch6 is
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)
+
+ -- Include aspects that can be specified by a
+ -- subprogram name, which can be an operator.
+
+ in Aspect_Stable_Properties
+ | Aspect_Integer_Literal
+ | Aspect_Real_Literal
+ | Aspect_String_Literal
+ | Aspect_Aggregate)
then
Find_Direct_Name (N);
@@ -4504,29 +4505,6 @@ package body Sem_Ch6 is
end if;
end if;
- -- If the subprogram has a class-wide clone, build its body as a copy
- -- of the original body, and rewrite body of original subprogram as a
- -- wrapper that calls the clone. If N is a stub, this construction will
- -- take place when the proper body is analyzed. No action needed if this
- -- subprogram has been eliminated.
-
- if Present (Spec_Id)
- and then Present (Class_Wide_Clone (Spec_Id))
- and then (Comes_From_Source (N) or else Was_Expression_Function (N))
- and then Nkind (N) /= N_Subprogram_Body_Stub
- and then not (Expander_Active and then Is_Eliminated (Spec_Id))
- then
- Build_Class_Wide_Clone_Body (Spec_Id, N);
-
- -- This is the new body for the existing primitive operation
-
- Rewrite (N, Build_Class_Wide_Clone_Call
- (Sloc (N), New_List, Spec_Id, Parent (Spec_Id)));
- Set_Has_Completion (Spec_Id, False);
- Analyze (N);
- return;
- end if;
-
-- Place subprogram on scope stack, and make formals visible. If there
-- is a spec, the visible entity remains that of the spec.
@@ -7760,7 +7738,7 @@ package body Sem_Ch6 is
("RETURN statement missing following this statement<<!",
Last_Stm);
Error_Msg_N
- ("\Program_Error ]<<!", Last_Stm);
+ ("\Program_Error [<<!", Last_Stm);
end if;
-- Note: we set Err even though we have not issued a warning
@@ -9480,13 +9458,12 @@ package body Sem_Ch6 is
end if;
-- Here if type is not frozen yet. It is illegal to have a primitive
- -- equality declared in the private part if the type is visible.
+ -- equality declared in the private part if the type is visible
+ -- (RM 4.5.2(9.8)).
elsif not In_Same_List (Parent (Typ), Decl)
and then not Is_Limited_Type (Typ)
then
- -- Shouldn't we give an RM reference here???
-
if Ada_Version >= Ada_2012 then
Error_Msg_N
("equality operator appears too late<<", Eq_Op);
@@ -9817,7 +9794,8 @@ package body Sem_Ch6 is
-- conform when they do not, e.g. by converting 1+2 into 3.
function FCE (Given_E1 : Node_Id; Given_E2 : Node_Id) return Boolean;
- -- ???
+ -- Convenience function to abbreviate recursive calls to
+ -- Fully_Conformant_Expressions without having to pass Report.
function FCL (L1 : List_Id; L2 : List_Id) return Boolean;
-- Compare elements of two lists for conformance. Elements have to be
@@ -10419,6 +10397,7 @@ package body Sem_Ch6 is
begin
Set_Is_Immediately_Visible (E);
Set_Current_Entity (E);
+ pragma Assert (Prev /= E);
Set_Homonym (E, Prev);
end Install_Entity;
@@ -10778,7 +10757,7 @@ package body Sem_Ch6 is
Error_Msg_Node_2 := F_Typ;
Error_Msg_NE
("private operation& in generic unit does not override "
- & "any primitive operation of& (RM 12.3 (18))??",
+ & "any primitive operation of& (RM 12.3(18))??",
New_E, New_E);
end if;
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index f30a9aa..3852a9a 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -1768,14 +1768,34 @@ package body Sem_Ch7 is
end if;
-- Check preelaborable initialization for full type completing a
- -- private type for which pragma Preelaborable_Initialization given.
+ -- private type when aspect Preelaborable_Initialization is True
+ -- or is specified by Preelaborable_Initialization attributes
+ -- (in the case of a private type in a generic unit). We pass
+ -- the expression of the aspect (when present) to the parameter
+ -- Preelab_Init_Expr to take into account the rule that presumes
+ -- that subcomponents of generic formal types mentioned in the
+ -- type's P_I aspect have preelaborable initialization (see
+ -- AI12-0409 and RM 10.2.1(11.8/5)).
+
+ if Is_Type (E) and then Must_Have_Preelab_Init (E) then
+ declare
+ PI_Aspect : constant Node_Id :=
+ Find_Aspect
+ (E, Aspect_Preelaborable_Initialization);
+ PI_Expr : Node_Id := Empty;
+ begin
+ if Present (PI_Aspect) then
+ PI_Expr := Expression (PI_Aspect);
+ end if;
- if Is_Type (E)
- and then Must_Have_Preelab_Init (E)
- and then not Has_Preelaborable_Initialization (E)
- then
- Error_Msg_N
- ("full view of & does not have preelaborable initialization", E);
+ if not Has_Preelaborable_Initialization
+ (E, Preelab_Init_Expr => PI_Expr)
+ then
+ Error_Msg_N
+ ("full view of & does not have "
+ & "preelaborable initialization", E);
+ end if;
+ end;
end if;
Next_Entity (E);
@@ -1891,7 +1911,7 @@ package body Sem_Ch7 is
begin
Generate_Definition (Id);
Set_Is_Pure (Id, PF);
- Init_Size_Align (Id);
+ Reinit_Size_Align (Id);
if not Is_Package_Or_Generic_Package (Current_Scope)
or else In_Private_Part (Current_Scope)
@@ -2568,7 +2588,7 @@ package body Sem_Ch7 is
Set_Etype (Id, Id);
Set_Has_Delayed_Freeze (Id);
Set_Is_First_Subtype (Id);
- Init_Size_Align (Id);
+ Reinit_Size_Align (Id);
Set_Is_Constrained (Id,
No (Discriminant_Specifications (N))
@@ -2728,7 +2748,7 @@ package body Sem_Ch7 is
begin
Set_Size_Info (Priv, Full);
- Set_RM_Size (Priv, RM_Size (Full));
+ Copy_RM_Size (To => Priv, From => Full);
Set_Size_Known_At_Compile_Time
(Priv, Size_Known_At_Compile_Time (Full));
Set_Is_Volatile (Priv, Is_Volatile (Full));
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 78d2426..494ec64 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -426,12 +426,10 @@ package body Sem_Ch8 is
-- body at the point of freezing will not work. Subp is the subprogram
-- for which N provides the Renaming_As_Body.
- procedure Check_In_Previous_With_Clause
- (N : Node_Id;
- Nam : Node_Id);
+ procedure Check_In_Previous_With_Clause (N, Nam : Node_Id);
-- N is a use_package clause and Nam the package name, or N is a use_type
-- clause and Nam is the prefix of the type name. In either case, verify
- -- that the package is visible at that point in the context: either it
+ -- that the package is visible at that point in the context: either it
-- appears in a previous with_clause, or because it is a fully qualified
-- name and the root ancestor appears in a previous with_clause.
@@ -1461,7 +1459,7 @@ package body Sem_Ch8 is
Mutate_Ekind (Id, E_Variable);
end if;
- Init_Object_Size_Align (Id);
+ Reinit_Object_Size_Align (Id);
-- If N comes from source then check that the original node is an
-- object reference since there may have been several rewritting and
@@ -2541,8 +2539,8 @@ package body Sem_Ch8 is
and then Is_Class_Wide_Type (Get_Instance_Of (Etype (Formal)))
then
Formal_Typ := Etype (Formal);
- Actual_Typ := Get_Instance_Of (Formal_Typ);
- Root_Typ := Etype (Actual_Typ);
+ Actual_Typ := Base_Type (Get_Instance_Of (Formal_Typ));
+ Root_Typ := Root_Type (Actual_Typ);
exit;
end if;
@@ -2592,6 +2590,15 @@ package body Sem_Ch8 is
elsif CW_Prim_Op = Root_Prim_Op then
Prim_Op := Root_Prim_Op;
+ -- The two subprograms are legal but the class-wide subprogram is
+ -- a class-wide wrapper built for a previous instantiation; the
+ -- wrapper has precedence.
+
+ elsif Present (Alias (CW_Prim_Op))
+ and then Is_Class_Wide_Wrapper (Ultimate_Alias (CW_Prim_Op))
+ then
+ Prim_Op := CW_Prim_Op;
+
-- Otherwise both candidate subprograms are user-defined and
-- ambiguous.
@@ -2690,6 +2697,8 @@ package body Sem_Ch8 is
Set_Corresponding_Body (Spec_Decl, Defining_Entity (Body_Decl));
end if;
+ Set_Is_Class_Wide_Wrapper (Wrap_Id);
+
-- If the operator carries an Eliminated pragma, indicate that the
-- wrapper is also to be eliminated, to prevent spurious error when
-- using gnatelim on programs that include box-initialization of
@@ -4670,10 +4679,7 @@ package body Sem_Ch8 is
-- Check_In_Previous_With_Clause --
-----------------------------------
- procedure Check_In_Previous_With_Clause
- (N : Node_Id;
- Nam : Entity_Id)
- is
+ procedure Check_In_Previous_With_Clause (N, Nam : Node_Id) is
Pack : constant Entity_Id := Entity (Original_Node (Nam));
Item : Node_Id;
Par : Node_Id;
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index ab25dd0..5293efb 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -2024,7 +2024,7 @@ package body Sem_Ch9 is
Mutate_Ekind (T, E_Protected_Type);
Set_Is_First_Subtype (T);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Etype (T, T);
Set_Has_Delayed_Freeze (T);
Set_Stored_Constraint (T, No_Elist);
@@ -2143,7 +2143,7 @@ package body Sem_Ch9 is
while Present (E) loop
if Ekind (E) = E_Void then
Mutate_Ekind (E, E_Component);
- Init_Component_Location (E);
+ Reinit_Component_Location (E);
end if;
Next_Entity (E);
@@ -3151,7 +3151,7 @@ package body Sem_Ch9 is
Mutate_Ekind (T, E_Task_Type);
Set_Is_First_Subtype (T, True);
Set_Has_Task (T, True);
- Init_Size_Align (T);
+ Reinit_Size_Align (T);
Set_Etype (T, T);
Set_Has_Delayed_Freeze (T, True);
Set_Stored_Constraint (T, No_Elist);
diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb
index b303229..538da57 100644
--- a/gcc/ada/sem_dim.adb
+++ b/gcc/ada/sem_dim.adb
@@ -318,7 +318,7 @@ package body Sem_Dim is
(N : Node_Id;
Description_Needed : Boolean := False) return String;
-- Given a node N, return the dimension symbols of N, preceded by "has
- -- dimension" if Description_Needed. if N is dimensionless, return "'[']",
+ -- dimension" if Description_Needed. If N is dimensionless, return "'[']",
-- or "is dimensionless" if Description_Needed.
function Dimension_System_Root (T : Entity_Id) return Entity_Id;
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 064e2b5..cba3c9d 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -32,9 +32,11 @@ with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Exp_Disp; use Exp_Disp;
with Exp_Util; use Exp_Util;
+with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
with Exp_Tss; use Exp_Tss;
with Errout; use Errout;
+with Freeze; use Freeze;
with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
with Nlists; use Nlists;
@@ -197,6 +199,91 @@ package body Sem_Disp is
return Empty;
end Covered_Interface_Op;
+ ----------------------------------
+ -- Covered_Interface_Primitives --
+ ----------------------------------
+
+ function Covered_Interface_Primitives (Prim : Entity_Id) return Elist_Id is
+ Tagged_Type : constant Entity_Id := Find_Dispatching_Type (Prim);
+ Elmt : Elmt_Id;
+ E : Entity_Id;
+ Result : Elist_Id := No_Elist;
+
+ begin
+ pragma Assert (Is_Dispatching_Operation (Prim));
+
+ -- Although this is a dispatching primitive we must check if its
+ -- dispatching type is available because it may be the primitive
+ -- of a private type not defined as tagged in its partial view.
+
+ if Present (Tagged_Type) and then Has_Interfaces (Tagged_Type) then
+
+ -- If the tagged type is frozen then the internal entities associated
+ -- with interfaces are available in the list of primitives of the
+ -- tagged type and can be used to speed up this search.
+
+ if Is_Frozen (Tagged_Type) then
+ Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
+ while Present (Elmt) loop
+ E := Node (Elmt);
+
+ if Present (Interface_Alias (E))
+ and then Alias (E) = Prim
+ then
+ if No (Result) then
+ Result := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Interface_Alias (E), Result);
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ -- Otherwise we must collect all the interface primitives and check
+ -- whether the Prim overrides (implements) some interface primitive.
+
+ else
+ declare
+ Ifaces_List : Elist_Id;
+ Iface_Elmt : Elmt_Id;
+ Iface : Entity_Id;
+ Iface_Prim : Entity_Id;
+
+ begin
+ Collect_Interfaces (Tagged_Type, Ifaces_List);
+
+ Iface_Elmt := First_Elmt (Ifaces_List);
+ while Present (Iface_Elmt) loop
+ Iface := Node (Iface_Elmt);
+
+ Elmt := First_Elmt (Primitive_Operations (Iface));
+ while Present (Elmt) loop
+ Iface_Prim := Node (Elmt);
+
+ if Chars (Iface_Prim) = Chars (Prim)
+ and then Is_Interface_Conformant
+ (Tagged_Type, Iface_Prim, Prim)
+ then
+ if No (Result) then
+ Result := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Iface_Prim, Result);
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ Next_Elmt (Iface_Elmt);
+ end loop;
+ end;
+ end if;
+ end if;
+
+ return Result;
+ end Covered_Interface_Primitives;
+
-------------------------------
-- Check_Controlling_Formals --
-------------------------------
@@ -592,6 +679,14 @@ package body Sem_Disp is
-- Start of processing for Check_Dispatching_Context
begin
+ -- Skip checking context of dispatching calls during preanalysis of
+ -- class-wide conditions since at that stage the expression is not
+ -- installed yet on its definite context.
+
+ if Inside_Class_Condition_Preanalysis then
+ return;
+ end if;
+
-- If the called subprogram is a private overriding, replace it
-- with its alias, which has the correct body. Verify that the
-- two subprograms have the same controlling type (this is not the
@@ -992,10 +1087,17 @@ package body Sem_Disp is
-- nonstatic values, then report an error. This is specified by
-- RM 6.1.1(18.2/5) (by AI12-0412).
+ -- Skip reporting this error on helpers and indirect-call wrappers
+ -- built to support class-wide preconditions.
+
if No (Control)
and then not Is_Abstract_Subprogram (Subp_Entity)
and then
Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Subp_Entity)
+ and then not
+ (Is_Subprogram (Current_Scope)
+ and then
+ Present (Class_Preconditions_Subprogram (Current_Scope)))
then
Error_Msg_N
("nondispatching call to nonabstract subprogram of "
@@ -1018,6 +1120,9 @@ package body Sem_Disp is
---------------------------------
procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id) is
+ function Is_Access_To_Subprogram_Wrapper (E : Entity_Id) return Boolean;
+ -- Return True if E is an access to subprogram wrapper
+
procedure Warn_On_Late_Primitive_After_Private_Extension
(Typ : Entity_Id;
Prim : Entity_Id);
@@ -1025,6 +1130,22 @@ package body Sem_Disp is
-- if it is a public primitive defined after some private extension of
-- the tagged type.
+ -------------------------------------
+ -- Is_Access_To_Subprogram_Wrapper --
+ -------------------------------------
+
+ function Is_Access_To_Subprogram_Wrapper (E : Entity_Id) return Boolean
+ is
+ Decl_N : constant Node_Id := Unit_Declaration_Node (E);
+ Par_N : constant Node_Id := Parent (List_Containing (Decl_N));
+
+ begin
+ -- Access to subprogram wrappers are declared in the freezing actions
+
+ return Nkind (Par_N) = N_Freeze_Entity
+ and then Ekind (Entity (Par_N)) = E_Access_Subprogram_Type;
+ end Is_Access_To_Subprogram_Wrapper;
+
----------------------------------------------------
-- Warn_On_Late_Primitive_After_Private_Extension --
----------------------------------------------------
@@ -1095,6 +1216,13 @@ package body Sem_Disp is
or else Is_Partial_Invariant_Procedure (Subp)
then
return;
+
+ -- Wrappers of access to subprograms are not primitive subprograms.
+
+ elsif Is_Wrapper (Subp)
+ and then Is_Access_To_Subprogram_Wrapper (Subp)
+ then
+ return;
end if;
Set_Is_Dispatching_Operation (Subp, False);
@@ -1407,7 +1535,39 @@ package body Sem_Disp is
Generate_Reference (Tagged_Type, Subp, 'P', False);
Override_Dispatching_Operation
(Tagged_Type, Old_Subp, Subp);
+ Set_Is_Dispatching_Operation (Subp);
+
+ -- Inherit decoration of controlling formals and
+ -- controlling result.
+
+ if Ekind (Old_Subp) = E_Function
+ and then Has_Controlling_Result (Old_Subp)
+ then
+ Set_Has_Controlling_Result (Subp);
+ end if;
+
+ if Present (First_Formal (Old_Subp)) then
+ declare
+ Old_Formal : Entity_Id;
+ Formal : Entity_Id;
+
+ begin
+ Formal := First_Formal (Subp);
+ Old_Formal := First_Formal (Old_Subp);
+
+ while Present (Old_Formal) loop
+ Set_Is_Controlling_Formal (Formal,
+ Is_Controlling_Formal (Old_Formal));
+
+ Next_Formal (Formal);
+ Next_Formal (Old_Formal);
+ end loop;
+ end;
+ end if;
end if;
+
+ Check_Inherited_Conditions (Tagged_Type,
+ Late_Overriding => True);
end if;
end if;
end;
@@ -2420,12 +2580,27 @@ package body Sem_Disp is
if No (Tag_Typ) then
return Result (1 .. 0);
+
+ -- Prevent cascaded errors
+
+ elsif Is_Concurrent_Type (Tag_Typ)
+ and then No (Corresponding_Record_Type (Tag_Typ))
+ and then Serious_Errors_Detected > 0
+ then
+ return Result (1 .. 0);
end if;
if Is_Concurrent_Type (Tag_Typ) then
Tag_Typ := Corresponding_Record_Type (Tag_Typ);
end if;
+ if Present (Tag_Typ)
+ and then Is_Private_Type (Tag_Typ)
+ and then Present (Full_View (Tag_Typ))
+ then
+ Tag_Typ := Full_View (Tag_Typ);
+ end if;
+
-- Search primitive operations of dispatching type
if Present (Tag_Typ)
@@ -2855,6 +3030,11 @@ package body Sem_Disp is
Next_Actual (Arg);
end loop;
+ -- Add class-wide precondition check if the target of this dispatching
+ -- call has or inherits class-wide preconditions.
+
+ Install_Class_Preconditions_Check (Call_Node);
+
-- Expansion of dispatching calls is suppressed on VM targets, because
-- the VM back-ends directly handle the generation of dispatching calls
-- and would have to undo any expansion to an indirect call.
diff --git a/gcc/ada/sem_disp.ads b/gcc/ada/sem_disp.ads
index 7b42cf5..f37391b 100644
--- a/gcc/ada/sem_disp.ads
+++ b/gcc/ada/sem_disp.ads
@@ -74,6 +74,10 @@ package Sem_Disp is
-- The Alias of Old_Subp is adjusted to point to the inherited procedure
-- of the full view because it is always this one which has to be called.
+ function Covered_Interface_Primitives (Prim : Entity_Id) return Elist_Id;
+ -- Returns all the interface primitives covered by Prim, when its
+ -- controlling type has progenitors.
+
function Covered_Interface_Op (Prim : Entity_Id) return Entity_Id;
-- Returns the interface primitive that Prim covers, when its controlling
-- type has progenitors.
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index f6edcac..1fbe037 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -1308,15 +1308,11 @@ package body Sem_Elab is
-- is set, then string " in SPARK" is added to the end of the message.
procedure Info_Variable_Reference
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean);
+ (Ref : Node_Id;
+ Var_Id : Entity_Id);
pragma Inline (Info_Variable_Reference);
-- Output information concerning reference Ref which mentions variable
- -- Var_Id. If flag Info_Msg is set, the routine emits an information
- -- message, otherwise it emits an error. If flag In_SPARK is set, then
- -- string " in SPARK" is added to the end of the message.
+ -- Var_Id. The routine emits an error suffixed with " in SPARK".
end Diagnostics;
use Diagnostics;
@@ -2070,7 +2066,7 @@ package body Sem_Elab is
-- Change the status of the elaboration phase of the compiler to Status
procedure Spec_And_Body_From_Entity
- (Id : Node_Id;
+ (Id : Entity_Id;
Spec_Decl : out Node_Id;
Body_Decl : out Node_Id);
pragma Inline (Spec_And_Body_From_Entity);
@@ -3036,11 +3032,9 @@ package body Sem_Elab is
pragma Inline (Nested_Scenarios);
-- Obtain the list of scenarios associated with subprogram body N
- procedure Set_Is_Traversed_Body
- (N : Node_Id;
- Val : Boolean := True);
+ procedure Set_Is_Traversed_Body (N : Node_Id);
pragma Inline (Set_Is_Traversed_Body);
- -- Mark subprogram body N as traversed depending on value Val
+ -- Mark subprogram body N as traversed
procedure Set_Nested_Scenarios
(N : Node_Id;
@@ -3105,18 +3099,11 @@ package body Sem_Elab is
-- Set_Is_Traversed_Body --
---------------------------
- procedure Set_Is_Traversed_Body
- (N : Node_Id;
- Val : Boolean := True)
- is
+ procedure Set_Is_Traversed_Body (N : Node_Id) is
pragma Assert (Present (N));
begin
- if Val then
- NE_Set.Insert (Traversed_Bodies_Set, N);
- else
- NE_Set.Delete (Traversed_Bodies_Set, N);
- end if;
+ NE_Set.Insert (Traversed_Bodies_Set, N);
end Set_Is_Traversed_Body;
--------------------------
@@ -6697,10 +6684,8 @@ package body Sem_Elab is
-----------------------------
procedure Info_Variable_Reference
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean)
+ (Ref : Node_Id;
+ Var_Id : Entity_Id)
is
begin
if Is_Read (Ref) then
@@ -6708,8 +6693,8 @@ package body Sem_Elab is
(Msg => "read of variable & during elaboration",
N => Ref,
Id => Var_Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
+ Info_Msg => False,
+ In_SPARK => True);
end if;
end Info_Variable_Reference;
end Diagnostics;
@@ -8638,10 +8623,8 @@ package body Sem_Elab is
elsif Is_Suitable_Variable_Reference (N) then
Info_Variable_Reference
- (Ref => N,
- Var_Id => Targ_Id,
- Info_Msg => False,
- In_SPARK => True);
+ (Ref => N,
+ Var_Id => Targ_Id);
-- No other scenario may impose a requirement on the context of
-- the main unit.
@@ -11805,19 +11788,15 @@ package body Sem_Elab is
-- by creating an entry for it in the ALI file of the main unit. Formal
-- In_State denotes the current state of the Processing phase.
- procedure Set_Is_Saved_Construct
- (Constr : Entity_Id;
- Val : Boolean := True);
+ procedure Set_Is_Saved_Construct (Constr : Entity_Id);
pragma Inline (Set_Is_Saved_Construct);
-- Mark invocation construct Constr as declared in the ALI file of the
- -- main unit depending on value Val.
+ -- main unit.
- procedure Set_Is_Saved_Relation
- (Rel : Invoker_Target_Relation;
- Val : Boolean := True);
+ procedure Set_Is_Saved_Relation (Rel : Invoker_Target_Relation);
pragma Inline (Set_Is_Saved_Relation);
-- Mark simple invocation relation Rel as recorded in the ALI file of
- -- the main unit depending on value Val.
+ -- the main unit.
function Target_Of
(Pos : Active_Scenario_Pos;
@@ -13307,34 +13286,20 @@ package body Sem_Elab is
-- Set_Is_Saved_Construct --
----------------------------
- procedure Set_Is_Saved_Construct
- (Constr : Entity_Id;
- Val : Boolean := True)
- is
+ procedure Set_Is_Saved_Construct (Constr : Entity_Id) is
pragma Assert (Present (Constr));
begin
- if Val then
- NE_Set.Insert (Saved_Constructs_Set, Constr);
- else
- NE_Set.Delete (Saved_Constructs_Set, Constr);
- end if;
+ NE_Set.Insert (Saved_Constructs_Set, Constr);
end Set_Is_Saved_Construct;
---------------------------
-- Set_Is_Saved_Relation --
---------------------------
- procedure Set_Is_Saved_Relation
- (Rel : Invoker_Target_Relation;
- Val : Boolean := True)
- is
+ procedure Set_Is_Saved_Relation (Rel : Invoker_Target_Relation) is
begin
- if Val then
- IR_Set.Insert (Saved_Relations_Set, Rel);
- else
- IR_Set.Delete (Saved_Relations_Set, Rel);
- end if;
+ IR_Set.Insert (Saved_Relations_Set, Rel);
end Set_Is_Saved_Relation;
------------------
@@ -13621,6 +13586,13 @@ package body Sem_Elab is
then
return True;
+ -- A call to an expression function that is not a completion cannot
+ -- cause an ABE because it has no prior declaration; this remains
+ -- true even if the FE transforms the callee into something else.
+
+ elsif Nkind (Original_Node (Spec_Decl)) = N_Expression_Function then
+ return True;
+
-- Subprogram bodies which wrap attribute references used as actuals
-- in instantiations are always ABE-safe. These bodies are artifacts
-- of expansion.
@@ -15835,7 +15807,7 @@ package body Sem_Elab is
-------------------------------
procedure Spec_And_Body_From_Entity
- (Id : Node_Id;
+ (Id : Entity_Id;
Spec_Decl : out Node_Id;
Body_Decl : out Node_Id)
is
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index a3a2864..20bc03a 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -118,7 +118,8 @@ package body Sem_Eval is
subtype CV_Range is Nat range 0 .. CV_Cache_Size;
type CV_Entry is record
- N : Node_Id;
+ N : Node_Id'Base;
+ -- We use 'Base here, in case we want to add a predicate to Node_Id
V : Uint;
end record;
@@ -3069,7 +3070,7 @@ package body Sem_Eval is
-- Note that in this case, both Right_Int and Left_Int are set
-- to No_Uint, so need to test for both.
- if Right_Int = No_Uint then
+ if No (Right_Int) then
Fold_Uint (N, Uint_0, Stat);
else
Fold_Uint (N,
@@ -3083,7 +3084,7 @@ package body Sem_Eval is
-- Note that in this case, both Right_Int and Left_Int are set
-- to No_Uint, so need to test for both.
- if Right_Int = No_Uint then
+ if No (Right_Int) then
Fold_Uint (N, Uint_1, Stat);
else
Fold_Uint (N,
@@ -5063,12 +5064,20 @@ package body Sem_Eval is
-- 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);
+ declare
+ M : Unat;
+ begin
+ if Expr_Value (Left) >= Uint_0 then
+ M := Uint_0;
+ else
+ M := Modulus;
+ end if;
+
+ Fold_Uint
+ (N,
+ (Expr_Value (Left) + M) / (Uint_2 ** Expr_Value (Right)),
+ Static => Static);
+ end;
end if;
elsif Op = N_Op_Shift_Right_Arithmetic then
Check_Elab_Call;
@@ -5741,6 +5750,8 @@ package body Sem_Eval is
elsif Has_Dynamic_Predicate_Aspect (Typ)
or else (Is_Derived_Type (Typ)
and then Has_Aspect (Typ, Aspect_Dynamic_Predicate))
+ or else (Has_Aspect (Typ, Aspect_Predicate)
+ and then not Has_Static_Predicate (Typ))
then
return False;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 0ff4e49..b3fa32a 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -6678,9 +6678,7 @@ package body Sem_Prag is
then
Pragma_Misplaced;
- elsif (Nkind (Parent_Node) = N_Generic_Package_Declaration
- or else Nkind (Parent_Node) =
- N_Generic_Subprogram_Declaration)
+ elsif Nkind (Parent_Node) in N_Generic_Declaration
and then Plist = Generic_Formal_Declarations (Parent_Node)
then
Pragma_Misplaced;
@@ -7562,7 +7560,7 @@ package body Sem_Prag is
end if;
if not Has_Alignment_Clause (Ent) then
- Init_Alignment (Ent);
+ Reinit_Alignment (Ent);
end if;
end Set_Atomic_VFA;
@@ -9532,7 +9530,11 @@ package body Sem_Prag is
Process_Import_Predefined_Type;
- else
+ -- Emit an error unless Relaxed_RM_Semantics since some legacy Ada
+ -- compilers may accept more cases, e.g. JGNAT allowed importing
+ -- a Java package.
+
+ elsif not Relaxed_RM_Semantics then
if From_Aspect_Specification (N) then
Error_Pragma_Arg
("entity for aspect% must be object, subprogram "
@@ -13400,11 +13402,11 @@ package body Sem_Prag is
Obj_Or_Type_Id := Defining_Entity (Obj_Or_Type_Decl);
-- Perform minimal verification to ensure that the argument is at
- -- least a variable or a type. Subsequent finer grained checks
- -- will be done at the end of the declarative region that
- -- contains the pragma.
+ -- least an object or a type. Subsequent finer grained checks will
+ -- be done at the end of the declarative region that contains the
+ -- pragma.
- if Ekind (Obj_Or_Type_Id) = E_Variable
+ if Ekind (Obj_Or_Type_Id) in E_Constant | E_Variable
or else Is_Type (Obj_Or_Type_Id)
then
@@ -14202,6 +14204,16 @@ package body Sem_Prag is
when Pragma_Compile_Time_Error | Pragma_Compile_Time_Warning =>
GNAT_Pragma;
+
+ -- These pragmas rely on the context. In adc files they raise
+ -- Constraint_Error. Ban them from use as configuration pragmas
+ -- even in cases where such a use could work.
+
+ if Is_Configuration_Pragma then
+ Error_Pragma
+ ("pragma% is not allowed as a configuration pragma");
+ end if;
+
Process_Compile_Time_Warning_Or_Error;
---------------------------
@@ -14835,9 +14847,41 @@ package body Sem_Prag is
& "effect?j?", N);
end if;
- --------------------
+ -----------------
+ -- CUDA_Device --
+ -----------------
+
+ when Pragma_CUDA_Device => CUDA_Device : declare
+ Arg_Node : Node_Id;
+ Device_Entity : Entity_Id;
+ begin
+ GNAT_Pragma;
+ Check_Arg_Count (1);
+ Check_Arg_Is_Library_Level_Local_Name (Arg1);
+
+ Arg_Node := Get_Pragma_Arg (Arg1);
+ Device_Entity := Entity (Arg_Node);
+
+ if Ekind (Device_Entity) in E_Variable
+ | E_Constant
+ | E_Procedure
+ | E_Function
+ then
+ Add_CUDA_Device_Entity
+ (Package_Specification_Of_Scope (Scope (Device_Entity)),
+ Device_Entity);
+
+ else
+ Error_Msg_NE ("& must be constant, variable or subprogram",
+ N,
+ Device_Entity);
+ end if;
+
+ end CUDA_Device;
+
+ ------------------
-- CUDA_Execute --
- --------------------
+ ------------------
-- pragma CUDA_Execute (PROCEDURE_CALL_STATEMENT,
-- EXPRESSION,
@@ -25892,23 +25936,6 @@ package body Sem_Prag is
("operation in class-wide condition must be primitive "
& "of &", Nod, Disp_Typ);
end if;
-
- -- Otherwise we have a call to an overridden primitive, and we
- -- will create a common class-wide clone for the body of
- -- original operation and its eventual inherited versions. If
- -- the original operation dispatches on result it is never
- -- inherited and there is no need for a clone. There is not
- -- need for a clone either in GNATprove mode, as cases that
- -- would require it are rejected (when an inherited primitive
- -- calls an overridden operation in a class-wide contract), and
- -- the clone would make proof impossible in some cases.
-
- elsif not Is_Abstract_Subprogram (Spec_Id)
- and then No (Class_Wide_Clone (Spec_Id))
- and then not Has_Controlling_Result (Spec_Id)
- and then not GNATprove_Mode
- then
- Build_Class_Wide_Clone_Decl (Spec_Id);
end if;
end;
@@ -26029,15 +26056,6 @@ package body Sem_Prag is
End_Scope;
end if;
- -- If analysis of the condition indicates that a class-wide clone
- -- has been created, build and analyze its declaration.
-
- if Is_Subprogram (Spec_Id)
- and then Present (Class_Wide_Clone (Spec_Id))
- then
- Analyze (Unit_Declaration_Node (Class_Wide_Clone (Spec_Id)));
- end if;
-
-- Currently it is not possible to inline pre/postconditions on a
-- subprogram subject to pragma Inline_Always.
@@ -29524,9 +29542,6 @@ package body Sem_Prag is
Msg_Arg : Node_Id;
Nam : Name_Id;
- Needs_Wrapper : Boolean;
- pragma Unreferenced (Needs_Wrapper);
-
-- Start of processing for Build_Pragma_Check_Equivalent
begin
@@ -29553,11 +29568,10 @@ package body Sem_Prag is
-- Build the inherited class-wide condition
Build_Class_Wide_Expression
- (Prag => Check_Prag,
- Subp => Subp_Id,
- Par_Subp => Inher_Id,
- Adjust_Sloc => True,
- Needs_Wrapper => Needs_Wrapper);
+ (Pragma_Or_Expr => Check_Prag,
+ Subp => Subp_Id,
+ Par_Subp => Inher_Id,
+ Adjust_Sloc => True);
-- If not an inherited condition simply copy the original pragma
@@ -31274,6 +31288,7 @@ package body Sem_Prag is
Pragma_C_Pass_By_Copy => 0,
Pragma_Comment => -1,
Pragma_Common_Object => 0,
+ Pragma_CUDA_Device => -1,
Pragma_CUDA_Execute => -1,
Pragma_CUDA_Global => -1,
Pragma_Compile_Time_Error => -1,
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
index e166481..fed24fd 100644
--- a/gcc/ada/sem_prag.ads
+++ b/gcc/ada/sem_prag.ads
@@ -49,6 +49,7 @@ package Sem_Prag is
Pragma_Contract_Cases => True,
Pragma_Convention => True,
Pragma_CPU => True,
+ Pragma_CUDA_Device => True,
Pragma_CUDA_Global => True,
Pragma_Default_Initial_Condition => True,
Pragma_Default_Storage_Pool => True,
@@ -429,7 +430,7 @@ package Sem_Prag is
function Get_Argument
(Prag : Node_Id;
- Context_Id : Node_Id := Empty) return Node_Id;
+ Context_Id : Entity_Id := Empty) return Node_Id;
-- Obtain the argument of pragma Prag depending on context and the nature
-- of the pragma. The argument is extracted in the following manner:
--
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 03d747e..0bdc463 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2920,6 +2920,16 @@ package body Sem_Res is
Expr : Node_Id;
begin
+ if Is_Derived_Type (Typ)
+ and then Is_Tagged_Type (Typ)
+ and then Base_Type (Etype (Callee)) /= Base_Type (Typ)
+ then
+ Callee :=
+ Corresponding_Primitive_Op
+ (Ancestor_Op => Callee,
+ Descendant_Type => Base_Type (Typ));
+ end if;
+
if Nkind (N) = N_Identifier then
Expr := Expression (Declaration_Node (Entity (N)));
@@ -2990,16 +3000,23 @@ package body Sem_Res is
Set_Etype (Call, Etype (Callee));
- -- Conversion needed in case of an inherited aspect
- -- of a derived type.
- --
- -- ??? Need to do something different here for downward
- -- tagged conversion case (which is only possible in the
- -- case of a null extension); the current call to
- -- Convert_To results in an error message about an illegal
- -- downward conversion.
+ if Base_Type (Etype (Call)) /= Base_Type (Typ) then
+ -- Conversion may be needed in case of an inherited
+ -- aspect of a derived type. For a null extension, we
+ -- use a null extension aggregate instead because the
+ -- downward type conversion would be illegal.
- Call := Convert_To (Typ, Call);
+ if Is_Null_Extension_Of
+ (Descendant => Typ,
+ Ancestor => Etype (Call))
+ then
+ Call := Make_Extension_Aggregate (Loc,
+ Ancestor_Part => Call,
+ Null_Record_Present => True);
+ else
+ Call := Convert_To (Typ, Call);
+ end if;
+ end if;
Rewrite (N, Call);
end;
@@ -3081,6 +3098,24 @@ package body Sem_Res is
Error_Msg_N ("\use -gnatf for details", N);
end if;
+ -- Recognize the case of a quantified expression being mistaken
+ -- for an iterated component association because the user
+ -- forgot the "all" or "some" keyword after "for". Because the
+ -- error message starts with "missing ALL", we automatically
+ -- benefit from the associated CODEFIX, which requires that
+ -- the message is located on the identifier following "for"
+ -- in order for the CODEFIX to insert "all" in the right place.
+
+ elsif Nkind (N) = N_Aggregate
+ and then List_Length (Component_Associations (N)) = 1
+ and then Nkind (First (Component_Associations (N)))
+ = N_Iterated_Component_Association
+ and then Is_Boolean_Type (Typ)
+ then
+ Error_Msg_N -- CODEFIX
+ ("missing ALL or SOME in quantified expression",
+ Defining_Identifier (First (Component_Associations (N))));
+
else
Wrong_Type (N, Typ);
end if;
@@ -3454,7 +3489,6 @@ package body Sem_Res is
procedure Resolve_Actuals (N : Node_Id; Nam : Entity_Id) is
Loc : constant Source_Ptr := Sloc (N);
A : Node_Id;
- A_Id : Entity_Id;
A_Typ : Entity_Id := Empty; -- init to avoid warning
F : Entity_Id;
F_Typ : Entity_Id;
@@ -4875,10 +4909,15 @@ package body Sem_Res is
-- Apply legality rule 3.9.2 (9/1)
+ -- Skip this check on helpers and indirect-call wrappers built to
+ -- support class-wide preconditions.
+
if (Is_Class_Wide_Type (A_Typ) or else Is_Dynamically_Tagged (A))
and then not Is_Class_Wide_Type (F_Typ)
and then not Is_Controlling_Formal (F)
and then not In_Instance
+ and then (not Is_Subprogram (Nam)
+ or else No (Class_Preconditions_Subprogram (Nam)))
then
Error_Msg_N ("class-wide argument not allowed here!", A);
@@ -4969,31 +5008,6 @@ package body Sem_Res is
-- must be resolved first.
Flag_Effectively_Volatile_Objects (A);
-
- -- An effectively volatile variable cannot act as an actual
- -- parameter in a procedure call when the variable has enabled
- -- property Effective_Reads and the corresponding formal is of
- -- mode IN (SPARK RM 7.1.3(10)).
-
- if Ekind (Nam) = E_Procedure
- and then Ekind (F) = E_In_Parameter
- and then Is_Entity_Name (A)
- then
- A_Id := Entity (A);
-
- if Ekind (A_Id) = E_Variable
- and then Is_Effectively_Volatile_For_Reading (Etype (A_Id))
- and then Effective_Reads_Enabled (A_Id)
- then
- Error_Msg_NE
- ("effectively volatile variable & cannot appear as "
- & "actual in procedure call", A, A_Id);
-
- Error_Msg_Name_1 := Name_Effective_Reads;
- Error_Msg_N ("\\variable has enabled property %", A);
- Error_Msg_N ("\\corresponding formal has mode IN", A);
- end if;
- end if;
end if;
-- A formal parameter of a specific tagged type whose related
@@ -5001,9 +5015,13 @@ package body Sem_Res is
-- "False" cannot act as an actual in a subprogram with value
-- "True" (SPARK RM 6.1.7(3)).
+ -- No check needed for helpers and indirect-call wrappers built to
+ -- support class-wide preconditions.
+
if Is_EVF_Expression (A)
and then Extensions_Visible_Status (Nam) =
Extensions_Visible_True
+ and then No (Class_Preconditions_Subprogram (Current_Scope))
then
Error_Msg_N
("formal parameter cannot act as actual parameter when "
@@ -7487,66 +7505,76 @@ package body Sem_Res is
(N : Node_Id;
Typ : Entity_Id)
is
- 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
- -- declarations, in analogy with block statements.
- -- Note that that scope has no explicit declaration, but
- -- appears as the scope of all entities declared therein.
+ Expr : constant Node_Id := Expression (N);
- Decl := First (Actions (N));
- while Present (Decl) loop
- exit when Nkind (Decl)
- in N_Object_Declaration | N_Object_Renaming_Declaration;
- Next (Decl);
- end loop;
+ Decl : Node_Id;
+ Local : Entity_Id := Empty;
- if Present (Decl) then
+ function Replace_Local (N : Node_Id) return Traverse_Result;
+ -- Use a tree traversal to replace each ocurrence of the name of
+ -- a local object declared in the construct, with the corresponding
+ -- entity. This replaces the usual way to perform name capture by
+ -- visibility, because it is not possible to place on the scope
+ -- stack the fake scope created for the analysis of the local
+ -- declarations; such a scope conflicts with the transient scopes
+ -- that may be generated if the expression includes function calls
+ -- requiring finalization.
- -- Need to establish a transient scope in case Expression (N)
- -- requires actions to be wrapped.
+ -------------------
+ -- Replace_Local --
+ -------------------
- declare
- 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;
+ function Replace_Local (N : Node_Id) return Traverse_Result is
+ begin
+ -- The identifier may be the prefix of a selected component,
+ -- but not a selector name, because the local entities do not
+ -- have a scope that can be named: a selected component whose
+ -- selector is a homonym of a local entity must denote some
+ -- global entity.
+
+ if Nkind (N) = N_Identifier
+ and then Chars (N) = Chars (Local)
+ and then No (Entity (N))
+ and then
+ (Nkind (Parent (N)) /= N_Selected_Component
+ or else N = Prefix (Parent (N)))
+ then
+ Set_Entity (N, Local);
+ Set_Etype (N, Etype (Local));
+ end if;
- Next (Node);
- end loop;
- end;
+ return OK;
+ end Replace_Local;
- if Need_Transient_Scope then
- Establish_Transient_Scope (Decl, Manage_Sec_Stack => True);
- else
- Push_Scope (Scope (Defining_Identifier (Decl)));
+ procedure Replace_Local_Ref is new Traverse_Proc (Replace_Local);
+
+ -- Start of processing for Resolve_Declare_Expression
+
+ begin
+
+ Decl := First (Actions (N));
+
+ while Present (Decl) loop
+ if Nkind (Decl) in
+ N_Object_Declaration | N_Object_Renaming_Declaration
+ and then Comes_From_Source (Defining_Identifier (Decl))
+ then
+ Local := Defining_Identifier (Decl);
+ Replace_Local_Ref (Expr);
end if;
- declare
- E : Entity_Id := First_Entity (Current_Scope);
- begin
- while Present (E) loop
- Set_Current_Entity (E);
- Set_Is_Immediately_Visible (E);
- Next_Entity (E);
- end loop;
- end;
+ Next (Decl);
+ end loop;
- Resolve (Expression (N), Typ);
- End_Scope;
+ -- The end of the declarative list is a freeze point for the
+ -- local declarations.
- else
- Resolve (Expression (N), Typ);
+ if Present (Local) then
+ Decl := Parent (Local);
+ Freeze_All (First_Entity (Scope (Local)), Decl);
end if;
+
+ Resolve (Expr, Typ);
end Resolve_Declare_Expression;
-----------------------------------------
@@ -9243,7 +9271,7 @@ package body Sem_Res is
-------------------------------
procedure Resolve_Indexed_Component (N : Node_Id; Typ : Entity_Id) is
- Name : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
Expr : Node_Id;
Array_Type : Entity_Id := Empty; -- to prevent junk warning
Index : Node_Id;
@@ -9254,7 +9282,7 @@ package body Sem_Res is
return;
end if;
- if Is_Overloaded (Name) then
+ if Is_Overloaded (Pref) then
-- Use the context type to select the prefix that yields the correct
-- component type.
@@ -9263,11 +9291,10 @@ package body Sem_Res is
I : Interp_Index;
It : Interp;
I1 : Interp_Index := 0;
- P : constant Node_Id := Prefix (N);
Found : Boolean := False;
begin
- Get_First_Interp (P, I, It);
+ Get_First_Interp (Pref, I, It);
while Present (It.Typ) loop
if (Is_Array_Type (It.Typ)
and then Covers (Typ, Component_Type (It.Typ)))
@@ -9279,7 +9306,7 @@ package body Sem_Res is
Component_Type (Designated_Type (It.Typ))))
then
if Found then
- It := Disambiguate (P, I1, I, Any_Type);
+ It := Disambiguate (Pref, I1, I, Any_Type);
if It = No_Interp then
Error_Msg_N ("ambiguous prefix for indexing", N);
@@ -9304,11 +9331,11 @@ package body Sem_Res is
end;
else
- Array_Type := Etype (Name);
+ Array_Type := Etype (Pref);
end if;
- Resolve (Name, Array_Type);
- Array_Type := Get_Actual_Subtype_If_Available (Name);
+ Resolve (Pref, Array_Type);
+ Array_Type := Get_Actual_Subtype_If_Available (Pref);
-- If the prefix's type is an access type, get to the real array type.
-- Note: we do not apply an access check because an explicit dereference
@@ -9351,19 +9378,18 @@ package body Sem_Res is
end loop;
end if;
- Resolve_Implicit_Dereference (Prefix (N));
+ Resolve_Implicit_Dereference (Pref);
Analyze_Dimension (N);
-- Do not generate the warning on suspicious index if we are analyzing
-- package Ada.Tags; otherwise we will report the warning with the
-- Prims_Ptr field of the dispatch table.
- if Scope (Etype (Prefix (N))) = Standard_Standard
+ if Scope (Etype (Pref)) = Standard_Standard
or else not
- Is_RTU (Cunit_Entity (Get_Source_Unit (Etype (Prefix (N)))),
- Ada_Tags)
+ Is_RTU (Cunit_Entity (Get_Source_Unit (Etype (Pref))), Ada_Tags)
then
- Warn_On_Suspicious_Index (Name, First (Expressions (N)));
+ Warn_On_Suspicious_Index (Pref, First (Expressions (N)));
Eval_Indexed_Component (N);
end if;
@@ -9375,16 +9401,16 @@ package body Sem_Res is
if Nkind (N) = N_Indexed_Component
and then Is_Atomic_Ref_With_Address (N)
and then not (Has_Atomic_Components (Array_Type)
- or else (Is_Entity_Name (Prefix (N))
+ or else (Is_Entity_Name (Pref)
and then Has_Atomic_Components
- (Entity (Prefix (N)))))
+ (Entity (Pref))))
and then not Is_Atomic (Component_Type (Array_Type))
and then Ada_Version < Ada_2022
then
Error_Msg_N
- ("??access to non-atomic component of atomic array", Prefix (N));
+ ("??access to non-atomic component of atomic array", Pref);
Error_Msg_N
- ("??\may cause unexpected accesses to atomic object", Prefix (N));
+ ("??\may cause unexpected accesses to atomic object", Pref);
end if;
end Resolve_Indexed_Component;
@@ -11192,13 +11218,13 @@ package body Sem_Res is
procedure Resolve_Slice (N : Node_Id; Typ : Entity_Id) is
Drange : constant Node_Id := Discrete_Range (N);
- Name : constant Node_Id := Prefix (N);
+ Pref : constant Node_Id := Prefix (N);
Array_Type : Entity_Id := Empty;
Dexpr : Node_Id := Empty;
Index_Type : Entity_Id;
begin
- if Is_Overloaded (Name) then
+ if Is_Overloaded (Pref) then
-- Use the context type to select the prefix that yields the correct
-- array type.
@@ -11207,11 +11233,10 @@ package body Sem_Res is
I : Interp_Index;
I1 : Interp_Index := 0;
It : Interp;
- P : constant Node_Id := Prefix (N);
Found : Boolean := False;
begin
- Get_First_Interp (P, I, It);
+ Get_First_Interp (Pref, I, It);
while Present (It.Typ) loop
if (Is_Array_Type (It.Typ)
and then Covers (Typ, It.Typ))
@@ -11220,7 +11245,7 @@ package body Sem_Res is
and then Covers (Typ, Designated_Type (It.Typ)))
then
if Found then
- It := Disambiguate (P, I1, I, Any_Type);
+ It := Disambiguate (Pref, I1, I, Any_Type);
if It = No_Interp then
Error_Msg_N ("ambiguous prefix for slicing", N);
@@ -11243,10 +11268,10 @@ package body Sem_Res is
end;
else
- Array_Type := Etype (Name);
+ Array_Type := Etype (Pref);
end if;
- Resolve (Name, Array_Type);
+ Resolve (Pref, Array_Type);
-- If the prefix's type is an access type, get to the real array type.
-- Note: we do not apply an access check because an explicit dereference
@@ -11262,12 +11287,12 @@ package body Sem_Res is
-- subtype.
if not Is_Constrained (Array_Type) then
- Remove_Side_Effects (Prefix (N));
+ Remove_Side_Effects (Pref);
declare
Obj : constant Node_Id :=
Make_Explicit_Dereference (Sloc (N),
- Prefix => New_Copy_Tree (Prefix (N)));
+ Prefix => New_Copy_Tree (Pref));
begin
Set_Etype (Obj, Array_Type);
Set_Parent (Obj, Parent (N));
@@ -11275,25 +11300,35 @@ package body Sem_Res is
end;
end if;
- elsif Is_Entity_Name (Name)
- or else Nkind (Name) = N_Explicit_Dereference
- or else (Nkind (Name) = N_Function_Call
- and then not Is_Constrained (Etype (Name)))
+ -- In CodePeer mode the attribute Image is not expanded, so when it
+ -- acts as a prefix of a slice, we handle it like a call to function
+ -- returning an unconstrained string. Same for the Wide variants of
+ -- attribute Image.
+
+ elsif Is_Entity_Name (Pref)
+ or else Nkind (Pref) = N_Explicit_Dereference
+ or else (Nkind (Pref) = N_Function_Call
+ and then not Is_Constrained (Etype (Pref)))
+ or else (CodePeer_Mode
+ and then Nkind (Pref) = N_Attribute_Reference
+ and then Attribute_Name (Pref) in Name_Image
+ | Name_Wide_Image
+ | Name_Wide_Wide_Image)
then
- Array_Type := Get_Actual_Subtype (Name);
+ Array_Type := Get_Actual_Subtype (Pref);
-- If the name is a selected component that depends on discriminants,
-- build an actual subtype for it. This can happen only when the name
-- itself is overloaded; otherwise the actual subtype is created when
-- the selected component is analyzed.
- elsif Nkind (Name) = N_Selected_Component
+ elsif Nkind (Pref) = N_Selected_Component
and then Full_Analysis
and then Depends_On_Discriminant (First_Index (Array_Type))
then
declare
Act_Decl : constant Node_Id :=
- Build_Actual_Subtype_Of_Component (Array_Type, Name);
+ Build_Actual_Subtype_Of_Component (Array_Type, Pref);
begin
Insert_Action (N, Act_Decl);
Array_Type := Defining_Identifier (Act_Decl);
@@ -11306,8 +11341,8 @@ package body Sem_Res is
-- check applied below (the range check won't get done if the
-- unconstrained subtype of the 'Image is used).
- elsif Nkind (Name) = N_Slice then
- Array_Type := Etype (Name);
+ elsif Nkind (Pref) = N_Slice then
+ Array_Type := Etype (Pref);
end if;
-- Obtain the type of the array index
@@ -11330,27 +11365,32 @@ package body Sem_Res is
if Tagged_Type_Expansion
and then RTU_Loaded (Ada_Tags)
- and then Nkind (Prefix (N)) = N_Selected_Component
- and then Present (Entity (Selector_Name (Prefix (N))))
- and then Entity (Selector_Name (Prefix (N))) =
+ and then Nkind (Pref) = N_Selected_Component
+ and then Present (Entity (Selector_Name (Pref)))
+ and then Entity (Selector_Name (Pref)) =
RTE_Record_Component (RE_Prims_Ptr)
then
null;
- -- The discrete_range is specified by a subtype indication. Create a
- -- shallow copy and inherit the type, parent and source location from
- -- the discrete_range. This ensures that the range check is inserted
- -- relative to the slice and that the runtime exception points to the
- -- proper construct.
+ -- The discrete_range is specified by a subtype name. Create an
+ -- equivalent range attribute, apply checks to this attribute, but
+ -- insert them into the range expression of the slice itself.
elsif Is_Entity_Name (Drange) then
- Dexpr := New_Copy (Scalar_Range (Entity (Drange)));
+ Dexpr :=
+ Make_Attribute_Reference
+ (Sloc (Drange),
+ Prefix =>
+ New_Occurrence_Of (Entity (Drange), Sloc (Drange)),
+ Attribute_Name => Name_Range);
+
+ Analyze_And_Resolve (Dexpr, Etype (Drange));
- Set_Etype (Dexpr, Etype (Drange));
- Set_Parent (Dexpr, Parent (Drange));
- Set_Sloc (Dexpr, Sloc (Drange));
+ elsif Nkind (Drange) = N_Subtype_Indication then
+ Dexpr := Range_Expression (Constraint (Drange));
- -- The discrete_range is a regular range. Resolve the bounds and remove
+ -- The discrete_range is a regular range (or a range attribute, which
+ -- will be resolved into a regular range). Resolve the bounds and remove
-- their side effects.
else
@@ -11365,7 +11405,7 @@ package body Sem_Res is
end if;
if Present (Dexpr) then
- Apply_Range_Check (Dexpr, Index_Type);
+ Apply_Range_Check (Dexpr, Index_Type, Insert_Node => Drange);
end if;
Set_Slice_Subtype (N);
@@ -11393,11 +11433,11 @@ package body Sem_Res is
-- Otherwise here is where we check suspicious indexes
if Nkind (Drange) = N_Range then
- Warn_On_Suspicious_Index (Name, Low_Bound (Drange));
- Warn_On_Suspicious_Index (Name, High_Bound (Drange));
+ Warn_On_Suspicious_Index (Pref, Low_Bound (Drange));
+ Warn_On_Suspicious_Index (Pref, High_Bound (Drange));
end if;
- Resolve_Implicit_Dereference (Prefix (N));
+ Resolve_Implicit_Dereference (Pref);
Analyze_Dimension (N);
Eval_Slice (N);
end Resolve_Slice;
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 396f616..8e5b067 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -444,6 +444,12 @@ package body Sem_Type is
Find_Dispatching_Type (E))
then
Add_One_Interp (N, Interface_Alias (E), T);
+
+ -- Otherwise this is the first interpretation, N has type Any_Type
+ -- and we must place the new type on the node.
+
+ else
+ Set_Etype (N, T);
end if;
return;
@@ -1403,7 +1409,9 @@ package body Sem_Type is
and then Nkind (Unit_Declaration_Node (S)) =
N_Subprogram_Renaming_Declaration
- -- Why the Comes_From_Source test here???
+ -- Determine if the renaming came from source or was generated as a
+ -- a result of generic expansion since the actual is represented by
+ -- a constructed subprogram renaming.
and then not Comes_From_Source (Unit_Declaration_Node (S))
@@ -1460,7 +1468,8 @@ package body Sem_Type is
then
return True;
- -- ??? There are possibly other cases to consider
+ -- Formal_Typ is a private view, or Opnd_Typ and Formal_Typ are
+ -- compatible only on a base-type basis.
else
return False;
@@ -3415,7 +3424,8 @@ package body Sem_Type is
-- Ada 2005 (AI-251): T1 is a concrete type that implements the
-- class-wide interface T2
- elsif Is_Class_Wide_Type (T2)
+ elsif Is_Tagged_Type (T1)
+ and then Is_Class_Wide_Type (T2)
and then Is_Interface (Etype (T2))
and then Interface_Present_In_Ancestor (Typ => T1,
Iface => Etype (T2))
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 01a4e2b..e79c534 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -391,8 +391,7 @@ package body Sem_Util is
and then (Is_Static_Coextension (N)
or else Is_Dynamic_Coextension (N))
then
- return Make_Level_Literal
- (Scope_Depth (Standard_Standard));
+ return Make_Level_Literal (Scope_Depth (Standard_Standard));
end if;
-- Named access types have a designated level
@@ -416,11 +415,14 @@ package body Sem_Util is
if Debug_Flag_Underscore_B then
return Make_Level_Literal (Typ_Access_Level (Etype (N)));
- -- Otherwise the level is that of the subprogram
+ -- For function calls the level is that of the innermost
+ -- master, otherwise (for allocators etc.) we get the level
+ -- of the corresponding anonymous access type, which is
+ -- calculated through the normal path of execution.
- else
+ elsif Nkind (N) = N_Function_Call then
return Make_Level_Literal
- (Subprogram_Access_Level (Entity (Name (N))));
+ (Innermost_Master_Scope_Depth (Expr));
end if;
end if;
@@ -713,32 +715,31 @@ package body Sem_Util is
return Make_Level_Literal (Typ_Access_Level (E) + 1);
- -- Move up the renamed entity if it came from source since
- -- expansion may have created a dummy renaming under certain
- -- circumstances.
+ -- Move up the renamed entity or object if it came from source
+ -- since expansion may have created a dummy renaming under
+ -- certain circumstances.
+
+ -- Note: We check if the original node of the renaming comes
+ -- from source because the node may have been rewritten.
elsif Present (Renamed_Object (E))
- and then Comes_From_Source (Renamed_Object (E))
+ and then Comes_From_Source (Original_Node (Renamed_Object (E)))
then
return Accessibility_Level (Renamed_Object (E));
+ -- Move up renamed entities
+
+ elsif Present (Renamed_Entity (E))
+ and then Comes_From_Source (Original_Node (Renamed_Entity (E)))
+ then
+ return Accessibility_Level (Renamed_Entity (E));
+
-- Named access types get their level from their associated type
elsif Is_Named_Access_Type (Etype (E)) then
return Make_Level_Literal
(Typ_Access_Level (Etype (E)));
- -- When E is a component of the current instance of a
- -- protected type, we assume the level to be deeper than that of
- -- the type itself.
-
- elsif not Is_Overloadable (E)
- and then Ekind (Scope (E)) = E_Protected_Type
- and then Comes_From_Source (Scope (E))
- then
- return Make_Level_Literal
- (Scope_Depth (Enclosing_Dynamic_Scope (E)) + 1);
-
-- Check if E is an expansion-generated renaming of an iterator
-- by examining Related_Expression. If so, determine the
-- accessibility level based on the original expression.
@@ -2223,180 +2224,6 @@ package body Sem_Util is
return Empty;
end Build_Actual_Subtype_Of_Component;
- ---------------------------------
- -- Build_Class_Wide_Clone_Body --
- ---------------------------------
-
- procedure Build_Class_Wide_Clone_Body
- (Spec_Id : Entity_Id;
- Bod : Node_Id)
- is
- Loc : constant Source_Ptr := Sloc (Bod);
- Clone_Id : constant Entity_Id := Class_Wide_Clone (Spec_Id);
- Clone_Body : Node_Id;
- Assoc_List : constant Elist_Id := New_Elmt_List;
-
- begin
- -- The declaration of the class-wide clone was created when the
- -- corresponding class-wide condition was analyzed.
-
- -- The body of the original condition may contain references to
- -- the formals of Spec_Id. In the body of the class-wide clone,
- -- these must be replaced with the corresponding formals of
- -- the clone.
-
- declare
- Spec_Formal_Id : Entity_Id := First_Formal (Spec_Id);
- Clone_Formal_Id : Entity_Id := First_Formal (Clone_Id);
- begin
- while Present (Spec_Formal_Id) loop
- Append_Elmt (Spec_Formal_Id, Assoc_List);
- Append_Elmt (Clone_Formal_Id, Assoc_List);
-
- Next_Formal (Spec_Formal_Id);
- Next_Formal (Clone_Formal_Id);
- end loop;
- end;
-
- Clone_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Copy_Subprogram_Spec (Parent (Clone_Id)),
- Declarations => Declarations (Bod),
- Handled_Statement_Sequence =>
- New_Copy_Tree (Handled_Statement_Sequence (Bod),
- Map => Assoc_List));
-
- -- The new operation is internal and overriding indicators do not apply
- -- (the original primitive may have carried one).
-
- Set_Must_Override (Specification (Clone_Body), False);
-
- -- If the subprogram body is the proper body of a stub, insert the
- -- subprogram after the stub, i.e. the same declarative region as
- -- the original sugprogram.
-
- if Nkind (Parent (Bod)) = N_Subunit then
- Insert_After (Corresponding_Stub (Parent (Bod)), Clone_Body);
-
- else
- Insert_Before (Bod, Clone_Body);
- end if;
-
- Analyze (Clone_Body);
- end Build_Class_Wide_Clone_Body;
-
- ---------------------------------
- -- Build_Class_Wide_Clone_Call --
- ---------------------------------
-
- function Build_Class_Wide_Clone_Call
- (Loc : Source_Ptr;
- Decls : List_Id;
- Spec_Id : Entity_Id;
- Spec : Node_Id) return Node_Id
- is
- Clone_Id : constant Entity_Id := Class_Wide_Clone (Spec_Id);
- Par_Type : constant Entity_Id := Find_Dispatching_Type (Spec_Id);
-
- Actuals : List_Id;
- Call : Node_Id;
- Formal : Entity_Id;
- New_Body : Node_Id;
- New_F_Spec : Entity_Id;
- New_Formal : Entity_Id;
-
- begin
- Actuals := Empty_List;
- Formal := First_Formal (Spec_Id);
- New_F_Spec := First (Parameter_Specifications (Spec));
-
- -- Build parameter association for call to class-wide clone.
-
- while Present (Formal) loop
- New_Formal := Defining_Identifier (New_F_Spec);
-
- -- If controlling argument and operation is inherited, add conversion
- -- to parent type for the call.
-
- if Etype (Formal) = Par_Type
- and then not Is_Empty_List (Decls)
- then
- Append_To (Actuals,
- Make_Type_Conversion (Loc,
- New_Occurrence_Of (Par_Type, Loc),
- New_Occurrence_Of (New_Formal, Loc)));
-
- else
- Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
- end if;
-
- Next_Formal (Formal);
- Next (New_F_Spec);
- end loop;
-
- if Ekind (Spec_Id) = E_Procedure then
- Call :=
- Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (Clone_Id, Loc),
- Parameter_Associations => Actuals);
- else
- Call :=
- Make_Simple_Return_Statement (Loc,
- Expression =>
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Clone_Id, Loc),
- Parameter_Associations => Actuals));
- end if;
-
- New_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Copy_Subprogram_Spec (Spec),
- Declarations => Decls,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Call),
- End_Label => Make_Identifier (Loc, Chars (Spec_Id))));
-
- return New_Body;
- end Build_Class_Wide_Clone_Call;
-
- ---------------------------------
- -- Build_Class_Wide_Clone_Decl --
- ---------------------------------
-
- procedure Build_Class_Wide_Clone_Decl (Spec_Id : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (Spec_Id);
- Clone_Id : constant Entity_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (Spec_Id), Suffix => "CL"));
-
- Decl : Node_Id;
- Spec : Node_Id;
-
- begin
- Spec := Copy_Subprogram_Spec (Parent (Spec_Id));
- Set_Must_Override (Spec, False);
- Set_Must_Not_Override (Spec, False);
- Set_Defining_Unit_Name (Spec, Clone_Id);
-
- Decl := Make_Subprogram_Declaration (Loc, Spec);
- Append (Decl, List_Containing (Unit_Declaration_Node (Spec_Id)));
-
- -- Link clone to original subprogram, for use when building body and
- -- wrapper call to inherited operation.
-
- Set_Class_Wide_Clone (Spec_Id, Clone_Id);
-
- -- Inherit debug info flag from Spec_Id to Clone_Id to allow debugging
- -- of the class-wide clone subprogram.
-
- if Needs_Debug_Info (Spec_Id) then
- Set_Debug_Info_Needed (Clone_Id);
- end if;
- end Build_Class_Wide_Clone_Decl;
-
-----------------------------
-- Build_Component_Subtype --
-----------------------------
@@ -5023,6 +4850,7 @@ package body Sem_Util is
and then not Mentions_Post_State (Expr)
and then not (Is_Ghost_Entity (Subp_Id)
and then Has_No_Output (Subp_Id))
+ and then not Is_Wrapper (Subp_Id)
then
if Pragma_Name (Prag) = Name_Contract_Cases then
Error_Msg_NE (Adjust_Message
@@ -5888,6 +5716,30 @@ package body Sem_Util is
end if;
end Choice_List;
+ ---------------------
+ -- Class_Condition --
+ ---------------------
+
+ function Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id) return Node_Id is
+
+ begin
+ case Kind is
+ when Class_Postcondition =>
+ return Class_Postconditions (Subp);
+
+ when Class_Precondition =>
+ return Class_Preconditions (Subp);
+
+ when Ignored_Class_Postcondition =>
+ return Ignored_Class_Postconditions (Subp);
+
+ when Ignored_Class_Precondition =>
+ return Ignored_Class_Preconditions (Subp);
+ end case;
+ end Class_Condition;
+
-------------------------
-- Collect_Body_States --
-------------------------
@@ -6737,11 +6589,14 @@ package body Sem_Util is
if Inside_Init_Proc then
declare
+ Init_Proc_Type : constant Entity_Id :=
+ Etype (First_Formal (Current_Scope_No_Loops));
+
Conc_Typ : constant Entity_Id :=
- Corresponding_Concurrent_Type
- (Entity (Parameter_Type (First
- (Parameter_Specifications
- (Parent (Current_Scope))))));
+ (if Present (Init_Proc_Type)
+ and then Init_Proc_Type in E_Record_Type_Id
+ then Corresponding_Concurrent_Type (Init_Proc_Type)
+ else Empty);
begin
-- Don't complain if the corresponding concurrent type
@@ -7083,6 +6938,79 @@ package body Sem_Util is
end if;
end Corresponding_Generic_Type;
+ --------------------------------
+ -- Corresponding_Primitive_Op --
+ --------------------------------
+
+ function Corresponding_Primitive_Op
+ (Ancestor_Op : Entity_Id;
+ Descendant_Type : Entity_Id) return Entity_Id
+ is
+ Typ : constant Entity_Id := Find_Dispatching_Type (Ancestor_Op);
+ Elmt : Elmt_Id;
+ Subp : Entity_Id;
+ Prim : Entity_Id;
+ begin
+ pragma Assert (Is_Dispatching_Operation (Ancestor_Op));
+ pragma Assert (Is_Ancestor (Typ, Descendant_Type)
+ or else Is_Progenitor (Typ, Descendant_Type));
+
+ Elmt := First_Elmt (Primitive_Operations (Descendant_Type));
+
+ while Present (Elmt) loop
+ Subp := Node (Elmt);
+
+ -- For regular primitives we only need to traverse the chain of
+ -- ancestors when the name matches the name of Ancestor_Op, but
+ -- for predefined dispatching operations we cannot rely on the
+ -- name of the primitive to identify a candidate since their name
+ -- is internally built adding a suffix to the name of the tagged
+ -- type.
+
+ if Chars (Subp) = Chars (Ancestor_Op)
+ or else Is_Predefined_Dispatching_Operation (Subp)
+ then
+ -- Handle case where Ancestor_Op is a primitive of a progenitor.
+ -- We rely on internal entities that map interface primitives:
+ -- their attribute Interface_Alias references the interface
+ -- primitive, and their Alias attribute references the primitive
+ -- of Descendant_Type implementing that interface primitive.
+
+ if Present (Interface_Alias (Subp)) then
+ if Interface_Alias (Subp) = Ancestor_Op then
+ return Alias (Subp);
+ end if;
+
+ -- Traverse the chain of ancestors searching for Ancestor_Op.
+ -- Overridden primitives have attribute Overridden_Operation;
+ -- inherited primitives have attribute Alias.
+
+ else
+ Prim := Subp;
+
+ while Present (Overridden_Operation (Prim))
+ or else Present (Alias (Prim))
+ loop
+ if Present (Overridden_Operation (Prim)) then
+ Prim := Overridden_Operation (Prim);
+ else
+ Prim := Alias (Prim);
+ end if;
+
+ if Prim = Ancestor_Op then
+ return Subp;
+ end if;
+ end loop;
+ end if;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ pragma Assert (False);
+ return Empty;
+ end Corresponding_Primitive_Op;
+
--------------------
-- Current_Entity --
--------------------
@@ -7455,7 +7383,7 @@ package body Sem_Util is
return False;
end if;
- Next_Index (Indx);
+ Next (Indx);
end loop;
end;
@@ -8102,8 +8030,7 @@ package body Sem_Util is
if Present (Spec_Id)
and then Nkind (Unit_Declaration_Node (Spec_Id)) in
- N_Generic_Package_Declaration |
- N_Generic_Subprogram_Declaration
+ N_Generic_Declaration
then
return Par;
end if;
@@ -8127,9 +8054,7 @@ package body Sem_Util is
begin
Par := Parent (N);
while Present (Par) loop
- if Nkind (Par) in N_Generic_Package_Declaration
- | N_Generic_Subprogram_Declaration
- then
+ if Nkind (Par) in N_Generic_Declaration then
return Par;
elsif Nkind (Par) in N_Package_Body | N_Subprogram_Body then
@@ -8138,9 +8063,7 @@ package body Sem_Util is
if Present (Spec_Id) then
Spec_Decl := Unit_Declaration_Node (Spec_Id);
- if Nkind (Spec_Decl) in N_Generic_Package_Declaration
- | N_Generic_Subprogram_Declaration
- then
+ if Nkind (Spec_Decl) in N_Generic_Declaration then
return Spec_Decl;
end if;
end if;
@@ -8743,6 +8666,10 @@ package body Sem_Util is
and then Comes_From_Source (C)
and then Comes_From_Source (Def_Id)
+ -- Don't warn within a generic instantiation
+
+ and then not In_Instance
+
-- Don't warn unless entity in question is in extended main source
and then In_Extended_Main_Source_Unit (Def_Id)
@@ -11802,7 +11729,7 @@ package body Sem_Util is
-- Set to a factor of the offset from the base object when Expr is a
-- selected or indexed component, based on Component_Bit_Offset and
-- Component_Size respectively. A negative value is used to represent
- -- a value which is not known at compile time.
+ -- a value that is not known at compile time.
procedure Check_Prefix;
-- Checks the prefix recursively in the case where the expression
@@ -11901,7 +11828,7 @@ package body Sem_Util is
Check_Prefix;
Offs := Indexed_Component_Bit_Offset (Expr);
- if Offs = No_Uint then
+ if No (Offs) then
Offs := Component_Size (Typ);
end if;
end;
@@ -11910,7 +11837,7 @@ package body Sem_Util is
-- If we have a null offset, the result is entirely determined by
-- the base object and has already been computed recursively.
- if Offs = Uint_0 then
+ if Present (Offs) and then Offs = Uint_0 then
null;
-- Case where we know the alignment of the object
@@ -11932,7 +11859,7 @@ package body Sem_Util is
else
-- If we have an offset, see if it is compatible
- if Offs /= No_Uint and Offs > Uint_0 then
+ if Present (Offs) and then Offs > Uint_0 then
if Offs mod (System_Storage_Unit * ObjA) /= 0 then
Set_Result (Known_Incompatible);
end if;
@@ -11961,7 +11888,7 @@ package body Sem_Util is
-- If we got an alignment, see if it is acceptable
- if ExpA /= No_Uint and then ExpA < ObjA then
+ if Present (ExpA) and then ExpA < ObjA then
Set_Result (Known_Incompatible);
end if;
@@ -11969,7 +11896,7 @@ package body Sem_Util is
-- alignment, then we are fine. Otherwise, if its size is
-- known, it must be big enough for the required alignment.
- if Offs /= No_Uint then
+ if Present (Offs) then
null;
-- See if Expr is an object with known size
@@ -11990,7 +11917,7 @@ package body Sem_Util is
-- acceptable, since the size is always a multiple of the
-- alignment.
- if SizA /= No_Uint then
+ if Present (SizA) then
if SizA mod (ObjA * Ttypes.System_Storage_Unit) /= 0 then
Set_Result (Known_Incompatible);
end if;
@@ -12001,7 +11928,7 @@ package body Sem_Util is
-- If we do not know required alignment, any non-zero offset is a
-- potential problem (but certainly may be OK, so result is unknown).
- elsif Offs /= No_Uint then
+ elsif Present (Offs) then
Set_Result (Unknown);
-- If we can't find the result by direct comparison of alignment
@@ -13399,13 +13326,22 @@ package body Sem_Util is
-- Has_Preelaborable_Initialization --
--------------------------------------
- function Has_Preelaborable_Initialization (E : Entity_Id) return Boolean is
+ function Has_Preelaborable_Initialization
+ (E : Entity_Id;
+ Preelab_Init_Expr : Node_Id := Empty) return Boolean
+ is
Has_PE : Boolean;
procedure Check_Components (E : Entity_Id);
-- Check component/discriminant chain, sets Has_PE False if a component
-- or discriminant does not meet the preelaborable initialization rules.
+ function Type_Named_In_Preelab_Init_Expression
+ (Typ : Entity_Id;
+ Expr : Node_Id) return Boolean;
+ -- Returns True iff Typ'Preelaborable_Initialization occurs in Expr
+ -- (where Expr may be a conjunction of one or more P_I attributes).
+
----------------------
-- Check_Components --
----------------------
@@ -13453,7 +13389,9 @@ package body Sem_Util is
-- component type has PI.
if No (Exp) then
- if not Has_Preelaborable_Initialization (Etype (Ent)) then
+ if not Has_Preelaborable_Initialization
+ (Etype (Ent), Preelab_Init_Expr)
+ then
Has_PE := False;
exit;
end if;
@@ -13470,6 +13408,44 @@ package body Sem_Util is
end loop;
end Check_Components;
+ --------------------------------------
+ -- Type_Named_In_Preelab_Expression --
+ --------------------------------------
+
+ function Type_Named_In_Preelab_Init_Expression
+ (Typ : Entity_Id;
+ Expr : Node_Id) return Boolean
+ is
+ begin
+ -- Return True if Expr is a Preelaborable_Initialization attribute
+ -- and the prefix is a subtype that has the same type as Typ.
+
+ if Nkind (Expr) = N_Attribute_Reference
+ and then Attribute_Name (Expr) = Name_Preelaborable_Initialization
+ and then Is_Entity_Name (Prefix (Expr))
+ and then Base_Type (Entity (Prefix (Expr))) = Base_Type (Typ)
+ then
+ return True;
+
+ -- In the case where Expr is a conjunction, test whether either
+ -- operand is a Preelaborable_Initialization attribute whose prefix
+ -- has the same type as Typ, and return True if so.
+
+ elsif Nkind (Expr) = N_Op_And
+ and then
+ (Type_Named_In_Preelab_Init_Expression (Typ, Left_Opnd (Expr))
+ or else
+ Type_Named_In_Preelab_Init_Expression (Typ, Right_Opnd (Expr)))
+ then
+ return True;
+
+ -- Typ not named in a Preelaborable_Initialization attribute of Expr
+
+ else
+ return False;
+ end if;
+ end Type_Named_In_Preelab_Init_Expression;
+
-- Start of processing for Has_Preelaborable_Initialization
begin
@@ -13499,7 +13475,8 @@ package body Sem_Util is
-- Array types have PI if the component type has PI
elsif Is_Array_Type (E) then
- Has_PE := Has_Preelaborable_Initialization (Component_Type (E));
+ Has_PE := Has_Preelaborable_Initialization
+ (Component_Type (E), Preelab_Init_Expr);
-- A derived type has preelaborable initialization if its parent type
-- has preelaborable initialization and (in the case of a derived record
@@ -13510,6 +13487,18 @@ package body Sem_Util is
elsif Is_Derived_Type (E) then
+ -- When the rule of RM 10.2.1(11.8/5) applies, we presume a component
+ -- of a generic formal derived type has preelaborable initialization.
+ -- (See comment on spec of Has_Preelaborable_Initialization.)
+
+ if Is_Generic_Type (E)
+ and then Present (Preelab_Init_Expr)
+ and then
+ Type_Named_In_Preelab_Init_Expression (E, Preelab_Init_Expr)
+ then
+ return True;
+ end if;
+
-- If the derived type is a private extension then it doesn't have
-- preelaborable initialization.
@@ -13519,7 +13508,8 @@ package body Sem_Util is
-- First check whether ancestor type has preelaborable initialization
- Has_PE := Has_Preelaborable_Initialization (Etype (Base_Type (E)));
+ Has_PE := Has_Preelaborable_Initialization
+ (Etype (Base_Type (E)), Preelab_Init_Expr);
-- If OK, check extension components (if any)
@@ -13545,7 +13535,20 @@ package body Sem_Util is
-- have preelaborable initialization.
elsif Is_Private_Type (E) then
- return False;
+
+ -- When the rule of RM 10.2.1(11.8/5) applies, we presume a component
+ -- of a generic formal private type has preelaborable initialization.
+ -- (See comment on spec of Has_Preelaborable_Initialization.)
+
+ if Is_Generic_Type (E)
+ and then Present (Preelab_Init_Expr)
+ and then
+ Type_Named_In_Preelab_Init_Expression (E, Preelab_Init_Expr)
+ then
+ return True;
+ else
+ return False;
+ end if;
-- Record type has PI if it is non private and all components have PI
@@ -15021,7 +15024,7 @@ package body Sem_Util is
begin
-- Return early if the component size is not known or variable
- if Off = No_Uint or else Off < Uint_0 then
+ if No (Off) or else Off < Uint_0 then
return No_Uint;
end if;
@@ -15544,7 +15547,7 @@ package body Sem_Util is
-- Pragma Invalid_Scalars did not specify an invalid value for this
-- type. Fall back to the value provided by the binder.
- if Value = No_Uint then
+ if No (Value) then
return Invalid_Binder_Value;
else
return Make_Integer_Literal (Loc, Intval => Value);
@@ -16252,12 +16255,14 @@ package body Sem_Util is
Names_Match (Assign_Indexed_1, Assign_Indexed_2);
end;
+ -- Checking for this aspect is performed elsewhere during freezing
+ when Aspect_No_Controlled_Parts =>
+ return True;
+
-- scalar-valued aspects; compare (static) values.
- when Aspect_Max_Entry_Queue_Length -- | Aspect_No_Controlled_Parts
- =>
- -- This should be unreachable. No_Controlled_Parts is
- -- not yet supported at all in GNAT and Max_Entry_Queue_Length
- -- is supported only for protected entries, not for types.
+ when Aspect_Max_Entry_Queue_Length =>
+ -- This should be unreachable. Max_Entry_Queue_Length is
+ -- supported only for protected entries, not for types.
pragma Assert (Serious_Errors_Detected /= 0);
return True;
@@ -16277,6 +16282,49 @@ package body Sem_Util is
or else Is_Task_Interface (T);
end Is_Concurrent_Interface;
+ ------------------------------------------------------
+ -- Is_Conjunction_Of_Formal_Preelab_Init_Attributes --
+ ------------------------------------------------------
+
+ function Is_Conjunction_Of_Formal_Preelab_Init_Attributes
+ (Expr : Node_Id) return Boolean
+ is
+
+ function Is_Formal_Preelab_Init_Attribute
+ (N : Node_Id) return Boolean;
+ -- Returns True if N is a Preelaborable_Initialization attribute
+ -- applied to a generic formal type, or N's Original_Node is such
+ -- an attribute.
+
+ --------------------------------------
+ -- Is_Formal_Preelab_Init_Attribute --
+ --------------------------------------
+
+ function Is_Formal_Preelab_Init_Attribute
+ (N : Node_Id) return Boolean
+ is
+ Orig_N : constant Node_Id := Original_Node (N);
+
+ begin
+ return Nkind (Orig_N) = N_Attribute_Reference
+ and then Attribute_Name (Orig_N) = Name_Preelaborable_Initialization
+ and then Is_Entity_Name (Prefix (Orig_N))
+ and then Is_Generic_Type (Entity (Prefix (Orig_N)));
+ end Is_Formal_Preelab_Init_Attribute;
+
+ -- Start of Is_Conjunction_Of_Formal_Preelab_Init_Attributes
+
+ begin
+ return Is_Formal_Preelab_Init_Attribute (Expr)
+ or else (Nkind (Expr) = N_Op_And
+ and then
+ Is_Conjunction_Of_Formal_Preelab_Init_Attributes
+ (Left_Opnd (Expr))
+ and then
+ Is_Conjunction_Of_Formal_Preelab_Init_Attributes
+ (Right_Opnd (Expr)));
+ end Is_Conjunction_Of_Formal_Preelab_Init_Attributes;
+
-----------------------
-- Is_Constant_Bound --
-----------------------
@@ -16869,6 +16917,15 @@ package body Sem_Util is
end if;
if Is_Entity_Name (P) then
+ -- The Etype may not be set on P (which is wrong) in certain
+ -- corner cases involving the deprecated front-end inlining of
+ -- subprograms (via -gnatN), so use the Etype set on the
+ -- the entity for these instances since we know it is present.
+
+ if No (Prefix_Type) then
+ Prefix_Type := Etype (Entity (P));
+ end if;
+
if Ekind (Entity (P)) = E_Generic_In_Out_Parameter then
Prefix_Type := Base_Type (Prefix_Type);
end if;
@@ -17483,9 +17540,9 @@ package body Sem_Util is
-- Is_False --
--------------
- function Is_False (U : Uint) return Boolean is
+ function Is_False (U : Opt_Ubool) return Boolean is
begin
- return (U = 0);
+ return not Is_True (U);
end Is_False;
---------------------------
@@ -17829,9 +17886,7 @@ package body Sem_Util is
-- a generic body modifies the Ekind of its spec to allow for recursive
-- calls.
- return
- Nkind (Spec_Decl) in N_Generic_Package_Declaration
- | N_Generic_Subprogram_Declaration;
+ return Nkind (Spec_Decl) in N_Generic_Declaration;
end Is_Generic_Declaration_Or_Body;
---------------------------
@@ -18112,6 +18167,19 @@ package body Sem_Util is
if Is_Formal (E) then
return False;
+
+ -- If we somehow got an empty value for Scope, the tree must be
+ -- malformed. Rather than blow up we return True in this case.
+
+ elsif No (Scope (E)) then
+ return True;
+
+ -- Handle loops since Enclosing_Dynamic_Scope skips them; required to
+ -- properly handle entities local to quantified expressions in library
+ -- level specifications.
+
+ elsif Ekind (Scope (E)) = E_Loop then
+ return False;
end if;
-- Normal test is simply that the enclosing dynamic scope is Standard
@@ -20981,9 +21049,9 @@ package body Sem_Util is
-- Is_True --
-------------
- function Is_True (U : Uint) return Boolean is
+ function Is_True (U : Opt_Ubool) return Boolean is
begin
- return U /= 0;
+ return No (U) or else U = Uint_1;
end Is_True;
--------------------------------------
@@ -21133,6 +21201,9 @@ package body Sem_Util is
-- Is_Variable --
-----------------
+ -- Should Is_Variable be refactored to better handle dereferences and
+ -- technical debt ???
+
function Is_Variable
(N : Node_Id;
Use_Original_Node : Boolean := True) return Boolean
@@ -21301,6 +21372,10 @@ package body Sem_Util is
and then Nkind (Parent (E)) /= N_Exception_Handler)
or else (K = E_Component
and then not In_Protected_Function (E))
+ or else (Present (Etype (E))
+ and then Is_Access_Object_Type (Etype (E))
+ and then Is_Access_Variable (Etype (E))
+ and then Is_Dereferenced (N))
or else K = E_Out_Parameter
or else K = E_In_Out_Parameter
or else K = E_Generic_In_Out_Parameter
@@ -22658,6 +22733,61 @@ package body Sem_Util is
return Result;
end Might_Raise;
+ ----------------------------------------
+ -- Nearest_Class_Condition_Subprogram --
+ ----------------------------------------
+
+ function Nearest_Class_Condition_Subprogram
+ (Kind : Condition_Kind;
+ Spec_Id : Entity_Id) return Entity_Id
+ is
+ Subp_Id : constant Entity_Id := Ultimate_Alias (Spec_Id);
+
+ begin
+ -- Prevent cascaded errors
+
+ if not Is_Dispatching_Operation (Subp_Id) then
+ return Empty;
+
+ -- No need to search if this subprogram has class-wide postconditions
+
+ elsif Present (Class_Condition (Kind, Subp_Id)) then
+ return Subp_Id;
+ end if;
+
+ -- Process the contracts of inherited subprograms, looking for
+ -- class-wide pre/postconditions.
+
+ declare
+ Subps : constant Subprogram_List := Inherited_Subprograms (Subp_Id);
+ Subp_Id : Entity_Id;
+
+ begin
+ for Index in Subps'Range loop
+ Subp_Id := Subps (Index);
+
+ if Present (Alias (Subp_Id)) then
+ Subp_Id := Ultimate_Alias (Subp_Id);
+ end if;
+
+ -- Wrappers of class-wide pre/postconditions reference the
+ -- parent primitive that has the inherited contract.
+
+ if Is_Wrapper (Subp_Id)
+ and then Present (LSP_Subprogram (Subp_Id))
+ then
+ Subp_Id := LSP_Subprogram (Subp_Id);
+ end if;
+
+ if Present (Class_Condition (Kind, Subp_Id)) then
+ return Subp_Id;
+ end if;
+ end loop;
+ end;
+
+ return Empty;
+ end Nearest_Class_Condition_Subprogram;
+
--------------------------------
-- Nearest_Enclosing_Instance --
--------------------------------
@@ -22984,7 +23114,7 @@ package body Sem_Util is
-- types.
elsif Is_Access_Type (Typ)
- or else (Consider_IS_NS and then (Is_Scalar_Type (Typ)))
+ or else (Consider_IS_NS and then Is_Scalar_Type (Typ))
then
return True;
@@ -24652,7 +24782,7 @@ package body Sem_Util is
-- Visit_Node --
----------------
- procedure Visit_Node (N : Node_Or_Entity_Id) is
+ procedure Visit_Node (N : Node_Id) is
begin
pragma Assert (Nkind (N) not in N_Entity);
@@ -24920,7 +25050,7 @@ package body Sem_Util is
Set_Public_Status (N);
if Kind in Type_Kind then
- Init_Size_Align (N);
+ Reinit_Size_Align (N);
end if;
return N;
@@ -24944,7 +25074,7 @@ package body Sem_Util is
Append_Entity (N, Scope_Id);
if Kind in Type_Kind then
- Init_Size_Align (N);
+ Reinit_Size_Align (N);
end if;
return N;
@@ -25996,6 +26126,33 @@ package body Sem_Util is
end if;
end Original_Corresponding_Operation;
+ -----------------------------------
+ -- Original_View_In_Visible_Part --
+ -----------------------------------
+
+ function Original_View_In_Visible_Part
+ (Typ : Entity_Id) return Boolean
+ is
+ Scop : constant Entity_Id := Scope (Typ);
+
+ begin
+ -- The scope must be a package
+
+ if not Is_Package_Or_Generic_Package (Scop) then
+ return False;
+ end if;
+
+ -- A type with a private declaration has a private view declared in
+ -- the visible part.
+
+ if Has_Private_Declaration (Typ) then
+ return True;
+ end if;
+
+ return List_Containing (Parent (Typ)) =
+ Visible_Declarations (Package_Specification (Scop));
+ end Original_View_In_Visible_Part;
+
-------------------
-- Output_Entity --
-------------------
@@ -28178,7 +28335,7 @@ package body Sem_Util is
begin
-- Detect an attempt to set a different value for the same scalar type
- pragma Assert (Slot = No_Uint);
+ pragma Assert (No (Slot));
Slot := Value;
end Set_Invalid_Scalar_Value;
@@ -28356,7 +28513,7 @@ package body Sem_Util is
-- We copy Esize, but not RM_Size, since in general RM_Size is
-- subtype specific and does not get inherited by all subtypes.
- Set_Esize (T1, Esize (T2));
+ Copy_Esize (To => T1, From => T2);
Set_Has_Biased_Representation (T1, Has_Biased_Representation (T2));
if Is_Discrete_Or_Fixed_Point_Type (T1)
@@ -28405,7 +28562,7 @@ package body Sem_Util is
-- Static_Boolean --
--------------------
- function Static_Boolean (N : Node_Id) return Uint is
+ function Static_Boolean (N : Node_Id) return Opt_Ubool is
begin
Analyze_And_Resolve (N, Standard_Boolean);
@@ -29197,7 +29354,7 @@ package body Sem_Util is
(Designated_Type (Btyp), Allow_Alt_Model);
end if;
- -- When an anonymous access type's Assoc_Ent is specifiedi,
+ -- When an anonymous access type's Assoc_Ent is specified,
-- calculate the result based on the general accessibility
-- level routine.
@@ -29219,10 +29376,22 @@ package body Sem_Util is
(Associated_Node_For_Itype (Typ));
if Present (Def_Ent) then
- -- When the type comes from an anonymous access parameter,
- -- the level is that of the subprogram declaration.
+ -- When the defining entity is a subprogram then we know the
+ -- anonymous access type Typ has been generated to either
+ -- describe an anonymous access type formal or an anonymous
+ -- access result type.
+
+ -- Since we are only interested in the formal case, avoid
+ -- the anonymous access result type.
+
+ if Ekind (Def_Ent) in Subprogram_Kind
+ and then not (Ekind (Def_Ent) = E_Function
+ and then Etype (Def_Ent) = Typ)
+ then
+ -- When the type comes from an anonymous access
+ -- parameter, the level is that of the subprogram
+ -- declaration.
- if Ekind (Def_Ent) in Subprogram_Kind then
return Scope_Depth (Def_Ent);
-- When the type is an access discriminant, the level is
@@ -31377,8 +31546,16 @@ package body Sem_Util is
-- type case correctly, so we avoid that problem by
-- returning True here.
return True;
+
elsif Ada_Version < Ada_2022 then
return False;
+
+ elsif Inside_Class_Condition_Preanalysis then
+ -- No need to evaluate it during preanalysis of a class-wide
+ -- pre/postcondition since the expression is not installed yet
+ -- on its definite context.
+ return False;
+
elsif not Is_Conditionally_Evaluated (Expr) then
return False;
else
@@ -31435,7 +31612,12 @@ package body Sem_Util is
-- quantified_expression.
if Nkind (Par) = N_Quantified_Expression
- and then Trailer = Condition (Par)
+ and then Trailer = Condition (Par)
+ then
+ return True;
+ elsif Nkind (Par) = N_Expression_With_Actions
+ and then
+ Nkind (Original_Node (Par)) = N_Quantified_Expression
then
return True;
end if;
@@ -31961,11 +32143,172 @@ package body Sem_Util is
end if;
end;
end if;
+
return False;
end Is_Access_Type_For_Indirect_Temp;
end Indirect_Temps;
end Old_Attr_Util;
+
+ package body Storage_Model_Support is
+
+ -----------------------------------
+ -- Get_Storage_Model_Type_Entity --
+ -----------------------------------
+
+ function Get_Storage_Model_Type_Entity
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id
+ is
+ pragma Assert
+ (Is_Type (Typ)
+ and then
+ Nam in Name_Address_Type
+ | Name_Null_Address
+ | Name_Allocate
+ | Name_Deallocate
+ | Name_Copy_From
+ | Name_Copy_To
+ | Name_Storage_Size);
+
+ SMT_Aspect_Value : constant Node_Id :=
+ Find_Value_Of_Aspect (Typ, Aspect_Storage_Model_Type);
+ Assoc : Node_Id;
+
+ begin
+ if No (SMT_Aspect_Value) then
+ return Empty;
+
+ else
+ Assoc := First (Component_Associations (SMT_Aspect_Value));
+ while Present (Assoc) loop
+ if Chars (First (Choices (Assoc))) = Nam then
+ return Entity (Expression (Assoc));
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ return Empty;
+ end if;
+ end Get_Storage_Model_Type_Entity;
+
+ -----------------------------------------
+ -- Has_Designated_Storage_Model_Aspect --
+ -----------------------------------------
+
+ function Has_Designated_Storage_Model_Aspect
+ (Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Present (Find_Aspect (Typ, Aspect_Designated_Storage_Model));
+ end Has_Designated_Storage_Model_Aspect;
+
+ -----------------------------------
+ -- Has_Storage_Model_Type_Aspect --
+ -----------------------------------
+
+ function Has_Storage_Model_Type_Aspect (Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Present (Find_Aspect (Typ, Aspect_Storage_Model_Type));
+ end Has_Storage_Model_Type_Aspect;
+
+ --------------------------
+ -- Storage_Model_Object --
+ --------------------------
+
+ function Storage_Model_Object (Typ : Entity_Id) return Entity_Id is
+ begin
+ if Has_Designated_Storage_Model_Aspect (Typ) then
+ return
+ Entity
+ (Find_Value_Of_Aspect (Typ, Aspect_Designated_Storage_Model));
+ else
+ return Empty;
+ end if;
+ end Storage_Model_Object;
+
+ ------------------------
+ -- Storage_Model_Type --
+ ------------------------
+
+ function Storage_Model_Type (Obj : Entity_Id) return Entity_Id is
+ begin
+ if Present
+ (Find_Value_Of_Aspect (Etype (Obj), Aspect_Storage_Model_Type))
+ then
+ return Etype (Obj);
+ else
+ return Empty;
+ end if;
+ end Storage_Model_Type;
+
+ --------------------------------
+ -- Storage_Model_Address_Type --
+ --------------------------------
+
+ function Storage_Model_Address_Type (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Address_Type);
+ end Storage_Model_Address_Type;
+
+ --------------------------------
+ -- Storage_Model_Null_Address --
+ --------------------------------
+
+ function Storage_Model_Null_Address (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Null_Address);
+ end Storage_Model_Null_Address;
+
+ ----------------------------
+ -- Storage_Model_Allocate --
+ ----------------------------
+
+ function Storage_Model_Allocate (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Allocate);
+ end Storage_Model_Allocate;
+
+ ------------------------------
+ -- Storage_Model_Deallocate --
+ ------------------------------
+
+ function Storage_Model_Deallocate (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Deallocate);
+ end Storage_Model_Deallocate;
+
+ -----------------------------
+ -- Storage_Model_Copy_From --
+ -----------------------------
+
+ function Storage_Model_Copy_From (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Copy_From);
+ end Storage_Model_Copy_From;
+
+ ---------------------------
+ -- Storage_Model_Copy_To --
+ ---------------------------
+
+ function Storage_Model_Copy_To (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Copy_To);
+ end Storage_Model_Copy_To;
+
+ --------------------------------
+ -- Storage_Model_Storage_Size --
+ --------------------------------
+
+ function Storage_Model_Storage_Size (Typ : Entity_Id) return Entity_Id is
+ begin
+ return Get_Storage_Model_Type_Entity (Typ, Name_Storage_Size);
+ end Storage_Model_Storage_Size;
+
+ end Storage_Model_Support;
+
begin
Erroutc.Subprogram_Name_Ptr := Subprogram_Name'Access;
end Sem_Util;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index b0d6a2a..85010b5 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -283,30 +283,6 @@ package Sem_Util is
-- take care of constructing declaration and body of the clone, and
-- building the calls to it within the appropriate wrappers.
- procedure Build_Class_Wide_Clone_Body
- (Spec_Id : Entity_Id;
- Bod : Node_Id);
- -- Build body of subprogram that has a class-wide condition that contains
- -- calls to other primitives. Spec_Id is the Id of the subprogram, and B
- -- is its source body, which becomes the body of the clone.
-
- function Build_Class_Wide_Clone_Call
- (Loc : Source_Ptr;
- Decls : List_Id;
- Spec_Id : Entity_Id;
- Spec : Node_Id) return Node_Id;
- -- Build a call to the common class-wide clone of a subprogram with
- -- class-wide conditions. The body of the subprogram becomes a wrapper
- -- for a call to the clone. The inherited operation becomes a similar
- -- wrapper to which modified conditions apply, and the call to the
- -- clone includes the proper conversion in a call the parent operation.
-
- procedure Build_Class_Wide_Clone_Decl (Spec_Id : Entity_Id);
- -- For a subprogram that has a class-wide condition that contains calls
- -- to other primitives, build an internal subprogram that is invoked
- -- through a type-specific wrapper for all inherited subprograms that
- -- may have a modified condition.
-
procedure Build_Constrained_Itype
(N : Node_Id;
Typ : Entity_Id;
@@ -356,7 +332,7 @@ package Sem_Util is
-- carries the name of the reference discriminant.
function Build_Overriding_Spec
- (Op : Node_Id;
+ (Op : Entity_Id;
Typ : Entity_Id) return Node_Id;
-- Build a subprogram specification for the wrapper of an inherited
-- operation with a modified pre- or postcondition (See AI12-0113).
@@ -527,6 +503,18 @@ package Sem_Util is
-- reasons these nodes have a different structure even though they play
-- similar roles in array aggregates.
+ type Condition_Kind is
+ (Ignored_Class_Precondition,
+ Ignored_Class_Postcondition,
+ Class_Precondition,
+ Class_Postcondition);
+ -- Kind of class-wide conditions
+
+ function Class_Condition
+ (Kind : Condition_Kind;
+ Subp : Entity_Id) return Node_Id;
+ -- Class-wide Kind condition of Subp
+
function Collect_Body_States (Body_Id : Entity_Id) return Elist_Id;
-- Gather the entities of all abstract states and objects declared in the
-- body state space of package body Body_Id.
@@ -638,6 +626,13 @@ package Sem_Util is
-- attribute, except in the case of formal private and derived types.
-- Possible optimization???
+ function Corresponding_Primitive_Op
+ (Ancestor_Op : Entity_Id;
+ Descendant_Type : Entity_Id) return Entity_Id;
+ -- Given a primitive subprogram of a tagged type and a (distinct)
+ -- descendant type of that type, find the corresponding primitive
+ -- subprogram of the descendant type.
+
function Current_Entity (N : Node_Id) return Entity_Id;
pragma Inline (Current_Entity);
-- Find the currently visible definition for a given identifier, that is to
@@ -1530,9 +1525,16 @@ package Sem_Util is
-- non-null), which causes the type to not have preelaborable
-- initialization.
- function Has_Preelaborable_Initialization (E : Entity_Id) return Boolean;
+ function Has_Preelaborable_Initialization
+ (E : Entity_Id;
+ Preelab_Init_Expr : Node_Id := Empty) return Boolean;
-- Return True iff type E has preelaborable initialization as defined in
-- Ada 2005 (see AI-161 for details of the definition of this attribute).
+ -- If Preelab_Init_Expr is present, indicates that the function should
+ -- presume that for any subcomponent of E that is of a formal private or
+ -- derived type that is referenced by a Preelaborable_Initialization
+ -- attribute within the expression Preelab_Init_Expr, the formal type has
+ -- preelaborable initialization (RM 10.2.1(11.8/5) and AI12-0409).
function Has_Prefix (N : Node_Id) return Boolean;
-- Return True if N has attribute Prefix
@@ -1828,6 +1830,13 @@ package Sem_Util is
-- Returns true if the two specifications of the given
-- nonoverridable aspect are compatible.
+ function Is_Conjunction_Of_Formal_Preelab_Init_Attributes
+ (Expr : Node_Id) return Boolean;
+ -- Returns True if Expr is a Preelaborable_Initialization attribute applied
+ -- to a formal type, or a sequence of two or more such attributes connected
+ -- by "and" operators, or if the Original_Node of Expr or its constituents
+ -- is such an attribute.
+
function Is_Constant_Bound (Exp : Node_Id) return Boolean;
-- Exp is the expression for an array bound. Determines whether the
-- bound is a compile-time known value, or a constant entity, or an
@@ -2038,11 +2047,17 @@ package Sem_Util is
-- 3) An if expression with at least one EVF dependent_expression
-- 4) A case expression with at least one EVF dependent_expression
- function Is_False (U : Uint) return Boolean;
+ function Is_False (U : Opt_Ubool) return Boolean;
pragma Inline (Is_False);
- -- The argument is a Uint value which is the Boolean'Pos value of a Boolean
- -- operand (i.e. is either 0 for False, or 1 for True). This function tests
- -- if it is False (i.e. zero).
+ -- True if U is Boolean'Pos (False) (i.e. Uint_0)
+
+ function Is_True (U : Opt_Ubool) return Boolean;
+ pragma Inline (Is_True);
+ -- True if U is Boolean'Pos (True) (i.e. Uint_1). Also True if U is
+ -- No_Uint; we allow No_Uint because Static_Boolean returns that in
+ -- case of error. It doesn't really matter whether the error case is
+ -- considered True or False, but we don't want this to blow up in that
+ -- case.
function Is_Fixed_Model_Number (U : Ureal; T : Entity_Id) return Boolean;
-- Returns True iff the number U is a model number of the fixed-point type
@@ -2406,12 +2421,6 @@ package Sem_Util is
-- unconditional transfer of control at run time, i.e. the following
-- statement definitely will not be executed.
- function Is_True (U : Uint) return Boolean;
- pragma Inline (Is_True);
- -- The argument is a Uint value which is the Boolean'Pos value of a Boolean
- -- operand (i.e. is either 0 for False, or 1 for True). This function tests
- -- if it is True (i.e. non-zero).
-
function Is_Unchecked_Conversion_Instance (Id : Entity_Id) return Boolean;
-- Determine whether an arbitrary entity denotes an instance of function
-- Ada.Unchecked_Conversion.
@@ -2598,6 +2607,12 @@ package Sem_Util is
-- if we're not sure, we return True. If N is a subprogram body, this is
-- about whether execution of that body can raise.
+ function Nearest_Class_Condition_Subprogram
+ (Kind : Condition_Kind;
+ Spec_Id : Entity_Id) return Entity_Id;
+ -- Return the nearest ancestor containing the merged class-wide conditions
+ -- that statically apply to Spec_Id; return Empty otherwise.
+
function Nearest_Enclosing_Instance (E : Entity_Id) return Entity_Id;
-- Return the entity of the nearest enclosing instance which encapsulates
-- entity E. If no such instance exits, return Empty.
@@ -2845,6 +2860,10 @@ package Sem_Util is
-- corresponding operation of S is the original corresponding operation of
-- S2. Otherwise, it is S itself.
+ function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean;
+ -- Returns True if the type Typ has a private view or if the public view
+ -- appears in the visible part of a package spec.
+
procedure Output_Entity (Id : Entity_Id);
-- Print entity Id to standard output. The name of the entity appears in
-- fully qualified form.
@@ -3199,7 +3218,7 @@ package Sem_Util is
-- predefined unit. The _Par version should be called only from the parser;
-- the _Sem version should be called only during semantic analysis.
- function Static_Boolean (N : Node_Id) return Uint;
+ function Static_Boolean (N : Node_Id) return Opt_Ubool;
-- This function analyzes the given expression node and then resolves it
-- as Standard.Boolean. If the result is static, then Uint_1 or Uint_0 is
-- returned corresponding to the value, otherwise an error message is
@@ -3531,4 +3550,76 @@ package Sem_Util is
end Indirect_Temps;
end Old_Attr_Util;
+
+ package Storage_Model_Support is
+
+ -- This package provides a set of utility functions related to support
+ -- for the Storage_Model feature. These functions provide an interface
+ -- that the compiler (in particular back-end phases such as gigi and
+ -- GNAT-LLVM) can use to easily obtain entities and operations that
+ -- are specified for types in the aspects Storage_Model_Type and
+ -- Designated_Storage_Model.
+
+ function Get_Storage_Model_Type_Entity
+ (Typ : Entity_Id;
+ Nam : Name_Id) return Entity_Id;
+ -- Given type Typ with aspect Storage_Model_Type, returns the Entity_Id
+ -- corresponding to the entity associated with Nam in the aspect. If the
+ -- type does not specify the aspect, or such an entity is not present,
+ -- then returns Empty. (Note: This function is modeled on function
+ -- Get_Iterable_Type_Primitive.)
+
+ function Has_Designated_Storage_Model_Aspect
+ (Typ : Entity_Id) return Boolean;
+ -- Returns True iff Typ specifies aspect Designated_Storage_Model
+
+ function Has_Storage_Model_Type_Aspect (Typ : Entity_Id) return Boolean;
+ -- Returns True iff Typ specifies aspect Storage_Model_Type
+
+ function Storage_Model_Object (Typ : Entity_Id) return Entity_Id;
+ -- Given an access type with aspect Designated_Storage_Model, returns
+ -- the storage-model object associated with that type; returns Empty
+ -- if there is no associated object.
+
+ function Storage_Model_Type (Obj : Entity_Id) return Entity_Id;
+ -- Given an object Obj of a type specifying aspect Storage_Model_Type,
+ -- returns that type; otherwise returns Empty.
+
+ function Storage_Model_Address_Type (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- the type specified for the Address_Type choice in that aspect;
+ -- returns Empty if the aspect or the type isn't specified.
+
+ function Storage_Model_Null_Address (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- constant specified for Null_Address choice in that aspect; returns
+ -- Empty if the aspect or the constant object isn't specified.
+
+ function Storage_Model_Allocate (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Allocate choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Deallocate (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Deallocate choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Copy_From (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Copy_From choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Copy_To (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- procedure specified for the Copy_To choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ function Storage_Model_Storage_Size (Typ : Entity_Id) return Entity_Id;
+ -- Given a type Typ that specifies aspect Storage_Model_Type, returns
+ -- function specified for Storage_Size choice in that aspect; returns
+ -- Empty if the aspect or the procedure isn't specified.
+
+ end Storage_Model_Support;
+
end Sem_Util;
diff --git a/gcc/ada/sinfo-utils.adb b/gcc/ada/sinfo-utils.adb
index 7f9bb89..cf0ecc1 100644
--- a/gcc/ada/sinfo-utils.adb
+++ b/gcc/ada/sinfo-utils.adb
@@ -23,7 +23,7 @@
-- --
------------------------------------------------------------------------------
-with Atree;
+with Atree; use Atree;
with Debug; use Debug;
with Output; use Output;
with Seinfo;
@@ -55,7 +55,7 @@ package body Sinfo.Utils is
-- The second method is much faster if the amount of Ada code being
-- compiled is large.
- ww : Node_Id'Base := Node_Id'First - 1;
+ ww : Node_Id'Base := Node_Low_Bound - 1;
pragma Export (Ada, ww);
Watch_Node : Node_Id'Base renames ww;
-- Node to "watch"; that is, whenever a node is created, we check if it
@@ -72,8 +72,8 @@ package body Sinfo.Utils is
procedure nnd (N : Node_Id);
pragma Export (Ada, nnd);
- -- For debugging. If debugging is turned on, New_Node and New_Entity call
- -- this. If debug flag N is turned on, this prints out the new node.
+ -- For debugging. If debugging is turned on, New_Node and New_Entity (etc.)
+ -- call this. If debug flag N is turned on, this prints out the new node.
--
-- If Node = Watch_Node, this prints out the new node and calls
-- New_Node_Breakpoint. Otherwise, does nothing.
@@ -191,7 +191,7 @@ package body Sinfo.Utils is
function End_Location (N : Node_Id) return Source_Ptr is
L : constant Uint := End_Span (N);
begin
- if L = No_Uint then
+ if No (L) then
return No_Location;
else
return Source_Ptr (Int (Sloc (N)) + UI_To_Int (L));
@@ -265,7 +265,7 @@ package body Sinfo.Utils is
if Fields (J) /= F_Link then -- Don't walk Parent!
declare
Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Field_Descriptors (Fields (J));
begin
if Is_In_Union_Id (Desc.Kind) then
Action (Get_Node_Field_Union (N, Desc.Offset));
@@ -290,7 +290,7 @@ package body Sinfo.Utils is
if Fields (J) /= F_Link then -- Don't walk Parent!
declare
Desc : Field_Descriptor renames
- Node_Field_Descriptors (Fields (J));
+ Field_Descriptors (Fields (J));
begin
if Is_In_Union_Id (Desc.Kind) then
Set_Node_Field_Union
diff --git a/gcc/ada/sinfo-utils.ads b/gcc/ada/sinfo-utils.ads
index 2023e67..e3bb8d4 100644
--- a/gcc/ada/sinfo-utils.ads
+++ b/gcc/ada/sinfo-utils.ads
@@ -23,7 +23,7 @@
-- --
------------------------------------------------------------------------------
-with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Nodes; use Sinfo.Nodes;
package Sinfo.Utils is
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 20a6125..b99edf7 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -411,10 +411,6 @@ package Sinfo is
-- Assignment_OK set if modification is OK
-- Is_Controlling_Actual set for controlling argument
- -- Note: the utility program that creates the Treeprs spec (in the file
- -- xtreeprs.adb) knows about the special fields here, so it must be
- -- modified if any change is made to these fields.
-
-- Note: see under (EXPRESSION) for further details on the use of
-- the Paren_Count field to record the number of parentheses levels.
diff --git a/gcc/ada/snames.adb-tmpl b/gcc/ada/snames.adb-tmpl
index a1ea3ee..8701ea9 100644
--- a/gcc/ada/snames.adb-tmpl
+++ b/gcc/ada/snames.adb-tmpl
@@ -258,6 +258,8 @@ package body Snames is
return Pragma_Interrupt_Priority;
when Name_Lock_Free =>
return Pragma_Lock_Free;
+ when Name_Preelaborable_Initialization =>
+ return Pragma_Preelaborable_Initialization;
when Name_Priority =>
return Pragma_Priority;
when Name_Secondary_Stack_Size =>
@@ -488,6 +490,7 @@ package body Snames is
or else N = Name_Interface
or else N = Name_Interrupt_Priority
or else N = Name_Lock_Free
+ or else N = Name_Preelaborable_Initialization
or else N = Name_Priority
or else N = Name_Secondary_Stack_Size
or else N = Name_Storage_Size
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index a67623b..e1af28b 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -37,6 +37,17 @@ package Snames is
-- some exceptions). See the body of Get_Attribute_Id for details. The
-- same is true of other enumeration types declared in this package.
+ -- ALSO NOTE: In the case of a name that corresponds to both an attribute
+ -- and a pragma, the Name_Id must be defined in the attribute section
+ -- (between First_Attribute_Name and Last_Attribute_Name). Also, please
+ -- add a comment in the list of Name_Ids at the point where the name would
+ -- normally appear alphabetically (for an example, see comment starting
+ -- "Note: CPU ..."). The Pragma_Id with that name must be defined in the
+ -- last section of literals for type Pragma_Id (see set of Pragma_Ids that
+ -- require special processing due to matching an attribute name). Finally,
+ -- the bodies of functions Get_Pragma_Id and Is_Pragma_Name must be updated
+ -- to test for each such pragma that shares a name with an attribute.
+
------------------
-- Preset Names --
------------------
@@ -138,6 +149,7 @@ package Snames is
Name_Default_Value : constant Name_Id := N + $;
Name_Default_Component_Value : constant Name_Id := N + $;
+ Name_Designated_Storage_Model : constant Name_Id := N + $;
Name_Dimension : constant Name_Id := N + $;
Name_Dimension_System : constant Name_Id := N + $;
Name_Disable_Controlled : constant Name_Id := N + $;
@@ -151,6 +163,8 @@ package Snames is
Name_Relaxed_Initialization : constant Name_Id := N + $;
Name_Stable_Properties : constant Name_Id := N + $;
Name_Static_Predicate : constant Name_Id := N + $;
+ Name_Storage_Model : constant Name_Id := N + $;
+ Name_Storage_Model_Type : constant Name_Id := N + $;
Name_String_Literal : constant Name_Id := N + $;
Name_Synchronization : constant Name_Id := N + $;
Name_Unimplemented : constant Name_Id := N + $;
@@ -515,6 +529,7 @@ package Snames is
Name_CPP_Constructor : constant Name_Id := N + $; -- GNAT
Name_CPP_Virtual : constant Name_Id := N + $; -- GNAT
Name_CPP_Vtable : constant Name_Id := N + $; -- GNAT
+ Name_CUDA_Device : constant Name_Id := N + $; -- GNAT
Name_CUDA_Execute : constant Name_Id := N + $; -- GNAT
Name_CUDA_Global : constant Name_Id := N + $; -- GNAT
@@ -624,7 +639,13 @@ package Snames is
Name_Precondition : constant Name_Id := N + $; -- GNAT
Name_Predicate : constant Name_Id := N + $; -- GNAT
Name_Predicate_Failure : constant Name_Id := N + $; -- Ada 12
- Name_Preelaborable_Initialization : constant Name_Id := N + $; -- Ada 05
+
+ -- Note: Preelaborable_Initialization is not in this list because its name
+ -- matches the name of the corresponding attribute. However, it is included
+ -- in the definition of the type Pragma_Id, and the functions Get_Pragma_Id
+ -- and Is_Pragma_Name correctly recognize and process that pragma name.
+ -- Preelaborable_Initialization is a standard Ada 2005 pragma.
+
Name_Preelaborate : constant Name_Id := N + $;
Name_Pre_Class : constant Name_Id := N + $; -- GNAT
@@ -761,6 +782,7 @@ package Snames is
-- Other special names used in processing attributes, aspects, and pragmas
+ Name_Address_Type : constant Name_Id := N + $;
Name_Aggregate : constant Name_Id := N + $;
Name_Allow : constant Name_Id := N + $;
Name_Amount : constant Name_Id := N + $;
@@ -780,6 +802,8 @@ package Snames is
Name_Component : constant Name_Id := N + $;
Name_Component_Size_4 : constant Name_Id := N + $;
Name_Copy : constant Name_Id := N + $;
+ Name_Copy_From : constant Name_Id := N + $;
+ Name_Copy_To : constant Name_Id := N + $;
Name_D_Float : constant Name_Id := N + $;
Name_Decreases : constant Name_Id := N + $;
Name_Disable : constant Name_Id := N + $;
@@ -849,6 +873,7 @@ package Snames is
Name_Nominal : constant Name_Id := N + $;
Name_Non_Volatile : constant Name_Id := N + $;
Name_None : constant Name_Id := N + $;
+ Name_Null_Address : constant Name_Id := N + $;
Name_On : constant Name_Id := N + $;
Name_Optional : constant Name_Id := N + $;
Name_Policy : constant Name_Id := N + $;
@@ -946,8 +971,8 @@ package Snames is
Name_Elaborated : constant Name_Id := N + $; -- GNAT
Name_Emax : constant Name_Id := N + $; -- Ada 83
Name_Enabled : constant Name_Id := N + $; -- GNAT
- Name_Enum_Rep : constant Name_Id := N + $; -- GNAT
- Name_Enum_Val : constant Name_Id := N + $; -- GNAT
+ Name_Enum_Rep : constant Name_Id := N + $; -- Ada 22
+ Name_Enum_Val : constant Name_Id := N + $; -- Ada 22
Name_Epsilon : constant Name_Id := N + $; -- Ada 83
Name_Exponent : constant Name_Id := N + $;
Name_External_Tag : constant Name_Id := N + $;
@@ -1000,17 +1025,18 @@ package Snames is
Name_Modulus : constant Name_Id := N + $;
Name_Null_Parameter : constant Name_Id := N + $; -- GNAT
Name_Object_Size : constant Name_Id := N + $; -- GNAT
- Name_Old : constant Name_Id := N + $; -- GNAT
+ Name_Old : constant Name_Id := N + $; -- Ada 12
Name_Overlaps_Storage : constant Name_Id := N + $; -- GNAT
Name_Partition_ID : constant Name_Id := N + $;
Name_Passed_By_Reference : constant Name_Id := N + $; -- GNAT
Name_Pool_Address : constant Name_Id := N + $; -- GNAT
Name_Pos : constant Name_Id := N + $;
Name_Position : constant Name_Id := N + $;
+ Name_Preelaborable_Initialization : constant Name_Id := N + $; -- Ada 22
Name_Priority : constant Name_Id := N + $; -- Ada 05
Name_Range : constant Name_Id := N + $;
Name_Range_Length : constant Name_Id := N + $; -- GNAT
- Name_Reduce : constant Name_Id := N + $; -- GNAT
+ Name_Reduce : constant Name_Id := N + $; -- Ada 22
Name_Ref : constant Name_Id := N + $; -- GNAT
Name_Restriction_Set : constant Name_Id := N + $; -- GNAT
Name_Result : constant Name_Id := N + $; -- GNAT
@@ -1374,7 +1400,6 @@ package Snames is
-- 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 + $;
@@ -1536,6 +1561,7 @@ package Snames is
Attribute_Pool_Address,
Attribute_Pos,
Attribute_Position,
+ Attribute_Preelaborable_Initialization,
Attribute_Priority,
Attribute_Range,
Attribute_Range_Length,
@@ -1843,6 +1869,7 @@ package Snames is
Pragma_CPP_Constructor,
Pragma_CPP_Virtual,
Pragma_CPP_Vtable,
+ Pragma_CUDA_Device,
Pragma_CUDA_Execute,
Pragma_CUDA_Global,
Pragma_Deadline_Floor,
@@ -1921,7 +1948,6 @@ package Snames is
Pragma_Precondition,
Pragma_Predicate,
Pragma_Predicate_Failure,
- Pragma_Preelaborable_Initialization,
Pragma_Preelaborate,
Pragma_Pre_Class,
Pragma_Provide_Shift_Operators,
@@ -1974,7 +2000,9 @@ package Snames is
-- The following pragmas are on their own, out of order, because of the
-- special processing required to deal with the fact that their names
- -- match existing attribute names.
+ -- match existing attribute names. Note that when a pragma is added in
+ -- this section, functions Get_Pragma_Id and Is_Pragma_Name must be
+ -- updated to account for the new pragma.
Pragma_CPU,
Pragma_Default_Scalar_Storage_Order,
@@ -1983,6 +2011,7 @@ package Snames is
Pragma_Interface,
Pragma_Interrupt_Priority,
Pragma_Lock_Free,
+ Pragma_Preelaborable_Initialization,
Pragma_Priority,
Pragma_Secondary_Stack_Size,
Pragma_Storage_Size,
diff --git a/gcc/ada/socket.c b/gcc/ada/socket.c
index 82e0c5a..5074c8e 100644
--- a/gcc/ada/socket.c
+++ b/gcc/ada/socket.c
@@ -314,6 +314,7 @@ __gnat_gethostbyaddr (const char *addr, int len, int type,
ret->h_addrtype = AF_INET;
ret->h_length = 4;
ret->h_addr_list = &vxw_h_addr_list;
+ return 0;
}
int
@@ -587,6 +588,9 @@ __gnat_inet_pton (int af, const char *src, void *dst) {
*(in_addr_t *)dst = addr;
}
return rc;
+
+#else
+ return -1;
#endif
}
#endif
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index c1f1ede..9b78ada 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -2075,7 +2075,7 @@ package body Sprint is
Sprint_Node (Name (Node));
Write_Char (';');
- when N_Generic_Package_Declaration =>
+ when N_Generic_Declaration =>
Extra_Blank_Line;
Write_Indent_Str_Sloc ("generic ");
Sprint_Indented_List (Generic_Formal_Declarations (Node));
@@ -2097,14 +2097,6 @@ package body Sprint is
Sprint_Node (Name (Node));
Write_Char (';');
- when N_Generic_Subprogram_Declaration =>
- Extra_Blank_Line;
- Write_Indent_Str_Sloc ("generic ");
- Sprint_Indented_List (Generic_Formal_Declarations (Node));
- Write_Indent;
- Sprint_Node (Specification (Node));
- Write_Char (';');
-
when N_Goto_Statement =>
Write_Indent_Str_Sloc ("goto ");
Sprint_Node (Name (Node));
@@ -4222,7 +4214,7 @@ package body Sprint is
-- Itype to be printed
declare
- B : constant Node_Id := Etype (Typ);
+ B : constant Entity_Id := Etype (Typ);
P : constant Node_Id := Parent (Typ);
S : constant Saved_Output_Buffer := Save_Output_Buffer;
-- Save current output buffer
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index aa38c5c..2c50b36 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -643,11 +643,11 @@ long __gnat_invalid_tzoff = 259273;
/* Reentrant localtime for Windows. */
extern void
-__gnat_localtime_tzoff (const time_t *, const int *, long *);
+__gnat_localtime_tzoff (const OS_Time *, const int *, long *);
static const unsigned long long w32_epoch_offset = 11644473600ULL;
void
-__gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
+__gnat_localtime_tzoff (const OS_Time *timer, const int *is_historic, long *off)
{
TIME_ZONE_INFORMATION tzi;
@@ -737,10 +737,10 @@ __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
the Lynx convention when building against the legacy API. */
extern void
-__gnat_localtime_tzoff (const time_t *, const int *, long *);
+__gnat_localtime_tzoff (const OS_Time *, const int *, long *);
void
-__gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
+__gnat_localtime_tzoff (const OS_Time *timer, const int *is_historic, long *off)
{
*off = 0;
}
@@ -756,21 +756,22 @@ extern void (*Lock_Task) (void);
extern void (*Unlock_Task) (void);
extern void
-__gnat_localtime_tzoff (const time_t *, const int *, long *);
+__gnat_localtime_tzoff (const OS_Time *, const int *, long *);
void
-__gnat_localtime_tzoff (const time_t *timer ATTRIBUTE_UNUSED,
+__gnat_localtime_tzoff (const OS_Time *timer ATTRIBUTE_UNUSED,
const int *is_historic ATTRIBUTE_UNUSED,
long *off ATTRIBUTE_UNUSED)
{
struct tm tp ATTRIBUTE_UNUSED;
+ const time_t time = (time_t) *timer;
/* AIX, HPUX, Sun Solaris */
#if defined (_AIX) || defined (__hpux__) || defined (__sun__)
{
(*Lock_Task) ();
- localtime_r (timer, &tp);
+ localtime_r (&time, &tp);
*off = (long) -timezone;
(*Unlock_Task) ();
@@ -787,7 +788,7 @@ __gnat_localtime_tzoff (const time_t *timer ATTRIBUTE_UNUSED,
{
(*Lock_Task) ();
- localtime_r (timer, &tp);
+ localtime_r (&time, &tp);
/* Try to read the environment variable TIMEZONE. The variable may not have
been initialize, in that case return an offset of zero (0) for UTC. */
@@ -833,7 +834,7 @@ __gnat_localtime_tzoff (const time_t *timer ATTRIBUTE_UNUSED,
|| defined (__GLIBC__) || defined (__DragonFly__) || defined (__OpenBSD__) \
|| defined (__DJGPP__) || defined (__QNX__)
{
- localtime_r (timer, &tp);
+ localtime_r (&time, &tp);
*off = tp.tm_gmtoff;
}
@@ -906,6 +907,10 @@ __gnat_is_file_not_found_error (int errno_val)
if (errno_val == ENOENT)
return 1;
#ifdef __vxworks
+ /* Starting with VxWorks 21.03, the fopen() function can set errno to
+ * ENODEV when the prefix of the path does not match any known device. */
+ else if (errno_val == ENODEV)
+ return 1;
/* In the case of VxWorks, we also have to take into account various
* filesystem-specific variants of this error.
*/
diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb
index 054d06c..2e9d2c2 100644
--- a/gcc/ada/treepr.adb
+++ b/gcc/ada/treepr.adb
@@ -130,9 +130,7 @@ package body Treepr is
procedure Capitalize (S : in out String);
-- Turns an identifier into Mixed_Case
- function Image (F : Node_Field) return String;
-
- function Image (F : Entity_Field) return String;
+ function Image (F : Node_Or_Entity_Field) return String;
procedure Print_Init;
-- Initialize for printing of tree with descendants
@@ -281,7 +279,7 @@ package body Treepr is
-- Image --
-----------
- function Image (F : Node_Field) return String is
+ function Image (F : Node_Or_Entity_Field) return String is
begin
case F is
when F_Alloc_For_BIP_Return =>
@@ -321,18 +319,6 @@ package body Treepr is
when F_TSS_Elist =>
return "TSS_Elist";
- when others =>
- declare
- Result : constant String := Capitalize (F'Img);
- begin
- return Result (3 .. Result'Last); -- Remove "F_"
- end;
- end case;
- end Image;
-
- function Image (F : Entity_Field) return String is
- begin
- case F is
when F_BIP_Initialization_Call =>
return "BIP_Initialization_Call";
when F_Body_Needed_For_SAL =>
@@ -614,7 +600,7 @@ package body Treepr is
Write_Str (UI_Image (Val));
Write_Str (") ");
- if Val /= No_Uint then
+ if Present (Val) then
Write_Location (End_Location (N));
end if;
end Print_End_Span;
@@ -666,7 +652,7 @@ package body Treepr is
for Field_Index in Fields'Range loop
declare
FD : Field_Descriptor renames
- Entity_Field_Descriptors (Fields (Field_Index));
+ Field_Descriptors (Fields (Field_Index));
begin
if Should_Print (Fields (Field_Index))
and then (FD.Kind = Flag_Field) = Print_Flags
@@ -1198,7 +1184,6 @@ package body Treepr is
Prefix : constant String := Prefix_Str & Prefix_Char;
Sfile : Source_File_Index;
- Fmt : UI_Format;
begin
if Phase /= Printing then
@@ -1266,14 +1251,21 @@ package body Treepr is
-- Print Chars field if present
- if Nkind (N) in N_Has_Chars and then Chars (N) /= No_Name then
- Print_Str (Prefix);
- Print_Str ("Chars = ");
- Print_Name (Chars (N));
- Write_Str (" (Name_Id=");
- Write_Int (Int (Chars (N)));
- Write_Char (')');
- Print_Eol;
+ if Nkind (N) in N_Has_Chars then
+ if Field_Is_Initial_Zero (N, F_Chars) then
+ Print_Str (Prefix);
+ Print_Str ("Chars = initial zero");
+ Print_Eol;
+
+ elsif Chars (N) /= No_Name then
+ Print_Str (Prefix);
+ Print_Str ("Chars = ");
+ Print_Name (Chars (N));
+ Write_Str (" (Name_Id=");
+ Write_Int (Int (Chars (N)));
+ Write_Char (')');
+ Print_Eol;
+ end if;
end if;
-- Special field print operations for non-entity nodes
@@ -1407,12 +1399,6 @@ package body Treepr is
end if;
end if;
- if Nkind (N) = N_Integer_Literal and then Print_In_Hex (N) then
- Fmt := Hex;
- else
- Fmt := Auto;
- end if;
-
declare
Fields : Node_Field_Array renames Node_Field_Table (Nkind (N)).all;
Should_Print : constant Node_Field_Set :=
@@ -1447,6 +1433,12 @@ package body Treepr is
=> False,
others => True);
+
+ Fmt : constant UI_Format :=
+ (if Nkind (N) = N_Integer_Literal and then Print_In_Hex (N)
+ then Hex
+ else Auto);
+
begin
-- Outer loop makes flags come out last
@@ -1454,7 +1446,7 @@ package body Treepr is
for Field_Index in Fields'Range loop
declare
FD : Field_Descriptor renames
- Node_Field_Descriptors (Fields (Field_Index));
+ Field_Descriptors (Fields (Field_Index));
begin
if Should_Print (Fields (Field_Index))
and then (FD.Kind = Flag_Field) = Print_Flags
@@ -1624,7 +1616,14 @@ package body Treepr is
if Nkind (N) in N_Has_Chars then
Write_Char (' ');
- Print_Name (Chars (N));
+
+ if Field_Is_Initial_Zero (N, F_Chars) then
+ Print_Str ("Chars = initial zero");
+ Print_Eol;
+
+ else
+ Print_Name (Chars (N));
+ end if;
end if;
if Nkind (N) in N_Entity then
@@ -2054,25 +2053,16 @@ package body Treepr is
New_Prefix : String (Prefix_Str'First .. Prefix_Str'Last + 2);
-- Prefix string for printing referenced fields
- procedure Visit_Descendant
- (D : Union_Id;
- No_Indent : Boolean := False);
+ procedure Visit_Descendant (D : Union_Id);
-- This procedure tests the given value of one of the Fields referenced
-- by the current node to determine whether to visit it recursively.
- -- Normally No_Indent is false, which means that the visited node will
- -- be indented using New_Prefix. If No_Indent is set to True, then
- -- this indentation is skipped, and Prefix_Str is used for the call
- -- to print the descendant. No_Indent is effective only if the
- -- referenced descendant is a node.
+ -- The visited node will be indented using New_Prefix.
----------------------
-- Visit_Descendant --
----------------------
- procedure Visit_Descendant
- (D : Union_Id;
- No_Indent : Boolean := False)
- is
+ procedure Visit_Descendant (D : Union_Id) is
begin
-- Case of descendant is a node
@@ -2145,11 +2135,7 @@ package body Treepr is
-- execute a return if the node is not to be visited), we can
-- go ahead and visit the node.
- if No_Indent then
- Visit_Node (Nod, Prefix_Str, Prefix_Char);
- else
- Visit_Node (Nod, New_Prefix, ' ');
- end if;
+ Visit_Node (Nod, New_Prefix, ' ');
end;
-- Case of descendant is a list
@@ -2265,7 +2251,7 @@ package body Treepr is
for Field_Index in A'Range loop
declare
F : constant Node_Field := A (Field_Index);
- FD : Field_Descriptor renames Node_Field_Descriptors (F);
+ FD : Field_Descriptor renames Field_Descriptors (F);
begin
if FD.Kind in Node_Id_Field | List_Id_Field | Elist_Id_Field
-- For all other kinds of descendants (strings, names, uints
@@ -2293,7 +2279,7 @@ package body Treepr is
for Field_Index in A'Range loop
declare
F : constant Entity_Field := A (Field_Index);
- FD : Field_Descriptor renames Entity_Field_Descriptors (F);
+ FD : Field_Descriptor renames Field_Descriptors (F);
begin
if FD.Kind in Node_Id_Field | List_Id_Field | Elist_Id_Field
then
diff --git a/gcc/ada/ttypes.ads b/gcc/ada/ttypes.ads
index 5f59607..62a1c4f 100644
--- a/gcc/ada/ttypes.ads
+++ b/gcc/ada/ttypes.ads
@@ -25,7 +25,7 @@
-- This package contains constants describing target properties
-with Types; use Types;
+with Types; use Types;
with Set_Targ;
package Ttypes is
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index a74bfb6..673f7c6 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -59,6 +59,15 @@ package Types is
subtype Pos is Int range 1 .. Int'Last;
-- Positive Int values
+ subtype Nonzero_Int is Int with Predicate => Nonzero_Int /= 0;
+
+ type Int_64 is range -2 ** 63 .. +2 ** 63 - 1;
+ -- Signed 64-bit integer
+
+ subtype Nat_64 is Int_64 range 0 .. Int_64'Last;
+ subtype Pos_64 is Int_64 range 1 .. Int_64'Last;
+ subtype Nonzero_Int_64 is Int_64 with Predicate => Nonzero_Int_64 /= 0;
+
type Word is mod 2 ** 32;
-- Unsigned 32-bit integer
@@ -989,6 +998,8 @@ package Types is
-- Offset of a node field, in units of the size of the field, which is
-- always a power of 2.
+ subtype Node_Offset is Field_Offset'Base range 1 .. Field_Offset'Base'Last;
+
subtype Slot_Count is Field_Offset;
-- Count of number of slots. Same type as Field_Offset to avoid
-- proliferation of type conversions.
diff --git a/gcc/ada/uintp.adb b/gcc/ada/uintp.adb
index 8183469..29d409b 100644
--- a/gcc/ada/uintp.adb
+++ b/gcc/ada/uintp.adb
@@ -73,6 +73,18 @@ package body Uintp is
-- These values are used in some cases where the use of numeric literals
-- would cause ambiguities (integer vs Uint).
+ type UI_Vector is array (Pos range <>) of Int;
+ -- Vector containing the integer values of a Uint value
+
+ -- Note: An earlier version of this package used pointers of arrays of Ints
+ -- (dynamically allocated) for the Uint type. The change leads to a few
+ -- less natural idioms used throughout this code, but eliminates all uses
+ -- of the heap except for the table package itself. For example, Uint
+ -- parameters are often converted to UI_Vectors for internal manipulation.
+ -- This is done by creating the local UI_Vector using the function N_Digits
+ -- on the Uint to find the size needed for the vector, and then calling
+ -- Init_Operand to copy the values out of the table into the vector.
+
----------------------------
-- UI_From_Int Hash Table --
----------------------------
@@ -98,12 +110,12 @@ package body Uintp is
-- Local Subprograms --
-----------------------
- function Direct (U : Uint) return Boolean;
+ function Direct (U : Valid_Uint) return Boolean;
pragma Inline (Direct);
-- Returns True if U is represented directly
- function Direct_Val (U : Uint) return Int;
- -- U is a Uint for is represented directly. The returned result is the
+ function Direct_Val (U : Valid_Uint) return Int;
+ -- U is a Uint that is represented directly. The returned result is the
-- value represented.
function GCD (Jin, Kin : Int) return Int;
@@ -117,7 +129,7 @@ package body Uintp is
-- UI_Image, and false for UI_Write, and Format is copied from the Format
-- parameter to UI_Image or UI_Write.
- procedure Init_Operand (UI : Uint; Vec : out UI_Vector);
+ procedure Init_Operand (UI : Valid_Uint; Vec : out UI_Vector);
pragma Inline (Init_Operand);
-- This procedure puts the value of UI into the vector in canonical
-- multiple precision format. The parameter should be of the correct size
@@ -127,7 +139,23 @@ package body Uintp is
-- contain the corresponding one or two digit value. The low bound of Vec
-- is always 1.
- function Least_Sig_Digit (Arg : Uint) return Int;
+ function Vector_To_Uint
+ (In_Vec : UI_Vector;
+ Negative : Boolean) return Valid_Uint;
+ -- Functions that calculate values in UI_Vectors, call this function to
+ -- create and return the Uint value. In_Vec contains the multiple precision
+ -- (Base) representation of a non-negative value. Leading zeroes are
+ -- permitted. Negative is set if the desired result is the negative of the
+ -- given value. The result will be either the appropriate directly
+ -- represented value, or a table entry in the proper canonical format is
+ -- created and returned.
+ --
+ -- Note that Init_Operand puts a signed value in the result vector, but
+ -- Vector_To_Uint is always presented with a non-negative value. The
+ -- processing of signs is something that is done by the caller before
+ -- calling Vector_To_Uint.
+
+ function Least_Sig_Digit (Arg : Valid_Uint) return Int;
pragma Inline (Least_Sig_Digit);
-- Returns the Least Significant Digit of Arg quickly. When the given Uint
-- is less than 2**15, the value returned is the input value, in this case
@@ -137,8 +165,8 @@ package body Uintp is
-- two.
procedure Most_Sig_2_Digits
- (Left : Uint;
- Right : Uint;
+ (Left : Valid_Uint;
+ Right : Valid_Uint;
Left_Hat : out Int;
Right_Hat : out Int);
-- Returns leading two significant digits from the given pair of Uint's.
@@ -146,29 +174,40 @@ package body Uintp is
-- K is as small as possible S.T. Right_Hat < Base * Base. It is required
-- that Left >= Right for the algorithm to work.
- function N_Digits (Input : Uint) return Int;
+ function N_Digits (Input : Valid_Uint) return Int;
pragma Inline (N_Digits);
-- Returns number of "digits" in a Uint
procedure UI_Div_Rem
- (Left, Right : Uint;
+ (Left, Right : Valid_Uint;
Quotient : out Uint;
Remainder : out Uint;
Discard_Quotient : Boolean := False;
Discard_Remainder : Boolean := False);
-- Compute Euclidean division of Left by Right. If Discard_Quotient is
- -- False then the quotient is returned in Quotient (otherwise Quotient is
- -- set to No_Uint). If Discard_Remainder is False, then the remainder is
- -- returned in Remainder (otherwise Remainder is set to No_Uint).
+ -- False then the quotient is returned in Quotient. If Discard_Remainder
+ -- is False, then the remainder is returned in Remainder.
--
- -- If Discard_Quotient is True, Quotient is set to No_Uint
- -- If Discard_Remainder is True, Remainder is set to No_Uint
+ -- If Discard_Quotient is True, Quotient is set to No_Uint.
+ -- If Discard_Remainder is True, Remainder is set to No_Uint.
+
+ function UI_Modular_Exponentiation
+ (B : Valid_Uint;
+ E : Valid_Uint;
+ Modulo : Valid_Uint) return Valid_Uint with Unreferenced;
+ -- Efficiently compute (B**E) rem Modulo
+
+ function UI_Modular_Inverse
+ (N : Valid_Uint; Modulo : Valid_Uint) return Valid_Uint with Unreferenced;
+ -- Compute the multiplicative inverse of N in modular arithmetics with the
+ -- given Modulo (uses Euclid's algorithm). Note: the call is considered
+ -- to be erroneous (and the behavior is undefined) if n is not invertible.
------------
-- Direct --
------------
- function Direct (U : Uint) return Boolean is
+ function Direct (U : Valid_Uint) return Boolean is
begin
return Int (U) <= Int (Uint_Direct_Last);
end Direct;
@@ -177,7 +216,7 @@ package body Uintp is
-- Direct_Val --
----------------
- function Direct_Val (U : Uint) return Int is
+ function Direct_Val (U : Valid_Uint) return Int is
begin
pragma Assert (Direct (U));
return Int (U) - Int (Uint_Direct_Bias);
@@ -224,8 +263,8 @@ package body Uintp is
Format : UI_Format)
is
Marks : constant Uintp.Save_Mark := Uintp.Mark;
- Base : Uint;
- Ainput : Uint;
+ Base : Valid_Uint;
+ Ainput : Valid_Uint;
Digs_Output : Natural := 0;
-- Counts digits output. In hex mode, but not in decimal mode, we
@@ -249,7 +288,7 @@ package body Uintp is
-- Output non-zero exponent. Note that we only use the exponent form in
-- the buffer case, so we know that To_Buffer is true.
- procedure Image_Uint (U : Uint);
+ procedure Image_Uint (U : Valid_Uint);
-- Internal procedure to output characters of non-negative Uint
-------------------
@@ -257,8 +296,8 @@ package body Uintp is
-------------------
function Better_In_Hex return Boolean is
- T16 : constant Uint := Uint_2**Int'(16);
- A : Uint;
+ T16 : constant Valid_Uint := Uint_2**Int'(16);
+ A : Valid_Uint;
begin
A := UI_Abs (Input);
@@ -336,11 +375,11 @@ package body Uintp is
-- Image_Uint --
----------------
- procedure Image_Uint (U : Uint) is
+ procedure Image_Uint (U : Valid_Uint) is
H : constant array (Int range 0 .. 15) of Character :=
"0123456789ABCDEF";
- Q, R : Uint;
+ Q, R : Valid_Uint;
begin
UI_Div_Rem (U, Base, Q, R);
@@ -361,7 +400,7 @@ package body Uintp is
-- Start of processing for Image_Out
begin
- if Input = No_Uint then
+ if No (Input) then
Image_Char ('?');
return;
end if;
@@ -403,7 +442,7 @@ package body Uintp is
-- Init_Operand --
-------------------
- procedure Init_Operand (UI : Uint; Vec : out UI_Vector) is
+ procedure Init_Operand (UI : Valid_Uint; Vec : out UI_Vector) is
Loc : Int;
pragma Assert (Vec'First = Int'(1));
@@ -454,7 +493,7 @@ package body Uintp is
-- Least_Sig_Digit --
---------------------
- function Least_Sig_Digit (Arg : Uint) return Int is
+ function Least_Sig_Digit (Arg : Valid_Uint) return Int is
V : Int;
begin
@@ -490,8 +529,8 @@ package body Uintp is
-----------------------
procedure Most_Sig_2_Digits
- (Left : Uint;
- Right : Uint;
+ (Left : Valid_Uint;
+ Right : Valid_Uint;
Left_Hat : out Int;
Right_Hat : out Int)
is
@@ -552,9 +591,7 @@ package body Uintp is
-- N_Digits --
---------------
- -- Note: N_Digits returns 1 for No_Uint
-
- function N_Digits (Input : Uint) return Int is
+ function N_Digits (Input : Valid_Uint) return Int is
begin
if Direct (Input) then
if Direct_Val (Input) >= Base then
@@ -572,7 +609,7 @@ package body Uintp is
-- Num_Bits --
--------------
- function Num_Bits (Input : Uint) return Nat is
+ function Num_Bits (Input : Valid_Uint) return Nat is
Bits : Nat;
Num : Nat;
@@ -633,7 +670,7 @@ package body Uintp is
procedure Release (M : Save_Mark) is
begin
- Uints.Set_Last (Uint'Max (M.Save_Uint, Uints_Min));
+ Uints.Set_Last (Valid_Uint'Max (M.Save_Uint, Uints_Min));
Udigits.Set_Last (Int'Max (M.Save_Udigit, Udigits_Min));
end Release;
@@ -641,7 +678,7 @@ package body Uintp is
-- Release_And_Save --
----------------------
- procedure Release_And_Save (M : Save_Mark; UI : in out Uint) is
+ procedure Release_And_Save (M : Save_Mark; UI : in out Valid_Uint) is
begin
if Direct (UI) then
Release (M);
@@ -667,7 +704,7 @@ package body Uintp is
end if;
end Release_And_Save;
- procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Uint) is
+ procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Valid_Uint) is
begin
if Direct (UI1) then
Release_And_Save (M, UI2);
@@ -713,7 +750,7 @@ package body Uintp is
-- UI_Abs --
-------------
- function UI_Abs (Right : Uint) return Uint is
+ function UI_Abs (Right : Valid_Uint) return Unat is
begin
if Right < Uint_0 then
return -Right;
@@ -726,18 +763,23 @@ package body Uintp is
-- UI_Add --
-------------
- function UI_Add (Left : Int; Right : Uint) return Uint is
+ function UI_Add (Left : Int; Right : Valid_Uint) return Valid_Uint is
begin
return UI_Add (UI_From_Int (Left), Right);
end UI_Add;
- function UI_Add (Left : Uint; Right : Int) return Uint is
+ function UI_Add (Left : Valid_Uint; Right : Int) return Valid_Uint is
begin
return UI_Add (Left, UI_From_Int (Right));
end UI_Add;
- function UI_Add (Left : Uint; Right : Uint) return Uint is
+ function UI_Add (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint is
begin
+ pragma Assert (Present (Left));
+ pragma Assert (Present (Right));
+ -- Assertions are here in case we're called from C++ code, which does
+ -- not check the predicates.
+
-- Simple cases of direct operands and addition of zero
if Direct (Left) then
@@ -902,7 +944,7 @@ package body Uintp is
-- UI_Decimal_Digits_Hi --
--------------------------
- function UI_Decimal_Digits_Hi (U : Uint) return Nat is
+ function UI_Decimal_Digits_Hi (U : Valid_Uint) return Nat is
begin
-- The maximum value of a "digit" is 32767, which is 5 decimal digits,
-- so an N_Digit number could take up to 5 times this number of digits.
@@ -916,7 +958,7 @@ package body Uintp is
-- UI_Decimal_Digits_Lo --
--------------------------
- function UI_Decimal_Digits_Lo (U : Uint) return Nat is
+ function UI_Decimal_Digits_Lo (U : Valid_Uint) return Nat is
begin
-- The maximum value of a "digit" is 32767, which is more than four
-- decimal digits, but not a full five digits. The easily computed
@@ -931,24 +973,27 @@ package body Uintp is
-- UI_Div --
------------
- function UI_Div (Left : Int; Right : Uint) return Uint is
+ function UI_Div (Left : Int; Right : Nonzero_Uint) return Valid_Uint is
begin
return UI_Div (UI_From_Int (Left), Right);
end UI_Div;
- function UI_Div (Left : Uint; Right : Int) return Uint is
+ function UI_Div
+ (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ is
begin
return UI_Div (Left, UI_From_Int (Right));
end UI_Div;
- function UI_Div (Left, Right : Uint) return Uint is
- Quotient : Uint;
- Remainder : Uint;
- pragma Warnings (Off, Remainder);
+ function UI_Div
+ (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ is
+ Quotient : Valid_Uint;
+ Ignored_Remainder : Uint;
begin
UI_Div_Rem
(Left, Right,
- Quotient, Remainder,
+ Quotient, Ignored_Remainder,
Discard_Remainder => True);
return Quotient;
end UI_Div;
@@ -958,7 +1003,7 @@ package body Uintp is
----------------
procedure UI_Div_Rem
- (Left, Right : Uint;
+ (Left, Right : Valid_Uint;
Quotient : out Uint;
Remainder : out Uint;
Discard_Quotient : Boolean := False;
@@ -1232,14 +1277,13 @@ package body Uintp is
if not Discard_Remainder then
declare
Remainder_V : UI_Vector (1 .. R_Length);
- Discard_Int : Int;
- pragma Warnings (Off, Discard_Int);
+ Ignore : Int;
begin
pragma Assert (D /= Int'(0));
UI_Div_Vector
(Dividend (Dividend'Last - R_Length + 1 .. Dividend'Last),
D,
- Remainder_V, Discard_Int);
+ Remainder_V, Ignore);
Remainder := Vector_To_Uint (Remainder_V, L_Vec (1) < Int_0);
end;
end if;
@@ -1251,17 +1295,17 @@ package body Uintp is
-- UI_Eq --
------------
- function UI_Eq (Left : Int; Right : Uint) return Boolean is
+ function UI_Eq (Left : Int; Right : Valid_Uint) return Boolean is
begin
return not UI_Ne (UI_From_Int (Left), Right);
end UI_Eq;
- function UI_Eq (Left : Uint; Right : Int) return Boolean is
+ function UI_Eq (Left : Valid_Uint; Right : Int) return Boolean is
begin
return not UI_Ne (Left, UI_From_Int (Right));
end UI_Eq;
- function UI_Eq (Left : Uint; Right : Uint) return Boolean is
+ function UI_Eq (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
return not UI_Ne (Left, Right);
end UI_Eq;
@@ -1270,22 +1314,24 @@ package body Uintp is
-- UI_Expon --
--------------
- function UI_Expon (Left : Int; Right : Uint) return Uint is
+ function UI_Expon (Left : Int; Right : Unat) return Valid_Uint is
begin
return UI_Expon (UI_From_Int (Left), Right);
end UI_Expon;
- function UI_Expon (Left : Uint; Right : Int) return Uint is
+ function UI_Expon (Left : Valid_Uint; Right : Nat) return Valid_Uint is
begin
return UI_Expon (Left, UI_From_Int (Right));
end UI_Expon;
- function UI_Expon (Left : Int; Right : Int) return Uint is
+ function UI_Expon (Left : Int; Right : Nat) return Valid_Uint is
begin
return UI_Expon (UI_From_Int (Left), UI_From_Int (Right));
end UI_Expon;
- function UI_Expon (Left : Uint; Right : Uint) return Uint is
+ function UI_Expon
+ (Left : Valid_Uint; Right : Unat) return Valid_Uint
+ is
begin
pragma Assert (Right >= Uint_0);
@@ -1358,9 +1404,9 @@ package body Uintp is
-- If we fall through, then we have the general case (see Knuth 4.6.3)
declare
- N : Uint := Right;
- Squares : Uint := Left;
- Result : Uint := Uint_1;
+ N : Valid_Uint := Right;
+ Squares : Valid_Uint := Left;
+ Result : Valid_Uint := Uint_1;
M : constant Uintp.Save_Mark := Uintp.Mark;
begin
@@ -1383,7 +1429,7 @@ package body Uintp is
-- UI_From_CC --
----------------
- function UI_From_CC (Input : Char_Code) return Uint is
+ function UI_From_CC (Input : Char_Code) return Valid_Uint is
begin
return UI_From_Int (Int (Input));
end UI_From_CC;
@@ -1392,19 +1438,19 @@ package body Uintp is
-- UI_From_Int --
-----------------
- function UI_From_Int (Input : Int) return Uint is
+ function UI_From_Int (Input : Int) return Valid_Uint is
U : Uint;
begin
if Min_Direct <= Input and then Input <= Max_Direct then
- return Uint (Int (Uint_Direct_Bias) + Input);
+ return Valid_Uint (Int (Uint_Direct_Bias) + Input);
end if;
-- If already in the hash table, return entry
U := UI_Ints.Get (Input);
- if U /= No_Uint then
+ if Present (U) then
return U;
end if;
@@ -1438,7 +1484,7 @@ package body Uintp is
-- UI_From_Integral --
----------------------
- function UI_From_Integral (Input : In_T) return Uint is
+ function UI_From_Integral (Input : In_T) return Valid_Uint is
begin
-- If in range of our normal conversion function, use it so we can use
-- direct access and our cache.
@@ -1459,7 +1505,7 @@ package body Uintp is
-- Base is defined so that 3 Uint digits is sufficient to hold the
-- largest possible Int value.
- U : Uint;
+ U : Valid_Uint;
V : UI_Vector (1 .. Max_For_In_T);
begin
@@ -1489,8 +1535,8 @@ package body Uintp is
-- We use the same notation as Knuth (U_Hat standing for the obvious)
- function UI_GCD (Uin, Vin : Uint) return Uint is
- U, V : Uint;
+ function UI_GCD (Uin, Vin : Valid_Uint) return Valid_Uint is
+ U, V : Valid_Uint;
-- Copies of Uin and Vin
U_Hat, V_Hat : Int;
@@ -1498,7 +1544,7 @@ package body Uintp is
A, B, C, D, T, Q, Den1, Den2 : Int;
- Tmp_UI : Uint;
+ Tmp_UI : Valid_Uint;
Marks : constant Uintp.Save_Mark := Uintp.Mark;
Iterations : Integer := 0;
@@ -1591,17 +1637,17 @@ package body Uintp is
-- UI_Ge --
------------
- function UI_Ge (Left : Int; Right : Uint) return Boolean is
+ function UI_Ge (Left : Int; Right : Valid_Uint) return Boolean is
begin
return not UI_Lt (UI_From_Int (Left), Right);
end UI_Ge;
- function UI_Ge (Left : Uint; Right : Int) return Boolean is
+ function UI_Ge (Left : Valid_Uint; Right : Int) return Boolean is
begin
return not UI_Lt (Left, UI_From_Int (Right));
end UI_Ge;
- function UI_Ge (Left : Uint; Right : Uint) return Boolean is
+ function UI_Ge (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
return not UI_Lt (Left, Right);
end UI_Ge;
@@ -1610,17 +1656,17 @@ package body Uintp is
-- UI_Gt --
------------
- function UI_Gt (Left : Int; Right : Uint) return Boolean is
+ function UI_Gt (Left : Int; Right : Valid_Uint) return Boolean is
begin
return UI_Lt (Right, UI_From_Int (Left));
end UI_Gt;
- function UI_Gt (Left : Uint; Right : Int) return Boolean is
+ function UI_Gt (Left : Valid_Uint; Right : Int) return Boolean is
begin
return UI_Lt (UI_From_Int (Right), Left);
end UI_Gt;
- function UI_Gt (Left : Uint; Right : Uint) return Boolean is
+ function UI_Gt (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
return UI_Lt (Left => Right, Right => Left);
end UI_Gt;
@@ -1647,7 +1693,10 @@ package body Uintp is
-- UI_Is_In_Int_Range --
-------------------------
- function UI_Is_In_Int_Range (Input : Uint) return Boolean is
+ function UI_Is_In_Int_Range (Input : Valid_Uint) return Boolean is
+ pragma Assert (Present (Input));
+ -- Assertion is here in case we're called from C++ code, which does
+ -- not check the predicates.
begin
-- Make sure we don't get called before Initialize
@@ -1656,8 +1705,7 @@ package body Uintp is
if Direct (Input) then
return True;
else
- return Input >= Uint_Int_First
- and then Input <= Uint_Int_Last;
+ return Input >= Uint_Int_First and then Input <= Uint_Int_Last;
end if;
end UI_Is_In_Int_Range;
@@ -1665,17 +1713,17 @@ package body Uintp is
-- UI_Le --
------------
- function UI_Le (Left : Int; Right : Uint) return Boolean is
+ function UI_Le (Left : Int; Right : Valid_Uint) return Boolean is
begin
return not UI_Lt (Right, UI_From_Int (Left));
end UI_Le;
- function UI_Le (Left : Uint; Right : Int) return Boolean is
+ function UI_Le (Left : Valid_Uint; Right : Int) return Boolean is
begin
return not UI_Lt (UI_From_Int (Right), Left);
end UI_Le;
- function UI_Le (Left : Uint; Right : Uint) return Boolean is
+ function UI_Le (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
return not UI_Lt (Left => Right, Right => Left);
end UI_Le;
@@ -1684,18 +1732,23 @@ package body Uintp is
-- UI_Lt --
------------
- function UI_Lt (Left : Int; Right : Uint) return Boolean is
+ function UI_Lt (Left : Int; Right : Valid_Uint) return Boolean is
begin
return UI_Lt (UI_From_Int (Left), Right);
end UI_Lt;
- function UI_Lt (Left : Uint; Right : Int) return Boolean is
+ function UI_Lt (Left : Valid_Uint; Right : Int) return Boolean is
begin
return UI_Lt (Left, UI_From_Int (Right));
end UI_Lt;
- function UI_Lt (Left : Uint; Right : Uint) return Boolean is
+ function UI_Lt (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
+ pragma Assert (Present (Left));
+ pragma Assert (Present (Right));
+ -- Assertions are here in case we're called from C++ code, which does
+ -- not check the predicates.
+
-- Quick processing for identical arguments
if Int (Left) = Int (Right) then
@@ -1777,17 +1830,17 @@ package body Uintp is
-- UI_Max --
------------
- function UI_Max (Left : Int; Right : Uint) return Uint is
+ function UI_Max (Left : Int; Right : Valid_Uint) return Valid_Uint is
begin
return UI_Max (UI_From_Int (Left), Right);
end UI_Max;
- function UI_Max (Left : Uint; Right : Int) return Uint is
+ function UI_Max (Left : Valid_Uint; Right : Int) return Valid_Uint is
begin
return UI_Max (Left, UI_From_Int (Right));
end UI_Max;
- function UI_Max (Left : Uint; Right : Uint) return Uint is
+ function UI_Max (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint is
begin
if Left >= Right then
return Left;
@@ -1800,17 +1853,17 @@ package body Uintp is
-- UI_Min --
------------
- function UI_Min (Left : Int; Right : Uint) return Uint is
+ function UI_Min (Left : Int; Right : Valid_Uint) return Valid_Uint is
begin
return UI_Min (UI_From_Int (Left), Right);
end UI_Min;
- function UI_Min (Left : Uint; Right : Int) return Uint is
+ function UI_Min (Left : Valid_Uint; Right : Int) return Valid_Uint is
begin
return UI_Min (Left, UI_From_Int (Right));
end UI_Min;
- function UI_Min (Left : Uint; Right : Uint) return Uint is
+ function UI_Min (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint is
begin
if Left <= Right then
return Left;
@@ -1823,18 +1876,22 @@ package body Uintp is
-- UI_Mod --
-------------
- function UI_Mod (Left : Int; Right : Uint) return Uint is
+ function UI_Mod (Left : Int; Right : Nonzero_Uint) return Valid_Uint is
begin
return UI_Mod (UI_From_Int (Left), Right);
end UI_Mod;
- function UI_Mod (Left : Uint; Right : Int) return Uint is
+ function UI_Mod
+ (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ is
begin
return UI_Mod (Left, UI_From_Int (Right));
end UI_Mod;
- function UI_Mod (Left : Uint; Right : Uint) return Uint is
- Urem : constant Uint := Left rem Right;
+ function UI_Mod
+ (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ is
+ Urem : constant Valid_Uint := Left rem Right;
begin
if (Left < Uint_0) = (Right < Uint_0)
@@ -1851,15 +1908,15 @@ package body Uintp is
-------------------------------
function UI_Modular_Exponentiation
- (B : Uint;
- E : Uint;
- Modulo : Uint) return Uint
+ (B : Valid_Uint;
+ E : Valid_Uint;
+ Modulo : Valid_Uint) return Valid_Uint
is
M : constant Save_Mark := Mark;
- Result : Uint := Uint_1;
- Base : Uint := B;
- Exponent : Uint := E;
+ Result : Valid_Uint := Uint_1;
+ Base : Valid_Uint := B;
+ Exponent : Valid_Uint := E;
begin
while Exponent /= Uint_0 loop
@@ -1879,15 +1936,17 @@ package body Uintp is
-- UI_Modular_Inverse --
------------------------
- function UI_Modular_Inverse (N : Uint; Modulo : Uint) return Uint is
+ function UI_Modular_Inverse
+ (N : Valid_Uint; Modulo : Valid_Uint) return Valid_Uint
+ is
M : constant Save_Mark := Mark;
- U : Uint;
- V : Uint;
- Q : Uint;
- R : Uint;
- X : Uint;
- Y : Uint;
- T : Uint;
+ U : Valid_Uint;
+ V : Valid_Uint;
+ Q : Valid_Uint;
+ R : Valid_Uint;
+ X : Valid_Uint;
+ Y : Valid_Uint;
+ T : Valid_Uint;
S : Int := 1;
begin
@@ -1923,17 +1982,17 @@ package body Uintp is
-- UI_Mul --
------------
- function UI_Mul (Left : Int; Right : Uint) return Uint is
+ function UI_Mul (Left : Int; Right : Valid_Uint) return Valid_Uint is
begin
return UI_Mul (UI_From_Int (Left), Right);
end UI_Mul;
- function UI_Mul (Left : Uint; Right : Int) return Uint is
+ function UI_Mul (Left : Valid_Uint; Right : Int) return Valid_Uint is
begin
return UI_Mul (Left, UI_From_Int (Right));
end UI_Mul;
- function UI_Mul (Left : Uint; Right : Uint) return Uint is
+ function UI_Mul (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint is
begin
-- Case where product fits in the range of a 32-bit integer
@@ -1991,20 +2050,24 @@ package body Uintp is
-- UI_Ne --
------------
- function UI_Ne (Left : Int; Right : Uint) return Boolean is
+ function UI_Ne (Left : Int; Right : Valid_Uint) return Boolean is
begin
return UI_Ne (UI_From_Int (Left), Right);
end UI_Ne;
- function UI_Ne (Left : Uint; Right : Int) return Boolean is
+ function UI_Ne (Left : Valid_Uint; Right : Int) return Boolean is
begin
return UI_Ne (Left, UI_From_Int (Right));
end UI_Ne;
- function UI_Ne (Left : Uint; Right : Uint) return Boolean is
+ function UI_Ne (Left : Valid_Uint; Right : Valid_Uint) return Boolean is
begin
- -- Quick processing for identical arguments. Note that this takes
- -- care of the case of two No_Uint arguments.
+ pragma Assert (Present (Left));
+ pragma Assert (Present (Right));
+ -- Assertions are here in case we're called from C++ code, which does
+ -- not check the predicates.
+
+ -- Quick processing for identical arguments
if Int (Left) = Int (Right) then
return False;
@@ -2062,7 +2125,7 @@ package body Uintp is
-- UI_Negate --
----------------
- function UI_Negate (Right : Uint) return Uint is
+ function UI_Negate (Right : Valid_Uint) return Valid_Uint is
begin
-- Case where input is directly represented. Note that since the range
-- of Direct values is non-symmetrical, the result may not be directly
@@ -2095,20 +2158,23 @@ package body Uintp is
-- UI_Rem --
-------------
- function UI_Rem (Left : Int; Right : Uint) return Uint is
+ function UI_Rem (Left : Int; Right : Nonzero_Uint) return Valid_Uint is
begin
return UI_Rem (UI_From_Int (Left), Right);
end UI_Rem;
- function UI_Rem (Left : Uint; Right : Int) return Uint is
+ function UI_Rem
+ (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ is
begin
return UI_Rem (Left, UI_From_Int (Right));
end UI_Rem;
- function UI_Rem (Left, Right : Uint) return Uint is
- Remainder : Uint;
- Quotient : Uint;
- pragma Warnings (Off, Quotient);
+ function UI_Rem
+ (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ is
+ Remainder : Valid_Uint;
+ Ignored_Quotient : Uint;
begin
pragma Assert (Right /= Uint_0);
@@ -2118,7 +2184,8 @@ package body Uintp is
else
UI_Div_Rem
- (Left, Right, Quotient, Remainder, Discard_Quotient => True);
+ (Left, Right, Ignored_Quotient, Remainder,
+ Discard_Quotient => True);
return Remainder;
end if;
end UI_Rem;
@@ -2127,17 +2194,17 @@ package body Uintp is
-- UI_Sub --
------------
- function UI_Sub (Left : Int; Right : Uint) return Uint is
+ function UI_Sub (Left : Int; Right : Valid_Uint) return Valid_Uint is
begin
return UI_Add (Left, -Right);
end UI_Sub;
- function UI_Sub (Left : Uint; Right : Int) return Uint is
+ function UI_Sub (Left : Valid_Uint; Right : Int) return Valid_Uint is
begin
return UI_Add (Left, -Right);
end UI_Sub;
- function UI_Sub (Left : Uint; Right : Uint) return Uint is
+ function UI_Sub (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint is
begin
if Direct (Left) and then Direct (Right) then
return UI_From_Int (Direct_Val (Left) - Direct_Val (Right));
@@ -2150,7 +2217,7 @@ package body Uintp is
-- UI_To_CC --
--------------
- function UI_To_CC (Input : Uint) return Char_Code is
+ function UI_To_CC (Input : Valid_Uint) return Char_Code is
begin
if Direct (Input) then
return Char_Code (Direct_Val (Input));
@@ -2183,9 +2250,7 @@ package body Uintp is
-- UI_To_Int --
---------------
- function UI_To_Int (Input : Uint) return Int is
- pragma Assert (Input /= No_Uint);
-
+ function UI_To_Int (Input : Valid_Uint) return Int is
begin
if Direct (Input) then
return Direct_Val (Input);
@@ -2234,9 +2299,7 @@ package body Uintp is
-- UI_To_Uns64 --
-----------------
- function UI_To_Unsigned_64 (Input : Uint) return Unsigned_64 is
- pragma Assert (Input /= No_Uint);
-
+ function UI_To_Unsigned_64 (Input : Valid_Uint) return Unsigned_64 is
begin
if Input < Uint_0 then
raise Constraint_Error;
@@ -2285,8 +2348,7 @@ package body Uintp is
function Vector_To_Uint
(In_Vec : UI_Vector;
- Negative : Boolean)
- return Uint
+ Negative : Boolean) return Valid_Uint
is
Size : Int;
Val : Int;
@@ -2306,9 +2368,9 @@ package body Uintp is
if Size = Int_1 then
if Negative then
- return Uint (Int (Uint_Direct_Bias) - In_Vec (J));
+ return Valid_Uint (Int (Uint_Direct_Bias) - In_Vec (J));
else
- return Uint (Int (Uint_Direct_Bias) + In_Vec (J));
+ return Valid_Uint (Int (Uint_Direct_Bias) + In_Vec (J));
end if;
-- Positive two digit values may be in direct representation range
@@ -2317,7 +2379,7 @@ package body Uintp is
Val := In_Vec (J) * Base + In_Vec (J + 1);
if Val <= Max_Direct then
- return Uint (Int (Uint_Direct_Bias) + Val);
+ return Valid_Uint (Int (Uint_Direct_Bias) + Val);
end if;
end if;
diff --git a/gcc/ada/uintp.ads b/gcc/ada/uintp.ads
index b2f2315..d9f1f8f 100644
--- a/gcc/ada/uintp.ads
+++ b/gcc/ada/uintp.ads
@@ -90,22 +90,23 @@ package Uintp is
Uint_Minus_127 : constant Uint;
Uint_Minus_128 : constant Uint;
- subtype Valid_Uint is Uint with Predicate => Valid_Uint /= No_Uint;
- subtype Unat is Valid_Uint with Predicate => Unat >= Uint_0;
- subtype Upos is Valid_Uint with Predicate => Upos >= Uint_0;
- subtype Nonzero_Uint is Valid_Uint with Predicate => Nonzero_Uint /= Uint_0;
+ -- Functions for detecting No_Uint. Note that clients of this package
+ -- cannot use "=" and "/=" to compare with No_Uint; they must use No
+ -- and Present instead.
+
+ function No (X : Uint) return Boolean is (X = No_Uint);
+ -- Note that this is using the predefined "=", not the "=" declared below,
+ -- which would blow up on No_Uint.
- type UI_Vector is array (Pos range <>) of Int;
- -- Vector containing the integer values of a Uint value
+ function Present (X : Uint) return Boolean is (not No (X));
- -- Note: An earlier version of this package used pointers of arrays of Ints
- -- (dynamically allocated) for the Uint type. The change leads to a few
- -- less natural idioms used throughout this code, but eliminates all uses
- -- of the heap except for the table package itself. For example, Uint
- -- parameters are often converted to UI_Vectors for internal manipulation.
- -- This is done by creating the local UI_Vector using the function N_Digits
- -- on the Uint to find the size needed for the vector, and then calling
- -- Init_Operand to copy the values out of the table into the vector.
+ subtype Valid_Uint is Uint with Predicate => Present (Valid_Uint);
+ subtype Unat is Valid_Uint with Predicate => Unat >= Uint_0; -- natural
+ subtype Upos is Valid_Uint with Predicate => Upos >= Uint_1; -- positive
+ subtype Nonzero_Uint is Valid_Uint with Predicate => Nonzero_Uint /= Uint_0;
+ subtype Ubool is Valid_Uint with Predicate => Ubool in Uint_0 | Uint_1;
+ subtype Opt_Ubool is Uint with
+ Predicate => No (Opt_Ubool) or else Opt_Ubool in Ubool;
-----------------
-- Subprograms --
@@ -116,177 +117,150 @@ package Uintp is
-- unit, these are among the few tables that can be expanded during
-- gigi processing.
- function UI_Abs (Right : Uint) return Uint;
+ function UI_Abs (Right : Valid_Uint) return Unat;
pragma Inline (UI_Abs);
-- Returns abs function of universal integer
- function UI_Add (Left : Uint; Right : Uint) return Uint;
- function UI_Add (Left : Int; Right : Uint) return Uint;
- function UI_Add (Left : Uint; Right : Int) return Uint;
+ function UI_Add (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint;
+ function UI_Add (Left : Int; Right : Valid_Uint) return Valid_Uint;
+ function UI_Add (Left : Valid_Uint; Right : Int) return Valid_Uint;
-- Returns sum of two integer values
- function UI_Decimal_Digits_Hi (U : Uint) return Nat;
+ function UI_Decimal_Digits_Hi (U : Valid_Uint) return Nat;
-- Returns an estimate of the number of decimal digits required to
-- represent the absolute value of U. This estimate is correct or high,
-- i.e. it never returns a value that is too low. The accuracy of the
-- estimate affects only the effectiveness of comparison optimizations
-- in Urealp.
- function UI_Decimal_Digits_Lo (U : Uint) return Nat;
+ function UI_Decimal_Digits_Lo (U : Valid_Uint) return Nat;
-- Returns an estimate of the number of decimal digits required to
-- represent the absolute value of U. This estimate is correct or low,
-- i.e. it never returns a value that is too high. The accuracy of the
-- estimate affects only the effectiveness of comparison optimizations
-- in Urealp.
- function UI_Div (Left : Uint; Right : Uint) return Uint;
- function UI_Div (Left : Int; Right : Uint) return Uint;
- function UI_Div (Left : Uint; Right : Int) return Uint;
+ function UI_Div (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Div (Left : Int; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Div (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint;
-- Returns quotient of two integer values. Fatal error if Right = 0
- function UI_Eq (Left : Uint; Right : Uint) return Boolean;
- function UI_Eq (Left : Int; Right : Uint) return Boolean;
- function UI_Eq (Left : Uint; Right : Int) return Boolean;
+ function UI_Eq (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Eq (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Eq (Left : Valid_Uint; Right : Int) return Boolean;
pragma Inline (UI_Eq);
-- Compares integer values for equality
- function UI_Expon (Left : Uint; Right : Uint) return Uint;
- function UI_Expon (Left : Int; Right : Uint) return Uint;
- function UI_Expon (Left : Uint; Right : Int) return Uint;
- function UI_Expon (Left : Int; Right : Int) return Uint;
+ function UI_Expon (Left : Valid_Uint; Right : Unat) return Valid_Uint;
+ function UI_Expon (Left : Int; Right : Unat) return Valid_Uint;
+ function UI_Expon (Left : Valid_Uint; Right : Nat) return Valid_Uint;
+ function UI_Expon (Left : Int; Right : Nat) return Valid_Uint;
-- Returns result of exponentiating two integer values.
-- Fatal error if Right is negative.
- function UI_GCD (Uin, Vin : Uint) return Uint;
+ function UI_GCD (Uin, Vin : Valid_Uint) return Valid_Uint;
-- Computes GCD of input values. Assumes Uin >= Vin >= 0
- function UI_Ge (Left : Uint; Right : Uint) return Boolean;
- function UI_Ge (Left : Int; Right : Uint) return Boolean;
- function UI_Ge (Left : Uint; Right : Int) return Boolean;
+ function UI_Ge (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Ge (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Ge (Left : Valid_Uint; Right : Int) return Boolean;
pragma Inline (UI_Ge);
-- Compares integer values for greater than or equal
- function UI_Gt (Left : Uint; Right : Uint) return Boolean;
- function UI_Gt (Left : Int; Right : Uint) return Boolean;
- function UI_Gt (Left : Uint; Right : Int) return Boolean;
+ function UI_Gt (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Gt (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Gt (Left : Valid_Uint; Right : Int) return Boolean;
pragma Inline (UI_Gt);
-- Compares integer values for greater than
- function UI_Is_In_Int_Range (Input : Uint) return Boolean;
+ function UI_Is_In_Int_Range (Input : Valid_Uint) return Boolean;
pragma Inline (UI_Is_In_Int_Range);
- -- Determines if universal integer is in Int range
+ -- Determines if universal integer is in Int range.
- function UI_Le (Left : Uint; Right : Uint) return Boolean;
- function UI_Le (Left : Int; Right : Uint) return Boolean;
- function UI_Le (Left : Uint; Right : Int) return Boolean;
+ function UI_Le (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Le (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Le (Left : Valid_Uint; Right : Int) return Boolean;
pragma Inline (UI_Le);
-- Compares integer values for less than or equal
- function UI_Lt (Left : Uint; Right : Uint) return Boolean;
- function UI_Lt (Left : Int; Right : Uint) return Boolean;
- function UI_Lt (Left : Uint; Right : Int) return Boolean;
+ function UI_Lt (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Lt (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Lt (Left : Valid_Uint; Right : Int) return Boolean;
-- Compares integer values for less than
- function UI_Max (Left : Uint; Right : Uint) return Uint;
- function UI_Max (Left : Int; Right : Uint) return Uint;
- function UI_Max (Left : Uint; Right : Int) return Uint;
+ function UI_Max (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint;
+ function UI_Max (Left : Int; Right : Valid_Uint) return Valid_Uint;
+ function UI_Max (Left : Valid_Uint; Right : Int) return Valid_Uint;
-- Returns maximum of two integer values
- function UI_Min (Left : Uint; Right : Uint) return Uint;
- function UI_Min (Left : Int; Right : Uint) return Uint;
- function UI_Min (Left : Uint; Right : Int) return Uint;
+ function UI_Min (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint;
+ function UI_Min (Left : Int; Right : Valid_Uint) return Valid_Uint;
+ function UI_Min (Left : Valid_Uint; Right : Int) return Valid_Uint;
-- Returns minimum of two integer values
- function UI_Mod (Left : Uint; Right : Uint) return Uint;
- function UI_Mod (Left : Int; Right : Uint) return Uint;
- function UI_Mod (Left : Uint; Right : Int) return Uint;
+ function UI_Mod (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Mod (Left : Int; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Mod (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint;
pragma Inline (UI_Mod);
-- Returns mod function of two integer values
- function UI_Mul (Left : Uint; Right : Uint) return Uint;
- function UI_Mul (Left : Int; Right : Uint) return Uint;
- function UI_Mul (Left : Uint; Right : Int) return Uint;
+ function UI_Mul (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint;
+ function UI_Mul (Left : Int; Right : Valid_Uint) return Valid_Uint;
+ function UI_Mul (Left : Valid_Uint; Right : Int) return Valid_Uint;
-- Returns product of two integer values
- function UI_Ne (Left : Uint; Right : Uint) return Boolean;
- function UI_Ne (Left : Int; Right : Uint) return Boolean;
- function UI_Ne (Left : Uint; Right : Int) return Boolean;
+ function UI_Ne (Left : Valid_Uint; Right : Valid_Uint) return Boolean;
+ function UI_Ne (Left : Int; Right : Valid_Uint) return Boolean;
+ function UI_Ne (Left : Valid_Uint; Right : Int) return Boolean;
pragma Inline (UI_Ne);
-- Compares integer values for inequality
- function UI_Negate (Right : Uint) return Uint;
+ function UI_Negate (Right : Valid_Uint) return Valid_Uint;
pragma Inline (UI_Negate);
-- Returns negative of universal integer
- function UI_Rem (Left : Uint; Right : Uint) return Uint;
- function UI_Rem (Left : Int; Right : Uint) return Uint;
- function UI_Rem (Left : Uint; Right : Int) return Uint;
+ function UI_Rem (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Rem (Left : Int; Right : Nonzero_Uint) return Valid_Uint;
+ function UI_Rem (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint;
-- Returns rem of two integer values
- function UI_Sub (Left : Uint; Right : Uint) return Uint;
- function UI_Sub (Left : Int; Right : Uint) return Uint;
- function UI_Sub (Left : Uint; Right : Int) return Uint;
+ function UI_Sub (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint;
+ function UI_Sub (Left : Int; Right : Valid_Uint) return Valid_Uint;
+ function UI_Sub (Left : Valid_Uint; Right : Int) return Valid_Uint;
pragma Inline (UI_Sub);
-- Returns difference of two integer values
- function UI_Modular_Exponentiation
- (B : Uint;
- E : Uint;
- Modulo : Uint) return Uint;
- -- Efficiently compute (B**E) rem Modulo
-
- function UI_Modular_Inverse (N : Uint; Modulo : Uint) return Uint;
- -- Compute the multiplicative inverse of N in modular arithmetics with the
- -- given Modulo (uses Euclid's algorithm). Note: the call is considered
- -- to be erroneous (and the behavior is undefined) if n is not invertible.
-
- function UI_From_Int (Input : Int) return Uint;
+ function UI_From_Int (Input : Int) return Valid_Uint;
-- Converts Int value to universal integer form
generic
type In_T is range <>;
- function UI_From_Integral (Input : In_T) return Uint;
+ function UI_From_Integral (Input : In_T) return Valid_Uint;
-- Likewise, but converts from any integer type. Must not be applied to
-- biased types (instantiation will provide a warning if actual is a biased
-- type).
- function UI_From_CC (Input : Char_Code) return Uint;
+ function UI_From_CC (Input : Char_Code) return Valid_Uint;
-- Converts Char_Code value to universal integer form
- function UI_To_Int (Input : Uint) return Int;
+ function UI_To_Int (Input : Valid_Uint) return Int;
-- Converts universal integer value to Int. Constraint_Error if value is
-- not in appropriate range.
type Unsigned_64 is mod 2**64;
- function UI_To_Unsigned_64 (Input : Uint) return Unsigned_64;
+ function UI_To_Unsigned_64 (Input : Valid_Uint) return Unsigned_64;
-- Converts universal integer value to Unsigned_64. Constraint_Error if
-- value is not in appropriate range.
- function UI_To_CC (Input : Uint) return Char_Code;
+ function UI_To_CC (Input : Valid_Uint) return Char_Code;
-- Converts universal integer value to Char_Code. Constraint_Error if value
-- is not in Char_Code range.
- function Num_Bits (Input : Uint) return Nat;
+ function Num_Bits (Input : Valid_Uint) return Nat;
-- Approximate number of binary bits in given universal integer. This
-- function is used for capacity checks, and it can be one bit off
-- without affecting its usage.
- function Vector_To_Uint
- (In_Vec : UI_Vector;
- Negative : Boolean) return Uint;
- -- Functions that calculate values in UI_Vectors, call this function to
- -- create and return the Uint value. In_Vec contains the multiple precision
- -- (Base) representation of a non-negative value. Leading zeroes are
- -- permitted. Negative is set if the desired result is the negative of the
- -- given value. The result will be either the appropriate directly
- -- represented value, or a table entry in the proper canonical format is
- -- created and returned.
- --
- -- Note that Init_Operand puts a signed value in the result vector, but
- -- Vector_To_Uint is always presented with a non-negative value. The
- -- processing of signs is something that is done by the caller before
- -- calling Vector_To_Uint.
-
---------------------
-- Output Routines --
---------------------
@@ -338,58 +312,97 @@ package Uintp is
-- Operator Renamings --
------------------------
- function "+" (Left : Uint; Right : Uint) return Uint renames UI_Add;
- function "+" (Left : Int; Right : Uint) return Uint renames UI_Add;
- function "+" (Left : Uint; Right : Int) return Uint renames UI_Add;
-
- function "/" (Left : Uint; Right : Uint) return Uint renames UI_Div;
- function "/" (Left : Int; Right : Uint) return Uint renames UI_Div;
- function "/" (Left : Uint; Right : Int) return Uint renames UI_Div;
-
- function "*" (Left : Uint; Right : Uint) return Uint renames UI_Mul;
- function "*" (Left : Int; Right : Uint) return Uint renames UI_Mul;
- function "*" (Left : Uint; Right : Int) return Uint renames UI_Mul;
-
- function "-" (Left : Uint; Right : Uint) return Uint renames UI_Sub;
- function "-" (Left : Int; Right : Uint) return Uint renames UI_Sub;
- function "-" (Left : Uint; Right : Int) return Uint renames UI_Sub;
-
- function "**" (Left : Uint; Right : Uint) return Uint renames UI_Expon;
- function "**" (Left : Uint; Right : Int) return Uint renames UI_Expon;
- function "**" (Left : Int; Right : Uint) return Uint renames UI_Expon;
- function "**" (Left : Int; Right : Int) return Uint renames UI_Expon;
-
- function "abs" (Real : Uint) return Uint renames UI_Abs;
-
- function "mod" (Left : Uint; Right : Uint) return Uint renames UI_Mod;
- function "mod" (Left : Int; Right : Uint) return Uint renames UI_Mod;
- function "mod" (Left : Uint; Right : Int) return Uint renames UI_Mod;
-
- function "rem" (Left : Uint; Right : Uint) return Uint renames UI_Rem;
- function "rem" (Left : Int; Right : Uint) return Uint renames UI_Rem;
- function "rem" (Left : Uint; Right : Int) return Uint renames UI_Rem;
-
- function "-" (Real : Uint) return Uint renames UI_Negate;
-
- function "=" (Left : Uint; Right : Uint) return Boolean renames UI_Eq;
- function "=" (Left : Int; Right : Uint) return Boolean renames UI_Eq;
- function "=" (Left : Uint; Right : Int) return Boolean renames UI_Eq;
-
- function ">=" (Left : Uint; Right : Uint) return Boolean renames UI_Ge;
- function ">=" (Left : Int; Right : Uint) return Boolean renames UI_Ge;
- function ">=" (Left : Uint; Right : Int) return Boolean renames UI_Ge;
-
- function ">" (Left : Uint; Right : Uint) return Boolean renames UI_Gt;
- function ">" (Left : Int; Right : Uint) return Boolean renames UI_Gt;
- function ">" (Left : Uint; Right : Int) return Boolean renames UI_Gt;
-
- function "<=" (Left : Uint; Right : Uint) return Boolean renames UI_Le;
- function "<=" (Left : Int; Right : Uint) return Boolean renames UI_Le;
- function "<=" (Left : Uint; Right : Int) return Boolean renames UI_Le;
-
- function "<" (Left : Uint; Right : Uint) return Boolean renames UI_Lt;
- function "<" (Left : Int; Right : Uint) return Boolean renames UI_Lt;
- function "<" (Left : Uint; Right : Int) return Boolean renames UI_Lt;
+ function "+" (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint
+ renames UI_Add;
+ function "+" (Left : Int; Right : Valid_Uint) return Valid_Uint
+ renames UI_Add;
+ function "+" (Left : Valid_Uint; Right : Int) return Valid_Uint
+ renames UI_Add;
+
+ function "/" (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Div;
+ function "/" (Left : Int; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Div;
+ function "/" (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ renames UI_Div;
+
+ function "*" (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint
+ renames UI_Mul;
+ function "*" (Left : Int; Right : Valid_Uint) return Valid_Uint
+ renames UI_Mul;
+ function "*" (Left : Valid_Uint; Right : Int) return Valid_Uint
+ renames UI_Mul;
+
+ function "-" (Left : Valid_Uint; Right : Valid_Uint) return Valid_Uint
+ renames UI_Sub;
+ function "-" (Left : Int; Right : Valid_Uint) return Valid_Uint
+ renames UI_Sub;
+ function "-" (Left : Valid_Uint; Right : Int) return Valid_Uint
+ renames UI_Sub;
+
+ function "**" (Left : Valid_Uint; Right : Unat) return Valid_Uint
+ renames UI_Expon;
+ function "**" (Left : Valid_Uint; Right : Nat) return Valid_Uint
+ renames UI_Expon;
+ function "**" (Left : Int; Right : Unat) return Valid_Uint
+ renames UI_Expon;
+ function "**" (Left : Int; Right : Nat) return Valid_Uint
+ renames UI_Expon;
+
+ function "abs" (Real : Valid_Uint) return Unat
+ renames UI_Abs;
+
+ function "mod" (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Mod;
+ function "mod" (Left : Int; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Mod;
+ function "mod" (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ renames UI_Mod;
+
+ function "rem" (Left : Valid_Uint; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Rem;
+ function "rem" (Left : Int; Right : Nonzero_Uint) return Valid_Uint
+ renames UI_Rem;
+ function "rem" (Left : Valid_Uint; Right : Nonzero_Int) return Valid_Uint
+ renames UI_Rem;
+
+ function "-" (Real : Valid_Uint) return Valid_Uint
+ renames UI_Negate;
+
+ function "=" (Left : Valid_Uint; Right : Valid_Uint) return Boolean
+ renames UI_Eq;
+ function "=" (Left : Int; Right : Valid_Uint) return Boolean
+ renames UI_Eq;
+ function "=" (Left : Valid_Uint; Right : Int) return Boolean
+ renames UI_Eq;
+
+ function ">=" (Left : Valid_Uint; Right : Valid_Uint) return Boolean
+ renames UI_Ge;
+ function ">=" (Left : Int; Right : Valid_Uint) return Boolean
+ renames UI_Ge;
+ function ">=" (Left : Valid_Uint; Right : Int) return Boolean
+ renames UI_Ge;
+
+ function ">" (Left : Valid_Uint; Right : Valid_Uint) return Boolean
+ renames UI_Gt;
+ function ">" (Left : Int; Right : Valid_Uint) return Boolean
+ renames UI_Gt;
+ function ">" (Left : Valid_Uint; Right : Int) return Boolean
+ renames UI_Gt;
+
+ function "<=" (Left : Valid_Uint; Right : Valid_Uint) return Boolean
+ renames UI_Le;
+ function "<=" (Left : Int; Right : Valid_Uint) return Boolean
+ renames UI_Le;
+ function "<=" (Left : Valid_Uint; Right : Int) return Boolean
+ renames UI_Le;
+
+ function "<" (Left : Valid_Uint; Right : Valid_Uint) return Boolean
+ renames UI_Lt;
+ function "<" (Left : Int; Right : Valid_Uint) return Boolean
+ renames UI_Lt;
+ function "<" (Left : Valid_Uint; Right : Int) return Boolean
+ renames UI_Lt;
-----------------------------
-- Mark/Release Processing --
@@ -409,12 +422,12 @@ package Uintp is
procedure Release (M : Save_Mark);
-- Release storage allocated since mark was noted
- procedure Release_And_Save (M : Save_Mark; UI : in out Uint);
+ procedure Release_And_Save (M : Save_Mark; UI : in out Valid_Uint);
-- Like Release, except that the given Uint value (which is typically among
-- the data being released) is recopied after the release, so that it is
-- the most recent item, and UI is updated to point to its copied location.
- procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Uint);
+ procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Valid_Uint);
-- Like Release, except that the given Uint values (which are typically
-- among the data being released) are recopied after the release, so that
-- they are the most recent items, and UI1 and UI2 are updated if necessary
@@ -518,7 +531,7 @@ private
-- UI_Mul to efficiently compute the product in this case.
type Save_Mark is record
- Save_Uint : Uint;
+ Save_Uint : Valid_Uint;
Save_Udigit : Int;
end record;
@@ -537,8 +550,9 @@ private
-- Some subprograms defined in this package manipulate the Udigits table
-- directly, while for others it is more convenient to work with locally
-- defined arrays of the digits of the Universal Integers. The type
- -- UI_Vector is defined for this purpose and some internal subprograms
- -- used for converting from one to the other are defined.
+ -- UI_Vector is declared in the package body for this purpose and some
+ -- internal subprograms used for converting from one to the other are
+ -- defined.
type Uint_Entry is record
Length : aliased Pos;
diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb
index c88ccec..bca3527 100644
--- a/gcc/ada/usage.adb
+++ b/gcc/ada/usage.adb
@@ -483,8 +483,10 @@ begin
Write_Line (" .B turn off warnings for biased representation");
Write_Line (" c+ turn on warnings for constant conditional");
Write_Line (" C* turn off warnings for constant conditional");
- Write_Line (" .c+ turn on warnings for unrepped components");
- Write_Line (" .C* turn off warnings for unrepped components");
+ Write_Line (" .c+ turn on warnings for components without " &
+ "representation clauses");
+ Write_Line (" .C* turn off warnings for components without " &
+ "representation clauses");
Write_Line (" _c* turn on warnings for unknown " &
"Compile_Time_Warning");
Write_Line (" _C turn off warnings for unknown " &
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index c7e8ba92..5328f85 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,123 @@
+2021-09-16 Maxim Blinov <maxim.blinov@embecosm.com>
+
+ PR bootstrap/102242
+ * engine.cc (INCLUDE_UNIQUE_PTR): Define.
+
+2021-09-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102225
+ * analyzer.h (compat_types_p): New decl.
+ * constraint-manager.cc
+ (constraint_manager::get_or_add_equiv_class): Guard against NULL
+ type when checking for pointer types.
+ * region-model-impl-calls.cc (region_model::impl_call_realloc):
+ Guard against NULL lhs type/region. Guard against the size value
+ not being of a compatible type for dynamic extents.
+ * region-model.cc (compat_types_p): Make non-static.
+
+2021-08-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/99260
+ * analyzer.h (class custom_edge_info): New class, adapted from
+ exploded_edge::custom_info_t. Make member functions const.
+ Make update_model return bool, converting edge param from
+ reference to a pointer, and adding a ctxt param.
+ (class path_context): New class.
+ * call-info.cc: New file.
+ * call-info.h: New file.
+ * engine.cc: Include "analyzer/call-info.h" and <memory>.
+ (impl_region_model_context::impl_region_model_context): Update for
+ new m_path_ctxt field.
+ (impl_region_model_context::bifurcate): New.
+ (impl_region_model_context::terminate_path): New.
+ (impl_region_model_context::get_malloc_map): New.
+ (impl_sm_context::impl_sm_context): Update for new m_path_ctxt
+ field.
+ (impl_sm_context::get_fndecl_for_call): Likewise.
+ (impl_sm_context::set_next_state): Likewise.
+ (impl_sm_context::warn): Likewise.
+ (impl_sm_context::is_zero_assignment): Likewise.
+ (impl_sm_context::get_path_context): New.
+ (impl_sm_context::m_path_ctxt): New.
+ (impl_region_model_context::on_condition): Update for new
+ path_ctxt param. Handle m_enode_for_diag being NULL.
+ (impl_region_model_context::on_phi): Update for new path_ctxt
+ param.
+ (exploded_node::on_stmt): Add path_ctxt param, updating ctor calls
+ to use it as necessary. Use it to bail out after sm-handling,
+ if needed.
+ (exploded_node::detect_leaks): Update for new path_ctxt param.
+ (dynamic_call_info_t::update_model): Update for conversion of
+ exploded_edge::custom_info_t to custom_edge_info.
+ (dynamic_call_info_t::add_events_to_path): Likewise.
+ (rewind_info_t::update_model): Likewise.
+ (rewind_info_t::add_events_to_path): Likewise.
+ (exploded_edge::exploded_edge): Likewise.
+ (exploded_graph::add_edge): Likewise.
+ (exploded_graph::maybe_process_run_of_before_supernode_enodes):
+ Update for new path_ctxt param.
+ (class impl_path_context): New.
+ (exploded_graph::process_node): Update for new path_ctxt param.
+ Create an impl_path_context and pass it to exploded_node::on_stmt.
+ Use it to terminate iterating stmts if terminate_path is called
+ on it. After processing a run of stmts, query path_ctxt to
+ potentially terminate the analysis path, and/or to "bifurcate" the
+ analysis into multiple additional paths.
+ (feasibility_state::maybe_update_for_edge): Update for new
+ update_model ctxt param.
+ * exploded-graph.h
+ (impl_region_model_context::impl_region_model_context): Add
+ path_ctxt param.
+ (impl_region_model_context::bifurcate): New.
+ (impl_region_model_context::terminate_path): New
+ (impl_region_model_context::get_ext_state): New.
+ (impl_region_model_context::get_malloc_map): New.
+ (impl_region_model_context::m_path_ctxt): New field.
+ (exploded_node::on_stmt): Add path_ctxt param.
+ (class exploded_edge::custom_info_t): Move to analyzer.h, renaming
+ to custom_edge_info, and making the changes as noted in analyzer.h
+ above.
+ (exploded_edge::exploded_edge): Update for these changes to
+ exploded_edge::custom_info_t.
+ (exploded_edge::m_custom_info): Likewise.
+ (class dynamic_call_info_t): Likewise.
+ (class rewind_info_t): Likewise.
+ (exploded_graph::add_edge): Likewise.
+ * program-state.cc (program_state::on_edge): Update for new
+ path_ctxt param.
+ (program_state::push_call): Likewise.
+ (program_state::returning_call): Likewise.
+ (program_state::prune_for_point): Likewise.
+ * region-model-impl-calls.cc: Include "analyzer/call-info.h".
+ (call_details::get_fndecl_for_call): New.
+ (region_model::impl_call_realloc): Reimplement.
+ * region-model.cc (region_model::on_call_pre): Move call to
+ impl_call_realloc to...
+ (region_model::on_call_post): ...here. Consolidate creation
+ of call_details instance.
+ (noop_region_model_context::bifurcate): New.
+ (noop_region_model_context::terminate_path): New.
+ * region-model.h (call_details::get_call_stmt): New.
+ (call_details::get_fndecl_for_call): New.
+ (region_model::on_realloc_with_move): New.
+ (region_model_context::bifurcate): New.
+ (region_model_context::terminate_path): New.
+ (region_model_context::get_ext_state): New.
+ (region_model_context::get_malloc_map): New.
+ (noop_region_model_context::bifurcate): New.
+ (noop_region_model_context::terminate_path): New.
+ (noop_region_model_context::get_ext_state): New.
+ (noop_region_model_context::get_malloc_map): New.
+ * sm-malloc.cc: Include "analyzer/program-state.h".
+ (malloc_state_machine::on_realloc_call): Reimplement.
+ (malloc_state_machine::on_realloc_with_move): New.
+ (region_model::on_realloc_with_move): New.
+ * sm-signal.cc (class signal_delivery_edge_info_t): Update for
+ conversion from exploded_edge::custom_info_t to custom_edge_info.
+ * sm.h (sm_context::get_path_context): New.
+ * svalue.cc (svalue::maybe_get_constant): Call
+ unwrap_any_unmergeable.
+
2021-08-25 Ankur Saini <arsenic@sourceware.org>
PR analyzer/101980
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 05d4751..3ba4e21 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -203,6 +203,8 @@ private:
extern location_t get_stmt_location (const gimple *stmt, function *fun);
+extern bool compat_types_p (tree src_type, tree dst_type);
+
/* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
class plugin_analyzer_init_iface
@@ -220,6 +222,57 @@ enum access_direction
DIR_WRITE
};
+/* Abstract base class for associating custom data with an
+ exploded_edge, for handling non-standard edges such as
+ rewinding from a longjmp, signal handlers, etc.
+ Also used when "bifurcating" state: splitting the execution
+ path in non-standard ways (e.g. for simulating the various
+ outcomes of "realloc"). */
+
+class custom_edge_info
+{
+public:
+ virtual ~custom_edge_info () {}
+
+ /* Hook for making .dot label more readable. */
+ virtual void print (pretty_printer *pp) const = 0;
+
+ /* Hook for updating MODEL within exploded_path::feasible_p
+ and when handling bifurcation. */
+ virtual bool update_model (region_model *model,
+ const exploded_edge *eedge,
+ region_model_context *ctxt) const = 0;
+
+ virtual void add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) const = 0;
+};
+
+/* Abstract base class for splitting state.
+
+ Most of the state-management code in the analyzer involves
+ modifying state objects in-place, which assumes a single outcome.
+
+ This class provides an escape hatch to allow for multiple outcomes
+ for such updates e.g. for modelling multiple outcomes from function
+ calls, such as the various outcomes of "realloc". */
+
+class path_context
+{
+public:
+ virtual ~path_context () {}
+
+ /* Hook for clients to split state with a non-standard path.
+ Take ownership of INFO. */
+ virtual void bifurcate (custom_edge_info *info) = 0;
+
+ /* Hook for clients to terminate the standard path. */
+ virtual void terminate_path () = 0;
+
+ /* Hook for clients to determine if the standard path has been
+ terminated. */
+ virtual bool terminate_path_p () const = 0;
+};
+
} // namespace ana
extern bool is_special_named_call_p (const gcall *call, const char *funcname,
diff --git a/gcc/analyzer/call-info.cc b/gcc/analyzer/call-info.cc
new file mode 100644
index 0000000..1d44cb8
--- /dev/null
+++ b/gcc/analyzer/call-info.cc
@@ -0,0 +1,162 @@
+/* Subclasses of custom_edge_info for describing outcomes of function calls.
+ Copyright (C) 2021 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 "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "diagnostic-core.h"
+#include "options.h"
+#include "cgraph.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 "ordered-hash-map.h"
+#include "cfg.h"
+#include "digraph.h"
+#include "analyzer/supergraph.h"
+#include "sbitmap.h"
+#include "analyzer/call-string.h"
+#include "analyzer/program-point.h"
+#include "analyzer/store.h"
+#include "analyzer/region-model.h"
+#include "analyzer/constraint-manager.h"
+#include "diagnostic-event-id.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/region-model-reachability.h"
+#include "analyzer/analyzer-selftests.h"
+#include "analyzer/program-state.h"
+#include "diagnostic-path.h"
+#include "analyzer/checker-path.h"
+#include "analyzer/diagnostic-manager.h"
+#include "alloc-pool.h"
+#include "fibonacci_heap.h"
+#include "shortest-paths.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/call-info.h"
+
+#if ENABLE_ANALYZER
+
+namespace ana {
+
+/* class call_info : public custom_eedge_info_t. */
+
+/* Implementation of custom_edge_info::print vfunc for call_info:
+ use get_desc to get a label_text, and print it to PP. */
+
+void
+call_info::print (pretty_printer *pp) const
+{
+ label_text desc (get_desc (pp_show_color (pp)));
+ pp_string (pp, desc.m_buffer);
+ desc.maybe_free ();
+}
+
+/* Implementation of custom_edge_info::add_events_to_path vfunc for
+ call_info: add a custom_event using call_info::get_desc as its
+ description. */
+
+void
+call_info::add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) const
+{
+ class call_event : public custom_event
+ {
+ public:
+ call_event (location_t loc, tree fndecl, int depth,
+ const call_info *call_info)
+ : custom_event (loc, fndecl, depth),
+ m_call_info (call_info)
+ {}
+
+ label_text get_desc (bool can_colorize) const
+ {
+ return m_call_info->get_desc (can_colorize);
+ }
+
+ private:
+ const call_info *m_call_info;
+ };
+
+ const exploded_node *src_node = eedge.m_src;
+ const program_point &src_point = src_node->get_point ();
+ tree caller_fndecl = src_point.get_fndecl ();
+ const int stack_depth = src_point.get_stack_depth ();
+
+ emission_path->add_event (new call_event (get_call_stmt ()->location,
+ caller_fndecl,
+ stack_depth,
+ this));
+}
+
+/* Recreate a call_details instance from this call_info. */
+
+call_details
+call_info::get_call_details (region_model *model,
+ region_model_context *ctxt) const
+{
+ return call_details (m_call_stmt, model, ctxt);
+}
+
+/* call_info's ctor.
+
+ The call_info instance will outlive the call_details instance;
+ call_details instances are typically created on the stack. */
+
+call_info::call_info (const call_details &cd)
+: m_call_stmt (cd.get_call_stmt ()),
+ m_fndecl (cd.get_fndecl_for_call ())
+{
+ gcc_assert (m_fndecl);
+}
+
+/* class success_call_info : public call_info. */
+
+/* Implementation of call_info::get_desc vfunc for success_call_info. */
+
+label_text
+success_call_info::get_desc (bool can_colorize) const
+{
+ return make_label_text (can_colorize, "when %qE succeeds", get_fndecl ());
+}
+
+/* class failed_call_info : public call_info. */
+
+/* Implementation of call_info::get_desc vfunc for failed_call_info. */
+
+label_text
+failed_call_info::get_desc (bool can_colorize) const
+{
+ return make_label_text (can_colorize, "when %qE fails", get_fndecl ());
+}
+
+} // namespace ana
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/call-info.h b/gcc/analyzer/call-info.h
new file mode 100644
index 0000000..369d217
--- /dev/null
+++ b/gcc/analyzer/call-info.h
@@ -0,0 +1,83 @@
+/* Subclasses of custom_edge_info for describing outcomes of function calls.
+ Copyright (C) 2021 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_CALL_INFO_H
+#define GCC_ANALYZER_CALL_INFO_H
+
+namespace ana {
+
+/* Subclass of custom_edge_info for an outcome of a call.
+ This is still abstract; the update_model and get_desc vfuncs must be
+ implemented. */
+
+class call_info : public custom_edge_info
+{
+public:
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+ void add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) const FINAL OVERRIDE;
+
+ const gcall *get_call_stmt () const { return m_call_stmt; }
+ tree get_fndecl () const { return m_fndecl; }
+
+ virtual label_text get_desc (bool can_colorize) const = 0;
+
+ call_details get_call_details (region_model *model,
+ region_model_context *ctxt) const;
+
+protected:
+ call_info (const call_details &cd);
+
+private:
+ const gcall *m_call_stmt;
+ tree m_fndecl;
+};
+
+/* Subclass of call_info for a "success" outcome of a call,
+ adding a "when `FNDECL' succeeds" message.
+ This is still abstract: the custom_edge_info::update_model vfunc
+ must be implemented. */
+
+class success_call_info : public call_info
+{
+public:
+ label_text get_desc (bool can_colorize) const FINAL OVERRIDE;
+
+protected:
+ success_call_info (const call_details &cd) : call_info (cd) {}
+};
+
+/* Subclass of call_info for a "failure" outcome of a call,
+ adding a "when `FNDECL' fails" message.
+ This is still abstract: the custom_edge_info::update_model vfunc
+ must be implemented. */
+
+class failed_call_info : public call_info
+{
+public:
+ label_text get_desc (bool can_colorize) const FINAL OVERRIDE;
+
+protected:
+ failed_call_info (const call_details &cd) : call_info (cd) {}
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_CALL_INFO_H */
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index dc65c8d..6df23fb 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -2088,10 +2088,11 @@ constraint_manager::get_or_add_equiv_class (const svalue *sval)
/* Convert all NULL pointers to (void *) to avoid state explosions
involving all of the various (foo *)NULL vs (bar *)NULL. */
- if (POINTER_TYPE_P (sval->get_type ()))
- if (tree cst = sval->maybe_get_constant ())
- if (zerop (cst))
- sval = m_mgr->get_or_create_constant_svalue (null_pointer_node);
+ if (sval->get_type ())
+ if (POINTER_TYPE_P (sval->get_type ()))
+ if (tree cst = sval->maybe_get_constant ())
+ if (zerop (cst))
+ sval = m_mgr->get_or_create_constant_svalue (null_pointer_node);
/* Try svalue match. */
if (get_equiv_class_by_svalue (sval, &result))
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 9c604d1..f21f8e5 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
+#define INCLUDE_UNIQUE_PTR
#include "system.h"
#include "coretypes.h"
#include "tree.h"
@@ -62,9 +63,11 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/checker-path.h"
#include "analyzer/state-purge.h"
#include "analyzer/bar-chart.h"
+#include "analyzer/call-info.h"
#include <zlib.h>
#include "plugin.h"
#include "target.h"
+#include <memory>
/* For an overview, see gcc/doc/analyzer.texi. */
@@ -80,6 +83,7 @@ impl_region_model_context (exploded_graph &eg,
const program_state *old_state,
program_state *new_state,
uncertainty_t *uncertainty,
+ path_context *path_ctxt,
const gimple *stmt,
stmt_finder *stmt_finder)
: m_eg (&eg), m_logger (eg.get_logger ()),
@@ -89,7 +93,8 @@ impl_region_model_context (exploded_graph &eg,
m_stmt (stmt),
m_stmt_finder (stmt_finder),
m_ext_state (eg.get_ext_state ()),
- m_uncertainty (uncertainty)
+ m_uncertainty (uncertainty),
+ m_path_ctxt (path_ctxt)
{
}
@@ -104,7 +109,8 @@ impl_region_model_context (program_state *state,
m_stmt (NULL),
m_stmt_finder (NULL),
m_ext_state (ext_state),
- m_uncertainty (uncertainty)
+ m_uncertainty (uncertainty),
+ m_path_ctxt (NULL)
{
}
@@ -183,6 +189,37 @@ impl_region_model_context::purge_state_involving (const svalue *sval)
smap->purge_state_involving (sval, m_ext_state);
}
+void
+impl_region_model_context::bifurcate (custom_edge_info *info)
+{
+ if (m_path_ctxt)
+ m_path_ctxt->bifurcate (info);
+ else
+ delete info;
+}
+
+void
+impl_region_model_context::terminate_path ()
+{
+ if (m_path_ctxt)
+ return m_path_ctxt->terminate_path ();
+}
+
+bool
+impl_region_model_context::get_malloc_map (sm_state_map **out_smap,
+ const state_machine **out_sm,
+ unsigned *out_sm_idx)
+{
+ unsigned malloc_sm_idx;
+ if (!m_ext_state.get_sm_idx_by_name ("malloc", &malloc_sm_idx))
+ return false;
+
+ *out_smap = m_new_state->m_checker_states[malloc_sm_idx];
+ *out_sm = &m_ext_state.get_sm (malloc_sm_idx);
+ *out_sm_idx = malloc_sm_idx;
+ return true;
+}
+
/* struct setjmp_record. */
int
@@ -237,12 +274,14 @@ public:
program_state *new_state,
const sm_state_map *old_smap,
sm_state_map *new_smap,
+ path_context *path_ctxt,
stmt_finder *stmt_finder = NULL)
: sm_context (sm_idx, sm),
m_logger (eg.get_logger ()),
m_eg (eg), m_enode_for_diag (enode_for_diag),
m_old_state (old_state), m_new_state (new_state),
m_old_smap (old_smap), m_new_smap (new_smap),
+ m_path_ctxt (path_ctxt),
m_stmt_finder (stmt_finder)
{
}
@@ -252,7 +291,7 @@ public:
tree get_fndecl_for_call (const gcall *call) FINAL OVERRIDE
{
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/,
+ (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
NULL, call);
region_model *model = m_new_state->m_region_model;
return model->get_fndecl_for_call (call, &old_ctxt);
@@ -292,7 +331,7 @@ public:
LOG_FUNC (logger);
impl_region_model_context new_ctxt (m_eg, m_enode_for_diag,
m_old_state, m_new_state,
- NULL,
+ NULL, NULL,
stmt);
const svalue *var_new_sval
= m_new_state->m_region_model->get_rvalue (var, &new_ctxt);
@@ -320,12 +359,12 @@ public:
logger * const logger = get_logger ();
LOG_FUNC (logger);
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/,
+ (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
NULL, stmt);
impl_region_model_context new_ctxt (m_eg, m_enode_for_diag,
m_old_state, m_new_state,
- NULL,
+ NULL, NULL,
stmt);
const svalue *origin_new_sval
= m_new_state->m_region_model->get_rvalue (origin, &new_ctxt);
@@ -353,7 +392,7 @@ public:
LOG_FUNC (get_logger ());
gcc_assert (d); // take ownership
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL);
+ (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, NULL);
const svalue *var_old_sval
= m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
@@ -418,7 +457,7 @@ public:
if (!assign_stmt)
return NULL_TREE;
impl_region_model_context old_ctxt
- (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, stmt);
+ (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, stmt);
if (const svalue *sval
= m_new_state->m_region_model->get_gassign_result (assign_stmt,
&old_ctxt))
@@ -428,6 +467,11 @@ public:
return NULL_TREE;
}
+ path_context *get_path_context () const FINAL OVERRIDE
+ {
+ return m_path_ctxt;
+ }
+
log_user m_logger;
exploded_graph &m_eg;
exploded_node *m_enode_for_diag;
@@ -435,6 +479,7 @@ public:
program_state *m_new_state;
const sm_state_map *m_old_smap;
sm_state_map *m_new_smap;
+ path_context *m_path_ctxt;
stmt_finder *m_stmt_finder;
};
@@ -751,9 +796,13 @@ impl_region_model_context::on_condition (const svalue *lhs,
impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
m_old_state, m_new_state,
m_old_state->m_checker_states[sm_idx],
- m_new_state->m_checker_states[sm_idx]);
+ m_new_state->m_checker_states[sm_idx],
+ m_path_ctxt);
sm.on_condition (&sm_ctxt,
- m_enode_for_diag->get_supernode (), m_stmt,
+ (m_enode_for_diag
+ ? m_enode_for_diag->get_supernode ()
+ : NULL),
+ m_stmt,
lhs, op, rhs);
}
}
@@ -773,7 +822,8 @@ impl_region_model_context::on_phi (const gphi *phi, tree rhs)
impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
m_old_state, m_new_state,
m_old_state->m_checker_states[sm_idx],
- m_new_state->m_checker_states[sm_idx]);
+ m_new_state->m_checker_states[sm_idx],
+ m_path_ctxt);
sm.on_phi (&sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
}
}
@@ -1190,7 +1240,8 @@ exploded_node::on_stmt (exploded_graph &eg,
const supernode *snode,
const gimple *stmt,
program_state *state,
- uncertainty_t *uncertainty)
+ uncertainty_t *uncertainty,
+ path_context *path_ctxt)
{
logger *logger = eg.get_logger ();
LOG_SCOPE (logger);
@@ -1215,7 +1266,7 @@ exploded_node::on_stmt (exploded_graph &eg,
impl_region_model_context ctxt (eg, this,
&old_state, state, uncertainty,
- stmt);
+ path_ctxt, stmt);
bool unknown_side_effects = false;
bool terminate_path = false;
@@ -1235,13 +1286,16 @@ exploded_node::on_stmt (exploded_graph &eg,
= old_state.m_checker_states[sm_idx];
sm_state_map *new_smap = state->m_checker_states[sm_idx];
impl_sm_context sm_ctxt (eg, sm_idx, sm, this, &old_state, state,
- old_smap, new_smap);
+ old_smap, new_smap, path_ctxt);
/* Allow the state_machine to handle the stmt. */
if (sm.on_stmt (&sm_ctxt, snode, stmt))
unknown_side_effects = false;
}
+ if (path_ctxt->terminate_path_p ())
+ return on_stmt_flags::terminate_path ();
+
on_stmt_post (stmt, state, unknown_side_effects, &ctxt);
return on_stmt_flags ();
@@ -1592,7 +1646,7 @@ exploded_node::detect_leaks (exploded_graph &eg)
uncertainty_t uncertainty;
impl_region_model_context ctxt (eg, this,
- &old_state, &new_state, &uncertainty,
+ &old_state, &new_state, &uncertainty, NULL,
get_stmt ());
const svalue *result = NULL;
new_state.m_region_model->pop_frame (NULL, &result, &ctxt);
@@ -1627,27 +1681,30 @@ exploded_node::dump_succs_and_preds (FILE *outf) const
}
}
-/* class dynamic_call_info_t : public exploded_edge::custom_info_t. */
+/* class dynamic_call_info_t : public custom_edge_info. */
-/* Implementation of exploded_edge::custom_info_t::update_model vfunc
+/* Implementation of custom_edge_info::update_model vfunc
for dynamic_call_info_t.
Update state for the dynamically discorverd calls */
-void
+bool
dynamic_call_info_t::update_model (region_model *model,
- const exploded_edge &eedge)
+ const exploded_edge *eedge,
+ region_model_context *) const
{
- const program_state &dest_state = eedge.m_dest->get_state ();
+ gcc_assert (eedge);
+ const program_state &dest_state = eedge->m_dest->get_state ();
*model = *dest_state.m_region_model;
+ return true;
}
-/* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc
+/* Implementation of custom_edge_info::add_events_to_path vfunc
for dynamic_call_info_t. */
void
dynamic_call_info_t::add_events_to_path (checker_path *emission_path,
- const exploded_edge &eedge)
+ const exploded_edge &eedge) const
{
const exploded_node *src_node = eedge.m_src;
const program_point &src_point = src_node->get_point ();
@@ -1671,21 +1728,23 @@ dynamic_call_info_t::add_events_to_path (checker_path *emission_path,
}
-/* class rewind_info_t : public exploded_edge::custom_info_t. */
+/* class rewind_info_t : public custom_edge_info. */
-/* Implementation of exploded_edge::custom_info_t::update_model vfunc
+/* Implementation of custom_edge_info::update_model vfunc
for rewind_info_t.
Update state for the special-case of a rewind of a longjmp
to a setjmp (which doesn't have a superedge, but does affect
state). */
-void
+bool
rewind_info_t::update_model (region_model *model,
- const exploded_edge &eedge)
+ const exploded_edge *eedge,
+ region_model_context *) const
{
- const program_point &longjmp_point = eedge.m_src->get_point ();
- const program_point &setjmp_point = eedge.m_dest->get_point ();
+ gcc_assert (eedge);
+ const program_point &longjmp_point = eedge->m_src->get_point ();
+ const program_point &setjmp_point = eedge->m_dest->get_point ();
gcc_assert (longjmp_point.get_stack_depth ()
>= setjmp_point.get_stack_depth ());
@@ -1693,14 +1752,15 @@ rewind_info_t::update_model (region_model *model,
model->on_longjmp (get_longjmp_call (),
get_setjmp_call (),
setjmp_point.get_stack_depth (), NULL);
+ return true;
}
-/* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc
+/* Implementation of custom_edge_info::add_events_to_path vfunc
for rewind_info_t. */
void
rewind_info_t::add_events_to_path (checker_path *emission_path,
- const exploded_edge &eedge)
+ const exploded_edge &eedge) const
{
const exploded_node *src_node = eedge.m_src;
const program_point &src_point = src_node->get_point ();
@@ -1727,7 +1787,7 @@ rewind_info_t::add_events_to_path (checker_path *emission_path,
exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
- custom_info_t *custom_info)
+ custom_edge_info *custom_info)
: dedge<eg_traits> (src, dest), m_sedge (sedge),
m_custom_info (custom_info)
{
@@ -2432,7 +2492,7 @@ exploded_graph::get_or_create_node (const program_point &point,
exploded_edge *
exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
- exploded_edge::custom_info_t *custom_info)
+ custom_edge_info *custom_info)
{
if (get_logger ())
get_logger ()->log ("creating edge EN: %i -> EN: %i",
@@ -2866,7 +2926,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
uncertainty_t uncertainty;
impl_region_model_context ctxt (*this, iter_enode,
&state, next_state,
- &uncertainty, NULL);
+ &uncertainty, NULL, NULL);
const cfg_superedge *last_cfg_superedge
= iter_sedge->dyn_cast_cfg_superedge ();
if (last_cfg_superedge)
@@ -3095,6 +3155,72 @@ exploded_graph::maybe_create_dynamic_call (const gcall *call,
return false;
}
+/* Subclass of path_context for use within exploded_graph::process_node,
+ so that we can split states e.g. at "realloc" calls. */
+
+class impl_path_context : public path_context
+{
+public:
+ impl_path_context (const program_state *cur_state)
+ : m_cur_state (cur_state),
+ m_terminate_path (false)
+ {
+ }
+
+ bool bifurcation_p () const
+ {
+ return m_custom_eedge_infos.length () > 0;
+ }
+
+ const program_state &get_state_at_bifurcation () const
+ {
+ gcc_assert (m_state_at_bifurcation);
+ return *m_state_at_bifurcation;
+ }
+
+ void
+ bifurcate (custom_edge_info *info) FINAL OVERRIDE
+ {
+ if (m_state_at_bifurcation)
+ /* Verify that the state at bifurcation is consistent when we
+ split into multiple out-edges. */
+ gcc_assert (*m_state_at_bifurcation == *m_cur_state);
+ else
+ /* Take a copy of the cur_state at the moment when bifurcation
+ happens. */
+ m_state_at_bifurcation
+ = std::unique_ptr<program_state> (new program_state (*m_cur_state));
+
+ /* Take ownership of INFO. */
+ m_custom_eedge_infos.safe_push (info);
+ }
+
+ void terminate_path () FINAL OVERRIDE
+ {
+ m_terminate_path = true;
+ }
+
+ bool terminate_path_p () const FINAL OVERRIDE
+ {
+ return m_terminate_path;
+ }
+
+ const vec<custom_edge_info *> & get_custom_eedge_infos ()
+ {
+ return m_custom_eedge_infos;
+ }
+
+private:
+ const program_state *m_cur_state;
+
+ /* Lazily-created copy of the state before the split. */
+ std::unique_ptr<program_state> m_state_at_bifurcation;
+
+ auto_vec <custom_edge_info *> m_custom_eedge_infos;
+
+ bool m_terminate_path;
+};
+
/* The core of exploded_graph::process_worklist (the main analysis loop),
handling one node in the worklist.
@@ -3150,7 +3276,7 @@ exploded_graph::process_node (exploded_node *node)
{
impl_region_model_context ctxt (*this, node,
&state, &next_state,
- &uncertainty, NULL);
+ &uncertainty, NULL, NULL);
const cfg_superedge *last_cfg_superedge
= point.get_from_edge ()->dyn_cast_cfg_superedge ();
if (last_cfg_superedge)
@@ -3188,6 +3314,9 @@ exploded_graph::process_node (exploded_node *node)
the sm-state-change occurs on an edge where the src enode has
exactly one stmt, the one that caused the change. */
program_state next_state (state);
+
+ impl_path_context path_ctxt (&next_state);
+
uncertainty_t uncertainty;
const supernode *snode = point.get_supernode ();
unsigned stmt_idx;
@@ -3210,7 +3339,8 @@ exploded_graph::process_node (exploded_node *node)
/* Process the stmt. */
exploded_node::on_stmt_flags flags
- = node->on_stmt (*this, snode, stmt, &next_state, &uncertainty);
+ = node->on_stmt (*this, snode, stmt, &next_state, &uncertainty,
+ &path_ctxt);
node->m_num_processed_stmts++;
/* If flags.m_terminate_path, stop analyzing; any nodes/edges
@@ -3222,7 +3352,7 @@ exploded_graph::process_node (exploded_node *node)
{
impl_region_model_context ctxt (*this, node,
&old_state, &next_state,
- &uncertainty, stmt);
+ &uncertainty, NULL, stmt);
program_state::detect_leaks (old_state, next_state, NULL,
get_ext_state (), &ctxt);
}
@@ -3238,7 +3368,9 @@ exploded_graph::process_node (exploded_node *node)
&uncertainty);
if (flag_analyzer_fine_grained
- || state_change_requires_new_enode_p (old_state, next_state))
+ || state_change_requires_new_enode_p (old_state, next_state)
+ || path_ctxt.bifurcation_p ()
+ || path_ctxt.terminate_path_p ())
{
program_point split_point
= program_point::before_stmt (point.get_supernode (),
@@ -3282,9 +3414,66 @@ exploded_graph::process_node (exploded_node *node)
point.get_call_string ())
: program_point::after_supernode (point.get_supernode (),
point.get_call_string ()));
- exploded_node *next = get_or_create_node (next_point, next_state, node);
- if (next)
- add_edge (node, next, NULL);
+ if (path_ctxt.terminate_path_p ())
+ {
+ if (logger)
+ logger->log ("not adding node: terminating path");
+ }
+ else
+ {
+ exploded_node *next
+ = get_or_create_node (next_point, next_state, node);
+ if (next)
+ add_edge (node, next, NULL);
+ }
+
+ /* If we have custom edge infos, "bifurcate" the state
+ accordingly, potentially creating a new state/enode/eedge
+ instances. For example, to handle a "realloc" call, we
+ might split into 3 states, for the "failure",
+ "resizing in place", and "moving to a new buffer" cases. */
+ for (auto edge_info : path_ctxt.get_custom_eedge_infos ())
+ {
+ if (logger)
+ {
+ logger->start_log_line ();
+ logger->log_partial ("bifurcating for edge: ");
+ edge_info->print (logger->get_printer ());
+ logger->end_log_line ();
+ }
+ program_state bifurcated_new_state
+ (path_ctxt.get_state_at_bifurcation ());
+
+ /* Apply edge_info to state. */
+ impl_region_model_context
+ bifurcation_ctxt (*this,
+ NULL, // enode_for_diag
+ &path_ctxt.get_state_at_bifurcation (),
+ &bifurcated_new_state,
+ NULL, // uncertainty_t *uncertainty
+ NULL, // path_context *path_ctxt
+ stmt);
+ if (edge_info->update_model (bifurcated_new_state.m_region_model,
+ NULL, /* no exploded_edge yet. */
+ &bifurcation_ctxt))
+ {
+ exploded_node *next2
+ = get_or_create_node (next_point, bifurcated_new_state, node);
+ if (next2)
+ {
+ /* Take ownership of edge_info. */
+ add_edge (node, next2, NULL, edge_info);
+ }
+ else
+ delete edge_info;
+ }
+ else
+ {
+ if (logger)
+ logger->log ("infeasible state, not adding node");
+ delete edge_info;
+ }
+ }
}
break;
case PK_AFTER_SUPERNODE:
@@ -3351,6 +3540,7 @@ exploded_graph::process_node (exploded_node *node)
&state,
&next_state,
&uncertainty,
+ NULL,
point.get_stmt());
region_model *model = state.m_region_model;
@@ -3968,7 +4158,7 @@ feasibility_state::maybe_update_for_edge (logger *logger,
}
else if (eedge->m_custom_info)
{
- eedge->m_custom_info->update_model (&m_model, *eedge);
+ eedge->m_custom_info->update_model (&m_model, eedge, NULL);
}
}
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 6890e84..b9c1767 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -37,6 +37,7 @@ class impl_region_model_context : public region_model_context
const program_state *old_state,
program_state *new_state,
uncertainty_t *uncertainty,
+ path_context *path_ctxt,
const gimple *stmt,
stmt_finder *stmt_finder = NULL);
@@ -76,6 +77,16 @@ class impl_region_model_context : public region_model_context
void purge_state_involving (const svalue *sval) FINAL OVERRIDE;
+ void bifurcate (custom_edge_info *info) FINAL OVERRIDE;
+ void terminate_path () FINAL OVERRIDE;
+ const extrinsic_state *get_ext_state () const FINAL OVERRIDE
+ {
+ return &m_ext_state;
+ }
+ bool get_malloc_map (sm_state_map **out_smap,
+ const state_machine **out_sm,
+ unsigned *out_sm_idx) FINAL OVERRIDE;
+
exploded_graph *m_eg;
log_user m_logger;
exploded_node *m_enode_for_diag;
@@ -85,6 +96,7 @@ class impl_region_model_context : public region_model_context
stmt_finder *m_stmt_finder;
const extrinsic_state &m_ext_state;
uncertainty_t *m_uncertainty;
+ path_context *m_path_ctxt;
};
/* A <program_point, program_state> pair, used internally by
@@ -224,7 +236,8 @@ class exploded_node : public dnode<eg_traits>
const supernode *snode,
const gimple *stmt,
program_state *state,
- uncertainty_t *uncertainty);
+ uncertainty_t *uncertainty,
+ path_context *path_ctxt);
void on_stmt_pre (exploded_graph &eg,
const gimple *stmt,
program_state *state,
@@ -319,28 +332,9 @@ public:
class exploded_edge : public dedge<eg_traits>
{
public:
- /* Abstract base class for associating custom data with an
- exploded_edge, for handling non-standard edges such as
- rewinding from a longjmp, signal handlers, etc. */
- class custom_info_t
- {
- public:
- virtual ~custom_info_t () {}
-
- /* Hook for making .dot label more readable . */
- virtual void print (pretty_printer *pp) = 0;
-
- /* Hook for updating MODEL within exploded_path::feasible_p. */
- virtual void update_model (region_model *model,
- const exploded_edge &eedge) = 0;
-
- virtual void add_events_to_path (checker_path *emission_path,
- const exploded_edge &eedge) = 0;
- };
-
exploded_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
- custom_info_t *custom_info);
+ custom_edge_info *custom_info);
~exploded_edge ();
void dump_dot (graphviz_out *gv, const dump_args_t &args)
const FINAL OVERRIDE;
@@ -356,7 +350,7 @@ class exploded_edge : public dedge<eg_traits>
a signal is delivered to a signal-handler.
Owned by this class. */
- custom_info_t *m_custom_info;
+ custom_edge_info *m_custom_info;
private:
DISABLE_COPY_AND_ASSIGN (exploded_edge);
@@ -365,7 +359,7 @@ private:
/* Extra data for an exploded_edge that represents dynamic call info ( calls
that doesn't have an underlying superedge representing the call ). */
-class dynamic_call_info_t : public exploded_edge::custom_info_t
+class dynamic_call_info_t : public custom_edge_info
{
public:
dynamic_call_info_t (const gcall *dynamic_call,
@@ -374,7 +368,7 @@ public:
m_is_returning_call (is_returning_call)
{}
- void print (pretty_printer *pp) FINAL OVERRIDE
+ void print (pretty_printer *pp) const FINAL OVERRIDE
{
if (m_is_returning_call)
pp_string (pp, "dynamic_return");
@@ -382,11 +376,12 @@ public:
pp_string (pp, "dynamic_call");
}
- void update_model (region_model *model,
- const exploded_edge &eedge) FINAL OVERRIDE;
+ bool update_model (region_model *model,
+ const exploded_edge *eedge,
+ region_model_context *ctxt) const FINAL OVERRIDE;
void add_events_to_path (checker_path *emission_path,
- const exploded_edge &eedge) FINAL OVERRIDE;
+ const exploded_edge &eedge) const FINAL OVERRIDE;
private:
const gcall *m_dynamic_call;
const bool m_is_returning_call;
@@ -396,7 +391,7 @@ private:
/* Extra data for an exploded_edge that represents a rewind from a
longjmp to a setjmp (or from a siglongjmp to a sigsetjmp). */
-class rewind_info_t : public exploded_edge::custom_info_t
+class rewind_info_t : public custom_edge_info
{
public:
rewind_info_t (const setjmp_record &setjmp_record,
@@ -405,16 +400,17 @@ public:
m_longjmp_call (longjmp_call)
{}
- void print (pretty_printer *pp) FINAL OVERRIDE
+ void print (pretty_printer *pp) const FINAL OVERRIDE
{
pp_string (pp, "rewind");
}
- void update_model (region_model *model,
- const exploded_edge &eedge) FINAL OVERRIDE;
+ bool update_model (region_model *model,
+ const exploded_edge *eedge,
+ region_model_context *ctxt) const FINAL OVERRIDE;
void add_events_to_path (checker_path *emission_path,
- const exploded_edge &eedge) FINAL OVERRIDE;
+ const exploded_edge &eedge) const FINAL OVERRIDE;
const program_point &get_setjmp_point () const
{
@@ -829,7 +825,7 @@ public:
exploded_node *enode_for_diag);
exploded_edge *add_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
- exploded_edge::custom_info_t *custom = NULL);
+ custom_edge_info *custom = NULL);
per_program_point_data *
get_or_create_per_program_point_data (const program_point &);
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index ea53c61..c1ff0d8 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1013,7 +1013,7 @@ program_state::on_edge (exploded_graph &eg,
impl_region_model_context ctxt (eg, enode,
&enode->get_state (),
this,
- uncertainty,
+ uncertainty, NULL,
last_stmt);
if (!m_region_model->maybe_update_for_edge (*succ,
last_stmt,
@@ -1052,6 +1052,7 @@ program_state::push_call (exploded_graph &eg,
&enode->get_state (),
this,
uncertainty,
+ NULL,
last_stmt);
m_region_model->update_for_gcall (call_stmt, &ctxt);
}
@@ -1074,6 +1075,7 @@ program_state::returning_call (exploded_graph &eg,
&enode->get_state (),
this,
uncertainty,
+ NULL,
last_stmt);
m_region_model->update_for_return_gcall (call_stmt, &ctxt);
}
@@ -1152,7 +1154,7 @@ program_state::prune_for_point (exploded_graph &eg,
impl_region_model_context ctxt (eg, enode_for_diag,
this,
&new_state,
- uncertainty,
+ uncertainty, NULL,
point.get_stmt ());
detect_leaks (*this, new_state, NULL, eg.get_ext_state (), &ctxt);
}
diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc
index e5a6cb2..ff2ae9c 100644
--- a/gcc/analyzer/region-model-impl-calls.cc
+++ b/gcc/analyzer/region-model-impl-calls.cc
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/program-point.h"
#include "analyzer/store.h"
#include "analyzer/region-model.h"
+#include "analyzer/call-info.h"
#include "gimple-pretty-print.h"
#if ENABLE_ANALYZER
@@ -158,6 +159,15 @@ call_details::get_arg_string_literal (unsigned idx) const
return NULL;
}
+/* Attempt to get the fndecl used at this call, if known, or NULL_TREE
+ otherwise. */
+
+tree
+call_details::get_fndecl_for_call () const
+{
+ return m_model->get_fndecl_for_call (m_call, m_ctxt);
+}
+
/* Dump a multiline representation of this call to PP. */
void
@@ -486,15 +496,183 @@ region_model::impl_call_operator_delete (const call_details &cd)
}
}
-/* Handle the on_call_pre part of "realloc". */
+/* Handle the on_call_post part of "realloc":
+
+ void *realloc(void *ptr, size_t size);
+
+ realloc(3) is awkward, since it has various different outcomes
+ that are best modelled as separate exploded nodes/edges.
+
+ We first check for sm-state, in
+ malloc_state_machine::on_realloc_call, so that we
+ can complain about issues such as realloc of a non-heap
+ pointer, and terminate the path for such cases (and issue
+ the complaints at the call's exploded node).
+
+ Assuming that these checks pass, we split the path here into
+ three special cases (and terminate the "standard" path):
+ (A) failure, returning NULL
+ (B) success, growing the buffer in-place without moving it
+ (C) success, allocating a new buffer, copying the content
+ of the old buffer to it, and freeing the old buffer.
+
+ Each of these has a custom_edge_info subclass, which updates
+ the region_model and sm-state of the destination state. */
void
-region_model::impl_call_realloc (const call_details &)
+region_model::impl_call_realloc (const call_details &cd)
{
- /* Currently we don't support bifurcating state, so there's no good
- way to implement realloc(3).
- For now, malloc_state_machine::on_realloc_call has a minimal
- implementation to suppress false positives. */
+ /* Three custom subclasses of custom_edge_info, for handling the various
+ outcomes of "realloc". */
+
+ /* Concrete custom_edge_info: a realloc call that fails, returning NULL. */
+ class failure : public failed_call_info
+ {
+ public:
+ failure (const call_details &cd)
+ : failed_call_info (cd)
+ {
+ }
+
+ bool update_model (region_model *model,
+ const exploded_edge *,
+ region_model_context *ctxt) const FINAL OVERRIDE
+ {
+ /* Return NULL; everything else is unchanged. */
+ const call_details cd (get_call_details (model, ctxt));
+ if (cd.get_lhs_type ())
+ {
+ const svalue *zero
+ = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
+ model->set_value (cd.get_lhs_region (),
+ zero,
+ cd.get_ctxt ());
+ }
+ return true;
+ }
+ };
+
+ /* Concrete custom_edge_info: a realloc call that succeeds, growing
+ the existing buffer without moving it. */
+ class success_no_move : public call_info
+ {
+ public:
+ success_no_move (const call_details &cd)
+ : call_info (cd)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const FINAL OVERRIDE
+ {
+ return make_label_text (can_colorize,
+ "when %qE succeeds, without moving buffer",
+ get_fndecl ());
+ }
+
+ bool update_model (region_model *model,
+ const exploded_edge *,
+ region_model_context *ctxt) const FINAL OVERRIDE
+ {
+ /* Update size of buffer and return the ptr unchanged. */
+ const call_details cd (get_call_details (model, ctxt));
+ const svalue *ptr_sval = cd.get_arg_svalue (0);
+ const svalue *size_sval = cd.get_arg_svalue (1);
+ if (const region *buffer_reg = ptr_sval->maybe_get_region ())
+ if (compat_types_p (size_sval->get_type (), size_type_node))
+ model->set_dynamic_extents (buffer_reg, size_sval);
+ if (cd.get_lhs_region ())
+ {
+ model->set_value (cd.get_lhs_region (), ptr_sval, cd.get_ctxt ());
+ const svalue *zero
+ = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
+ return model->add_constraint (ptr_sval, NE_EXPR, zero, cd.get_ctxt ());
+ }
+ else
+ return true;
+ }
+ };
+
+ /* Concrete custom_edge_info: a realloc call that succeeds, freeing
+ the existing buffer and moving the content to a freshly allocated
+ buffer. */
+ class success_with_move : public call_info
+ {
+ public:
+ success_with_move (const call_details &cd)
+ : call_info (cd)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const FINAL OVERRIDE
+ {
+ return make_label_text (can_colorize,
+ "when %qE succeeds, moving buffer",
+ get_fndecl ());
+ }
+ bool update_model (region_model *model,
+ const exploded_edge *,
+ region_model_context *ctxt) const FINAL OVERRIDE
+ {
+ const call_details cd (get_call_details (model, ctxt));
+ const svalue *old_ptr_sval = cd.get_arg_svalue (0);
+ const svalue *new_size_sval = cd.get_arg_svalue (1);
+
+ /* Create the new region. */
+ const region *new_reg
+ = model->create_region_for_heap_alloc (new_size_sval);
+ const svalue *new_ptr_sval
+ = model->m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
+ if (cd.get_lhs_type ())
+ cd.maybe_set_lhs (new_ptr_sval);
+
+ if (const region *freed_reg = old_ptr_sval->maybe_get_region ())
+ {
+ /* Copy the data. */
+ const svalue *old_size_sval = model->get_dynamic_extents (freed_reg);
+ if (old_size_sval)
+ {
+ const region *sized_old_reg
+ = model->m_mgr->get_sized_region (freed_reg, NULL,
+ old_size_sval);
+ const svalue *buffer_content_sval
+ = model->get_store_value (sized_old_reg, cd.get_ctxt ());
+ model->set_value (new_reg, buffer_content_sval, cd.get_ctxt ());
+ }
+
+ /* Free the old region, so that pointers to the old buffer become
+ invalid. */
+
+ /* If the ptr points to an underlying heap region, delete it,
+ poisoning pointers. */
+ model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
+ model->m_dynamic_extents.remove (freed_reg);
+ }
+
+ /* Update the sm-state: mark the old_ptr_sval as "freed",
+ and the new_ptr_sval as "nonnull". */
+ model->on_realloc_with_move (cd, old_ptr_sval, new_ptr_sval);
+
+ if (cd.get_lhs_type ())
+ {
+ const svalue *zero
+ = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
+ return model->add_constraint (new_ptr_sval, NE_EXPR, zero,
+ cd.get_ctxt ());
+ }
+ else
+ return true;
+ }
+ };
+
+ /* Body of region_model::impl_call_realloc. */
+
+ if (cd.get_ctxt ())
+ {
+ cd.get_ctxt ()->bifurcate (new failure (cd));
+ cd.get_ctxt ()->bifurcate (new success_no_move (cd));
+ cd.get_ctxt ()->bifurcate (new success_with_move (cd));
+ cd.get_ctxt ()->terminate_path ();
+ }
}
/* Handle the on_call_pre part of "strcpy" and "__builtin_strcpy_chk". */
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 787f2ed..a14d107 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1132,7 +1132,6 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
return false;
break;
case BUILT_IN_REALLOC:
- impl_call_realloc (cd);
return false;
case BUILT_IN_STRCPY:
case BUILT_IN_STRCPY_CHK:
@@ -1276,9 +1275,9 @@ region_model::on_call_post (const gcall *call,
{
if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
{
+ call_details cd (call, this, ctxt);
if (is_named_call_p (callee_fndecl, "free", call, 1))
{
- call_details cd (call, this, ctxt);
impl_call_free (cd);
return;
}
@@ -1286,7 +1285,6 @@ region_model::on_call_post (const gcall *call,
|| is_named_call_p (callee_fndecl, "operator delete", call, 2)
|| is_named_call_p (callee_fndecl, "operator delete []", call, 1))
{
- call_details cd (call, this, ctxt);
impl_call_operator_delete (cd);
return;
}
@@ -1294,10 +1292,19 @@ region_model::on_call_post (const gcall *call,
__attribute__((malloc(FOO)))? */
if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl)))
{
- call_details cd (call, this, ctxt);
impl_deallocation_call (cd);
return;
}
+ if (fndecl_built_in_p (callee_fndecl, BUILT_IN_NORMAL)
+ && gimple_builtin_call_types_compatible_p (call, callee_fndecl))
+ switch (DECL_UNCHECKED_FUNCTION_CODE (callee_fndecl))
+ {
+ default:
+ break;
+ case BUILT_IN_REALLOC:
+ impl_call_realloc (cd);
+ return;
+ }
}
if (unknown_side_effects)
@@ -1706,7 +1713,7 @@ assert_compat_types (tree src_type, tree dst_type)
/* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
-static bool
+bool
compat_types_p (tree src_type, tree dst_type)
{
if (src_type && dst_type && !VOID_TYPE_P (dst_type))
@@ -3765,6 +3772,19 @@ region_model::unset_dynamic_extents (const region *reg)
m_dynamic_extents.remove (reg);
}
+/* class noop_region_model_context : public region_model_context. */
+
+void
+noop_region_model_context::bifurcate (custom_edge_info *info)
+{
+ delete info;
+}
+
+void
+noop_region_model_context::terminate_path ()
+{
+}
+
/* struct model_merger. */
/* Dump a multiline representation of this merger to PP. */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index f2c82b0..5fabf78 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -487,11 +487,15 @@ public:
unsigned num_args () const;
+ const gcall *get_call_stmt () const { return m_call; }
+
tree get_arg_tree (unsigned idx) const;
tree get_arg_type (unsigned idx) const;
const svalue *get_arg_svalue (unsigned idx) const;
const char *get_arg_string_literal (unsigned idx) const;
+ tree get_fndecl_for_call () const;
+
void dump_to_pp (pretty_printer *pp, bool simple) const;
void dump (bool simple) const;
@@ -732,6 +736,11 @@ class region_model
const svalue *get_capacity (const region *reg) const;
+ /* Implemented in sm-malloc.cc */
+ void on_realloc_with_move (const call_details &cd,
+ const svalue *old_ptr_sval,
+ const svalue *new_ptr_sval);
+
private:
const region *get_lvalue_1 (path_var pv, region_model_context *ctxt) const;
const svalue *get_rvalue_1 (path_var pv, region_model_context *ctxt) const;
@@ -867,6 +876,21 @@ class region_model_context
/* Hook for clients to purge state involving SVAL. */
virtual void purge_state_involving (const svalue *sval) = 0;
+
+ /* Hook for clients to split state with a non-standard path.
+ Take ownership of INFO. */
+ virtual void bifurcate (custom_edge_info *info) = 0;
+
+ /* Hook for clients to terminate the standard path. */
+ virtual void terminate_path () = 0;
+
+ virtual const extrinsic_state *get_ext_state () const = 0;
+
+ /* Hook for clients to access the "malloc" state machine in
+ any underlying program_state. */
+ virtual bool get_malloc_map (sm_state_map **out_smap,
+ const state_machine **out_sm,
+ unsigned *out_sm_idx) = 0;
};
/* A "do nothing" subclass of region_model_context. */
@@ -899,6 +923,18 @@ public:
uncertainty_t *get_uncertainty () OVERRIDE { return NULL; }
void purge_state_involving (const svalue *sval ATTRIBUTE_UNUSED) OVERRIDE {}
+
+ void bifurcate (custom_edge_info *info) OVERRIDE;
+ void terminate_path () OVERRIDE;
+
+ const extrinsic_state *get_ext_state () const OVERRIDE { return NULL; }
+
+ bool get_malloc_map (sm_state_map **,
+ const state_machine **,
+ unsigned *) OVERRIDE
+ {
+ return false;
+ }
};
/* A subclass of region_model_context for determining if operations fail
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 74c6fee..bf5e3c3 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "analyzer/function-set.h"
+#include "analyzer/program-state.h"
#if ENABLE_ANALYZER
@@ -387,6 +388,12 @@ public:
static bool unaffected_by_call_p (tree fndecl);
+ void on_realloc_with_move (region_model *model,
+ sm_state_map *smap,
+ const svalue *old_ptr_sval,
+ const svalue *new_ptr_sval,
+ const extrinsic_state &ext_state) const;
+
standard_deallocator_set m_free;
standard_deallocator_set m_scalar_delete;
standard_deallocator_set m_vector_delete;
@@ -1836,54 +1843,65 @@ malloc_state_machine::on_deallocator_call (sm_context *sm_ctxt,
}
}
-/* Implementation of realloc(3):
-
- void *realloc(void *ptr, size_t size);
-
- realloc(3) is awkward.
+/* Handle a call to "realloc".
+ Check for free of non-heap or mismatching allocators,
+ transitioning to the "stop" state for such cases.
- We currently don't have a way to express multiple possible outcomes
- from a function call, "bifurcating" the state such as:
- - success: non-NULL is returned
- - failure: NULL is returned, existing buffer is not freed.
- or even an N-way state split e.g.:
- - buffer grew successfully in-place
- - buffer was successfully moved to a larger allocation
- - buffer was successfully contracted
- - realloc failed, returning NULL, without freeing existing buffer.
- (PR analyzer/99260 tracks this)
-
- Given that we can currently only express one outcome, eliminate
- false positives by dropping state from the buffer. */
+ Otherwise, region_model::impl_call_realloc will later
+ get called (which will handle other sm-state transitions
+ when the state is bifurcated). */
void
malloc_state_machine::on_realloc_call (sm_context *sm_ctxt,
- const supernode *node ATTRIBUTE_UNUSED,
+ const supernode *node,
const gcall *call) const
{
- tree ptr = gimple_call_arg (call, 0);
+ const unsigned argno = 0;
+ const deallocator *d = &m_realloc;
+
+ tree arg = gimple_call_arg (call, argno);
- state_t state = sm_ctxt->get_state (call, ptr);
+ state_t state = sm_ctxt->get_state (call, arg);
- /* Detect mismatches. */
if (unchecked_p (state) || nonnull_p (state))
{
const allocation_state *astate = as_a_allocation_state (state);
gcc_assert (astate->m_deallocators);
- if (astate->m_deallocators != &m_free)
+ if (!astate->m_deallocators->contains_p (&m_free.m_deallocator))
{
/* Wrong allocator. */
- tree diag_ptr = sm_ctxt->get_diagnostic_tree (ptr);
+ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
pending_diagnostic *pd
- = new mismatching_deallocation (*this, diag_ptr,
+ = new mismatching_deallocation (*this, diag_arg,
astate->m_deallocators,
- &m_realloc);
- sm_ctxt->warn (node, call, ptr, pd);
+ d);
+ sm_ctxt->warn (node, call, arg, pd);
+ sm_ctxt->set_next_state (call, arg, m_stop);
+ if (path_context *path_ctxt = sm_ctxt->get_path_context ())
+ path_ctxt->terminate_path ();
}
}
-
- /* Transition ptr to "stop" state. */
- sm_ctxt->set_next_state (call, ptr, m_stop);
+ else if (state == m_free.m_deallocator.m_freed)
+ {
+ /* freed -> stop, with warning. */
+ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
+ sm_ctxt->warn (node, call, arg,
+ new double_free (*this, diag_arg, "free"));
+ sm_ctxt->set_next_state (call, arg, m_stop);
+ if (path_context *path_ctxt = sm_ctxt->get_path_context ())
+ path_ctxt->terminate_path ();
+ }
+ else if (state == m_non_heap)
+ {
+ /* non-heap -> stop, with warning. */
+ tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
+ sm_ctxt->warn (node, call, arg,
+ new free_of_non_heap (*this, diag_arg,
+ d->m_name));
+ sm_ctxt->set_next_state (call, arg, m_stop);
+ if (path_context *path_ctxt = sm_ctxt->get_path_context ())
+ path_ctxt->terminate_path ();
+ }
}
/* Implementation of state_machine::on_phi vfunc for malloc_state_machine. */
@@ -2015,6 +2033,30 @@ malloc_state_machine::on_zero_assignment (sm_context *sm_ctxt,
sm_ctxt->set_next_state (stmt, lhs, m_null);
}
+/* Special-case hook for handling realloc, for the "success with move to
+ a new buffer" case, marking OLD_PTR_SVAL as freed and NEW_PTR_SVAL as
+ non-null.
+
+ This is similar to on_deallocator_call and on_allocator_call,
+ but the checks happen in on_realloc_call, and by splitting the states. */
+
+void
+malloc_state_machine::
+on_realloc_with_move (region_model *model,
+ sm_state_map *smap,
+ const svalue *old_ptr_sval,
+ const svalue *new_ptr_sval,
+ const extrinsic_state &ext_state) const
+{
+ smap->set_state (model, old_ptr_sval,
+ m_free.m_deallocator.m_freed,
+ NULL, ext_state);
+
+ smap->set_state (model, new_ptr_sval,
+ m_free.m_nonnull,
+ NULL, ext_state);
+}
+
} // anonymous namespace
/* Internal interface to this file. */
@@ -2025,6 +2067,40 @@ make_malloc_state_machine (logger *logger)
return new malloc_state_machine (logger);
}
+/* Specialcase hook for handling realloc, for use by
+ region_model::impl_call_realloc::success_with_move::update_model. */
+
+void
+region_model::on_realloc_with_move (const call_details &cd,
+ const svalue *old_ptr_sval,
+ const svalue *new_ptr_sval)
+{
+ region_model_context *ctxt = cd.get_ctxt ();
+ if (!ctxt)
+ return;
+ const extrinsic_state *ext_state = ctxt->get_ext_state ();
+ if (!ext_state)
+ return;
+
+ sm_state_map *smap;
+ const state_machine *sm;
+ unsigned sm_idx;
+ if (!ctxt->get_malloc_map (&smap, &sm, &sm_idx))
+ return;
+
+ gcc_assert (smap);
+ gcc_assert (sm);
+
+ const malloc_state_machine &malloc_sm
+ = (const malloc_state_machine &)*sm;
+
+ malloc_sm.on_realloc_with_move (this,
+ smap,
+ old_ptr_sval,
+ new_ptr_sval,
+ *ext_state);
+}
+
} // namespace ana
#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc
index fcbf322..e8cbe2d 100644
--- a/gcc/analyzer/sm-signal.cc
+++ b/gcc/analyzer/sm-signal.cc
@@ -206,10 +206,10 @@ update_model_for_signal_handler (region_model *model,
/* Custom exploded_edge info: entry into a signal-handler. */
-class signal_delivery_edge_info_t : public exploded_edge::custom_info_t
+class signal_delivery_edge_info_t : public custom_edge_info
{
public:
- void print (pretty_printer *pp) FINAL OVERRIDE
+ void print (pretty_printer *pp) const FINAL OVERRIDE
{
pp_string (pp, "signal delivered");
}
@@ -220,15 +220,18 @@ public:
return custom_obj;
}
- void update_model (region_model *model,
- const exploded_edge &eedge) FINAL OVERRIDE
+ bool update_model (region_model *model,
+ const exploded_edge *eedge,
+ region_model_context *) const FINAL OVERRIDE
{
- update_model_for_signal_handler (model, eedge.m_dest->get_function ());
+ gcc_assert (eedge);
+ update_model_for_signal_handler (model, eedge->m_dest->get_function ());
+ return true;
}
void add_events_to_path (checker_path *emission_path,
const exploded_edge &eedge ATTRIBUTE_UNUSED)
- FINAL OVERRIDE
+ const FINAL OVERRIDE
{
emission_path->add_event
(new precanned_custom_event
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index 6bb036e..02faffb 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -257,6 +257,11 @@ public:
Otherwise return NULL_TREE. */
virtual tree is_zero_assignment (const gimple *stmt) = 0;
+ virtual path_context *get_path_context () const
+ {
+ return NULL;
+ }
+
protected:
sm_context (int sm_idx, const state_machine &sm)
: m_sm_idx (sm_idx), m_sm (sm) {}
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index 6913161..5f2fe4c 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -105,7 +105,8 @@ svalue::to_json () const
tree
svalue::maybe_get_constant () const
{
- if (const constant_svalue *cst_sval = dyn_cast_constant_svalue ())
+ const svalue *sval = unwrap_any_unmergeable ();
+ if (const constant_svalue *cst_sval = sval->dyn_cast_constant_svalue ())
return cst_sval->get_constant ();
else
return NULL_TREE;
diff --git a/gcc/asan.h b/gcc/asan.h
index 8c0b2ba..820c18b 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -255,8 +255,9 @@ static inline bool
sanitize_coverage_p (const_tree fn = current_function_decl)
{
return (flag_sanitize_coverage
- && lookup_attribute ("no_sanitize_coverage",
- DECL_ATTRIBUTES (fn)) == NULL_TREE);
+ && (fn == NULL_TREE
+ || lookup_attribute ("no_sanitize_coverage",
+ DECL_ATTRIBUTES (fn)) == NULL_TREE));
}
#endif /* TREE_ASAN */
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 0d22c20..83fafc9 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -1022,40 +1022,6 @@ common_function_versions (tree fn1, tree fn2)
return result;
}
-/* Return a new name by appending SUFFIX to the DECL name. If make_unique
- is true, append the full path name of the source file. */
-
-char *
-make_unique_name (tree decl, const char *suffix, bool make_unique)
-{
- char *global_var_name;
- int name_len;
- const char *name;
- const char *unique_name = NULL;
-
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-
- /* Get a unique name that can be used globally without any chances
- of collision at link time. */
- if (make_unique)
- unique_name = IDENTIFIER_POINTER (get_file_function_name ("\0"));
-
- name_len = strlen (name) + strlen (suffix) + 2;
-
- if (make_unique)
- name_len += strlen (unique_name) + 1;
- global_var_name = XNEWVEC (char, name_len);
-
- /* Use '.' to concatenate names as it is demangler friendly. */
- if (make_unique)
- snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name,
- suffix);
- else
- snprintf (global_var_name, name_len, "%s.%s", name, suffix);
-
- return global_var_name;
-}
-
/* Make a dispatcher declaration for the multi-versioned function DECL.
Calls to DECL function will be replaced with calls to the dispatcher
by the front-end. Return the decl created. */
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 87231b9..138c509 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -44,7 +44,6 @@ extern struct scoped_attributes* register_scoped_attributes (const struct attrib
extern char *sorted_attr_string (tree);
extern bool common_function_versions (tree, tree);
-extern char *make_unique_name (tree, const char *, bool);
extern tree make_dispatcher_decl (const tree);
extern bool is_function_default_version (const tree);
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index b915fdf..98c6d0b 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -2830,6 +2830,18 @@ debug (const bitmap_head *ptr)
fprintf (stderr, "<nil>\n");
}
+DEBUG_FUNCTION void
+debug (const auto_bitmap &ref)
+{
+ debug ((const bitmap_head &) ref);
+}
+
+DEBUG_FUNCTION void
+debug (const auto_bitmap *ptr)
+{
+ debug ((const bitmap_head *) ptr);
+}
+
void
bitmap_head::dump ()
{
diff --git a/gcc/bitmap.h b/gcc/bitmap.h
index 0846f79..1bddcdb 100644
--- a/gcc/bitmap.h
+++ b/gcc/bitmap.h
@@ -964,6 +964,9 @@ class auto_bitmap
bitmap_head m_bits;
};
+extern void debug (const auto_bitmap &ref);
+extern void debug (const auto_bitmap *ptr);
+
/* Base class for bitmap_view; see there for details. */
template<typename T, typename Traits = array_traits<T> >
class base_bitmap_view
diff --git a/gcc/btfout.c b/gcc/btfout.c
index 8cdd990..a787815 100644
--- a/gcc/btfout.c
+++ b/gcc/btfout.c
@@ -70,7 +70,7 @@ static char btf_info_section_label[MAX_BTF_LABEL_BYTES];
converted to BTF_KIND_VAR type records. Strictly accounts for the index
from the start of the variable type entries, does not include the number
of types emitted prior to the variable records. */
-static hash_map <ctf_dvdef_ref, unsigned int> *btf_var_ids;
+static GTY (()) hash_map <ctf_dvdef_ref, unsigned> *btf_var_ids;
/* Mapping of type IDs from original CTF ID to BTF ID. Types do not map
1-to-1 from CTF to BTF. To avoid polluting the CTF container when updating
@@ -156,7 +156,7 @@ init_btf_id_map (size_t len)
/* Return the BTF type ID of CTF type ID KEY, or BTF_INVALID_TYPEID if the CTF
type with ID KEY does not map to a BTF type. */
-static inline ctf_id_t
+ctf_id_t
get_btf_id (ctf_id_t key)
{
return btf_id_map[key];
@@ -1119,12 +1119,12 @@ btf_finalize (void)
funcs = NULL;
+ btf_var_ids->empty ();
+ btf_var_ids = NULL;
+
free (btf_id_map);
btf_id_map = NULL;
- ggc_free (btf_var_ids);
- btf_var_ids = NULL;
-
ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
ctfc_delete_container (tu_ctfc);
tu_ctfc = NULL;
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9954862..f1c3fea 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -105,7 +105,6 @@ builtin_info_type builtin_info[(int)END_BUILTINS];
bool force_folding_builtin_constant_p;
static int target_char_cast (tree, char *);
-static rtx get_memory_rtx (tree, tree);
static int apply_args_size (void);
static int apply_result_size (void);
static rtx result_vector (int, rtx);
@@ -142,7 +141,6 @@ static rtx expand_builtin_strcpy (tree, rtx);
static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
static rtx expand_builtin_strncpy (tree, rtx);
-static rtx expand_builtin_memset (tree, rtx, machine_mode);
static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
static rtx expand_builtin_bzero (tree);
static rtx expand_builtin_strlen (tree, rtx, machine_mode);
@@ -1356,7 +1354,7 @@ expand_builtin_prefetch (tree exp)
the maximum length of the block of memory that might be accessed or
NULL if unknown. */
-static rtx
+rtx
get_memory_rtx (tree exp, tree len)
{
tree orig_exp = exp;
@@ -3872,7 +3870,7 @@ builtin_memset_gen_str (void *data, void *prev,
try to get the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
-static rtx
+rtx
expand_builtin_memset (tree exp, rtx target, machine_mode mode)
{
if (!validate_arglist (exp,
@@ -5164,12 +5162,10 @@ default_emit_call_builtin___clear_cache (rtx begin, rtx end)
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))
- {
- error ("both arguments to %<__builtin___clear_cache%> must be pointers");
- return;
- }
+ gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
+ || CONST_INT_P (begin))
+ && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
+ || CONST_INT_P (end)));
if (targetm.have_clear_cache ())
{
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 16b47ac..5e4d86e 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -114,6 +114,7 @@ extern rtx builtin_strncpy_read_str (void *, void *, HOST_WIDE_INT,
fixed_size_mode);
extern rtx builtin_memset_read_str (void *, void *, HOST_WIDE_INT,
fixed_size_mode);
+extern rtx expand_builtin_memset (tree, rtx, machine_mode);
extern rtx expand_builtin_saveregs (void);
extern tree std_build_builtin_va_list (void);
extern tree std_fn_abi_va_list (tree);
@@ -145,6 +146,7 @@ extern char target_percent_s[3];
extern char target_percent_c[3];
extern char target_percent_s_newline[4];
extern bool target_char_cst_p (tree t, char *p);
+extern rtx get_memory_rtx (tree exp, tree len);
extern internal_fn associated_internal_fn (tree);
extern internal_fn replacement_internal_fn (gcall *);
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 5e3ac92..c5f5915 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,176 @@
+2021-10-14 Joseph Myers <joseph@codesourcery.com>
+
+ * c-format.c (printf_length_specs, scanf_length_specs)
+ (print_char_table, scan_char_table): Support DFP formats for C2X.
+ * c-format.h (TEX_D32, TEX_D64, TEX_D128): Remove.
+ (T2X_D32, T2X_D64, T2X_D128): New macros.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * c-omp.c (c_omp_check_context_selector): Rename to
+ omp_check_context_selector and move to omp-general.c.
+ (c_omp_mark_declare_variant): Rename to omp_mark_declare_variant and
+ move to omp-general.c.
+
+2021-10-12 Joseph Myers <joseph@codesourcery.com>
+
+ * c-format.c (print_char_table): Add %b and %B formats.
+ (scan_char_table): Add %b format.
+ * c-format.h (T2X_UI, T2X_UL, T2X_ULL, T2X_US, T2X_UC, T2X_ST)
+ (T2X_UPD, T2X_UIM): New macros.
+
+2021-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_finish_omp_atomic): Use
+ clear_padding_type_may_have_padding_p.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * c-opts.c (c_common_post_options): Use new macro
+ OPTION_SET_P.
+
+2021-10-07 Martin Liska <mliska@suse.cz>
+
+ * c-common.c (parse_optimize_options): Make
+ save_opt_decoded_options a pointer type.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102571
+ * c-omp.c (c_finish_omp_atomic): Optimize the case where type has
+ padding, but the non-padding bits are contiguous set of bytes
+ by adjusting the memcmp call arguments instead of emitting
+ __builtin_clear_padding and then comparing all the type's bytes.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine
+ __cpp_constexpr to 202110L rather than 201907L.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-common.h (do_warn_array_compare): Declare.
+ * c-warn.c (do_warn_array_compare): New.
+ * c.opt (Warray-compare): New option.
+
+2021-10-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-format.c: Remove a test of TARGET_FORMAT_TYPES with
+ NULL, this is not needed.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * c-common.c (decl_with_nonnull_addr_p): Handle members.
+ Check and perform warning suppression.
+ (c_common_truthvalue_conversion): Enhance warning suppression.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ PR target/102552
+ * c-common.c (parse_optimize_options): decoded_options[0] is
+ used for program name, so merged_decoded_options should also
+ respect that.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-ubsan.c (ubsan_instrument_division): Check the right
+ flag_sanitize_recover bit, depending on which sanitization
+ is done. Sanitize INT_MIN / -1 under SANITIZE_SI_OVERFLOW
+ rather than SANITIZE_DIVIDE. If both SANITIZE_SI_OVERFLOW
+ and SANITIZE_DIVIDE is enabled, neither check is known
+ to be false and flag_sanitize_recover bits for those two
+ aren't the same, emit both __ubsan_handle_divrem_overflow
+ and __ubsan_handle_divrem_overflow_abort calls.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * c-common.c (parse_optimize_options): Combine optimize
+ options with what was provided on the command line.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Also copy
+ OMP_CLAUSE_ORDER_REPRODUCIBLE.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * c-opts.c (c_common_init_options_struct): Set also
+ x_flag_default_complex_method.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Copy over OMP_CLAUSE_ALLOCATE_ALIGN.
+
+2021-09-20 Matthias Kretz <m.kretz@gsi.de>
+
+ * c-cppbuiltin.c (c_cpp_builtins_optimize_pragma): Define or
+ undefine __RECIPROCAL_MATH__, __NO_SIGNED_ZEROS__,
+ __NO_TRAPPING_MATH__, __ASSOCIATIVE_MATH__, and
+ __ROUNDING_MATH__ according to the new optimization flags.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Split order clause also to
+ distribute construct. Copy over OMP_CLAUSE_ORDER_UNCONSTRAINED.
+
+2021-09-17 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_finish_omp_atomic): Avoid creating
+ TARGET_EXPR if test is true, use create_tmp_var_raw instead of
+ create_tmp_var and add a zero initializer to TARGET_EXPRs that
+ had NULL initializer. When omitting operands after v = x,
+ use type of v rather than type of x. Fix type of vtmp
+ TARGET_EXPR.
+
+2021-09-13 Jason Merrill <jason@redhat.com>
+
+ * c.opt: Add -Winterference-size.
+ * c-cppbuiltin.c (cpp_atomic_builtins): Add __GCC_DESTRUCTIVE_SIZE
+ and __GCC_CONSTRUCTIVE_SIZE.
+
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.h (c_finish_omp_atomic): Add r and weak arguments.
+ * c-omp.c: Include gimple-fold.h.
+ (c_finish_omp_atomic): Add r and weak arguments. Add support for
+ OpenMP 5.1 atomics.
+
+2021-09-09 qing zhao <qing.zhao@oracle.com>
+
+ * c-attribs.c (handle_uninitialized_attribute): New function.
+ (c_common_attribute_table): Add "uninitialized" attribute.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * c-common.c (excess_precision_mode_join): Update below comments.
+ (c_ts18661_flt_eval_method): Set excess_precision_type to
+ EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16.
+ * c-cppbuiltin.c (cpp_atomic_builtins): Update below comments.
+ (c_cpp_flt_eval_method_iec_559): Set excess_precision_type to
+ EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-omp.c (c_finish_omp_flush): Handle MEMMODEL_SEQ_CST.
+
+2021-09-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.c (dump_ads): Generate pragmas to disable style checks
+ and -gnatwu warning for the package specification.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-attribs.c (handle_unavailable_attribute): New.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ * c.opt: Add -Wmissing-requires.
+
2021-08-25 Lewis Hyatt <lhyatt@gmail.com>
PR other/93067
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 827bcc7..b197d55 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -3440,11 +3440,12 @@ dump_ads (const char *source_file,
dump_ada_nodes (&pp, source_file);
/* We require Ada 2012 syntax, so generate corresponding pragma. */
- fputs ("pragma Ada_2012;\n", f);
+ fputs ("pragma Ada_2012;\n\n", f);
/* Disable style checks and warnings on unused entities since this file
is auto-generated and always has a with clause for Interfaces.C. */
- fputs ("pragma Style_Checks (Off);\npragma Warnings (\"U\");\n\n", f);
+ fputs ("pragma Style_Checks (Off);\n", f);
+ fputs ("pragma Warnings (Off, \"-gnatwu\");\n\n", f);
/* Dump withs. */
dump_ada_withs (f);
@@ -3452,7 +3453,10 @@ dump_ads (const char *source_file,
fprintf (f, "\npackage %s is\n\n", pkg_name);
pp_write_text_to_stream (&pp);
/* ??? need to free pp */
- fprintf (f, "end %s;\n", pkg_name);
+ fprintf (f, "end %s;\n\n", pkg_name);
+
+ fputs ("pragma Style_Checks (On);\n", f);
+ fputs ("pragma Warnings (On, \"-gnatwu\");\n", f);
fclose (f);
}
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index e60fb31..007b928 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -83,6 +83,7 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
+static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_reorder_attribute (tree *, tree, tree, int,
@@ -123,6 +124,8 @@ static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_unavailable_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int,
bool *) ATTRIBUTE_NONNULL(3);
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
@@ -331,6 +334,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_used_attribute, NULL },
{ "unused", 0, 0, false, false, false, false,
handle_unused_attribute, NULL },
+ { "uninitialized", 0, 0, true, false, false, false,
+ handle_uninitialized_attribute, NULL },
{ "retain", 0, 0, true, false, false, false,
handle_retain_attribute, NULL },
{ "externally_visible", 0, 0, true, false, false, false,
@@ -406,6 +411,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_novops_attribute, NULL },
{ "deprecated", 0, 1, false, false, false, false,
handle_deprecated_attribute, NULL },
+ { "unavailable", 0, 1, false, false, false, false,
+ handle_unavailable_attribute, NULL },
{ "vector_size", 1, 1, false, true, false, true,
handle_vector_size_attribute, NULL },
{ "visibility", 1, 1, false, false, false, false,
@@ -1613,6 +1620,30 @@ handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle an "uninitialized" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree decl = *node;
+ if (!VAR_P (decl))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored because %qD "
+ "is not a variable", name, decl);
+ *no_add_attrs = true;
+ }
+ else if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored because %qD "
+ "is not a local variable", name, decl);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "externally_visible" attribute; arguments as in
struct attribute_spec.handler. */
@@ -4122,6 +4153,71 @@ handle_deprecated_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "unavailable" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_unavailable_attribute (tree *node, tree name,
+ tree args, int flags,
+ bool *no_add_attrs)
+{
+ tree type = NULL_TREE;
+ int warn = 0;
+ tree what = NULL_TREE;
+
+ if (!args)
+ *no_add_attrs = true;
+ else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ {
+ error ("the message attached to %<unavailable%> is not a string");
+ *no_add_attrs = true;
+ }
+
+ if (DECL_P (*node))
+ {
+ tree decl = *node;
+ type = TREE_TYPE (decl);
+
+ if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == PARM_DECL
+ || VAR_OR_FUNCTION_DECL_P (decl)
+ || TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == CONST_DECL
+ || objc_method_decl (TREE_CODE (decl)))
+ TREE_UNAVAILABLE (decl) = 1;
+ else
+ warn = 1;
+ }
+ else if (TYPE_P (*node))
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+ TREE_UNAVAILABLE (*node) = 1;
+ type = *node;
+ }
+ else
+ warn = 1;
+
+ if (warn)
+ {
+ *no_add_attrs = true;
+ if (type && TYPE_NAME (type))
+ {
+ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ what = TYPE_NAME (*node);
+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (type)))
+ what = DECL_NAME (TYPE_NAME (type));
+ }
+ if (what)
+ warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
+ else
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ }
+
+ return NULL_TREE;
+}
+
/* Return the "base" type from TYPE that is suitable to apply attribute
vector_size to by stripping arrays, function types, etc. */
static tree
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 017e415..32c7e3e 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3393,14 +3393,16 @@ c_wrap_maybe_const (tree expr, bool non_const)
return expr;
}
-/* Return whether EXPR is a declaration whose address can never be
- NULL. */
+/* Return whether EXPR is a declaration whose address can never be NULL.
+ The address of the first struct member could be NULL only if it were
+ accessed through a NULL pointer, and such an access would be invalid. */
bool
decl_with_nonnull_addr_p (const_tree expr)
{
return (DECL_P (expr)
- && (TREE_CODE (expr) == PARM_DECL
+ && (TREE_CODE (expr) == FIELD_DECL
+ || TREE_CODE (expr) == PARM_DECL
|| TREE_CODE (expr) == LABEL_DECL
|| !DECL_WEAK (expr)));
}
@@ -3488,13 +3490,17 @@ c_common_truthvalue_conversion (location_t location, tree expr)
case ADDR_EXPR:
{
tree inner = TREE_OPERAND (expr, 0);
- if (decl_with_nonnull_addr_p (inner))
+ if (decl_with_nonnull_addr_p (inner)
+ /* Check both EXPR and INNER for suppression. */
+ && !warning_suppressed_p (expr, OPT_Waddress)
+ && !warning_suppressed_p (inner, OPT_Waddress))
{
- /* Common Ada programmer's mistake. */
+ /* Common Ada programmer's mistake. */
warning_at (location,
OPT_Waddress,
"the address of %qD will always evaluate as %<true%>",
inner);
+ suppress_warning (inner, OPT_Waddress);
return truthvalue_true_node;
}
break;
@@ -3627,8 +3633,17 @@ c_common_truthvalue_conversion (location_t location, tree expr)
break;
/* If this isn't narrowing the argument, we can ignore it. */
if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype))
- return c_common_truthvalue_conversion (location,
- TREE_OPERAND (expr, 0));
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ if ((TREE_CODE (fromtype) == POINTER_TYPE
+ && TREE_CODE (totype) == INTEGER_TYPE)
+ || warning_suppressed_p (expr, OPT_Waddress))
+ /* Suppress -Waddress for casts to intptr_t, propagating
+ any suppression from the enclosing expression to its
+ operand. */
+ suppress_warning (op0, OPT_Waddress);
+ return c_common_truthvalue_conversion (location, op0);
+ }
}
break;
@@ -5904,9 +5919,23 @@ parse_optimize_options (tree args, bool attr_p)
j++;
}
decoded_options_count = j;
- /* And apply them. */
+
+ /* Merge the decoded options with save_decoded_options. */
+ unsigned save_opt_count = save_opt_decoded_options->length ();
+ unsigned merged_decoded_options_count
+ = save_opt_count + decoded_options_count;
+ cl_decoded_option *merged_decoded_options
+ = XNEWVEC (cl_decoded_option, merged_decoded_options_count);
+
+ /* Note the first decoded_options is used for the program name. */
+ for (unsigned i = 0; i < save_opt_count; ++i)
+ merged_decoded_options[i + 1] = (*save_opt_decoded_options)[i];
+ for (unsigned i = 1; i < decoded_options_count; ++i)
+ merged_decoded_options[save_opt_count + i] = decoded_options[i];
+
+ /* And apply them. */
decode_options (&global_options, &global_options_set,
- decoded_options, decoded_options_count,
+ merged_decoded_options, merged_decoded_options_count,
input_location, global_dc, NULL);
free (decoded_options);
@@ -8778,7 +8807,7 @@ excess_precision_mode_join (enum flt_eval_method x,
This relates to the effective excess precision seen by the user,
which is the join point of the precision the target requests for
- -fexcess-precision={standard,fast} and the implicit excess precision
+ -fexcess-precision={standard,fast,16} and the implicit excess precision
the target uses. */
static enum flt_eval_method
@@ -8790,7 +8819,9 @@ c_ts18661_flt_eval_method (void)
enum excess_precision_type flag_type
= (flag_excess_precision == EXCESS_PRECISION_STANDARD
? EXCESS_PRECISION_TYPE_STANDARD
- : EXCESS_PRECISION_TYPE_FAST);
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16
+ : EXCESS_PRECISION_TYPE_FAST));
enum flt_eval_method requested
= targetm.c.excess_precision (flag_type);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d66bf15..078730f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1223,8 +1223,8 @@ extern tree c_finish_omp_critical (location_t, tree, tree, tree);
extern tree c_finish_omp_ordered (location_t, tree, tree);
extern void c_finish_omp_barrier (location_t);
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree, bool,
- enum omp_memory_order, bool = false);
+ tree, tree, tree, tree, tree, tree, bool,
+ enum omp_memory_order, bool, bool = false);
extern bool c_omp_depend_t_p (tree);
extern void c_finish_omp_depobj (location_t, tree, enum omp_clause_depend_kind,
tree);
@@ -1421,6 +1421,7 @@ extern bool warn_for_restrict (unsigned, tree *, unsigned);
extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
extern void warn_parm_array_mismatch (location_t, tree, tree);
extern void maybe_warn_sizeof_array_div (location_t, tree, tree, tree, tree);
+extern void do_warn_array_compare (location_t, tree_code, tree, tree);
/* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 3fa62bc..60e9e05 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -628,6 +628,31 @@ c_cpp_builtins_optimize_pragma (cpp_reader *pfile, tree prev_tree,
cpp_undef (pfile, "__FINITE_MATH_ONLY__");
cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=0");
}
+
+ if (!prev->x_flag_reciprocal_math && cur->x_flag_reciprocal_math)
+ cpp_define_unused (pfile, "__RECIPROCAL_MATH__");
+ else if (prev->x_flag_reciprocal_math && !cur->x_flag_reciprocal_math)
+ cpp_undef (pfile, "__RECIPROCAL_MATH__");
+
+ if (!prev->x_flag_signed_zeros && cur->x_flag_signed_zeros)
+ cpp_undef (pfile, "__NO_SIGNED_ZEROS__");
+ else if (prev->x_flag_signed_zeros && !cur->x_flag_signed_zeros)
+ cpp_define_unused (pfile, "__NO_SIGNED_ZEROS__");
+
+ if (!prev->x_flag_trapping_math && cur->x_flag_trapping_math)
+ cpp_undef (pfile, "__NO_TRAPPING_MATH__");
+ else if (prev->x_flag_trapping_math && !cur->x_flag_trapping_math)
+ cpp_define_unused (pfile, "__NO_TRAPPING_MATH__");
+
+ if (!prev->x_flag_associative_math && cur->x_flag_associative_math)
+ cpp_define_unused (pfile, "__ASSOCIATIVE_MATH__");
+ else if (prev->x_flag_associative_math && !cur->x_flag_associative_math)
+ cpp_undef (pfile, "__ASSOCIATIVE_MATH__");
+
+ if (!prev->x_flag_rounding_math && cur->x_flag_rounding_math)
+ cpp_define_unused (pfile, "__ROUNDING_MATH__");
+ else if (prev->x_flag_rounding_math && !cur->x_flag_rounding_math)
+ cpp_undef (pfile, "__ROUNDING_MATH__");
}
@@ -741,6 +766,20 @@ cpp_atomic_builtins (cpp_reader *pfile)
builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
targetm.atomic_test_and_set_trueval);
+ /* Macros for C++17 hardware interference size constants. Either both or
+ neither should be set. */
+ gcc_assert (!param_destruct_interfere_size
+ == !param_construct_interfere_size);
+ if (param_destruct_interfere_size)
+ {
+ /* FIXME The way of communicating these values to the library should be
+ part of the C++ ABI, whether macro or builtin. */
+ builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
+ param_destruct_interfere_size);
+ builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
+ param_construct_interfere_size);
+ }
+
/* ptr_type_node can't be used here since ptr_mode is only set when
toplev calls backend_init which is not done with -E or pch. */
psize = POINTER_SIZE_UNITS;
@@ -753,7 +792,7 @@ cpp_atomic_builtins (cpp_reader *pfile)
/* Return TRUE if the implicit excess precision in which the back-end will
compute floating-point calculations is not more than the explicit
excess precision that the front-end will apply under
- -fexcess-precision=[standard|fast].
+ -fexcess-precision=[standard|fast|16].
More intuitively, return TRUE if the excess precision proposed by the
front-end is the excess precision that will actually be used. */
@@ -764,7 +803,9 @@ c_cpp_flt_eval_method_iec_559 (void)
enum excess_precision_type front_end_ept
= (flag_excess_precision == EXCESS_PRECISION_STANDARD
? EXCESS_PRECISION_TYPE_STANDARD
- : EXCESS_PRECISION_TYPE_FAST);
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16
+ : EXCESS_PRECISION_TYPE_FAST));
enum flt_eval_method back_end
= targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
@@ -1011,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_init_captures=201803L");
cpp_define (pfile, "__cpp_generic_lambdas=201707L");
cpp_define (pfile, "__cpp_designated_initializers=201707L");
- cpp_define (pfile, "__cpp_constexpr=201907L");
+ if (cxx_dialect <= cxx20)
+ cpp_define (pfile, "__cpp_constexpr=201907L");
cpp_define (pfile, "__cpp_constexpr_in_decltype=201711L");
cpp_define (pfile, "__cpp_conditional_explicit=201806L");
cpp_define (pfile, "__cpp_consteval=201811L");
@@ -1030,6 +1072,7 @@ c_cpp_builtins (cpp_reader *pfile)
/* Set feature test macros for C++23. */
cpp_define (pfile, "__cpp_size_t_suffix=202011L");
cpp_define (pfile, "__cpp_if_consteval=202106L");
+ cpp_define (pfile, "__cpp_constexpr=202110L");
}
if (flag_concepts)
{
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index b4cb765a..e735e09 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -493,8 +493,8 @@ static const format_length_info printf_length_specs[] =
{ "Z", FMT_LEN_z, STD_EXT, NO_FMT, 0 },
{ "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
{ "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
- { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
- { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
+ { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
+ { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
{ NO_FMT, NO_FMT, 0 }
};
@@ -530,8 +530,8 @@ static const format_length_info scanf_length_specs[] =
{ "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
{ "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
{ "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
- { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
- { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
+ { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
+ { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
{ NO_FMT, NO_FMT, 0 }
};
@@ -703,20 +703,23 @@ static const format_char_info print_char_table[] =
{ "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "-wp0 +'I", "i", NULL },
{ "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
{ "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0'I", "i", NULL },
- { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
- { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#I", "", NULL },
+ { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "", NULL },
+ { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#I", "", NULL },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, 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, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* C99 conversion specifiers. */
- { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
- { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#", "", NULL },
+ { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "", NULL },
+ { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#", "", NULL },
+ /* C2X conversion specifiers. */
+ { "b", 0, STD_C2X, { T2X_UI, T2X_UC, T2X_US, T2X_UL, T2X_ULL, TEX_ULL, T2X_ST, T2X_UPD, T2X_UIM, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
/* X/Open conversion specifiers. */
{ "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
/* GNU conversion specifiers. */
{ "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", NULL },
+ { "B", 0, STD_EXT, { T2X_UI, T2X_UC, T2X_US, T2X_UL, T2X_ULL, TEX_ULL, T2X_ST, T2X_UPD, T2X_UIM, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
@@ -867,15 +870,17 @@ static const format_char_info scan_char_table[] =
{ "di", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL },
{ "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL },
{ "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
- { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
+ { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "*w'", "W", NULL },
{ "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "cW", NULL },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW", NULL },
{ "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "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, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* C99 conversion specifiers. */
- { "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
- { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
+ { "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "*w'", "W", NULL },
+ { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, T2X_D32, T2X_D64, T2X_D128 }, "*w'", "W", NULL },
+ /* C2X conversion specifiers. */
+ { "b", 1, STD_C2X, { T2X_UI, T2X_UC, T2X_US, T2X_UL, T2X_ULL, TEX_ULL, T2X_ST, T2X_UPD, T2X_UIM, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
/* X/Open conversion specifiers. */
{ "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
@@ -5150,7 +5155,7 @@ handle_format_attribute (tree *node, tree atname, tree args,
#ifdef TARGET_FORMAT_TYPES
/* If the target provides additional format types, we need to
add them to FORMAT_TYPES at first use. */
- if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types)
+ if (!dynamic_format_types)
{
dynamic_format_types = XNEWVEC (format_kind_info,
n_format_types + TARGET_N_FORMAT_TYPES);
diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
index 2f926f4..dfa1e11 100644
--- a/gcc/c-family/c-format.h
+++ b/gcc/c-family/c-format.h
@@ -278,13 +278,17 @@ struct format_kind_info
#define T89_S { STD_C89, NULL, T_S }
#define T_UI &unsigned_type_node
#define T89_UI { STD_C89, NULL, T_UI }
+#define T2X_UI { STD_C2X, NULL, T_UI }
#define T_UL &long_unsigned_type_node
#define T89_UL { STD_C89, NULL, T_UL }
+#define T2X_UL { STD_C2X, NULL, T_UL }
#define T_ULL &long_long_unsigned_type_node
#define T9L_ULL { STD_C9L, NULL, T_ULL }
+#define T2X_ULL { STD_C2X, NULL, T_ULL }
#define TEX_ULL { STD_EXT, NULL, T_ULL }
#define T_US &short_unsigned_type_node
#define T89_US { STD_C89, NULL, T_US }
+#define T2X_US { STD_C2X, NULL, T_US }
#define T_F &float_type_node
#define T89_F { STD_C89, NULL, T_F }
#define T99_F { STD_C99, NULL, T_F }
@@ -300,6 +304,7 @@ struct format_kind_info
#define T99_SC { STD_C99, NULL, T_SC }
#define T_UC &unsigned_char_type_node
#define T99_UC { STD_C99, NULL, T_UC }
+#define T2X_UC { STD_C2X, NULL, T_UC }
#define T_V &void_type_node
#define T89_G { STD_C89, NULL, &local_gimple_ptr_node }
#define T_CGRAPH_NODE { STD_C89, NULL, &local_cgraph_node_ptr_node }
@@ -314,22 +319,25 @@ struct format_kind_info
#define TEX_WI { STD_EXT, "wint_t", T_WI }
#define T_ST &size_type_node
#define T99_ST { STD_C99, "size_t", T_ST }
+#define T2X_ST { STD_C2X, "size_t", T_ST }
#define T_SST &signed_size_type_node
#define T99_SST { STD_C99, "signed size_t", T_SST }
#define T_PD &ptrdiff_type_node
#define T99_PD { STD_C99, "ptrdiff_t", T_PD }
#define T_UPD &unsigned_ptrdiff_type_node
#define T99_UPD { STD_C99, "unsigned ptrdiff_t", T_UPD }
+#define T2X_UPD { STD_C2X, "unsigned ptrdiff_t", T_UPD }
#define T_IM &intmax_type_node
#define T99_IM { STD_C99, "intmax_t", T_IM }
#define T_UIM &uintmax_type_node
#define T99_UIM { STD_C99, "uintmax_t", T_UIM }
+#define T2X_UIM { STD_C2X, "uintmax_t", T_UIM }
#define T_D32 &dfloat32_type_node
-#define TEX_D32 { STD_EXT, "_Decimal32", T_D32 }
+#define T2X_D32 { STD_C2X, "_Decimal32", T_D32 }
#define T_D64 &dfloat64_type_node
-#define TEX_D64 { STD_EXT, "_Decimal64", T_D64 }
+#define T2X_D64 { STD_C2X, "_Decimal64", T_D64 }
#define T_D128 &dfloat128_type_node
-#define TEX_D128 { STD_EXT, "_Decimal128", T_D128 }
+#define T2X_D128 { STD_C2X, "_Decimal128", T_D128 }
/* Structure describing how format attributes such as "printf" are
interpreted as "gnu_printf" or "ms_printf" on a particular system.
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 18de7e4..af9eba8 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "langhooks.h"
#include "bitmap.h"
+#include "gimple-fold.h"
/* Complete a #pragma oacc wait construct. LOC is the location of
@@ -215,15 +216,17 @@ c_finish_omp_taskyield (location_t loc)
tree
c_finish_omp_atomic (location_t loc, enum tree_code code,
enum tree_code opcode, tree lhs, tree rhs,
- tree v, tree lhs1, tree rhs1, bool swapped,
- enum omp_memory_order memory_order, bool test)
+ tree v, tree lhs1, tree rhs1, tree r, bool swapped,
+ enum omp_memory_order memory_order, bool weak,
+ bool test)
{
- tree x, type, addr, pre = NULL_TREE;
+ tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
HOST_WIDE_INT bitpos = 0, bitsize = 0;
+ enum tree_code orig_opcode = opcode;
if (lhs == error_mark_node || rhs == error_mark_node
|| v == error_mark_node || lhs1 == error_mark_node
- || rhs1 == error_mark_node)
+ || rhs1 == error_mark_node || r == error_mark_node)
return error_mark_node;
/* ??? According to one reading of the OpenMP spec, complex type are
@@ -243,6 +246,12 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
return error_mark_node;
}
+ if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
+ {
+ error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
+ "comparison result");
+ return error_mark_node;
+ }
if (opcode == RDIV_EXPR)
opcode = TRUNC_DIV_EXPR;
@@ -299,6 +308,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
x = build1 (OMP_ATOMIC_READ, type, addr);
SET_EXPR_LOCATION (x, loc);
OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
+ gcc_assert (!weak);
if (blhs)
x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
bitsize_int (bitsize), bitsize_int (bitpos));
@@ -313,12 +323,29 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
{
lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
bitsize_int (bitsize), bitsize_int (bitpos));
- if (swapped)
+ if (opcode == COND_EXPR)
+ {
+ bool save = in_late_binary_op;
+ in_late_binary_op = true;
+ std::swap (rhs, rhs1);
+ rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
+ in_late_binary_op = save;
+ }
+ else if (swapped)
rhs = build_binary_op (loc, opcode, rhs, lhs, true);
else if (opcode != NOP_EXPR)
rhs = build_binary_op (loc, opcode, lhs, rhs, true);
opcode = NOP_EXPR;
}
+ else if (opcode == COND_EXPR)
+ {
+ bool save = in_late_binary_op;
+ in_late_binary_op = true;
+ std::swap (rhs, rhs1);
+ rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
+ in_late_binary_op = save;
+ opcode = NOP_EXPR;
+ }
else if (swapped)
{
rhs = build_binary_op (loc, opcode, rhs, lhs, true);
@@ -343,6 +370,150 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
if (blhs)
rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
rhs, bitsize_int (bitpos));
+ if (orig_opcode == COND_EXPR)
+ {
+ if (error_operand_p (rhs1))
+ return error_mark_node;
+ gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
+ tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
+ if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
+ {
+ bool clear_padding = false;
+ HOST_WIDE_INT non_padding_start = 0;
+ HOST_WIDE_INT non_padding_end = 0;
+ if (BITS_PER_UNIT == 8
+ && CHAR_BIT == 8
+ && clear_padding_type_may_have_padding_p (cmptype))
+ {
+ HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
+ gcc_assert (sz > 0);
+ unsigned char *buf = XALLOCAVEC (unsigned char, sz);
+ memset (buf, ~0, sz);
+ clear_type_padding_in_mask (cmptype, buf);
+ for (i = 0; i < sz; i++)
+ if (buf[i] != (unsigned char) ~0)
+ {
+ clear_padding = true;
+ break;
+ }
+ if (clear_padding && buf[i] == 0)
+ {
+ /* Try to optimize. In the common case where
+ non-padding bits are all continuous and start
+ and end at a byte boundary, we can just adjust
+ the memcmp call arguments and don't need to
+ emit __builtin_clear_padding calls. */
+ if (i == 0)
+ {
+ for (i = 0; i < sz; i++)
+ if (buf[i] != 0)
+ break;
+ if (i < sz && buf[i] == (unsigned char) ~0)
+ {
+ non_padding_start = i;
+ for (; i < sz; i++)
+ if (buf[i] != (unsigned char) ~0)
+ break;
+ }
+ else
+ i = 0;
+ }
+ if (i != 0)
+ {
+ non_padding_end = i;
+ for (; i < sz; i++)
+ if (buf[i] != 0)
+ {
+ non_padding_start = 0;
+ non_padding_end = 0;
+ break;
+ }
+ }
+ }
+ }
+ tree inttype = NULL_TREE;
+ if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
+ {
+ HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
+ inttype = c_common_type_for_size (prec, 1);
+ if (inttype
+ && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
+ TYPE_SIZE (inttype))
+ || TYPE_PRECISION (inttype) != prec))
+ inttype = NULL_TREE;
+ }
+ if (inttype)
+ {
+ TREE_OPERAND (rhs1, 0)
+ = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
+ TREE_OPERAND (rhs1, 0));
+ TREE_OPERAND (rhs1, 1)
+ = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
+ TREE_OPERAND (rhs1, 1));
+ }
+ else
+ {
+ tree pcmptype = build_pointer_type (cmptype);
+ tree tmp1 = create_tmp_var_raw (cmptype);
+ TREE_ADDRESSABLE (tmp1) = 1;
+ DECL_CONTEXT (tmp1) = current_function_decl;
+ tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
+ TREE_OPERAND (rhs1, 0), NULL, NULL);
+ tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
+ tree tmp2 = create_tmp_var_raw (cmptype);
+ TREE_ADDRESSABLE (tmp2) = 1;
+ DECL_CONTEXT (tmp2) = current_function_decl;
+ tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
+ TREE_OPERAND (rhs1, 1), NULL, NULL);
+ tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
+ if (non_padding_start)
+ {
+ tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
+ size_int (non_padding_start));
+ tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
+ size_int (non_padding_start));
+ }
+ tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
+ rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
+ non_padding_end
+ ? size_int (non_padding_end
+ - non_padding_start)
+ : TYPE_SIZE_UNIT (cmptype));
+ rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
+ integer_zero_node);
+ if (clear_padding && non_padding_end == 0)
+ {
+ fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
+ tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
+ tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
+ rhs1 = omit_two_operands_loc (loc, boolean_type_node,
+ rhs1, cp2, cp1);
+ }
+ }
+ }
+ if (r && test)
+ rtmp = rhs1;
+ else if (r)
+ {
+ tree var = create_tmp_var_raw (boolean_type_node);
+ DECL_CONTEXT (var) = current_function_decl;
+ rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
+ boolean_false_node, NULL, NULL);
+ save = in_late_binary_op;
+ in_late_binary_op = true;
+ x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
+ loc, rhs1, NULL_TREE);
+ in_late_binary_op = save;
+ if (x == error_mark_node)
+ return error_mark_node;
+ gcc_assert (TREE_CODE (x) == MODIFY_EXPR
+ && TREE_OPERAND (x, 0) == var);
+ TREE_OPERAND (x, 0) = rtmp;
+ rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
+ }
+ rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs);
+ rhs1 = NULL_TREE;
+ }
/* Punt the actual generation of atomic operations to common code. */
if (code == OMP_ATOMIC)
@@ -350,6 +521,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
x = build2 (code, type, addr, rhs);
SET_EXPR_LOCATION (x, loc);
OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
+ OMP_ATOMIC_WEAK (x) = weak;
/* Generally it is hard to prove lhs1 and lhs are the same memory
location, just diagnose different variables. */
@@ -407,13 +579,28 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
}
}
if (blhs)
+ x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
+ bitsize_int (bitsize), bitsize_int (bitpos));
+ if (r && !test)
{
- x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
- bitsize_int (bitsize), bitsize_int (bitpos));
- type = TREE_TYPE (blhs);
+ vtmp = create_tmp_var_raw (TREE_TYPE (x));
+ DECL_CONTEXT (vtmp) = current_function_decl;
}
- x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
+ else
+ vtmp = v;
+ x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
loc, x, NULL_TREE);
+ if (x == error_mark_node)
+ return error_mark_node;
+ type = TREE_TYPE (x);
+ if (r && !test)
+ {
+ vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
+ build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
+ gcc_assert (TREE_CODE (x) == MODIFY_EXPR
+ && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
+ TREE_OPERAND (x, 0) = vtmp;
+ }
if (rhs1 && rhs1 != orig_lhs)
{
tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
@@ -446,6 +633,28 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
if (pre)
x = omit_one_operand_loc (loc, type, x, pre);
+ if (r && r != void_list_node)
+ {
+ in_late_binary_op = true;
+ tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
+ loc, rtmp, NULL_TREE);
+ in_late_binary_op = save;
+ if (x2 == error_mark_node)
+ return error_mark_node;
+ x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
+ }
+ if (v && vtmp != v)
+ {
+ in_late_binary_op = true;
+ tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
+ loc, vtmp, NULL_TREE);
+ in_late_binary_op = save;
+ if (x2 == error_mark_node)
+ return error_mark_node;
+ x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp,
+ void_node, x2);
+ x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
+ }
return x;
}
@@ -606,7 +815,7 @@ c_finish_omp_flush (location_t loc, int mo)
{
tree x;
- if (mo == MEMMODEL_LAST)
+ if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
{
x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
x = build_call_expr_loc (loc, x, 0);
@@ -1953,14 +2162,35 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
}
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
break;
- /* order clauses are allowed on for, simd and loop. */
+ /* order clauses are allowed on distribute, for, simd and loop. */
case OMP_CLAUSE_ORDER:
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
+ {
+ if (code == OMP_DISTRIBUTE)
+ {
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ break;
+ }
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_ORDER);
+ OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
+ = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
+ }
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
{
if (code == OMP_SIMD)
{
c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
OMP_CLAUSE_ORDER);
+ OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
+ = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
+ = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
s = C_OMP_CLAUSE_SPLIT_SIMD;
@@ -2333,6 +2563,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_DECL (clauses);
OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
= OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
+ OMP_CLAUSE_ALLOCATE_ALIGN (c)
+ = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[s];
cclauses[s] = c;
has_dup_allocate = true;
@@ -2679,143 +2911,6 @@ c_omp_predetermined_mapping (tree decl)
}
-/* Diagnose errors in an OpenMP context selector, return CTX if
- it is correct or error_mark_node otherwise. */
-
-tree
-c_omp_check_context_selector (location_t loc, tree ctx)
-{
- /* Each trait-set-selector-name can only be specified once.
- There are just 4 set names. */
- for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
- for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
- if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
- {
- error_at (loc, "selector set %qs specified more than once",
- IDENTIFIER_POINTER (TREE_PURPOSE (t1)));
- return error_mark_node;
- }
- for (tree t = ctx; t; t = TREE_CHAIN (t))
- {
- /* Each trait-selector-name can only be specified once. */
- if (list_length (TREE_VALUE (t)) < 5)
- {
- for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
- for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
- if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
- {
- error_at (loc,
- "selector %qs specified more than once in set %qs",
- IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- return error_mark_node;
- }
- }
- else
- {
- hash_set<tree> pset;
- for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
- if (pset.add (TREE_PURPOSE (t1)))
- {
- error_at (loc,
- "selector %qs specified more than once in set %qs",
- IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- return error_mark_node;
- }
- }
-
- static const char *const kind[] = {
- "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
- static const char *const vendor[] = {
- "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
- "llvm", "nvidia", "pgi", "ti", "unknown", NULL };
- static const char *const extension[] = { NULL };
- static const char *const atomic_default_mem_order[] = {
- "seq_cst", "relaxed", "acq_rel", NULL };
- struct known_properties { const char *set; const char *selector;
- const char *const *props; };
- known_properties props[] = {
- { "device", "kind", kind },
- { "implementation", "vendor", vendor },
- { "implementation", "extension", extension },
- { "implementation", "atomic_default_mem_order",
- atomic_default_mem_order } };
- for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
- for (unsigned i = 0; i < ARRAY_SIZE (props); i++)
- if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
- props[i].selector)
- && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t)),
- props[i].set))
- for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
- for (unsigned j = 0; ; j++)
- {
- if (props[i].props[j] == NULL)
- {
- if (TREE_PURPOSE (t2)
- && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
- " score"))
- break;
- if (props[i].props == atomic_default_mem_order)
- {
- error_at (loc,
- "incorrect property %qs of %qs selector",
- IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
- "atomic_default_mem_order");
- return error_mark_node;
- }
- else if (TREE_PURPOSE (t2))
- warning_at (loc, 0,
- "unknown property %qs of %qs selector",
- IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
- props[i].selector);
- else
- warning_at (loc, 0,
- "unknown property %qE of %qs selector",
- TREE_VALUE (t2), props[i].selector);
- break;
- }
- else if (TREE_PURPOSE (t2) == NULL_TREE)
- {
- const char *str = TREE_STRING_POINTER (TREE_VALUE (t2));
- if (!strcmp (str, props[i].props[j])
- && ((size_t) TREE_STRING_LENGTH (TREE_VALUE (t2))
- == strlen (str) + 1))
- break;
- }
- else if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
- props[i].props[j]))
- break;
- }
- }
- return ctx;
-}
-
-/* Register VARIANT as variant of some base function marked with
- #pragma omp declare variant. CONSTRUCT is corresponding construct
- selector set. */
-
-void
-c_omp_mark_declare_variant (location_t loc, tree variant, tree construct)
-{
- tree attr = lookup_attribute ("omp declare variant variant",
- DECL_ATTRIBUTES (variant));
- if (attr == NULL_TREE)
- {
- attr = tree_cons (get_identifier ("omp declare variant variant"),
- unshare_expr (construct),
- DECL_ATTRIBUTES (variant));
- DECL_ATTRIBUTES (variant) = attr;
- return;
- }
- if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
- || (construct != NULL_TREE
- && omp_context_selector_set_compare ("construct", TREE_VALUE (attr),
- construct)))
- error_at (loc, "%qD used as a variant with incompatible %<construct%> "
- "selector sets", variant);
-}
-
/* For OpenACC, the OMP_CLAUSE_MAP_KIND of an OMP_CLAUSE_MAP is used internally
to distinguish clauses as seen by the user. Return the "friendly" clause
name for error messages etc., where possible. See also
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index fdde082..0225cba 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -222,6 +222,7 @@ c_common_init_options_struct (struct gcc_options *opts)
/* By default, C99-like requirements for complex multiply and divide. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
}
/* Common initialization before calling option handlers. */
@@ -830,7 +831,7 @@ c_common_post_options (const char **pfilename)
for -ffp-contract=off). */
if (flag_iso
&& !c_dialect_cxx ()
- && (global_options_set.x_flag_fp_contract_mode
+ && (OPTION_SET_P (flag_fp_contract_mode)
== (enum fp_contract_mode) 0)
&& flag_unsafe_math_optimizations == 0)
flag_fp_contract_mode = FP_CONTRACT_OFF;
@@ -841,7 +842,7 @@ c_common_post_options (const char **pfilename)
the set specified in ISO C99/C11. */
if (!flag_iso
&& !c_dialect_cxx ()
- && (global_options_set.x_flag_permitted_flt_eval_methods
+ && (OPTION_SET_P (flag_permitted_flt_eval_methods)
== PERMITTED_FLT_EVAL_METHODS_DEFAULT))
flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
else
@@ -1039,7 +1040,7 @@ c_common_post_options (const char **pfilename)
/* Unless -f{,no-}ext-numeric-literals has been used explicitly,
for -std=c++{11,14,17,20,23} default to -fno-ext-numeric-literals. */
- if (flag_iso && !global_options_set.x_flag_ext_numeric_literals)
+ if (flag_iso && !OPTION_SET_P (flag_ext_numeric_literals))
cpp_opts->ext_numeric_literals = 0;
}
else if (warn_narrowing == -1)
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 12a7bca..a4509c6 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -39,8 +39,9 @@ along with GCC; see the file COPYING3. If not see
tree
ubsan_instrument_division (location_t loc, tree op0, tree op1)
{
- tree t, tt;
+ tree t, tt, x = NULL_TREE;
tree type = TREE_TYPE (op0);
+ enum sanitize_code flag = SANITIZE_DIVIDE;
/* At this point both operands should have the same type,
because they are already converted to RESULT_TYPE.
@@ -58,24 +59,42 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
op1, build_int_cst (type, 0));
else if (TREE_CODE (type) == REAL_TYPE
&& sanitize_flags_p (SANITIZE_FLOAT_DIVIDE))
- t = fold_build2 (EQ_EXPR, boolean_type_node,
- op1, build_real (type, dconst0));
+ {
+ t = fold_build2 (EQ_EXPR, boolean_type_node,
+ op1, build_real (type, dconst0));
+ flag = SANITIZE_FLOAT_DIVIDE;
+ }
else
- return NULL_TREE;
+ t = NULL_TREE;
/* We check INT_MIN / -1 only for signed types. */
if (TREE_CODE (type) == INTEGER_TYPE
- && sanitize_flags_p (SANITIZE_DIVIDE)
+ && sanitize_flags_p (SANITIZE_SI_OVERFLOW)
&& !TYPE_UNSIGNED (type))
{
- tree x;
tt = fold_build2 (EQ_EXPR, boolean_type_node, unshare_expr (op1),
build_int_cst (type, -1));
x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
TYPE_MIN_VALUE (type));
x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
- t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+ if (t == NULL_TREE || integer_zerop (t))
+ {
+ t = x;
+ x = NULL_TREE;
+ flag = SANITIZE_SI_OVERFLOW;
+ }
+ else if (flag_sanitize_undefined_trap_on_error
+ || (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0)
+ == ((flag_sanitize_recover & SANITIZE_SI_OVERFLOW) == 0)))
+ {
+ t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+ x = NULL_TREE;
+ }
+ else if (integer_zerop (x))
+ x = NULL_TREE;
}
+ else if (t == NULL_TREE)
+ return NULL_TREE;
/* If the condition was folded to 0, no need to instrument
this expression. */
@@ -95,7 +114,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
NULL_TREE);
data = build_fold_addr_expr_loc (loc, data);
enum built_in_function bcode
- = (flag_sanitize_recover & SANITIZE_DIVIDE)
+ = (flag_sanitize_recover & flag)
? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
: BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
tt = builtin_decl_explicit (bcode);
@@ -103,8 +122,20 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
op1 = unshare_expr (op1);
tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1));
+ if (x)
+ {
+ bcode = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
+ ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
+ : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
+ tree xt = builtin_decl_explicit (bcode);
+ op0 = unshare_expr (op0);
+ op1 = unshare_expr (op1);
+ xt = build_call_expr_loc (loc, xt, 3, data, ubsan_encode_value (op0),
+ ubsan_encode_value (op1));
+ x = fold_build3 (COND_EXPR, void_type_node, x, xt, void_node);
+ }
}
- t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, x ? x : void_node);
return t;
}
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 84ad663..99cde4a 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -3726,3 +3726,35 @@ maybe_warn_sizeof_array_div (location_t loc, tree arr, tree arr_type,
}
}
}
+
+/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
+ and relational comparisons between two operands of array type are
+ deprecated." We also warn in C and earlier C++ standards. CODE is
+ the code for this comparison, OP0 and OP1 are the operands. */
+
+void
+do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1)
+{
+ STRIP_NOPS (op0);
+ STRIP_NOPS (op1);
+ if (TREE_CODE (op0) == ADDR_EXPR)
+ op0 = TREE_OPERAND (op0, 0);
+ if (TREE_CODE (op1) == ADDR_EXPR)
+ op1 = TREE_OPERAND (op1, 0);
+
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Warray_compare,
+ (c_dialect_cxx () && cxx_dialect >= cxx20)
+ ? G_("comparison between two arrays is deprecated in C++20")
+ : G_("comparison between two arrays")))
+ {
+ /* C doesn't allow +arr. */
+ if (c_dialect_cxx ())
+ inform (location, "use unary %<+%> which decays operands to pointers "
+ "or %<&%D[0] %s &%D[0]%> to compare the addresses",
+ op0, op_symbol_code (code), op1);
+ else
+ inform (location, "use %<&%D[0] %s &%D[0]%> to compare the addresses",
+ op0, op_symbol_code (code), op1);
+ }
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9192970..06457ac 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -350,6 +350,10 @@ Warray-bounds=
LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0)
; in common.opt
+Warray-compare
+C ObjC C++ ObjC++ Var(warn_array_compare) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall)
+Warn about comparisons between two operands of array type.
+
Warray-parameter
C ObjC C++ ObjC++ Warning Alias(Warray-parameter=, 2, 0)
Warn about mismatched declarations of array parameters and unsafe accesses to them.
@@ -722,6 +726,11 @@ Winit-list-lifetime
C++ ObjC++ Var(warn_init_list) Warning Init(1)
Warn about uses of std::initializer_list that can result in dangling pointers.
+Winterference-size
+C++ ObjC++ Var(warn_interference_size) Warning Init(1)
+Warn about nonsensical values of --param destructive-interference-size or
+constructive-interference-size.
+
Wimplicit
C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
Warn about implicit declarations.
@@ -839,6 +848,10 @@ Wmissing-field-initializers
C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra)
Warn about missing fields in struct initializers.
+Wmissing-requires
+C++ ObjC++ Var(warn_missing_requires) Init(1) Warning
+Warn about likely missing requires keyword.
+
Wmultistatement-macros
C ObjC C++ ObjC++ Var(warn_multistatement_macros) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn about unsafe macros expanding to multiple statements used as a body of a clause such as if, else, while, switch, or for.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 27ccc32..1387318 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,133 @@
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ PR c/102763
+ * gimple-parser.c
+ (c_parser_gimple_postfix_expression_after_primary): Check
+ for a pointer do be dereferenced by ->.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * c-parser.c (c_finish_omp_declare_variant): Change call from
+ c_omp_check_context_selector to omp_check_context_selector. Change
+ call from c_omp_mark_declare_variant to omp_mark_declare_variant.
+
+2021-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_structured_block_sequence): New function.
+ (c_parser_omp_scan_loop_body): Use it.
+ (c_parser_omp_sections_scope): Likewise.
+
+2021-10-07 Richard Biener <rguenther@suse.de>
+
+ * c-typeck.c (lvalue_p): Also allow MEM_REF and TARGET_MEM_REF.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * gimple-parser.c (c_parser_gimple_postfix_expression):
+ Accept more address _Literals.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-typeck.c (parser_build_binary_op): Call do_warn_array_compare.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * c-typeck.c (maybe_warn_for_null_address): New function.
+ (build_binary_op): Call it.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-typeck.c (build_binary_op): Call ubsan_instrument_division
+ for division even for SANITIZE_SI_OVERFLOW.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_order): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
+2021-09-28 Andrew Pinski <apinski@marvell.com>
+
+ PR c/32122
+ * c-parser.c (c_parser_statement_after_labels): Pass
+ the c_expr instead of the tree to c_finish_goto_ptr.
+ * c-typeck.c (c_finish_goto_ptr): Change the second
+ argument type to c_expr.
+ * c-tree.h (c_finish_goto_ptr): Likewise.
+ Error out if the expression was not of a pointer type.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_allocate): Parse allocate clause
+ modifiers.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_order): Parse unconstrained
+ and reproducible modifiers.
+ (OMP_DISTRIBUTE_CLAUSE_MASK): Add order clause.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_default): Handle private and
+ firstprivate arguments, adjust diagnostics on unknown argument.
+
+2021-09-17 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_atomic): Reject atomic swap if capture
+ is true.
+
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_conditional_expression): If omp_atomic_lhs and
+ cond.value is >, < or == with omp_atomic_lhs as one of the operands,
+ don't call build_conditional_expr, instead build a COND_EXPR directly.
+ (c_parser_binary_expression): Avoid calling parser_build_binary_op
+ if omp_atomic_lhs even in more cases for >, < or ==.
+ (c_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics,
+ parse OpenMP 5.1 atomics and fail, compare and weak clauses, allow
+ acq_rel on atomic read/write and acq_rel/acquire clauses on update.
+ * c-typeck.c (build_binary_op): For flag_openmp only handle
+ MIN_EXPR/MAX_EXPR.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_flush): Parse 'seq_cst' clause on 'flush'
+ directive.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-decl.c (enum deprecated_states): Add unavailable state.
+ (merge_decls): Copy unavailability.
+ (quals_from_declspecs): Handle unavailable case.
+ (start_decl): Amend the logic handling suppression of nested
+ deprecation states to include unavailability.
+ (smallest_type_quals_location): Amend comment.
+ (grokdeclarator): Handle the unavailable deprecation state.
+ (declspecs_add_type): Set TREE_UNAVAILABLE from the decl specs.
+ * c-tree.h (struct c_declspecs): Add unavailable_p.
+ * c-typeck.c (build_component_ref): Handle unavailability.
+ (build_external_ref): Likewise.
+
+2021-09-01 Roger Sayle <roger@nextmovesoftware.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ PR c/79412
+ * c-decl.c (duplicate_decls): On significant mismatches, mark the
+ types of both (non-function) decls as error_mark_node, so that the
+ middle-end can see the code is malformed.
+ (free_attr_access_data): Don't process if the type has been set to
+ error_mark_node.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_device): Parse device-modifiers 'device_num'
+ and 'ancestor' in 'target device' clauses.
+
2021-08-23 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_clause_num_tasks,
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 221a67f..771efa3 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -73,13 +73,16 @@ enum decl_context
TYPENAME}; /* Typename (inside cast or sizeof) */
/* States indicating how grokdeclarator() should handle declspecs marked
- with __attribute__((deprecated)). An object declared as
- __attribute__((deprecated)) suppresses warnings of uses of other
- deprecated items. */
+ with __attribute__((deprecated)) or __attribute__((unavailable)).
+ An object declared as __attribute__((unavailable)) should suppress
+ any reports of being declared with unavailable or deprecated items.
+ An object declared as __attribute__((deprecated)) should suppress
+ warnings of uses of other deprecated items. */
enum deprecated_states {
DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
+ DEPRECATED_SUPPRESS,
+ UNAVAILABLE_DEPRECATED_SUPPRESS
};
@@ -2644,6 +2647,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
+ /* Merge unavailability. */
+ if (TREE_UNAVAILABLE (newdecl))
+ TREE_UNAVAILABLE (olddecl) = 1;
+
/* If a decl is in a system header and the other isn't, keep the one on the
system header. Otherwise, keep source location of definition rather than
declaration and of prototype rather than non-prototype unless that
@@ -2957,6 +2964,17 @@ duplicate_decls (tree newdecl, tree olddecl)
{
/* Avoid `unused variable' and other warnings for OLDDECL. */
suppress_warning (olddecl, OPT_Wunused);
+ /* If the types are completely different, poison them both with
+ error_mark_node. */
+ if (TREE_CODE (TREE_TYPE (newdecl)) != TREE_CODE (TREE_TYPE (olddecl))
+ && olddecl != error_mark_node
+ && seen_error ())
+ {
+ if (TREE_CODE (olddecl) != FUNCTION_DECL)
+ TREE_TYPE (olddecl) = error_mark_node;
+ if (TREE_CODE (newdecl) != FUNCTION_DECL)
+ TREE_TYPE (newdecl) = error_mark_node;
+ }
return false;
}
@@ -4881,6 +4899,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
&& !specs->typedef_p
&& !specs->explicit_signed_p
&& !specs->deprecated_p
+ && !specs->unavailable_p
&& !specs->long_p
&& !specs->long_long_p
&& !specs->short_p
@@ -5083,9 +5102,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
- /* An object declared as __attribute__((deprecated)) suppresses
+ /* An object declared as __attribute__((unavailable)) suppresses
+ warnings and errors from __attribute__((deprecated/unavailable))
+ components.
+ An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
- if (lookup_attribute ("deprecated", attributes))
+ if (lookup_attribute ("unavailable", attributes))
+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
+ else if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
@@ -6222,7 +6246,7 @@ smallest_type_quals_location (const location_t *locations,
set to indicate whether operands in *EXPR can be used in constant
expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
- deprecation warnings should be suppressed.
+ deprecation/unavailability warnings should be suppressed.
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
@@ -6352,8 +6376,14 @@ grokdeclarator (const struct c_declarator *declarator,
if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
+ {
+ if (declspecs->unavailable_p)
+ error_unavailable_use (declspecs->type, declspecs->decl_attr);
+ else if (declspecs->deprecated_p
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ }
if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope
@@ -10803,6 +10833,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->typespec_kind = spec.kind;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
+ if (TREE_UNAVAILABLE (type))
+ specs->unavailable_p = true;
/* Handle type specifier keywords. */
if (TREE_CODE (type) == IDENTIFIER_NODE
@@ -12209,7 +12241,7 @@ free_attr_access_data ()
attr_access::free_lang_data (attrs);
tree fntype = TREE_TYPE (n->decl);
- if (!fntype)
+ if (!fntype || fntype == error_mark_node)
continue;
tree attrs = TYPE_ATTRIBUTES (fntype);
if (!attrs)
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 356cf25..80dd61d 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -6141,7 +6141,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
val = c_parser_expression (parser);
val = convert_lvalue_to_rvalue (loc, val, false, true);
- stmt = c_finish_goto_ptr (loc, val.value);
+ stmt = c_finish_goto_ptr (loc, val);
}
else
c_parser_error (parser, "expected identifier or %<*%>");
@@ -7663,10 +7663,21 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
- ret.value = build_conditional_expr (colon_loc, cond.value,
- cond.original_code == C_MAYBE_CONST_EXPR,
- exp1.value, exp1.original_type, loc1,
- exp2.value, exp2.original_type, loc2);
+ if (__builtin_expect (omp_atomic_lhs != NULL, 0)
+ && (TREE_CODE (cond.value) == GT_EXPR
+ || TREE_CODE (cond.value) == LT_EXPR
+ || TREE_CODE (cond.value) == EQ_EXPR)
+ && c_tree_equal (exp2.value, omp_atomic_lhs)
+ && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
+ || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
+ ret.value = build3_loc (colon_loc, COND_EXPR, TREE_TYPE (omp_atomic_lhs),
+ cond.value, exp1.value, exp2.value);
+ else
+ ret.value
+ = build_conditional_expr (colon_loc, cond.value,
+ cond.original_code == C_MAYBE_CONST_EXPR,
+ exp1.value, exp1.original_type, loc1,
+ exp2.value, exp2.original_type, loc2);
ret.original_code = ERROR_MARK;
if (exp1.value == error_mark_node || exp2.value == error_mark_node)
ret.original_type = NULL;
@@ -7849,15 +7860,27 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
= convert_lvalue_to_rvalue (stack[sp].loc, \
stack[sp].expr, true, true); \
if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \
- && c_parser_peek_token (parser)->type == CPP_SEMICOLON \
- && ((1 << stack[sp].prec) \
- & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \
- | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \
+ && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
+ && ((1 << stack[sp].prec) \
+ & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
+ | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
+ | (1 << PREC_ADD) | (1 << PREC_MULT) \
+ | (1 << PREC_EQ)))) \
+ || ((c_parser_next_token_is (parser, CPP_QUERY) \
+ || (omp_atomic_lhs == void_list_node \
+ && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
+ && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
&& stack[sp].op != TRUNC_MOD_EXPR \
+ && stack[sp].op != GE_EXPR \
+ && stack[sp].op != LE_EXPR \
+ && stack[sp].op != NE_EXPR \
&& stack[0].expr.value != error_mark_node \
&& 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))) \
+ && (omp_atomic_lhs == void_list_node \
+ || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
+ || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
+ || (stack[sp].op == EQ_EXPR \
+ && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
{ \
tree t = make_node (stack[1].op); \
TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
@@ -13397,6 +13420,9 @@ c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
/* OpenMP 2.5:
default ( none | shared )
+ OpenMP 5.1:
+ default ( private | firstprivate )
+
OpenACC:
default ( none | present ) */
@@ -13423,9 +13449,24 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
break;
case 'p':
- if (strcmp ("present", p) != 0 || !is_oacc)
+ if (is_oacc)
+ {
+ if (strcmp ("present", p) != 0)
+ goto invalid_kind;
+ kind = OMP_CLAUSE_DEFAULT_PRESENT;
+ }
+ else
+ {
+ if (strcmp ("private", p) != 0)
+ goto invalid_kind;
+ kind = OMP_CLAUSE_DEFAULT_PRIVATE;
+ }
+ break;
+
+ case 'f':
+ if (strcmp ("firstprivate", p) != 0 || is_oacc)
goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_PRESENT;
+ kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
break;
case 's':
@@ -13446,7 +13487,8 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
if (is_oacc)
c_parser_error (parser, "expected %<none%> or %<present%>");
else
- c_parser_error (parser, "expected %<none%> or %<shared%>");
+ c_parser_error (parser, "expected %<none%>, %<shared%>, "
+ "%<private%> or %<firstprivate%>");
}
parens.skip_until_found_close (parser);
@@ -14568,7 +14610,14 @@ c_parser_oacc_clause_wait (c_parser *parser, tree list)
/* OpenMP 5.0:
- order ( concurrent ) */
+ order ( concurrent )
+
+ OpenMP 5.1:
+ order ( order-modifier : concurrent )
+
+ order-modifier:
+ reproducible
+ unconstrained */
static tree
c_parser_omp_clause_order (c_parser *parser, tree list)
@@ -14576,10 +14625,29 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
location_t loc = c_parser_peek_token (parser)->location;
tree c;
const char *p;
+ bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
return list;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "unconstrained") == 0)
+ unconstrained = true;
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
+ {
+ c_parser_error (parser, "expected %<reproducible%> or "
+ "%<unconstrained%>");
+ goto out_err;
+ }
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
if (!c_parser_next_token_is (parser, CPP_NAME))
{
c_parser_error (parser, "expected %<concurrent%>");
@@ -14593,8 +14661,10 @@ c_parser_omp_clause_order (c_parser *parser, tree list)
}
c_parser_consume_token (parser);
parens.skip_until_found_close (parser);
- /* check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order"); */
+ check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
+ OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -15239,7 +15309,15 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
c_parser_omp_clause_allocate (c_parser *parser, tree list)
@@ -15247,6 +15325,7 @@ 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;
+ tree align = NULL_TREE;
matching_parens parens;
if (!parens.require_open (parser))
@@ -15257,17 +15336,128 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
|| (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"))
+ bool has_modifiers = false;
+ tree orig_type = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ unsigned int n = 3;
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON)
+ has_modifiers = true;
+ else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COMMA
+ && (c_parser_peek_nth_token_raw (parser, n + 2)->type
+ == CPP_NAME)
+ && (c_parser_peek_nth_token_raw (parser, n + 3)->type
+ == CPP_OPEN_PAREN))
+ {
+ c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
+ const char *q = IDENTIFIER_POINTER (tok->value);
+ n += 4;
+ if ((strcmp (q, "allocator") == 0
+ || strcmp (q, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser,
+ &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON))
+ has_modifiers = true;
+ }
+ }
+ if (has_modifiers)
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens2;;
+ parens2.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);
+ if (strcmp (p, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ c_token *tok = c_parser_peek_token (parser);
+ const char *q = "";
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ q = IDENTIFIER_POINTER (tok->value);
+ if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
+ {
+ c_parser_error (parser, "expected %<allocator%> or "
+ "%<align%>");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ else if (strcmp (p, q) == 0)
+ {
+ error_at (tok->location, "duplicate %qs modifier", p);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!parens2.require_open (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
+ true);
+ if (strcmp (q, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ }
+ }
+ }
+ if (!has_modifiers)
+ {
+ 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);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ if (allocator
+ && (!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 "
@@ -15275,6 +15465,16 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
TREE_TYPE (allocator));
allocator = NULL_TREE;
}
+ if (align
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align)))
+ {
+ error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ align = NULL_TREE;
+ }
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
parens.skip_until_found_close (parser);
@@ -15285,9 +15485,12 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_ALLOCATE, list);
- if (allocator)
+ if (allocator || align)
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
parens.skip_until_found_close (parser);
return nl;
@@ -15945,37 +16148,87 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
}
/* OpenMP 4.0:
- device ( expression ) */
+ device ( expression )
+
+ OpenMP 5.0:
+ device ( [device-modifier :] integer-expression )
+
+ device-modifier:
+ ancestor | device_num */
static tree
c_parser_omp_clause_device (c_parser *parser, tree list)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- 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);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
+ location_t expr_loc;
+ c_expr expr;
+ tree c, t;
+ bool ancestor = false;
- parens.skip_until_found_close (parser);
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ c_token *tok = c_parser_peek_token (parser);
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ if (strcmp ("ancestor", p) == 0)
{
- c_parser_error (parser, "expected integer expression");
+ /* A requires directive with the reverse_offload clause must be
+ specified. */
+ if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
+ {
+ error_at (tok->location, "%<ancestor%> device modifier not "
+ "preceded by %<requires%> directive "
+ "with %<reverse_offload%> clause");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ ancestor = true;
+ }
+ else if (strcmp ("device_num", p) == 0)
+ ;
+ else
+ {
+ error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
+ parens.skip_until_found_close (parser);
return list;
}
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+
+ expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
+ t = c_fully_fold (t, false, NULL);
- check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
+ parens.skip_until_found_close (parser);
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
- OMP_CLAUSE_DEVICE_ID (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+ if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
+ {
+ error_at (expr_loc, "the %<device%> clause expression must evaluate to "
+ "%<1%>");
+ return list;
}
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
+
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
+
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
+
+ list = c;
return list;
}
@@ -17605,14 +17858,45 @@ c_parser_omp_allocate (location_t loc, c_parser *parser)
capture-block:
{ v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
- where x and v are lvalue expressions with scalar type.
+ OpenMP 5.1:
+ # pragma omp atomic compare new-line
+ conditional-update-atomic
+
+ # pragma omp atomic compare capture new-line
+ conditional-update-capture-atomic
+
+ conditional-update-atomic:
+ cond-expr-stmt | cond-update-stmt
+ cond-expr-stmt:
+ x = expr ordop x ? expr : x;
+ x = x ordop expr ? expr : x;
+ x = x == e ? d : x;
+ cond-update-stmt:
+ if (expr ordop x) { x = expr; }
+ if (x ordop expr) { x = expr; }
+ if (x == e) { x = d; }
+ ordop:
+ <, >
+ conditional-update-capture-atomic:
+ v = cond-expr-stmt
+ { v = x; cond-expr-stmt }
+ { cond-expr-stmt v = x; }
+ { v = x; cond-update-stmt }
+ { cond-update-stmt v = x; }
+ if (x == e) { x = d; } else { v = x; }
+ { r = x == e; if (r) { x = d; } }
+ { r = x == e; if (r) { x = d; } else { v = x; } }
+
+ where x, r and v are lvalue expressions with scalar type,
+ expr, e and d are expressions with scalar type and e might be
+ the same as v.
LOC is the location of the #pragma token. */
static void
c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
- tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+ tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
@@ -17624,6 +17908,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
bool non_lvalue_p;
bool first = true;
tree clauses = NULL_TREE;
+ bool capture = false;
+ bool compare = false;
+ bool weak = false;
+ enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool no_semicolon = false;
+ bool extra_scope = false;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
@@ -17642,6 +17932,10 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
enum tree_code new_code = ERROR_MARK;
enum omp_memory_order new_memory_order
= OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool new_capture = false;
+ bool new_compare = false;
+ bool new_weak = false;
+ enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
if (!strcmp (p, "read"))
new_code = OMP_ATOMIC_READ;
@@ -17649,7 +17943,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
new_code = NOP_EXPR;
else if (!strcmp (p, "update"))
new_code = OMP_ATOMIC;
- else if (!strcmp (p, "capture"))
+ else if (openacc && !strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
else if (openacc)
{
@@ -17657,6 +17951,47 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
"or %<capture%> clause");
}
+ else if (!strcmp (p, "capture"))
+ new_capture = true;
+ else if (!strcmp (p, "compare"))
+ new_compare = true;
+ else if (!strcmp (p, "weak"))
+ new_weak = true;
+ else if (!strcmp (p, "fail"))
+ {
+ matching_parens parens;
+
+ c_parser_consume_token (parser);
+ if (!parens.require_open (parser))
+ continue;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *q
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (!strcmp (q, "seq_cst"))
+ new_fail = OMP_MEMORY_ORDER_SEQ_CST;
+ else if (!strcmp (q, "acquire"))
+ new_fail = OMP_MEMORY_ORDER_ACQUIRE;
+ else if (!strcmp (q, "relaxed"))
+ new_fail = OMP_MEMORY_ORDER_RELAXED;
+ }
+
+ if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ c_parser_consume_token (parser);
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ error_at (cloc, "too many %qs clauses", "fail");
+ else
+ fail = new_fail;
+ }
+ else
+ c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
+ "or %<relaxed%>");
+ parens.skip_until_found_close (parser);
+ continue;
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -17677,8 +18012,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
p = NULL;
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
- "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
- "%<release%>, %<relaxed%> or %<hint%> clause");
+ "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
+ "%<seq_cst%>, %<acq_rel%>, %<release%>, "
+ "%<relaxed%> or %<hint%> clause");
}
if (p)
{
@@ -17701,6 +18037,27 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
else
memory_order = new_memory_order;
}
+ else if (new_capture)
+ {
+ if (capture)
+ error_at (cloc, "too many %qs clauses", "capture");
+ else
+ capture = true;
+ }
+ else if (new_compare)
+ {
+ if (compare)
+ error_at (cloc, "too many %qs clauses", "compare");
+ else
+ compare = true;
+ }
+ else if (new_weak)
+ {
+ if (weak)
+ error_at (cloc, "too many %qs clauses", "weak");
+ else
+ weak = true;
+ }
c_parser_consume_token (parser);
continue;
}
@@ -17711,6 +18068,30 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
+ if (capture)
+ {
+ if (code != OMP_ATOMIC)
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "capture");
+ else
+ code = OMP_ATOMIC_CAPTURE_NEW;
+ }
+ if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "compare");
+ compare = false;
+ }
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
+ fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ }
+ if (weak && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
+ weak = false;
+ }
if (openacc)
memory_order = OMP_MEMORY_ORDER_RELAXED;
else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
@@ -17735,7 +18116,6 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- case OMP_ATOMIC:
memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
@@ -17751,36 +18131,32 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
switch (code)
{
case OMP_ATOMIC_READ:
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_RELEASE)
+ if (memory_order == OMP_MEMORY_ORDER_RELEASE)
{
error_at (loc, "%<#pragma omp atomic read%> incompatible with "
- "%<acq_rel%> or %<release%> clauses");
+ "%<release%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+ if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
{
error_at (loc, "%<#pragma omp atomic write%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- }
- 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)
- {
- error_at (loc, "%<#pragma omp atomic update%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
+ "%<acquire%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
break;
}
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ memory_order
+ = (enum omp_memory_order) (memory_order
+ | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
switch (code)
{
@@ -17829,6 +18205,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
c_parser_consume_token (parser);
structured_block = true;
}
+ else if (compare
+ && c_parser_next_token_is_keyword (parser, RID_IF))
+ break;
else
{
v = c_parser_cast_expression (parser, NULL).value;
@@ -17840,6 +18219,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
v = non_lvalue (v);
if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
goto saw_error;
+ if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
+ {
+ eloc = c_parser_peek_token (parser)->location;
+ error_at (eloc, "expected expression");
+ goto saw_error;
+ }
}
break;
default:
@@ -17849,6 +18234,179 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
/* For structured_block case we don't know yet whether
old or new x should be captured. */
restart:
+ if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
+ {
+ c_parser_consume_token (parser);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ goto saw_error;
+ eloc = c_parser_peek_token (parser)->location;
+ c_expr cmp_expr;
+ if (r)
+ {
+ cmp_expr = c_parser_cast_expression (parser, NULL);
+ cmp_expr = default_function_array_conversion (eloc, cmp_expr);
+ }
+ else
+ cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
+ parens.skip_until_found_close (parser);
+ if (cmp_expr.value == error_mark_node)
+ goto saw_error;
+ if (r)
+ {
+ if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
+ goto bad_if;
+ cmp_expr.value = rhs1;
+ rhs1 = NULL_TREE;
+ gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
+ }
+ if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ ;
+ else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
+ "expected %<==%> comparison in %<if%> condition");
+ goto saw_error;
+ }
+ else if (TREE_CODE (cmp_expr.value) != GT_EXPR
+ && TREE_CODE (cmp_expr.value) != LT_EXPR)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
+ "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
+ "condition");
+ goto saw_error;
+ }
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ goto saw_error;
+
+ extra_scope = true;
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_cast_expression (parser, NULL);
+ lhs = expr.value;
+ expr = default_function_array_conversion (eloc, expr);
+ unfolded_lhs = expr.value;
+ lhs = c_fully_fold (lhs, false, NULL, true);
+ orig_lhs = lhs;
+ if (lhs == error_mark_node)
+ goto saw_error;
+ if (!lvalue_p (unfolded_lhs))
+ lhs = non_lvalue (lhs);
+ if (!c_parser_next_token_is (parser, CPP_EQ))
+ {
+ c_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
+ c_parser_consume_token (parser);
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ rhs1 = expr.value;
+
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ goto saw_error;
+
+ if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ goto saw_error;
+
+ extra_scope = false;
+ no_semicolon = true;
+
+ if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
+ {
+ if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
+ false, NULL, true);
+ rhs1 = c_fully_fold (rhs1, false, NULL, true);
+ }
+ else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
+ ? MIN_EXPR : MAX_EXPR);
+ rhs = c_fully_fold (rhs1, false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
+ false, NULL, true);
+ }
+ else
+ goto bad_if;
+ }
+ else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
+ goto bad_if;
+ else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
+ && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
+ ? MAX_EXPR : MIN_EXPR);
+ rhs = c_fully_fold (rhs1, false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
+ false, NULL, true);
+ }
+ else
+ {
+ bad_if:
+ c_parser_error (parser,
+ "invalid form of %<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ {
+ if (code != OMP_ATOMIC_CAPTURE_NEW
+ || (structured_block && r == NULL_TREE)
+ || TREE_CODE (cmp_expr.value) != EQ_EXPR)
+ {
+ eloc = c_parser_peek_token (parser)->location;
+ error_at (eloc, "unexpected %<else%>");
+ goto saw_error;
+ }
+
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ goto saw_error;
+
+ extra_scope = true;
+ v = c_parser_cast_expression (parser, NULL).value;
+ non_lvalue_p = !lvalue_p (v);
+ v = c_fully_fold (v, false, NULL, true);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (non_lvalue_p)
+ v = non_lvalue (v);
+ if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+ goto saw_error;
+
+ expr = c_parser_expr_no_commas (parser, NULL);
+
+ if (!c_tree_equal (expr.value, unfolded_lhs))
+ goto bad_if;
+
+ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ goto saw_error;
+
+ if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ goto saw_error;
+
+ extra_scope = false;
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ if (r == NULL_TREE)
+ /* Signal to c_finish_omp_atomic that in
+ if (x == e) { x = d; } else { v = x; }
+ case the store to v should be conditional. */
+ r = void_list_node;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+ {
+ c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
+ goto saw_error;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW
+ && r != NULL_TREE
+ && v == NULL_TREE)
+ code = OMP_ATOMIC;
+ goto stmt_done;
+ }
eloc = c_parser_peek_token (parser)->location;
expr = c_parser_cast_expression (parser, NULL);
lhs = expr.value;
@@ -17858,9 +18416,14 @@ restart:
orig_lhs = lhs;
switch (TREE_CODE (lhs))
{
+ invalid_compare:
+ error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
+ /* FALLTHRU */
case ERROR_MARK:
saw_error:
c_parser_skip_to_end_of_block_or_statement (parser);
+ if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ c_parser_consume_token (parser);
if (structured_block)
{
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -17883,6 +18446,8 @@ restart:
unfolded_lhs = NULL_TREE;
opcode = PLUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case POSTDECREMENT_EXPR:
@@ -17894,6 +18459,8 @@ restart:
unfolded_lhs = NULL_TREE;
opcode = MINUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case COMPOUND_EXPR:
@@ -17923,6 +18490,8 @@ restart:
&& !structured_block
&& TREE_CODE (orig_lhs) == COMPOUND_EXPR)
code = OMP_ATOMIC_CAPTURE_OLD;
+ if (compare)
+ goto invalid_compare;
break;
}
if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
@@ -17938,6 +18507,8 @@ restart:
&& !structured_block
&& TREE_CODE (orig_lhs) == COMPOUND_EXPR)
code = OMP_ATOMIC_CAPTURE_OLD;
+ if (compare)
+ goto invalid_compare;
break;
}
}
@@ -17945,6 +18516,11 @@ restart:
default:
if (!lvalue_p (unfolded_lhs))
lhs = non_lvalue (lhs);
+ if (compare && !c_parser_next_token_is (parser, CPP_EQ))
+ {
+ c_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
switch (c_parser_peek_token (parser)->type)
{
case CPP_MULT_EQ:
@@ -17991,6 +18567,8 @@ restart:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
+ if (compare)
+ break;
if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
{
opcode = TREE_CODE (rhs1);
@@ -18011,6 +18589,78 @@ restart:
goto stmt_done;
}
break;
+ case COND_EXPR:
+ if (!compare)
+ break;
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
+ break;
+ if (!TREE_OPERAND (rhs1, 1))
+ break;
+ if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
+ break;
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
+ unfolded_lhs))
+ {
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 1),
+ false, NULL, true);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
+ NULL, true);
+ goto stmt_done;
+ }
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
+ TREE_OPERAND (rhs1, 1)))
+ {
+ opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
+ ? MIN_EXPR : MAX_EXPR);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 0),
+ false, NULL, true);
+ goto stmt_done;
+ }
+ }
+ else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
+ break;
+ else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
+ unfolded_lhs))
+ {
+ if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
+ TREE_OPERAND (rhs1, 1)))
+ {
+ opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
+ ? MAX_EXPR : MIN_EXPR);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
+ 0), 1),
+ false, NULL, true);
+ goto stmt_done;
+ }
+ }
+ break;
+ case EQ_EXPR:
+ if (!compare
+ || code != OMP_ATOMIC_CAPTURE_NEW
+ || !structured_block
+ || v
+ || r)
+ break;
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+ && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
+ {
+ r = lhs;
+ lhs = NULL_TREE;
+ c_parser_consume_token (parser);
+ goto restart;
+ }
+ break;
case ERROR_MARK:
goto saw_error;
default:
@@ -18030,7 +18680,7 @@ restart:
c_parser_consume_token (parser);
goto restart;
}
- if (structured_block)
+ if (structured_block && !compare)
{
opcode = NOP_EXPR;
expr = default_function_array_read_conversion (eloc, expr);
@@ -18059,10 +18709,12 @@ restart:
break;
}
stmt_done:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
{
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ if (!no_semicolon
+ && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
goto saw_error;
+ no_semicolon = false;
v = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (v);
v = c_fully_fold (v, false, NULL, true);
@@ -18085,10 +18737,16 @@ stmt_done:
}
if (structured_block)
{
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ if (!no_semicolon)
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
}
done:
+ if (weak && opcode != COND_EXPR)
+ {
+ error_at (loc, "%<weak%> clause requires atomic equality comparison");
+ weak = false;
+ }
if (unfolded_lhs && unfolded_lhs1
&& !c_tree_equal (unfolded_lhs, unfolded_lhs1))
{
@@ -18097,12 +18755,12 @@ done:
stmt = error_mark_node;
}
else
- stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
- swapped, memory_order);
+ stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
+ swapped, memory_order, weak);
if (stmt != error_mark_node)
add_stmt (stmt);
- if (!structured_block)
+ if (!structured_block && !no_semicolon)
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
@@ -18289,7 +18947,9 @@ c_parser_omp_flush (c_parser *parser)
const char *p
= IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (!strcmp (p, "acq_rel"))
+ if (!strcmp (p, "seq_cst"))
+ mo = MEMMODEL_SEQ_CST;
+ else if (!strcmp (p, "acq_rel"))
mo = MEMMODEL_ACQ_REL;
else if (!strcmp (p, "release"))
mo = MEMMODEL_RELEASE;
@@ -18297,7 +18957,8 @@ c_parser_omp_flush (c_parser *parser)
mo = MEMMODEL_ACQUIRE;
else
error_at (c_parser_peek_token (parser)->location,
- "expected %<acq_rel%>, %<release%> or %<acquire%>");
+ "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
+ "%<acquire%>");
c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -18315,6 +18976,31 @@ c_parser_omp_flush (c_parser *parser)
c_finish_omp_flush (loc, mo);
}
+/* Parse an OpenMP structured block sequence. KIND is the corresponding
+ separating directive. */
+
+static tree
+c_parser_omp_structured_block_sequence (c_parser *parser,
+ enum pragma_kind kind)
+{
+ tree stmt = push_stmt_list ();
+ c_parser_statement (parser, NULL);
+ do
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ break;
+
+ if (kind != PRAGMA_NONE
+ && c_parser_peek_token (parser)->pragma_kind == kind)
+ break;
+ c_parser_statement (parser, NULL);
+ }
+ while (1);
+ return pop_stmt_list (stmt);
+}
+
/* OpenMP 5.0:
scan-loop-body:
@@ -18336,7 +19022,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
return;
}
- substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -18371,7 +19057,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
error ("expected %<#pragma omp scan%>");
clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
- substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -19199,6 +19885,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
section-directive[opt] structured-block
section-sequence section-directive structured-block
+ OpenMP 5.1 allows structured-block-sequence instead of structured-block.
+
SECTIONS_LOC is the location of the #pragma omp sections. */
static tree
@@ -19220,7 +19908,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
{
- substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = c_parser_omp_structured_block_sequence (parser,
+ PRAGMA_OMP_SECTION);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -19246,7 +19935,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
error_suppress = true;
}
- substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = c_parser_omp_structured_block_sequence (parser,
+ PRAGMA_OMP_SECTION);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -19750,7 +20440,8 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
| (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))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
c_parser_omp_distribute (location_t loc, c_parser *parser,
@@ -21003,7 +21694,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
tree ctx = c_parser_omp_context_selector_specification (parser, parms);
if (ctx == error_mark_node)
goto fail;
- ctx = c_omp_check_context_selector (match_loc, ctx);
+ ctx = omp_check_context_selector (match_loc, ctx);
if (ctx != error_mark_node && variant != error_mark_node)
{
if (TREE_CODE (variant) != FUNCTION_DECL)
@@ -21033,7 +21724,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
{
C_DECL_USED (variant) = 1;
tree construct = omp_get_context_selector (ctx, "construct", NULL);
- c_omp_mark_declare_variant (match_loc, variant, construct);
+ omp_mark_declare_variant (match_loc, variant, construct);
if (omp_context_selector_matches (ctx))
{
tree attr
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index a8a90ea..a046c6b 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -370,6 +370,8 @@ struct c_declspecs {
BOOL_BITFIELD explicit_signed_p : 1;
/* Whether the specifiers include a deprecated typedef. */
BOOL_BITFIELD deprecated_p : 1;
+ /* Whether the specifiers include an unavailable typedef. */
+ BOOL_BITFIELD unavailable_p : 1;
/* Whether the type defaulted to "int" because there were no type
specifiers. */
BOOL_BITFIELD default_int_p : 1;
@@ -744,7 +746,7 @@ extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
-extern tree c_finish_goto_ptr (location_t, tree);
+extern tree c_finish_goto_ptr (location_t, c_expr val);
extern tree c_expr_to_decl (tree, bool *, bool *);
extern tree c_finish_omp_construct (location_t, enum tree_code, tree, tree);
extern tree c_finish_oacc_data (location_t, tree, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index d9f26d6..0aac978 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2558,7 +2558,9 @@ build_component_ref (location_t loc, tree datum, tree component,
|| (use_datum_quals && TREE_THIS_VOLATILE (datum)))
TREE_THIS_VOLATILE (ref) = 1;
- if (TREE_DEPRECATED (subdatum))
+ if (TREE_UNAVAILABLE (subdatum))
+ error_unavailable_use (subdatum, NULL_TREE);
+ else if (TREE_DEPRECATED (subdatum))
warn_deprecated_use (subdatum, NULL_TREE);
datum = ref;
@@ -2843,7 +2845,9 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
- if (TREE_DEPRECATED (ref))
+ if (TREE_UNAVAILABLE (ref))
+ error_unavailable_use (ref, NULL_TREE);
+ else if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref, NULL_TREE);
/* Recursive call does not count as usage. */
@@ -3936,7 +3940,14 @@ parser_build_binary_op (location_t location, enum tree_code code,
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
warning_at (location, OPT_Waddress,
- "comparison with string literal results in unspecified behavior");
+ "comparison with string literal results in unspecified "
+ "behavior");
+
+ if (warn_array_compare
+ && TREE_CODE_CLASS (code) == tcc_comparison
+ && TREE_CODE (type1) == ARRAY_TYPE
+ && TREE_CODE (type2) == ARRAY_TYPE)
+ do_warn_array_compare (location, code, arg1.value, arg2.value);
if (TREE_OVERFLOW_P (result.value)
&& !TREE_OVERFLOW_P (arg1.value)
@@ -4957,6 +4968,10 @@ lvalue_p (const_tree ref)
case STRING_CST:
return true;
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+ here as well. */
case INDIRECT_REF:
case ARRAY_REF:
case VAR_DECL:
@@ -10779,10 +10794,19 @@ c_finish_goto_label (location_t loc, tree label)
the GOTO. */
tree
-c_finish_goto_ptr (location_t loc, tree expr)
+c_finish_goto_ptr (location_t loc, c_expr val)
{
+ tree expr = val.value;
tree t;
pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
+ if (expr != error_mark_node
+ && !POINTER_TYPE_P (TREE_TYPE (expr))
+ && !null_pointer_constant_p (expr))
+ {
+ error_at (val.get_location (),
+ "computed goto must be pointer type");
+ expr = build_zero_cst (ptr_type_node);
+ }
expr = c_fully_fold (expr, false, NULL);
expr = convert (ptr_type_node, expr);
t = build1 (GOTO_EXPR, void_type_node, expr);
@@ -11541,6 +11565,110 @@ build_vec_cmp (tree_code code, tree type,
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
+/* Possibly warn about an address of OP never being NULL in a comparison
+ operation CODE involving null. */
+
+static void
+maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
+{
+ if (!warn_address || warning_suppressed_p (op, OPT_Waddress))
+ return;
+
+ if (TREE_CODE (op) == NOP_EXPR)
+ {
+ /* Allow casts to intptr_t to suppress the warning. */
+ tree type = TREE_TYPE (op);
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ return;
+ op = TREE_OPERAND (op, 0);
+ }
+
+ if (TREE_CODE (op) == POINTER_PLUS_EXPR)
+ {
+ /* Allow a cast to void* to suppress the warning. */
+ tree type = TREE_TYPE (TREE_TYPE (op));
+ if (VOID_TYPE_P (type))
+ return;
+
+ /* Adding any value to a null pointer, including zero, is undefined
+ in C. This includes the expression &p[0] where p is the null
+ pointer, although &p[0] will have been folded to p by this point
+ and so not diagnosed. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the pointer operand in %qE must not be NULL",
+ op);
+
+ return;
+ }
+
+ if (TREE_CODE (op) != ADDR_EXPR)
+ return;
+
+ op = TREE_OPERAND (op, 0);
+
+ if (TREE_CODE (op) == IMAGPART_EXPR
+ || TREE_CODE (op) == REALPART_EXPR)
+ {
+ /* The address of either complex part may not be null. */
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+ return;
+ }
+
+ /* Set to true in the loop below if OP dereferences is operand.
+ In such a case the ultimate target need not be a decl for
+ the null [in]equality test to be constant. */
+ bool deref = false;
+
+ /* Get the outermost array or object, or member. */
+ while (handled_component_p (op))
+ {
+ if (TREE_CODE (op) == COMPONENT_REF)
+ {
+ /* Get the member (its address is never null). */
+ op = TREE_OPERAND (op, 1);
+ break;
+ }
+
+ /* Get the outer array/object to refer to in the warning. */
+ op = TREE_OPERAND (op, 0);
+ deref = true;
+ }
+
+ if ((!deref && !decl_with_nonnull_addr_p (op))
+ || from_macro_expansion_at (loc))
+ return;
+
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qE will never be NULL",
+ op);
+ else
+ warning_at (loc, OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qE will never be NULL",
+ op);
+
+ if (DECL_P (op))
+ inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
@@ -12176,44 +12304,12 @@ build_binary_op (location_t location, enum tree_code code,
short_compare = 1;
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
- if (TREE_CODE (op0) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
- }
+ maybe_warn_for_null_address (location, op0, code);
result_type = type0;
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
- if (TREE_CODE (op1) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))
- && !from_macro_expansion_at (location))
- {
- if (code == EQ_EXPR)
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<false%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- else
- warning_at (location,
- OPT_Waddress,
- "the comparison will always evaluate as %<true%> "
- "for the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
- }
+ maybe_warn_for_null_address (location, op1, code);
result_type = type1;
}
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
@@ -12422,6 +12518,13 @@ build_binary_op (location_t location, enum tree_code code,
maybe_warn_bool_compare (location, code, orig_op0, orig_op1);
break;
+ case MIN_EXPR:
+ case MAX_EXPR:
+ /* Used for OpenMP atomics. */
+ gcc_assert (flag_openmp);
+ common = 1;
+ break;
+
default:
gcc_unreachable ();
}
@@ -12713,7 +12816,9 @@ build_binary_op (location_t location, enum tree_code code,
}
if (sanitize_flags_p ((SANITIZE_SHIFT
- | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
&& current_function_decl != NULL_TREE
&& (doing_div_or_mod || doing_shift)
&& !require_constant_value)
@@ -12724,7 +12829,8 @@ build_binary_op (location_t location, enum tree_code code,
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
if (doing_div_or_mod && (sanitize_flags_p ((SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE))))
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))))
instrument_expr = ubsan_instrument_division (location, op0, op1);
else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index c8d9db6..f3d9935 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1622,16 +1622,20 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
tree val = c_parser_gimple_postfix_expression (parser).value;
if (! val
|| val == error_mark_node
- || (!CONSTANT_CLASS_P (val)
- && !(addr_p
- && (TREE_CODE (val) == STRING_CST
- || DECL_P (val)))))
+ || (!CONSTANT_CLASS_P (val) && !addr_p))
{
c_parser_error (parser, "invalid _Literal");
return expr;
}
if (addr_p)
- val = build1 (ADDR_EXPR, type, val);
+ {
+ val = build1 (ADDR_EXPR, type, val);
+ if (!is_gimple_invariant_address (val))
+ {
+ c_parser_error (parser, "invalid _Literal");
+ return expr;
+ }
+ }
if (neg_p)
{
val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);
@@ -1813,6 +1817,14 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
case CPP_DEREF:
{
/* Structure element reference. */
+ if (!POINTER_TYPE_P (TREE_TYPE (expr.value)))
+ {
+ c_parser_error (parser, "dereference of non-pointer");
+ expr.set_error ();
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ return expr;
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 7b1e1ba..82fc505 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -3239,7 +3239,8 @@ pass_jump::execute (function *)
if (dump_file)
dump_flow_info (dump_file, dump_flags);
cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+ | (flag_thread_jumps && flag_expensive_optimizations
+ ? CLEANUP_THREADING : 0));
return 0;
}
@@ -3274,7 +3275,10 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *) { return flag_thread_jumps; }
+ virtual bool gate (function *)
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
virtual unsigned int execute (function *);
}; // class pass_jump_after_combine
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 50b9b17..6446e16 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -161,6 +161,12 @@ verify_flow_info (void)
err = 1;
}
+ if (bb->flags & ~cfun->cfg->bb_flags_allocated)
+ {
+ error ("verify_flow_info: unallocated flag set on BB %d", bb->index);
+ err = 1;
+ }
+
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (last_visited [e->dest->index] == bb)
@@ -202,6 +208,13 @@ verify_flow_info (void)
err = 1;
}
+ if (e->flags & ~cfun->cfg->edge_flags_allocated)
+ {
+ error ("verify_flow_info: unallocated edge flag set on %d -> %d",
+ e->src->index, e->dest->index);
+ err = 1;
+ }
+
edge_checksum[e->dest->index] += (size_t) e;
}
if (n_fallthru > 1)
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 8f3af00..de07865 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2236,7 +2236,7 @@ cgraph_node::dump (FILE *f)
}
fprintf (f, "\n");
- if (count.ipa ().initialized_p ())
+ if (!body_removed && count.ipa ().initialized_p ())
{
bool ok = true;
bool min = false;
@@ -2245,7 +2245,7 @@ cgraph_node::dump (FILE *f)
FOR_EACH_ALIAS (this, ref)
if (dyn_cast <cgraph_node *> (ref->referring)->count.initialized_p ())
sum += dyn_cast <cgraph_node *> (ref->referring)->count.ipa ();
-
+
if (inlined_to
|| (symtab->state < EXPANSION
&& ultimate_alias_target () == this && only_called_directly_p ()))
diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c
index 6b5d61d..19423d3 100644
--- a/gcc/collect-utils.c
+++ b/gcc/collect-utils.c
@@ -57,6 +57,43 @@ fatal_signal (int signum)
so its normal effect occurs. */
kill (getpid (), signum);
}
+
+/* Setup the signal handlers for the utils. */
+void
+setup_signals (void)
+{
+#ifdef SIGQUIT
+ if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
+ signal (SIGQUIT, fatal_signal);
+#endif
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN)
+ signal (SIGINT, fatal_signal);
+#ifdef SIGALRM
+ if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
+ signal (SIGALRM, fatal_signal);
+#endif
+#ifdef SIGHUP
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
+ signal (SIGHUP, fatal_signal);
+#endif
+ if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
+ signal (SIGSEGV, fatal_signal);
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
+ signal (SIGTERM, fatal_signal);
+#ifdef SIGPIPE
+ if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
+ signal (SIGPIPE, fatal_signal);
+#endif
+#ifdef SIGBUS
+ if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
+ signal (SIGBUS, fatal_signal);
+#endif
+#ifdef SIGCHLD
+ /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+ receive the signal. A different setting is inheritable */
+ signal (SIGCHLD, SIG_DFL);
+#endif
+}
/* Wait for a process to finish, and exit if a nonzero status is found. */
diff --git a/gcc/collect-utils.h b/gcc/collect-utils.h
index 4f0e3ce..15f831d 100644
--- a/gcc/collect-utils.h
+++ b/gcc/collect-utils.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
extern void notice (const char *, ...)
__attribute__ ((format (printf, 1, 2)));
extern void fatal_signal (int);
+extern void setup_signals (void);
extern struct pex_obj *collect_execute (const char *, char **,
const char *, const char *,
diff --git a/gcc/collect2.c b/gcc/collect2.c
index 07092c2..d47fe3f 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -301,7 +301,6 @@ const char tool_name[] = "collect2";
static symkind is_ctor_dtor (const char *);
-static void handler (int);
static void maybe_unlink_list (char **);
static void add_to_list (struct head *, const char *);
static int extract_init_priority (const char *);
@@ -408,14 +407,6 @@ collect_atexit (void)
tool_cleanup (false);
}
-static void
-handler (int signo)
-{
- tool_cleanup (true);
-
- signal (signo, SIG_DFL);
- raise (signo);
-}
/* Notify user of a non-error, without translating the format string. */
void
notice_translated (const char *cmsgid, ...)
@@ -907,11 +898,7 @@ main (int argc, char **argv)
COLLECT2_HOST_INITIALIZATION;
#endif
-#ifdef SIGCHLD
- /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
- receive the signal. A different setting is inheritable */
- signal (SIGCHLD, SIG_DFL);
-#endif
+ setup_signals ();
/* Unlock the stdio streams. */
unlock_std_streams ();
@@ -1051,27 +1038,6 @@ main (int argc, char **argv)
if (argc < 2)
fatal_error (input_location, "no arguments");
-#ifdef SIGQUIT
- if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
- signal (SIGQUIT, handler);
-#endif
- if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- signal (SIGINT, handler);
-#ifdef SIGALRM
- if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
- signal (SIGALRM, handler);
-#endif
-#ifdef SIGHUP
- if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, handler);
-#endif
- if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
- signal (SIGSEGV, handler);
-#ifdef SIGBUS
- if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
- signal (SIGBUS, handler);
-#endif
-
/* Extract COMPILER_PATH and PATH into our prefix list. */
prefix_from_env ("COMPILER_PATH", &cpath);
prefix_from_env ("PATH", &path);
@@ -2333,10 +2299,15 @@ is_lto_object_file (const char *prog_name)
LTO_SEGMENT_NAME,
&errmsg, &err);
if (!inobj)
- return false;
+ {
+ close (infd);
+ return false;
+ }
errmsg = simple_object_find_sections (inobj, has_lto_section,
(void *) &found, &err);
+ simple_object_release_read (inobj);
+ close (infd);
if (! errmsg && found)
return true;
diff --git a/gcc/combine.c b/gcc/combine.c
index cb5fa40..03e9a78 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -3063,6 +3063,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
return 0;
}
+ /* We cannot safely duplicate volatile references in any case. */
+
+ if ((added_sets_2 && volatile_refs_p (PATTERN (i2)))
+ || (added_sets_1 && volatile_refs_p (PATTERN (i1)))
+ || (added_sets_0 && volatile_refs_p (PATTERN (i0))))
+ {
+ undo_all ();
+ return 0;
+ }
+
/* Count how many auto_inc expressions there were in the original insns;
we need to have the same number in the resulting patterns. */
@@ -5903,7 +5913,8 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
if (HWI_COMPUTABLE_MODE_P (mode)
&& (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
&& (temp = get_last_value (XEXP (x, 0)))
- && COMPARISON_P (temp))
+ && COMPARISON_P (temp)
+ && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (XEXP (x, 0))))
return gen_lowpart (mode, XEXP (x, 0));
break;
@@ -11556,7 +11567,27 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
bool changed = false;
if (GET_CODE (pat) == SET)
- changed = change_zero_ext (pat);
+ {
+ /* For an unrecognized single set of a constant, try placing it in
+ the constant pool, if this function already uses one. */
+ rtx src = SET_SRC (pat);
+ if (CONSTANT_P (src)
+ && !CONST_INT_P (src)
+ && crtl->uses_const_pool)
+ {
+ machine_mode mode = GET_MODE (src);
+ if (mode == VOIDmode)
+ mode = GET_MODE (SET_DEST (pat));
+ src = force_const_mem (mode, src);
+ if (src)
+ {
+ SUBST (SET_SRC (pat), src);
+ changed = true;
+ }
+ }
+ else
+ changed = change_zero_ext (pat);
+ }
else if (GET_CODE (pat) == PARALLEL)
{
int i;
diff --git a/gcc/common.opt b/gcc/common.opt
index ed8ab5f..a2af7fb 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -59,6 +59,9 @@ enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE
Variable
int flag_complex_method = 1
+Variable
+int flag_default_complex_method = 1
+
; Language specific warning pass for unused results.
Variable
bool flag_warn_unused_result = false
@@ -1509,7 +1512,7 @@ Common Var(flag_emit_class_debug_always) Init(0)
Do not suppress C++ class debug information.
fexceptions
-Common Var(flag_exceptions) Optimization
+Common Var(flag_exceptions) Optimization EnabledBy(fnon-call-exceptions)
Enable exception handling.
fexpensive-optimizations
@@ -1518,7 +1521,7 @@ Perform a number of minor, expensive optimizations.
fexcess-precision=
Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision) Init(EXCESS_PRECISION_DEFAULT) Optimization SetByCombined
--fexcess-precision=[fast|standard] Specify handling of excess floating-point precision.
+-fexcess-precision=[fast|standard|16] Specify handling of excess floating-point precision.
Enum
Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
@@ -1529,6 +1532,9 @@ Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
EnumValue
Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
+EnumValue
+Enum(excess_precision) String(16) Value(EXCESS_PRECISION_FLOAT16)
+
; Whether we permit the extended set of values for FLT_EVAL_METHOD
; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
fpermitted-flt-eval-methods=
@@ -1917,7 +1923,7 @@ EnumValue
Enum(ira_algorithm) String(priority) Value(IRA_ALGORITHM_PRIORITY)
fira-region=
-Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_AUTODETECT) Optimization
+Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_ONE) Optimization
-fira-region=[one|all|mixed] Set regions for IRA.
Enum
@@ -2393,7 +2399,7 @@ Common Var(flag_live_range_shrinkage) Init(0) Optimization
Relief of register pressure through live range shrinkage.
frename-registers
-Common Var(flag_rename_registers) Init(2) Optimization
+Common Var(flag_rename_registers) Optimization EnabledBy(funroll-loops)
Perform a register renaming optimization pass.
fschedule-fusion
@@ -2791,7 +2797,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-cselim
-Common Var(flag_tree_cselim) Init(2) Optimization
+Common Var(flag_tree_cselim) Optimization
Transform condition stores into unconditional ones.
ftree-switch-conversion
@@ -2929,7 +2935,7 @@ Common Var(flag_unit_at_a_time) Init(1)
Compile whole compilation unit at a time.
funroll-loops
-Common Var(flag_unroll_loops) Optimization
+Common Var(flag_unroll_loops) Optimization EnabledBy(funroll-all-loops)
Perform loop unrolling when iteration count is known.
funroll-all-loops
@@ -2997,19 +3003,16 @@ Common Undocumented Var(flag_use_linker_plugin)
; Positive if we should track variables, negative if we should run
; the var-tracking pass only to discard debug annotations, zero if
-; we're not to run it. When flag_var_tracking == 2 (AUTODETECT_VALUE) it
-; will be set according to optimize, debug_info_level and debug_hooks
-; in process_options ().
+; we're not to run it.
fvar-tracking
-Common Var(flag_var_tracking) Init(2) PerFunction
+Common Var(flag_var_tracking) PerFunction EnabledBy(fvar-tracking-uninit)
Perform variable tracking.
; Positive if we should track variables at assignments, negative if
; we should run the var-tracking pass only to discard debug
-; annotations. When flag_var_tracking_assignments ==
-; AUTODETECT_VALUE it will be set according to flag_var_tracking.
+; annotations.
fvar-tracking-assignments
-Common Var(flag_var_tracking_assignments) Init(2) PerFunction
+Common Var(flag_var_tracking_assignments) PerFunction
Perform variable tracking by annotating assignments.
; Nonzero if we should toggle flag_var_tracking_assignments after
@@ -3020,15 +3023,14 @@ Toggle -fvar-tracking-assignments.
; Positive if we should track uninitialized variables, negative if
; we should run the var-tracking pass only to discard debug
-; annotations. When flag_var_tracking_uninit == AUTODETECT_VALUE it
-; will be set according to flag_var_tracking.
+; annotations.
fvar-tracking-uninit
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 Optimization
+Common Var(flag_tree_vectorize) Optimization
Enable vectorization on trees.
ftree-vectorizer-verbose=
@@ -3078,6 +3080,22 @@ ftree-scev-cprop
Common Var(flag_tree_scev_cprop) Init(1) Optimization
Enable copy propagation of scalar-evolution information.
+ftrivial-auto-var-init=
+Common Joined RejectNegative Enum(auto_init_type) Var(flag_auto_var_init) Init(AUTO_INIT_UNINITIALIZED) Optimization
+-ftrivial-auto-var-init=[uninitialized|pattern|zero] Add initializations to automatic variables.
+
+Enum
+Name(auto_init_type) Type(enum auto_init_type) UnknownError(unrecognized automatic variable initialization type %qs)
+
+EnumValue
+Enum(auto_init_type) String(uninitialized) Value(AUTO_INIT_UNINITIALIZED)
+
+EnumValue
+Enum(auto_init_type) String(pattern) Value(AUTO_INIT_PATTERN)
+
+EnumValue
+Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
+
; -fverbose-asm causes extra commentary information to be produced in
; the generated assembly code (to make it more readable). This option
; is generally only of use to those who actually need to read the
@@ -3136,7 +3154,7 @@ Common Var(flag_value_profile_transformations) Optimization
Use expression value profiles in optimizations.
fweb
-Common Var(flag_web) Init(2) Optimization
+Common Var(flag_web) Optimization EnabledBy(funroll-loops)
Construct webs and split unrelated uses of single variable.
ftree-builtin-call-dce
@@ -3168,11 +3186,11 @@ Common Driver RejectNegative JoinedOrMissing
Generate debug information in default format.
gas-loc-support
-Common Driver Var(dwarf2out_as_loc_support) Init(2)
+Common Driver Var(dwarf2out_as_loc_support)
Assume assembler support for (DWARF2+) .loc directives.
gas-locview-support
-Common Driver Var(dwarf2out_as_locview_support) Init(2)
+Common Driver Var(dwarf2out_as_locview_support)
Assume assembler support for view in (DWARF2+) .loc directives.
gcoff
@@ -3226,7 +3244,7 @@ Common Driver JoinedOrMissing
Generate debug information in default extended format.
ginline-points
-Common Driver Var(debug_inline_points) Init(2)
+Common Driver Var(debug_inline_points)
Generate extended entry point information for inlined functions.
ginternal-reset-location-views
@@ -3266,7 +3284,7 @@ Common Driver JoinedOrMissing Negative(gvms)
Generate debug information in extended STABS format.
gstatement-frontiers
-Common Driver Var(debug_nonbind_markers_p) Init(2)
+Common Driver Var(debug_nonbind_markers_p)
Emit progressive recommended breakpoint locations.
gstrict-dwarf
@@ -3282,7 +3300,7 @@ Common Driver Var(flag_gtoggle)
Toggle debug information generation.
gvariable-location-views
-Common Driver Var(debug_variable_location_views, 1) Init(2)
+Common Driver Var(debug_variable_location_views, 1)
Augment variable location lists with progressive views.
gvariable-location-views=incompat5
diff --git a/gcc/common/config/arm/arm-common.c b/gcc/common/config/arm/arm-common.c
index 481aa9e..de898a7 100644
--- a/gcc/common/config/arm/arm-common.c
+++ b/gcc/common/config/arm/arm-common.c
@@ -115,7 +115,12 @@ const char *
arm_rewrite_mcpu (int argc, const char **argv)
{
gcc_assert (argc);
+
+#ifdef HAVE_GAS_ARM_EXTENDED_ARCH
+ return argv[argc - 1];
+#else
return arm_rewrite_selected_cpu (argv[argc - 1]);
+#endif
}
/* Comparator for arm_rewrite_selected_arch. Compare the two arch extension
@@ -223,7 +228,12 @@ const char *
arm_rewrite_march (int argc, const char **argv)
{
gcc_assert (argc);
+
+#ifdef HAVE_GAS_ARM_EXTENDED_ARCH
+ return argv[argc - 1];
+#else
return arm_rewrite_selected_arch (argv[argc - 1]);
+#endif
}
#include "arm-cpu-cdata.h"
diff --git a/gcc/common/config/avr/avr-common.c b/gcc/common/config/avr/avr-common.c
index 6486659..a6939ad 100644
--- a/gcc/common/config/avr/avr-common.c
+++ b/gcc/common/config/avr/avr-common.c
@@ -77,7 +77,8 @@ static const struct default_options avr_option_optimization_table[] =
static bool
avr_handle_option (struct gcc_options *opts, struct gcc_options*,
- const struct cl_decoded_option *decoded, location_t loc)
+ const struct cl_decoded_option *decoded,
+ location_t loc ATTRIBUTE_UNUSED)
{
int value = decoded->value;
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
index 458f41d..bbf29bdb 100644
--- a/gcc/common/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -46,6 +46,10 @@ struct __processor_model2
# define CHECK___builtin_cpu_is(cpu)
#endif
+#ifndef CHECK___builtin_cpu_supports
+# define CHECK___builtin_cpu_supports(isa)
+#endif
+
/* Return non-zero if the processor has feature F. */
static inline int
@@ -731,6 +735,8 @@ get_available_features (struct __processor_model *cpu_model,
set_feature (FEATURE_AVX5124FMAPS);
if (edx & bit_AVX512VP2INTERSECT)
set_feature (FEATURE_AVX512VP2INTERSECT);
+ if (edx & bit_AVX512FP16)
+ set_feature (FEATURE_AVX512FP16);
}
__cpuid_count (7, 1, eax, ebx, ecx, edx);
@@ -931,6 +937,50 @@ cpu_indicator_init (struct __processor_model *cpu_model,
else
cpu_model->__cpu_vendor = VENDOR_OTHER;
+ if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2))
+ {
+ CHECK___builtin_cpu_supports ("x86-64");
+ set_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_X86_64_BASELINE);
+ if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2))
+ {
+ CHECK___builtin_cpu_supports ("x86-64-v2");
+ set_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_X86_64_V2);
+ if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C)
+ && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA)
+ && has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_LZCNT)
+ && has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_MOVBE))
+ {
+ CHECK___builtin_cpu_supports ("x86-64-v3");
+ set_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_X86_64_V3);
+ if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX512BW)
+ && has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX512CD)
+ && has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX512DQ)
+ && has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX512VL))
+ {
+ CHECK___builtin_cpu_supports ("x86-64-v4");
+ set_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_X86_64_V4);
+ }
+ }
+ }
+ }
+
gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 76ab1a1..2c9e1cc 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_AVX5124VNNIW_SET OPTION_MASK_ISA2_AVX5124VNNIW
#define OPTION_MASK_ISA_AVX512VBMI2_SET \
(OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512F_SET)
+#define OPTION_MASK_ISA_AVX512FP16_SET OPTION_MASK_ISA_AVX512BW_SET
+#define OPTION_MASK_ISA2_AVX512FP16_SET OPTION_MASK_ISA2_AVX512FP16
#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
@@ -231,6 +233,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_AVX5124FMAPS_UNSET OPTION_MASK_ISA2_AVX5124FMAPS
#define OPTION_MASK_ISA2_AVX5124VNNIW_UNSET OPTION_MASK_ISA2_AVX5124VNNIW
#define OPTION_MASK_ISA_AVX512VBMI2_UNSET OPTION_MASK_ISA_AVX512VBMI2
+#define OPTION_MASK_ISA_AVX512FP16_UNSET OPTION_MASK_ISA_AVX512BW_UNSET
+#define OPTION_MASK_ISA2_AVX512FP16_UNSET OPTION_MASK_ISA2_AVX512FP16
#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
@@ -313,7 +317,8 @@ along with GCC; see the file COPYING3. If not see
(OPTION_MASK_ISA2_AVX512BF16_UNSET \
| OPTION_MASK_ISA2_AVX5124FMAPS_UNSET \
| OPTION_MASK_ISA2_AVX5124VNNIW_UNSET \
- | OPTION_MASK_ISA2_AVX512VP2INTERSECT_UNSET)
+ | OPTION_MASK_ISA2_AVX512VP2INTERSECT_UNSET \
+ | OPTION_MASK_ISA2_AVX512FP16_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
@@ -326,7 +331,9 @@ along with GCC; see the file COPYING3. If not see
(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
+#define OPTION_MASK_ISA2_AVX512BW_UNSET \
+ (OPTION_MASK_ISA2_AVX512BF16_UNSET \
+ | OPTION_MASK_ISA2_AVX512FP16_UNSET)
/* Set 1 << value as value of -malign-FLAG option. */
@@ -853,6 +860,21 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_mavx512fp16:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVX512FP16_SET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512FP16_SET;
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512FP16_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512FP16_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512FP16_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512FP16_UNSET;
+ }
+ return true;
+
case OPT_mavx512vnni:
if (value)
{
@@ -1913,7 +1935,7 @@ const pta processor_alias_table[] =
M_CPU_TYPE (INTEL_GOLDMONT), P_PROC_SSE4_2},
{"goldmont-plus", PROCESSOR_GOLDMONT_PLUS, CPU_GLM, PTA_GOLDMONT_PLUS,
M_CPU_TYPE (INTEL_GOLDMONT_PLUS), P_PROC_SSE4_2},
- {"tremont", PROCESSOR_TREMONT, CPU_GLM, PTA_TREMONT,
+ {"tremont", PROCESSOR_TREMONT, CPU_HASWELL, PTA_TREMONT,
M_CPU_TYPE (INTEL_TREMONT), P_PROC_SSE4_2},
{"knl", PROCESSOR_KNL, CPU_SLM, PTA_KNL,
M_CPU_TYPE (INTEL_KNL), P_PROC_AVX512F},
diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
index e68dd65..dc1a9fa 100644
--- a/gcc/common/config/i386/i386-cpuinfo.h
+++ b/gcc/common/config/i386/i386-cpuinfo.h
@@ -102,6 +102,7 @@ enum feature_priority
P_MMX,
P_SSE,
P_SSE2,
+ P_X86_64_BASELINE,
P_SSE3,
P_SSSE3,
P_PROC_SSSE3,
@@ -111,6 +112,7 @@ enum feature_priority
P_SSE4_2,
P_PROC_SSE4_2,
P_POPCNT,
+ P_X86_64_V2,
P_AES,
P_PCLMUL,
P_AVX,
@@ -125,8 +127,10 @@ enum feature_priority
P_BMI2,
P_AVX2,
P_PROC_AVX2,
+ P_X86_64_V3,
P_AVX512F,
P_PROC_AVX512F,
+ P_X86_64_V4,
P_PROC_DYNAMIC
};
@@ -228,6 +232,11 @@ enum processor_features
FEATURE_AESKLE,
FEATURE_WIDEKL,
FEATURE_AVXVNNI,
+ FEATURE_AVX512FP16,
+ FEATURE_X86_64_BASELINE,
+ FEATURE_X86_64_V2,
+ FEATURE_X86_64_V3,
+ FEATURE_X86_64_V4,
CPU_FEATURE_MAX
};
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
index 898c18f..7784010 100644
--- a/gcc/common/config/i386/i386-isas.h
+++ b/gcc/common/config/i386/i386-isas.h
@@ -169,4 +169,10 @@ ISA_NAMES_TABLE_START
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_ENTRY("avx512fp16", FEATURE_AVX512FP16, P_NONE, "-mavx512fp16")
+ ISA_NAMES_TABLE_ENTRY("x86-64", FEATURE_X86_64_BASELINE, P_X86_64_BASELINE,
+ NULL)
+ ISA_NAMES_TABLE_ENTRY("x86-64-v2", FEATURE_X86_64_V2, P_X86_64_V2, NULL)
+ ISA_NAMES_TABLE_ENTRY("x86-64-v3", FEATURE_X86_64_V3, P_X86_64_V3, NULL)
+ ISA_NAMES_TABLE_ENTRY("x86-64-v4", FEATURE_X86_64_V4, P_X86_64_V4, NULL)
ISA_NAMES_TABLE_END
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0ff5cac..3675e06 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -249,6 +249,9 @@ md_file=
# Obsolete configurations.
case ${target} in
tile*-*-* \
+ | cr16-*-* \
+ | hppa[12]*-*-hpux10* \
+ | hppa[12]*-*-hpux11* \
)
if test "x$enable_obsolete" != xyes; then
echo "*** Configuration ${target} is obsolete." >&2
@@ -276,6 +279,9 @@ case ${target} in
| crisv32-*-* \
| i[34567]86-go32-* \
| i[34567]86-*-go32* \
+ | m32r-*-linux* \
+ | m32rle-*-linux* \
+ | m68k*-*-openbsd* \
| m68k-*-uclinuxoldabi* \
| mips64orion*-*-rtems* \
| pdp11-*-bsd \
@@ -416,7 +422,7 @@ i[34567]86-*-* | x86_64-*-*)
tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
amxbf16intrin.h x86gprintrin.h uintrintrin.h
hresetintrin.h keylockerintrin.h avxvnniintrin.h
- mwaitintrin.h"
+ mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h"
;;
ia64-*-*)
extra_headers=ia64intrin.h
@@ -660,6 +666,7 @@ case ${target} in
*-*-darwin*)
tmake_file="t-darwin "
tm_file="${tm_file} darwin.h"
+ tm_d_file="${tm_d_file} tm-dwarf2.h"
darwin_os=`echo ${target} | sed 's/.*darwin\([0-9.]*\).*$/\1/'`
darwin_maj=`expr "$darwin_os" : '\([0-9]*\).*'`
macos_min=`expr "$darwin_os" : '[0-9]*\.\([0-9]*\).*'`
@@ -1525,6 +1532,8 @@ bpf-*-*)
use_collect2=no
extra_headers="bpf-helpers.h"
use_gcc_stdint=provide
+ extra_objs="coreout.o"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/bpf/coreout.c"
;;
cr16-*-elf)
tm_file="elfos.h ${tm_file} newlib-stdint.h"
@@ -1532,7 +1541,7 @@ cr16-*-elf)
use_collect2=no
;;
cris-*-elf | cris-*-none)
- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
tmake_file="cris/t-cris cris/t-elfmulti"
gas=yes
extra_options="${extra_options} cris/elf.opt"
@@ -2293,26 +2302,10 @@ lm32-*-uclinux*)
tmake_file="${tmake_file} lm32/t-lm32"
;;
m32r-*-elf*)
- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
;;
m32rle-*-elf*)
- tm_file="dbxelf.h elfos.h newlib-stdint.h m32r/little.h ${tm_file}"
- ;;
-m32r-*-linux*)
- tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} m32r/linux.h"
- tmake_file="${tmake_file} m32r/t-linux t-slibgcc"
- gnu_ld=yes
- if test x$enable_threads = xyes; then
- thread_file='posix'
- fi
- ;;
-m32rle-*-linux*)
- tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h m32r/little.h ${tm_file} m32r/linux.h"
- tmake_file="${tmake_file} m32r/t-linux t-slibgcc"
- gnu_ld=yes
- if test x$enable_threads = xyes; then
- thread_file='posix'
- fi
+ tm_file="elfos.h newlib-stdint.h m32r/little.h ${tm_file}"
;;
m68k-*-elf* | fido-*-elf*)
case ${target} in
@@ -2352,17 +2345,6 @@ m68k*-*-netbsdelf*)
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
tm_defines="${tm_defines} MOTOROLA=1 CHAR_FAST8=1 SHORT_FAST16=1"
;;
-m68k*-*-openbsd*)
- default_m68k_cpu=68020
- default_cf_cpu=5475
- # needed to unconfuse gdb
- tm_defines="${tm_defines} OBSD_OLD_GAS"
- tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h m68k/openbsd.h"
- extra_options="${extra_options} openbsd.opt"
- tmake_file="t-openbsd m68k/t-openbsd"
- # we need collect2 until our bug is fixed...
- use_collect2=yes
- ;;
m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux
# with uClibc, using the new GNU/Linux-style
# ABI.
@@ -2512,7 +2494,7 @@ mips*-img-linux*)
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h"
extra_options="${extra_options} linux-android.opt"
tmake_file="${tmake_file} mips/t-img-linux"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=37 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
with_arch_32="mips32r6"
with_arch_64="mips64r6"
gnu_ld=yes
@@ -2522,7 +2504,7 @@ mips*-mti-linux*)
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h"
extra_options="${extra_options} linux-android.opt"
tmake_file="${tmake_file} mips/t-mti-linux"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
with_arch_32="mips32r2"
with_arch_64="mips64r2"
gnu_ld=yes
@@ -2553,16 +2535,30 @@ mips*-*-linux*) # Linux MIPS, either endian.
target_cpu_default=MASK_SOFT_FLOAT_ABI
enable_mips_multilibs="yes"
;;
+ mipsisa64r6*-*-linux-gnuabi64)
+ default_mips_abi=64
+ default_mips_arch=mips64r6
+ enable_mips_multilibs="yes"
+ ;;
mipsisa64r6*-*-linux*)
default_mips_abi=n32
default_mips_arch=mips64r6
enable_mips_multilibs="yes"
;;
+ mipsisa64r2*-*-linux-gnuabi64)
+ default_mips_abi=64
+ default_mips_arch=mips64r2
+ enable_mips_multilibs="yes"
+ ;;
mipsisa64r2*-*-linux*)
default_mips_abi=n32
default_mips_arch=mips64r2
enable_mips_multilibs="yes"
;;
+ mips64*-*-linux-gnuabi64 | mipsisa64*-*-linux-gnuabi64)
+ default_mips_abi=64
+ enable_mips_multilibs="yes"
+ ;;
mips64*-*-linux* | mipsisa64*-*-linux*)
default_mips_abi=n32
enable_mips_multilibs="yes"
@@ -2578,14 +2574,14 @@ mips*-*-linux*) # Linux MIPS, either endian.
mips*-mti-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h mips/sde.h mips/mti-elf.h"
tmake_file="mips/t-mti-elf"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
with_arch_32="mips32r2"
with_arch_64="mips64r2"
;;
mips*-img-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h mips/sde.h mips/mti-elf.h"
tmake_file="mips/t-img-elf"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=37 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
with_arch_32="mips32r6"
with_arch_64="mips64r6"
;;
@@ -2610,22 +2606,22 @@ mips*-sde-elf*)
esac
case ${target} in
mipsisa32r6*)
- tm_defines="MIPS_ISA_DEFAULT=37 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
;;
mipsisa32r2*)
- tm_defines="MIPS_ISA_DEFAULT=33 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
;;
mipsisa32*)
- tm_defines="MIPS_ISA_DEFAULT=32 MIPS_ABI_DEFAULT=ABI_32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32 MIPS_ABI_DEFAULT=ABI_32"
;;
mipsisa64r6*)
- tm_defines="MIPS_ISA_DEFAULT=69 MIPS_ABI_DEFAULT=ABI_N32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6 MIPS_ABI_DEFAULT=ABI_N32"
;;
mipsisa64r2*)
- tm_defines="MIPS_ISA_DEFAULT=65 MIPS_ABI_DEFAULT=ABI_N32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2 MIPS_ABI_DEFAULT=ABI_N32"
;;
mipsisa64*)
- tm_defines="MIPS_ISA_DEFAULT=64 MIPS_ABI_DEFAULT=ABI_N32"
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_ABI_DEFAULT=ABI_N32"
;;
esac
;;
@@ -2639,22 +2635,22 @@ mipsisa64r6-*-elf* | mipsisa64r6el-*-elf*)
tmake_file="mips/t-isa3264"
case ${target} in
mipsisa32r6*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=37"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6"
;;
mipsisa32r2*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2"
;;
mipsisa32*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32"
;;
mipsisa64r6*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=69"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6"
;;
mipsisa64r2*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=65"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2"
;;
mipsisa64*)
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=64"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64"
;;
esac
case ${target} in
@@ -2674,12 +2670,12 @@ mipsisa64r6-*-elf* | mipsisa64r6el-*-elf*)
mipsisa64sr71k-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
tmake_file=mips/t-sr71k
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sr71000\\\" MIPS_ABI_DEFAULT=ABI_EABI"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_CPU_STRING_DEFAULT=\\\"sr71000\\\" MIPS_ABI_DEFAULT=ABI_EABI"
;;
mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
tmake_file="mips/t-elf mips/t-sb1"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
;;
mips-*-elf* | mipsel-*-elf* | mipsr5900-*-elf* | mipsr5900el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
@@ -2688,12 +2684,12 @@ mips-*-elf* | mipsel-*-elf* | mipsr5900-*-elf* | mipsr5900el-*-elf*)
mips64r5900-*-elf* | mips64r5900el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h"
tmake_file="mips/t-elf"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_N32"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_N32"
;;
mips64-*-elf* | mips64el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
tmake_file="mips/t-elf"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_O64"
;;
mips64vr-*-elf* | mips64vrel-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/vr.h mips/elf.h"
@@ -2703,7 +2699,7 @@ mips64vr-*-elf* | mips64vrel-*-elf*)
mips64orion-*-elf* | mips64orionel-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elforion.h mips/elf.h"
tmake_file="mips/t-elf"
- tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_O64"
;;
mips*-*-rtems*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/rtems.h rtems.h"
@@ -2722,11 +2718,7 @@ mmix-knuth-mmixware)
use_gcc_stdint=wrap
;;
mn10300-*-*)
- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
- if test x$stabs = xyes
- then
- tm_file="${tm_file} dbx.h"
- fi
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
use_collect2=no
use_gcc_stdint=wrap
;;
@@ -3521,11 +3513,6 @@ vax-*-netbsdelf*)
extra_options="${extra_options} netbsd.opt netbsd-elf.opt vax/elf.opt"
tm_defines="${tm_defines} CHAR_FAST8=1 SHORT_FAST16=1"
;;
-vax-*-openbsd*)
- tm_file="vax/vax.h vax/openbsd1.h openbsd.h openbsd-stdint.h openbsd-libpthread.h vax/openbsd.h"
- extra_options="${extra_options} openbsd.opt"
- use_collect2=yes
- ;;
visium-*-elf*)
tm_file="dbxelf.h elfos.h ${tm_file} visium/elf.h newlib-stdint.h"
tmake_file="visium/t-visium visium/t-crtstuff"
@@ -3541,30 +3528,30 @@ xstormy16-*-elf)
tmake_file="stormy16/t-stormy16"
;;
xtensa*-*-elf*)
- tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h xtensa/elf.h"
+ tm_file="${tm_file} elfos.h newlib-stdint.h xtensa/elf.h"
extra_options="${extra_options} xtensa/elf.opt"
;;
xtensa*-*-linux*)
- tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/linux.h"
+ tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/linux.h"
tmake_file="${tmake_file} xtensa/t-xtensa"
;;
xtensa*-*-uclinux*)
- tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/uclinux.h"
+ tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/uclinux.h"
tmake_file="${tmake_file} xtensa/t-xtensa"
extra_options="${extra_options} xtensa/uclinux.opt"
;;
am33_2.0-*-linux*)
- tm_file="mn10300/mn10300.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h mn10300/linux.h"
+ tm_file="mn10300/mn10300.h elfos.h gnu-user.h linux.h glibc-stdint.h mn10300/linux.h"
gas=yes gnu_ld=yes
use_collect2=no
;;
m32c-*-rtems*)
- tm_file="dbxelf.h elfos.h ${tm_file} m32c/rtems.h rtems.h newlib-stdint.h"
+ tm_file="elfos.h ${tm_file} m32c/rtems.h rtems.h newlib-stdint.h"
c_target_objs="m32c-pragma.o"
cxx_target_objs="m32c-pragma.o"
;;
m32c-*-elf*)
- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
c_target_objs="m32c-pragma.o"
cxx_target_objs="m32c-pragma.o"
;;
@@ -5353,16 +5340,16 @@ case ${target} in
default_mips_abi=$with_abi
fi
case ${default_mips_arch} in
- mips1) tm_defines="$tm_defines MIPS_ISA_DEFAULT=1" ;;
- mips2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=2" ;;
- mips3) tm_defines="$tm_defines MIPS_ISA_DEFAULT=3" ;;
- mips4) tm_defines="$tm_defines MIPS_ISA_DEFAULT=4" ;;
- mips32) tm_defines="$tm_defines MIPS_ISA_DEFAULT=32" ;;
- mips32r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=33" ;;
- mips32r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=37" ;;
- mips64) tm_defines="$tm_defines MIPS_ISA_DEFAULT=64" ;;
- mips64r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=65" ;;
- mips64r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=69" ;;
+ mips1) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS1" ;;
+ mips2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS2" ;;
+ mips3) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3" ;;
+ mips4) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS4" ;;
+ mips32) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32" ;;
+ mips32r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2" ;;
+ mips32r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6" ;;
+ mips64) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64" ;;
+ mips64r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2" ;;
+ mips64r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6" ;;
esac
case ${default_mips_abi} in
32) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_32" ;;
diff --git a/gcc/config.in b/gcc/config.in
index d8a810b..b5bec39 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1331,6 +1331,13 @@
#endif
+/* Define if your Arm assembler permits context-specific feature extensions.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_ARM_EXTENDED_ARCH
+#endif
+
+
/* Define if your assembler supports .balign and .p2align. */
#ifndef USED_FOR_TARGET
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
@@ -1456,30 +1463,66 @@
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for fiji. */
+/* Define if your assembler expects amdgcn_target gfx908+xnack syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V3_SYNTAX
+#endif
+
+
+/* Define if your assembler expects amdgcn_target gfx908:xnack+ syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V4_SYNTAX
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for fiji. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_FIJI
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx900. */
+/* Define if your assembler allows -mattr=+sramecc for gfx900. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX900
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx906. */
+/* Define if your assembler allows -mattr=+sramecc for gfx906. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX906
#endif
-/* Define if your assembler allows -mattr=+sram-ecc for gfx908. */
+/* Define if your assembler allows -mattr=+sramecc for gfx908. */
#ifndef USED_FOR_TARGET
#undef HAVE_GCN_SRAM_ECC_GFX908
#endif
+/* Define if your assembler allows -mattr=+xnack for fiji. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_FIJI
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx900. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX900
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx906. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX906
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx908. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX908
+#endif
+
+
/* Define to 1 if you have the `getchar_unlocked' function. */
#ifndef USED_FOR_TARGET
#undef HAVE_GETCHAR_UNLOCKED
diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
index b749727..a3b32e0 100644
--- a/gcc/config/aarch64/aarch64-arches.def
+++ b/gcc/config/aarch64/aarch64-arches.def
@@ -37,6 +37,8 @@ AARCH64_ARCH("armv8.3-a", generic, 8_3A, 8, AARCH64_FL_FOR_ARCH8_3)
AARCH64_ARCH("armv8.4-a", generic, 8_4A, 8, AARCH64_FL_FOR_ARCH8_4)
AARCH64_ARCH("armv8.5-a", generic, 8_5A, 8, AARCH64_FL_FOR_ARCH8_5)
AARCH64_ARCH("armv8.6-a", generic, 8_6A, 8, AARCH64_FL_FOR_ARCH8_6)
+AARCH64_ARCH("armv8.7-a", generic, 8_7A, 8, AARCH64_FL_FOR_ARCH8_7)
AARCH64_ARCH("armv8-r", generic, 8R , 8, AARCH64_FL_FOR_ARCH8_R)
+AARCH64_ARCH("armv9-a", generic, 9A , 9, AARCH64_FL_FOR_ARCH9)
#undef AARCH64_ARCH
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index f6b41d9..1a507ea 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -29,6 +29,7 @@
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
+#include "ssa.h"
#include "memmodel.h"
#include "tm_p.h"
#include "expmed.h"
@@ -181,6 +182,10 @@ static enum aarch64_type_qualifiers
aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_poly, qualifier_poly, qualifier_poly };
#define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
+static enum aarch64_type_qualifiers
+aarch64_types_binop_ppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_poly, qualifier_poly, qualifier_unsigned };
+#define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
static enum aarch64_type_qualifiers
aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
@@ -206,6 +211,10 @@ aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
qualifier_unsigned, qualifier_immediate };
#define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
static enum aarch64_type_qualifiers
+aarch64_types_ternop_sssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_none, qualifier_none, qualifier_none, qualifier_unsigned };
+#define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
+static enum aarch64_type_qualifiers
aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
#define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
@@ -213,6 +222,10 @@ static enum aarch64_type_qualifiers
aarch64_types_ternop_suss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_unsigned, qualifier_none, qualifier_none };
#define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
+static enum aarch64_type_qualifiers
+aarch64_types_binop_pppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_unsigned };
+#define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
static enum aarch64_type_qualifiers
@@ -593,7 +606,7 @@ enum aarch64_simd_type
};
#undef ENTRY
-struct aarch64_simd_type_info
+struct GTY(()) aarch64_simd_type_info
{
enum aarch64_simd_type type;
@@ -625,14 +638,14 @@ struct aarch64_simd_type_info
#define ENTRY(E, M, Q, G) \
{E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
-static struct aarch64_simd_type_info aarch64_simd_types [] = {
+static GTY(()) struct aarch64_simd_type_info aarch64_simd_types [] = {
#include "aarch64-simd-builtin-types.def"
};
#undef ENTRY
-static tree aarch64_simd_intOI_type_node = NULL_TREE;
-static tree aarch64_simd_intCI_type_node = NULL_TREE;
-static tree aarch64_simd_intXI_type_node = NULL_TREE;
+static GTY(()) tree aarch64_simd_intOI_type_node = NULL_TREE;
+static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE;
+static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE;
/* The user-visible __fp16 type, and a pointer to that type. Used
across the back-end. */
@@ -2333,6 +2346,27 @@ aarch64_general_builtin_rsqrt (unsigned int fn)
return NULL_TREE;
}
+/* Return true if the lane check can be removed as there is no
+ error going to be emitted. */
+static bool
+aarch64_fold_builtin_lane_check (tree arg0, tree arg1, tree arg2)
+{
+ if (TREE_CODE (arg0) != INTEGER_CST)
+ return false;
+ if (TREE_CODE (arg1) != INTEGER_CST)
+ return false;
+ if (TREE_CODE (arg2) != INTEGER_CST)
+ return false;
+
+ auto totalsize = wi::to_widest (arg0);
+ auto elementsize = wi::to_widest (arg1);
+ if (totalsize == 0 || elementsize == 0)
+ return false;
+ auto lane = wi::to_widest (arg2);
+ auto high = wi::udiv_trunc (totalsize, elementsize);
+ return wi::ltu_p (lane, high);
+}
+
#undef VAR1
#define VAR1(T, N, MAP, FLAG, A) \
case AARCH64_SIMD_BUILTIN_##T##_##N##A:
@@ -2353,6 +2387,11 @@ aarch64_general_fold_builtin (unsigned int fcode, tree type,
VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
VAR1 (UNOP, floatv2di, 2, ALL, v2df)
return fold_build1 (FLOAT_EXPR, type, args[0]);
+ case AARCH64_SIMD_BUILTIN_LANE_CHECK:
+ gcc_assert (n_args == 3);
+ if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
+ return void_node;
+ break;
default:
break;
}
@@ -2440,6 +2479,14 @@ aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt)
}
break;
}
+ case AARCH64_SIMD_BUILTIN_LANE_CHECK:
+ if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
+ {
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
+ new_stmt = gimple_build_nop ();
+ }
+ break;
default:
break;
}
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index b2aa167..77da310 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -162,4 +162,13 @@ AARCH64_CORE("cortex-a76.cortex-a55", cortexa76cortexa55, cortexa53, 8_2A, AAR
/* Armv8-R Architecture Processors. */
AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_ARCH8_R, cortexa53, 0x41, 0xd15, -1)
+/* Armv9.0-A Architecture Processors. */
+
+/* Arm ('A') cores. */
+AARCH64_CORE("cortex-a510", cortexa510, cortexa55, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
+
+AARCH64_CORE("cortex-a710", cortexa710, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
+
+AARCH64_CORE("cortex-x2", cortexx2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
+
#undef AARCH64_CORE
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 579328c..b61f1df 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -232,4 +232,7 @@ 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")
+/* Enabling/Disabling "ls64" only changes "ls64". */
+AARCH64_OPT_EXTENSION("ls64", AARCH64_FL_LS64, 0, 0, false, "")
+
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 402453a..35dc075 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -721,6 +721,8 @@
/* Implemented by aarch64_qtbl1<mode>. */
VAR2 (BINOP, qtbl1, 0, NONE, v8qi, v16qi)
VAR2 (BINOPU, qtbl1, 0, NONE, v8qi, v16qi)
+ VAR2 (BINOP_PPU, qtbl1, 0, NONE, v8qi, v16qi)
+ VAR2 (BINOP_SSU, qtbl1, 0, NONE, v8qi, v16qi)
/* Implemented by aarch64_qtbl2<mode>. */
VAR2 (BINOP, qtbl2, 0, NONE, v8qi, v16qi)
@@ -734,6 +736,8 @@
/* Implemented by aarch64_qtbx1<mode>. */
VAR2 (TERNOP, qtbx1, 0, NONE, v8qi, v16qi)
VAR2 (TERNOPU, qtbx1, 0, NONE, v8qi, v16qi)
+ VAR2 (TERNOP_PPPU, qtbx1, 0, NONE, v8qi, v16qi)
+ VAR2 (TERNOP_SSSU, qtbx1, 0, NONE, v8qi, v16qi)
/* Implemented by aarch64_qtbx2<mode>. */
VAR2 (TERNOP, qtbx2, 0, NONE, v8qi, v16qi)
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index f71b287..bc92213 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -3416,6 +3416,7 @@ register_vector_type (vector_type_index type)
installing an incorrect type. */
if (decl
&& TREE_CODE (decl) == TYPE_DECL
+ && TREE_TYPE (decl) != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype)
vectype = TREE_TYPE (decl);
acle_vector_types[0][type] = vectype;
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index 359fe0e..8fe4c72 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -8126,6 +8126,160 @@
UNSPEC_COND_FCMUO))]
)
+;; Similar to *fcm<cmp_op><mode>_and_combine, but for BIC rather than AND.
+;; In this case, we still need a separate NOT/BIC operation, but predicating
+;; the comparison on the BIC operand removes the need for a PTRUE.
+(define_insn_and_split "*fcm<cmp_op><mode>_bic_combine"
+ [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:SVE_FULL_F 2 "register_operand" "w")
+ (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ SVE_COND_FP_CMP_I0))
+ (match_operand:<VPRED> 4 "register_operand" "Upa"))
+ (match_dup:<VPRED> 1)))
+ (clobber (match_scratch:<VPRED> 5 "=&Upl"))]
+ "TARGET_SVE"
+ "#"
+ "&& 1"
+ [(set (match_dup 5)
+ (unspec:<VPRED>
+ [(match_dup 4)
+ (const_int SVE_MAYBE_NOT_PTRUE)
+ (match_dup 2)
+ (match_dup 3)]
+ SVE_COND_FP_CMP_I0))
+ (set (match_dup 0)
+ (and:<VPRED>
+ (not:<VPRED>
+ (match_dup 5))
+ (match_dup 4)))]
+{
+ if (can_create_pseudo_p ())
+ operands[5] = gen_reg_rtx (<VPRED>mode);
+}
+)
+
+;; Make sure that we expand to a nor when the operand 4 of
+;; *fcm<cmp_op><mode>_bic_combine is a not.
+(define_insn_and_split "*fcm<cmp_op><mode>_nor_combine"
+ [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:SVE_FULL_F 2 "register_operand" "w")
+ (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ SVE_COND_FP_CMP_I0))
+ (not:<VPRED>
+ (match_operand:<VPRED> 4 "register_operand" "Upa")))
+ (match_dup:<VPRED> 1)))
+ (clobber (match_scratch:<VPRED> 5 "=&Upl"))]
+ "TARGET_SVE"
+ "#"
+ "&& 1"
+ [(set (match_dup 5)
+ (unspec:<VPRED>
+ [(match_dup 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_dup 2)
+ (match_dup 3)]
+ SVE_COND_FP_CMP_I0))
+ (set (match_dup 0)
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (match_dup 5))
+ (not:<VPRED>
+ (match_dup 4)))
+ (match_dup 1)))]
+{
+ if (can_create_pseudo_p ())
+ operands[5] = gen_reg_rtx (<VPRED>mode);
+}
+)
+
+(define_insn_and_split "*fcmuo<mode>_bic_combine"
+ [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:SVE_FULL_F 2 "register_operand" "w")
+ (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ UNSPEC_COND_FCMUO))
+ (match_operand:<VPRED> 4 "register_operand" "Upa"))
+ (match_dup:<VPRED> 1)))
+ (clobber (match_scratch:<VPRED> 5 "=&Upl"))]
+ "TARGET_SVE"
+ "#"
+ "&& 1"
+ [(set (match_dup 5)
+ (unspec:<VPRED>
+ [(match_dup 4)
+ (const_int SVE_MAYBE_NOT_PTRUE)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_COND_FCMUO))
+ (set (match_dup 0)
+ (and:<VPRED>
+ (not:<VPRED>
+ (match_dup 5))
+ (match_dup 4)))]
+{
+ if (can_create_pseudo_p ())
+ operands[5] = gen_reg_rtx (<VPRED>mode);
+}
+)
+
+;; Same for unordered comparisons.
+(define_insn_and_split "*fcmuo<mode>_nor_combine"
+ [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:SVE_FULL_F 2 "register_operand" "w")
+ (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ UNSPEC_COND_FCMUO))
+ (not:<VPRED>
+ (match_operand:<VPRED> 4 "register_operand" "Upa")))
+ (match_dup:<VPRED> 1)))
+ (clobber (match_scratch:<VPRED> 5 "=&Upl"))]
+ "TARGET_SVE"
+ "#"
+ "&& 1"
+ [(set (match_dup 5)
+ (unspec:<VPRED>
+ [(match_dup 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_COND_FCMUO))
+ (set (match_dup 0)
+ (and:<VPRED>
+ (and:<VPRED>
+ (not:<VPRED>
+ (match_dup 5))
+ (not:<VPRED>
+ (match_dup 4)))
+ (match_dup 1)))]
+{
+ if (can_create_pseudo_p ())
+ operands[5] = gen_reg_rtx (<VPRED>mode);
+}
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] Absolute comparisons
;; -------------------------------------------------------------------------
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index e491c29..12be913 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,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,neoverse512tvb,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,neoverse512tvb,saphira,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3213585..76d99d2 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9770,7 +9770,6 @@ aarch64_classify_address (struct aarch64_address_info *info,
|| mode == TImode
|| mode == TFmode
|| (BYTES_BIG_ENDIAN && advsimd_struct_p));
-
/* If we are dealing with ADDR_QUERY_LDP_STP_N that means the incoming mode
corresponds to the actual size of the memory being loaded/stored and the
mode of the corresponding addressing mode is half of that. */
@@ -9779,12 +9778,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
mode = DFmode;
bool allow_reg_index_p = (!load_store_pair_p
- && (known_lt (GET_MODE_SIZE (mode), 16)
+ && ((vec_flags == 0
+ && known_lt (GET_MODE_SIZE (mode), 16))
|| vec_flags == VEC_ADVSIMD
|| vec_flags & VEC_SVE_DATA));
- /* For SVE, only accept [Rn], [Rn, Rm, LSL #shift] and
- [Rn, #offset, MUL VL]. */
+ /* For SVE, only accept [Rn], [Rn, #offset, MUL VL] and [Rn, Rm, LSL #shift].
+ The latter is not valid for SVE predicates, and that's rejected through
+ allow_reg_index_p above. */
if ((vec_flags & (VEC_SVE_DATA | VEC_SVE_PRED)) != 0
&& (code != REG && code != PLUS))
return false;
@@ -15486,125 +15487,121 @@ aarch64_add_stmt_cost (class vec_info *vinfo, void *data, int count,
int misalign, enum vect_cost_model_location where)
{
auto *costs = static_cast<aarch64_vector_costs *> (data);
- unsigned retval = 0;
-
- if (flag_vect_cost_model)
- {
- fractional_cost stmt_cost
- = aarch64_builtin_vectorization_cost (kind, vectype, misalign);
-
- bool in_inner_loop_p = (where == vect_body
- && stmt_info
- && stmt_in_inner_loop_p (vinfo, stmt_info));
-
- /* Do one-time initialization based on the vinfo. */
- loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (vinfo);
- bb_vec_info bb_vinfo = dyn_cast<bb_vec_info> (vinfo);
- if (!costs->analyzed_vinfo && aarch64_use_new_vector_costs_p ())
- {
- if (loop_vinfo)
- aarch64_analyze_loop_vinfo (loop_vinfo, costs);
- else
- aarch64_analyze_bb_vinfo (bb_vinfo, costs);
- costs->analyzed_vinfo = true;
- }
-
- /* Try to get a more accurate cost by looking at STMT_INFO instead
- of just looking at KIND. */
- if (stmt_info && aarch64_use_new_vector_costs_p ())
- {
- if (vectype && aarch64_sve_only_stmt_p (stmt_info, vectype))
- costs->saw_sve_only_op = true;
- /* If we scalarize a strided store, the vectorizer costs one
- vec_to_scalar for each element. However, we can store the first
- element using an FP store without a separate extract step. */
- if (vect_is_store_elt_extraction (kind, stmt_info))
- count -= 1;
+ fractional_cost stmt_cost
+ = aarch64_builtin_vectorization_cost (kind, vectype, misalign);
- stmt_cost = aarch64_detect_scalar_stmt_subtype
- (vinfo, kind, stmt_info, stmt_cost);
+ bool in_inner_loop_p = (where == vect_body
+ && stmt_info
+ && stmt_in_inner_loop_p (vinfo, stmt_info));
- if (vectype && costs->vec_flags)
- stmt_cost = aarch64_detect_vector_stmt_subtype (vinfo, kind,
- stmt_info, vectype,
- where, stmt_cost);
- }
-
- /* Do any SVE-specific adjustments to the cost. */
- if (stmt_info && vectype && aarch64_sve_mode_p (TYPE_MODE (vectype)))
- stmt_cost = aarch64_sve_adjust_stmt_cost (vinfo, kind, stmt_info,
- vectype, stmt_cost);
-
- if (stmt_info && aarch64_use_new_vector_costs_p ())
- {
- /* Account for any extra "embedded" costs that apply additively
- to the base cost calculated above. */
- stmt_cost = aarch64_adjust_stmt_cost (kind, stmt_info, vectype,
- stmt_cost);
-
- /* If we're recording a nonzero vector loop body cost for the
- innermost loop, also estimate the operations that would need
- to be issued by all relevant implementations of the loop. */
- auto *issue_info = aarch64_tune_params.vec_costs->issue_info;
- if (loop_vinfo
- && issue_info
- && costs->vec_flags
- && where == vect_body
- && (!LOOP_VINFO_LOOP (loop_vinfo)->inner || in_inner_loop_p)
- && vectype
- && stmt_cost != 0)
+ /* Do one-time initialization based on the vinfo. */
+ loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (vinfo);
+ bb_vec_info bb_vinfo = dyn_cast<bb_vec_info> (vinfo);
+ if (!costs->analyzed_vinfo && aarch64_use_new_vector_costs_p ())
+ {
+ if (loop_vinfo)
+ aarch64_analyze_loop_vinfo (loop_vinfo, costs);
+ else
+ aarch64_analyze_bb_vinfo (bb_vinfo, costs);
+ costs->analyzed_vinfo = true;
+ }
+
+ /* Try to get a more accurate cost by looking at STMT_INFO instead
+ of just looking at KIND. */
+ if (stmt_info && aarch64_use_new_vector_costs_p ())
+ {
+ if (vectype && aarch64_sve_only_stmt_p (stmt_info, vectype))
+ costs->saw_sve_only_op = true;
+
+ /* If we scalarize a strided store, the vectorizer costs one
+ vec_to_scalar for each element. However, we can store the first
+ element using an FP store without a separate extract step. */
+ if (vect_is_store_elt_extraction (kind, stmt_info))
+ count -= 1;
+
+ stmt_cost = aarch64_detect_scalar_stmt_subtype
+ (vinfo, kind, stmt_info, stmt_cost);
+
+ if (vectype && costs->vec_flags)
+ stmt_cost = aarch64_detect_vector_stmt_subtype (vinfo, kind,
+ stmt_info, vectype,
+ where, stmt_cost);
+ }
+
+ /* Do any SVE-specific adjustments to the cost. */
+ if (stmt_info && vectype && aarch64_sve_mode_p (TYPE_MODE (vectype)))
+ stmt_cost = aarch64_sve_adjust_stmt_cost (vinfo, kind, stmt_info,
+ vectype, stmt_cost);
+
+ if (stmt_info && aarch64_use_new_vector_costs_p ())
+ {
+ /* Account for any extra "embedded" costs that apply additively
+ to the base cost calculated above. */
+ stmt_cost = aarch64_adjust_stmt_cost (kind, stmt_info, vectype,
+ stmt_cost);
+
+ /* If we're recording a nonzero vector loop body cost for the
+ innermost loop, also estimate the operations that would need
+ to be issued by all relevant implementations of the loop. */
+ auto *issue_info = aarch64_tune_params.vec_costs->issue_info;
+ if (loop_vinfo
+ && issue_info
+ && costs->vec_flags
+ && where == vect_body
+ && (!LOOP_VINFO_LOOP (loop_vinfo)->inner || in_inner_loop_p)
+ && vectype
+ && stmt_cost != 0)
+ {
+ /* Record estimates for the scalar code. */
+ aarch64_count_ops (vinfo, costs, count, kind, stmt_info, vectype,
+ 0, &costs->scalar_ops, issue_info->scalar,
+ vect_nunits_for_cost (vectype));
+
+ if (aarch64_sve_mode_p (vinfo->vector_mode) && issue_info->sve)
{
- /* Record estimates for the scalar code. */
- aarch64_count_ops (vinfo, costs, count, kind, stmt_info, vectype,
- 0, &costs->scalar_ops, issue_info->scalar,
- vect_nunits_for_cost (vectype));
-
- if (aarch64_sve_mode_p (vinfo->vector_mode) && issue_info->sve)
- {
- /* Record estimates for a possible Advanced SIMD version
- of the SVE code. */
- aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
- vectype, VEC_ADVSIMD, &costs->advsimd_ops,
- issue_info->advsimd,
- aarch64_estimated_sve_vq ());
-
- /* Record estimates for the SVE code itself. */
- aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
- vectype, VEC_ANY_SVE, &costs->sve_ops,
- issue_info->sve, 1);
- }
- else
- /* Record estimates for the Advanced SIMD code. Treat SVE like
- Advanced SIMD if the CPU has no specific SVE costs. */
- aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
- vectype, VEC_ADVSIMD, &costs->advsimd_ops,
- issue_info->advsimd, 1);
+ /* Record estimates for a possible Advanced SIMD version
+ of the SVE code. */
+ aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
+ vectype, VEC_ADVSIMD, &costs->advsimd_ops,
+ issue_info->advsimd,
+ aarch64_estimated_sve_vq ());
+
+ /* Record estimates for the SVE code itself. */
+ aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
+ vectype, VEC_ANY_SVE, &costs->sve_ops,
+ issue_info->sve, 1);
}
-
- /* If we're applying the SVE vs. Advanced SIMD unrolling heuristic,
- estimate the number of statements in the unrolled Advanced SIMD
- loop. For simplicitly, we assume that one iteration of the
- Advanced SIMD loop would need the same number of statements
- as one iteration of the SVE loop. */
- if (where == vect_body && costs->unrolled_advsimd_niters)
- costs->unrolled_advsimd_stmts
- += count * costs->unrolled_advsimd_niters;
+ else
+ /* Record estimates for the Advanced SIMD code. Treat SVE like
+ Advanced SIMD if the CPU has no specific SVE costs. */
+ aarch64_count_ops (vinfo, costs, count, kind, stmt_info,
+ vectype, VEC_ADVSIMD, &costs->advsimd_ops,
+ issue_info->advsimd, 1);
}
- /* Statements in an inner loop relative to the loop being
- vectorized are weighted more heavily. The value here is
- arbitrary and could potentially be improved with analysis. */
- if (in_inner_loop_p)
- {
- gcc_assert (loop_vinfo);
- count *= LOOP_VINFO_INNER_LOOP_COST_FACTOR (loop_vinfo); /* FIXME */
- }
+ /* If we're applying the SVE vs. Advanced SIMD unrolling heuristic,
+ estimate the number of statements in the unrolled Advanced SIMD
+ loop. For simplicitly, we assume that one iteration of the
+ Advanced SIMD loop would need the same number of statements
+ as one iteration of the SVE loop. */
+ if (where == vect_body && costs->unrolled_advsimd_niters)
+ costs->unrolled_advsimd_stmts
+ += count * costs->unrolled_advsimd_niters;
+ }
- retval = (count * stmt_cost).ceil ();
- costs->region[where] += retval;
+ /* Statements in an inner loop relative to the loop being
+ vectorized are weighted more heavily. The value here is
+ arbitrary and could potentially be improved with analysis. */
+ if (in_inner_loop_p)
+ {
+ gcc_assert (loop_vinfo);
+ count *= LOOP_VINFO_INNER_LOOP_COST_FACTOR (loop_vinfo); /* FIXME */
}
+ unsigned retval = (count * stmt_cost).ceil ();
+ costs->region[where] += retval;
+
return retval;
}
@@ -16539,6 +16536,28 @@ aarch64_override_options_internal (struct gcc_options *opts)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l1_cache_line_size,
aarch64_tune_params.prefetch->l1_cache_line_size);
+
+ if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic AArch64 target, cover the current range of cache line
+ sizes. */
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ 256);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ 64);
+ }
+
if (aarch64_tune_params.prefetch->l2_cache_size >= 0)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l2_cache_size,
@@ -23367,7 +23386,8 @@ aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst,
}
/* Expand cpymem, as if from a __builtin_memcpy. Return true if
- we succeed, otherwise return false. */
+ we succeed, otherwise return false, indicating that a libcall to
+ memcpy should be emitted. */
bool
aarch64_expand_cpymem (rtx *operands)
@@ -23384,11 +23404,13 @@ aarch64_expand_cpymem (rtx *operands)
unsigned HOST_WIDE_INT size = INTVAL (operands[2]);
- /* Inline up to 256 bytes when optimizing for speed. */
+ /* Try to inline up to 256 bytes. */
unsigned HOST_WIDE_INT max_copy_size = 256;
- if (optimize_function_for_size_p (cfun))
- max_copy_size = 128;
+ bool size_p = optimize_function_for_size_p (cfun);
+
+ if (size > max_copy_size)
+ return false;
int copy_bits = 256;
@@ -23398,13 +23420,14 @@ aarch64_expand_cpymem (rtx *operands)
|| !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;
- }
+ copy_bits = 128;
- if (size > max_copy_size)
- return false;
+ /* Emit an inline load+store sequence and count the number of operations
+ involved. We use a simple count of just the loads and stores emitted
+ rather than rtx_insn count as all the pointer adjustments and reg copying
+ in this function will get optimized away later in the pipeline. */
+ start_sequence ();
+ unsigned nops = 0;
base = copy_to_mode_reg (Pmode, XEXP (dst, 0));
dst = adjust_automodify_address (dst, VOIDmode, base, 0);
@@ -23433,7 +23456,8 @@ aarch64_expand_cpymem (rtx *operands)
cur_mode = V4SImode;
aarch64_copy_one_block_and_progress_pointers (&src, &dst, cur_mode);
-
+ /* A single block copy is 1 load + 1 store. */
+ nops += 2;
n -= mode_bits;
/* Emit trailing copies using overlapping unaligned accesses - this is
@@ -23448,7 +23472,16 @@ aarch64_expand_cpymem (rtx *operands)
n = n_bits;
}
}
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ /* A memcpy libcall in the worst case takes 3 instructions to prepare the
+ arguments + 1 for the call. */
+ unsigned libcall_cost = 4;
+ if (size_p && libcall_cost < nops)
+ return false;
+
+ emit_insn (seq);
return true;
}
@@ -23511,40 +23544,37 @@ aarch64_expand_setmem (rtx *operands)
if (!CONST_INT_P (operands[1]))
return false;
- bool speed_p = !optimize_function_for_size_p (cfun);
+ bool size_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;
+ /* Attempt a sequence with a vector broadcast followed by stores.
+ Count the number of operations involved to see if it's worth it for
+ code size. */
+ start_sequence ();
+ unsigned nops = 0;
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);
-
+ nops++;
/* 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))
+ const int copy_limit = (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS)
? GET_MODE_BITSIZE (TImode) : 256;
while (n > 0)
@@ -23560,14 +23590,14 @@ aarch64_expand_setmem (rtx *operands)
mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant ();
aarch64_set_one_block_and_progress_pointer (src, &dst, cur_mode);
-
+ nops++;
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 + 4 + 2 + 1. */
- if (n > 0 && n < copy_limit / 2)
+ 8 + 4 + 2 + 1. Only do this when -mstrict-align is not supplied. */
+ if (n > 0 && n < copy_limit / 2 && !STRICT_ALIGNMENT)
{
next_mode = smallest_mode_for_size (n, MODE_INT);
int n_bits = GET_MODE_BITSIZE (next_mode).to_constant ();
@@ -23576,7 +23606,15 @@ aarch64_expand_setmem (rtx *operands)
n = n_bits;
}
}
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ /* A call to memset in the worst case requires 3 instructions to prepare
+ the arguments + 1 for the call. Prefer the inline sequence for size if
+ it is no longer than that. */
+ if (size_p && nops > 4)
+ return false;
+ emit_insn (seq);
return true;
}
@@ -25045,6 +25083,7 @@ aarch64_excess_precision (enum excess_precision_type type)
? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
case EXCESS_PRECISION_TYPE_IMPLICIT:
+ case EXCESS_PRECISION_TYPE_FLOAT16:
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
default:
gcc_unreachable ();
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index bfffbcd..2792bb2 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -231,6 +231,15 @@ extern unsigned aarch64_architecture_version;
/* Pointer Authentication (PAUTH) extension. */
#define AARCH64_FL_PAUTH (1ULL << 40)
+/* 64-byte atomic load/store extensions. */
+#define AARCH64_FL_LS64 (1ULL << 41)
+
+/* Armv8.7-a architecture extensions. */
+#define AARCH64_FL_V8_7 (1ULL << 42)
+
+/* Armv9.0-A. */
+#define AARCH64_FL_V9 (1ULL << 43) /* Armv9.0-A Architecture. */
+
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -255,8 +264,13 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_FL_FOR_ARCH8_6 \
(AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_V8_6 | AARCH64_FL_FPSIMD \
| AARCH64_FL_I8MM | AARCH64_FL_BF16)
+#define AARCH64_FL_FOR_ARCH8_7 \
+ (AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V8_7 | AARCH64_FL_LS64)
+
#define AARCH64_FL_FOR_ARCH8_R \
(AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_R)
+#define AARCH64_FL_FOR_ARCH9 \
+ (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9)
/* Macros to test ISA flags. */
@@ -295,6 +309,7 @@ extern unsigned aarch64_architecture_version;
#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)
+#define AARCH64_ISA_V9 (aarch64_isa_flags & AARCH64_FL_V9)
/* Crypto is an optional extension to AdvSIMD. */
#define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -1262,13 +1277,13 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* This type is the user-visible __fp16, and a pointer to that type. We
need it in many places in the backend. Defined in aarch64-builtins.c. */
-extern tree aarch64_fp16_type_node;
-extern tree aarch64_fp16_ptr_type_node;
+extern GTY(()) tree aarch64_fp16_type_node;
+extern GTY(()) tree aarch64_fp16_ptr_type_node;
/* This type is the user-visible __bf16, and a pointer to that type. Defined
in aarch64-builtins.c. */
-extern tree aarch64_bf16_type_node;
-extern tree aarch64_bf16_ptr_type_node;
+extern GTY(()) tree aarch64_bf16_type_node;
+extern GTY(()) tree aarch64_bf16_ptr_type_node;
/* The generic unwind code in libgcc does not initialize the frame pointer.
So in order to unwind a function using a frame pointer, the very first
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 635a223..24068f8 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -10416,15 +10416,14 @@ __extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1_p8 (poly8x16_t __tab, uint8x8_t __idx)
{
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __tab,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__tab, __idx);
}
__extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1_s8 (int8x16_t __tab, uint8x8_t __idx)
{
- return __builtin_aarch64_qtbl1v8qi (__tab, (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ssu (__tab, __idx);
}
__extension__ extern __inline uint8x8_t
@@ -10438,15 +10437,14 @@ __extension__ extern __inline poly8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1q_p8 (poly8x16_t __tab, uint8x16_t __idx)
{
- return (poly8x16_t) __builtin_aarch64_qtbl1v16qi ((int8x16_t) __tab,
- (int8x16_t) __idx);
+ return __builtin_aarch64_qtbl1v16qi_ppu (__tab, __idx);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbl1q_s8 (int8x16_t __tab, uint8x16_t __idx)
{
- return __builtin_aarch64_qtbl1v16qi (__tab, (int8x16_t) __idx);
+ return __builtin_aarch64_qtbl1v16qi_ssu (__tab, __idx);
}
__extension__ extern __inline uint8x16_t
@@ -10460,7 +10458,7 @@ __extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1_s8 (int8x8_t __r, int8x16_t __tab, uint8x8_t __idx)
{
- return __builtin_aarch64_qtbx1v8qi (__r, __tab, (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_sssu (__r, __tab, __idx);
}
__extension__ extern __inline uint8x8_t
@@ -10474,16 +10472,14 @@ __extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1_p8 (poly8x8_t __r, poly8x16_t __tab, uint8x8_t __idx)
{
- return (poly8x8_t) __builtin_aarch64_qtbx1v8qi ((int8x8_t) __r,
- (int8x16_t) __tab,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_pppu (__r, __tab, __idx);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1q_s8 (int8x16_t __r, int8x16_t __tab, uint8x16_t __idx)
{
- return __builtin_aarch64_qtbx1v16qi (__r, __tab, (int8x16_t) __idx);
+ return __builtin_aarch64_qtbx1v16qi_sssu (__r, __tab, __idx);
}
__extension__ extern __inline uint8x16_t
@@ -10497,9 +10493,7 @@ __extension__ extern __inline poly8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vqtbx1q_p8 (poly8x16_t __r, poly8x16_t __tab, uint8x16_t __idx)
{
- return (poly8x16_t) __builtin_aarch64_qtbx1v16qi ((int8x16_t) __r,
- (int8x16_t) __tab,
- (int8x16_t) __idx);
+ return __builtin_aarch64_qtbx1v16qi_pppu (__r, __tab, __idx);
}
/* V7 legacy table intrinsics. */
@@ -10528,8 +10522,7 @@ vtbl1_p8 (poly8x8_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab,
vcreate_p8 (__AARCH64_UINT64_C (0x0)));
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__temp, __idx);
}
__extension__ extern __inline int8x8_t
@@ -10553,8 +10546,7 @@ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vtbl2_p8 (poly8x8x2_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab.val[0], __tab.val[1]);
- return (poly8x8_t) __builtin_aarch64_qtbl1v8qi ((int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbl1v8qi_ppu (__temp, __idx);
}
__extension__ extern __inline int8x8_t
@@ -10653,9 +10645,7 @@ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vtbx2_p8 (poly8x8_t __r, poly8x8x2_t __tab, uint8x8_t __idx)
{
poly8x16_t __temp = vcombine_p8 (__tab.val[0], __tab.val[1]);
- return (poly8x8_t) __builtin_aarch64_qtbx1v8qi ((int8x8_t) __r,
- (int8x16_t) __temp,
- (int8x8_t) __idx);
+ return __builtin_aarch64_qtbx1v8qi_pppu (__r, __temp, __idx);
}
/* End of temporary inline asm. */
@@ -16208,7 +16198,7 @@ vld1_u8_x3 (const uint8_t *__a)
__extension__ extern __inline int8x8x3_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vld1_s8_x3 (const uint8_t *__a)
+vld1_s8_x3 (const int8_t *__a)
{
int8x8x3_t __i;
__builtin_aarch64_simd_ci __o;
@@ -16260,7 +16250,7 @@ vld1_u32_x3 (const uint32_t *__a)
__extension__ extern __inline int32x2x3_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vld1_s32_x3 (const uint32_t *__a)
+vld1_s32_x3 (const int32_t *__a)
{
int32x2x3_t __i;
__builtin_aarch64_simd_ci __o;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index c702e68..fced7ce 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -575,7 +575,7 @@ alpha_option_override (void)
}
/* Default the definition of "small data" to 8 bytes. */
- if (!global_options_set.x_g_switch_value)
+ if (!OPTION_SET_P (g_switch_value))
g_switch_value = 8;
/* Infer TARGET_SMALL_DATA from -fpic/-fPIC. */
diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h
index b8673b6..0033b00 100644
--- a/gcc/config/alpha/vms.h
+++ b/gcc/config/alpha/vms.h
@@ -145,9 +145,13 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info;
#undef INIT_CUMULATIVE_ARGS
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
- (CUM).num_args = 0; \
- (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \
- (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64;
+ do \
+ { \
+ (CUM).num_args = 0; \
+ (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \
+ (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64; \
+ } \
+ while (0)
#define DEFAULT_PCC_STRUCT_RETURN 0
@@ -244,7 +248,7 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info;
while (0)
#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE VMS_AND_DWARF2_DEBUG
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
#define ASM_PN_FORMAT "%s___%lu"
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 92797db..8244f37 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -1441,7 +1441,7 @@ arc_override_options (void)
target_flags |= MASK_NO_SDATA_SET;
/* Check for small data option */
- if (!global_options_set.x_g_switch_value && !TARGET_NO_SDATA_SET)
+ if (!OPTION_SET_P (g_switch_value) && !TARGET_NO_SDATA_SET)
g_switch_value = TARGET_LL64 ? 8 : 4;
/* A7 has an issue with delay slots. */
@@ -1455,7 +1455,7 @@ arc_override_options (void)
target_flags &= ~MASK_MILLICODE_THUNK_SET;
/* Set unaligned to all HS cpus. */
- if (!global_options_set.x_unaligned_access && TARGET_HS)
+ if (!OPTION_SET_P (unaligned_access) && TARGET_HS)
unaligned_access = 1;
/* These need to be done at start up. It's convenient to do them here. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 90ba85e..4919d27 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -4966,8 +4966,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(const_int 1))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_dup 0) (plus (match_dup 0) (const_int -1)))
- (unspec [(const_int 0)] UNSPEC_ARC_LP)
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
+ (unspec:SI [(const_int 0)] UNSPEC_ARC_LP)
(clobber (match_dup 2))])]
""
{
@@ -4996,8 +4996,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(const_int 1))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_dup 0) (plus (match_dup 0) (const_int -1)))
- (unspec [(const_int 0)] UNSPEC_ARC_LP)
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
+ (unspec:SI [(const_int 0)] UNSPEC_ARC_LP)
(clobber (match_scratch:SI 2 "=X,&r"))]
""
"@
diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index bcc9ebe..d0d0d0f 100644
--- a/gcc/config/arm/arm-cpus.in
+++ b/gcc/config/arm/arm-cpus.in
@@ -1612,6 +1612,16 @@ begin cpu cortex-r52
part d13
end cpu cortex-r52
+begin cpu cortex-r52plus
+ cname cortexr52plus
+ tune flags LDSCHED
+ architecture armv8-r+crc+simd
+ option nofp.dp remove FP_DBL ALL_SIMD
+ costs cortex
+ vendor 41
+ part d16
+end cpu cortex-r52plus
+
# FPU entries
# format:
# begin fpu <name>
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index 5692d4f..8bb0c9f 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -282,6 +282,9 @@ Enum(processor_type) String(cortex-m55) Value( TARGET_CPU_cortexm55)
EnumValue
Enum(processor_type) String(cortex-r52) Value( TARGET_CPU_cortexr52)
+EnumValue
+Enum(processor_type) String(cortex-r52plus) Value( TARGET_CPU_cortexr52plus)
+
Enum
Name(arm_arch) Type(int)
Known ARM architectures (for use with the -march= option):
diff --git a/gcc/config/arm/arm-tune.md b/gcc/config/arm/arm-tune.md
index b9df864..6482833 100644
--- a/gcc/config/arm/arm-tune.md
+++ b/gcc/config/arm/arm-tune.md
@@ -49,5 +49,5 @@
cortexx1,neoversen1,cortexa75cortexa55,
cortexa76cortexa55,neoversev1,neoversen2,
cortexm23,cortexm33,cortexm35p,
- cortexm55,cortexr52"
+ cortexm55,cortexr52,cortexr52plus"
(const (symbol_ref "((enum attr_tune) arm_tune)")))
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5c92941..e51f60a 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -71,6 +71,7 @@
#include "gimple.h"
#include "selftest.h"
#include "tree-vectorizer.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -303,11 +304,6 @@ static bool aarch_macro_fusion_pair_p (rtx_insn*, rtx_insn*);
static int arm_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
tree vectype,
int misalign ATTRIBUTE_UNUSED);
-static unsigned arm_add_stmt_cost (vec_info *vinfo, void *data, int count,
- enum vect_cost_for_stmt kind,
- struct _stmt_vec_info *stmt_info,
- tree vectype, int misalign,
- enum vect_cost_model_location where);
static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
bool op0_preserve_value);
@@ -768,8 +764,6 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
arm_builtin_vectorization_cost
-#undef TARGET_VECTORIZE_ADD_STMT_COST
-#define TARGET_VECTORIZE_ADD_STMT_COST arm_add_stmt_cost
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON \
@@ -3468,7 +3462,7 @@ arm_option_override (void)
arm_active_target.isa = sbitmap_alloc (isa_num_bits);
- if (!global_options_set.x_arm_fpu_index)
+ if (!OPTION_SET_P (arm_fpu_index))
{
bool ok;
int fpu_index;
@@ -3528,7 +3522,7 @@ arm_option_override (void)
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
/* Override the default structure alignment for AAPCS ABI. */
- if (!global_options_set.x_arm_structure_size_boundary)
+ if (!OPTION_SET_P (arm_structure_size_boundary))
{
if (TARGET_AAPCS_BASED)
arm_structure_size_boundary = 8;
@@ -3553,12 +3547,12 @@ arm_option_override (void)
if (TARGET_VXWORKS_RTP)
{
- if (!global_options_set.x_arm_pic_data_is_text_relative)
+ if (!OPTION_SET_P (arm_pic_data_is_text_relative))
arm_pic_data_is_text_relative = 0;
}
else if (flag_pic
&& !arm_pic_data_is_text_relative
- && !(global_options_set.x_target_flags & MASK_SINGLE_PIC_BASE))
+ && !(OPTION_SET_P (target_flags) & MASK_SINGLE_PIC_BASE))
/* When text & data segments don't have a fixed displacement, the
intended use is with a single, read only, pic base register.
Unless the user explicitly requested not to do that, set
@@ -3669,6 +3663,28 @@ arm_option_override (void)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_line_size,
current_tune->prefetch.l1_cache_line_size);
+ if (current_tune->prefetch.l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic ARM target, JF Bastien proposed using 64 for both. */
+ /* ??? Cortex A9 has a 32-byte cache line, so why not 32 for
+ constructive? */
+ /* More recent Cortex chips have a 64-byte cache line, but are marked
+ ARM_PREFETCH_NOT_BENEFICIAL, so they get these defaults. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+ }
+
if (current_tune->prefetch.l1_cache_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_size,
@@ -8508,8 +8524,7 @@ thumb2_legitimate_address_p (machine_mode mode, rtx x, int strict_p)
bool use_ldrd;
enum rtx_code code = GET_CODE (x);
- if (TARGET_HAVE_MVE
- && (mode == V8QImode || mode == E_V4QImode || mode == V4HImode))
+ if (TARGET_HAVE_MVE && VALID_MVE_MODE (mode))
return mve_vector_mem_operand (mode, x, strict_p);
if (arm_address_register_rtx_p (x, strict_p))
@@ -12220,39 +12235,6 @@ arm_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
}
}
-/* Implement targetm.vectorize.add_stmt_cost. */
-
-static unsigned
-arm_add_stmt_cost (vec_info *vinfo, void *data, int count,
- enum vect_cost_for_stmt kind,
- struct _stmt_vec_info *stmt_info, tree vectype,
- int misalign, enum vect_cost_model_location where)
-{
- unsigned *cost = (unsigned *) data;
- unsigned retval = 0;
-
- if (flag_vect_cost_model)
- {
- int stmt_cost = arm_builtin_vectorization_cost (kind, vectype, misalign);
-
- /* Statements in an inner loop relative to the loop being
- vectorized are weighted more heavily. The value here is
- arbitrary and could potentially be improved with analysis. */
- if (where == vect_body && stmt_info
- && stmt_in_inner_loop_p (vinfo, stmt_info))
- {
- loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (vinfo);
- gcc_assert (loop_vinfo);
- count *= LOOP_VINFO_INNER_LOOP_COST_FACTOR (loop_vinfo); /* FIXME. */
- }
-
- retval = (unsigned) (count * stmt_cost);
- cost[where] += retval;
- }
-
- return retval;
-}
-
/* Return true if and only if this insn can dual-issue only as older. */
static bool
cortexa7_older_only (rtx_insn *insn)
@@ -13411,53 +13393,49 @@ mve_vector_mem_operand (machine_mode mode, rtx op, bool strict)
|| code == PRE_INC || code == POST_DEC)
{
reg_no = REGNO (XEXP (op, 0));
- return (((mode == E_V8QImode || mode == E_V4QImode || mode == E_V4HImode)
- ? reg_no <= LAST_LO_REGNUM
- :(reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM))
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
- }
- else if ((code == POST_MODIFY || code == PRE_MODIFY)
- && GET_CODE (XEXP (op, 1)) == PLUS && REG_P (XEXP (XEXP (op, 1), 1)))
+ return ((mode == E_V8QImode || mode == E_V4QImode || mode == E_V4HImode)
+ ? reg_no <= LAST_LO_REGNUM
+ :(reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM))
+ || reg_no >= FIRST_PSEUDO_REGISTER;
+ }
+ else if (((code == POST_MODIFY || code == PRE_MODIFY)
+ && GET_CODE (XEXP (op, 1)) == PLUS
+ && XEXP (op, 0) == XEXP (XEXP (op, 1), 0)
+ && REG_P (XEXP (op, 0))
+ && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT)
+ /* Make sure to only accept PLUS after reload_completed, otherwise
+ this will interfere with auto_inc's pattern detection. */
+ || (reload_completed && code == PLUS && REG_P (XEXP (op, 0))
+ && GET_CODE (XEXP (op, 1)) == CONST_INT))
{
reg_no = REGNO (XEXP (op, 0));
- val = INTVAL (XEXP ( XEXP (op, 1), 1));
+ if (code == PLUS)
+ val = INTVAL (XEXP (op, 1));
+ else
+ val = INTVAL (XEXP(XEXP (op, 1), 1));
+
switch (mode)
{
case E_V16QImode:
- if (abs (val) <= 127)
- return ((reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
- return FALSE;
- case E_V8HImode:
- case E_V8HFmode:
- if (abs (val) <= 255)
- return ((reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
- return FALSE;
case E_V8QImode:
case E_V4QImode:
if (abs (val) <= 127)
- return (reg_no <= LAST_LO_REGNUM
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
+ return (reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
+ || reg_no >= FIRST_PSEUDO_REGISTER;
return FALSE;
+ case E_V8HImode:
+ case E_V8HFmode:
case E_V4HImode:
case E_V4HFmode:
if (val % 2 == 0 && abs (val) <= 254)
- return (reg_no <= LAST_LO_REGNUM
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
+ return reg_no <= LAST_LO_REGNUM
+ || reg_no >= FIRST_PSEUDO_REGISTER;
return FALSE;
case E_V4SImode:
case E_V4SFmode:
if (val % 4 == 0 && abs (val) <= 508)
- return ((reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
- return FALSE;
- case E_V2DImode:
- case E_V2DFmode:
- case E_TImode:
- if (val % 4 == 0 && val >= 0 && val <= 1020)
- return ((reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
- || (!strict && reg_no >= FIRST_PSEUDO_REGISTER));
+ return (reg_no < LAST_ARM_REGNUM && reg_no != SP_REGNUM)
+ || reg_no >= FIRST_PSEUDO_REGISTER;
return FALSE;
default:
return FALSE;
@@ -24254,7 +24232,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
else if (code == POST_MODIFY || code == PRE_MODIFY)
{
asm_fprintf (stream, "[%r", REGNO (XEXP (addr, 0)));
- postinc_reg = XEXP ( XEXP (x, 1), 1);
+ postinc_reg = XEXP (XEXP (addr, 1), 1);
if (postinc_reg && CONST_INT_P (postinc_reg))
{
if (code == POST_MODIFY)
@@ -25612,6 +25590,7 @@ arm_excess_precision (enum excess_precision_type type)
? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
case EXCESS_PRECISION_TYPE_IMPLICIT:
+ case EXCESS_PRECISION_TYPE_FLOAT16:
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
default:
gcc_unreachable ();
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5d3f21b..4adc976 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12617,6 +12617,22 @@
}"
)
+;; movmisalign for DImode
+(define_expand "movmisaligndi"
+ [(match_operand:DI 0 "general_operand")
+ (match_operand:DI 1 "general_operand")]
+ "unaligned_access"
+{
+ rtx lo_op0 = gen_lowpart (SImode, operands[0]);
+ rtx lo_op1 = gen_lowpart (SImode, operands[1]);
+ rtx hi_op0 = gen_highpart_mode (SImode, DImode, operands[0]);
+ rtx hi_op1 = gen_highpart_mode (SImode, DImode, operands[1]);
+
+ emit_insn (gen_movmisalignsi (lo_op0, lo_op1));
+ emit_insn (gen_movmisalignsi (hi_op0, hi_op1));
+ DONE;
+})
+
;; movmisalign patterns for HImode and SImode.
(define_expand "movmisalign<mode>"
[(match_operand:HSI 0 "general_operand")
diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
index e393518..a66af4d 100644
--- a/gcc/config/arm/mve.md
+++ b/gcc/config/arm/mve.md
@@ -7570,7 +7570,7 @@
;;
(define_insn "mve_vldrwq_fv4sf"
[(set (match_operand:V4SF 0 "s_register_operand" "=w")
- (unspec:V4SF [(match_operand:V4SI 1 "memory_operand" "Ux")]
+ (unspec:V4SF [(match_operand:V4SI 1 "mve_memory_operand" "Ux")]
VLDRWQ_F))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
@@ -7589,7 +7589,7 @@
;;
(define_insn "mve_vldrwq_<supf>v4si"
[(set (match_operand:V4SI 0 "s_register_operand" "=w")
- (unspec:V4SI [(match_operand:V4SI 1 "memory_operand" "Ux")]
+ (unspec:V4SI [(match_operand:V4SI 1 "mve_memory_operand" "Ux")]
VLDRWQ))
]
"TARGET_HAVE_MVE"
@@ -7608,7 +7608,7 @@
;;
(define_insn "mve_vldrwq_z_fv4sf"
[(set (match_operand:V4SF 0 "s_register_operand" "=w")
- (unspec:V4SF [(match_operand:V4SI 1 "memory_operand" "Ux")
+ (unspec:V4SF [(match_operand:V4SI 1 "mve_memory_operand" "Ux")
(match_operand:HI 2 "vpr_register_operand" "Up")]
VLDRWQ_F))
]
@@ -7628,7 +7628,7 @@
;;
(define_insn "mve_vldrwq_z_<supf>v4si"
[(set (match_operand:V4SI 0 "s_register_operand" "=w")
- (unspec:V4SI [(match_operand:V4SI 1 "memory_operand" "Ux")
+ (unspec:V4SI [(match_operand:V4SI 1 "mve_memory_operand" "Ux")
(match_operand:HI 2 "vpr_register_operand" "Up")]
VLDRWQ))
]
@@ -8282,7 +8282,7 @@
;; [vstrwq_f]
;;
(define_insn "mve_vstrwq_fv4sf"
- [(set (match_operand:V4SI 0 "memory_operand" "=Ux")
+ [(set (match_operand:V4SI 0 "mve_memory_operand" "=Ux")
(unspec:V4SI [(match_operand:V4SF 1 "s_register_operand" "w")]
VSTRWQ_F))
]
@@ -8301,7 +8301,7 @@
;; [vstrwq_p_f]
;;
(define_insn "mve_vstrwq_p_fv4sf"
- [(set (match_operand:V4SI 0 "memory_operand" "=Ux")
+ [(set (match_operand:V4SI 0 "mve_memory_operand" "=Ux")
(unspec:V4SI [(match_operand:V4SF 1 "s_register_operand" "w")
(match_operand:HI 2 "vpr_register_operand" "Up")]
VSTRWQ_F))
@@ -8321,7 +8321,7 @@
;; [vstrwq_p_s vstrwq_p_u]
;;
(define_insn "mve_vstrwq_p_<supf>v4si"
- [(set (match_operand:V4SI 0 "memory_operand" "=Ux")
+ [(set (match_operand:V4SI 0 "mve_memory_operand" "=Ux")
(unspec:V4SI [(match_operand:V4SI 1 "s_register_operand" "w")
(match_operand:HI 2 "vpr_register_operand" "Up")]
VSTRWQ))
@@ -8341,7 +8341,7 @@
;; [vstrwq_s vstrwq_u]
;;
(define_insn "mve_vstrwq_<supf>v4si"
- [(set (match_operand:V4SI 0 "memory_operand" "=Ux")
+ [(set (match_operand:V4SI 0 "mve_memory_operand" "=Ux")
(unspec:V4SI [(match_operand:V4SI 1 "s_register_operand" "w")]
VSTRWQ))
]
diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
index 68de4f0..e71d9b3 100644
--- a/gcc/config/arm/vec-common.md
+++ b/gcc/config/arm/vec-common.md
@@ -281,8 +281,8 @@
})
(define_expand "movmisalign<mode>"
- [(set (match_operand:VDQX 0 "neon_perm_struct_or_reg_operand")
- (unspec:VDQX [(match_operand:VDQX 1 "neon_perm_struct_or_reg_operand")]
+ [(set (match_operand:VDQ 0 "neon_perm_struct_or_reg_operand")
+ (unspec:VDQ [(match_operand:VDQ 1 "neon_perm_struct_or_reg_operand")]
UNSPEC_MISALIGNED_ACCESS))]
"ARM_HAVE_<MODE>_LDST && !BYTES_BIG_ENDIAN
&& unaligned_access && !TARGET_REALLY_IWMMXT"
diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index 37e4e9b..9b672e6 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -207,6 +207,7 @@ AVR_MCU ("atmega323", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega323__",
AVR_MCU ("atmega324a", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega324A__", 0x0100, 0x0, 0x8000, 0)
AVR_MCU ("atmega324p", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega324P__", 0x0100, 0x0, 0x8000, 0)
AVR_MCU ("atmega324pa", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega324PA__", 0x0100, 0x0, 0x8000, 0)
+AVR_MCU ("atmega324pb", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega324PB__", 0x0100, 0x0, 0x8000, 0)
AVR_MCU ("atmega325", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega325__", 0x0100, 0x0, 0x8000, 0)
AVR_MCU ("atmega325a", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega325A__", 0x0100, 0x0, 0x8000, 0)
AVR_MCU ("atmega325p", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATmega325P__", 0x0100, 0x0, 0x8000, 0)
diff --git a/gcc/config/avr/elf.h b/gcc/config/avr/elf.h
index 2f0eb0d..5f2d1e0 100644
--- a/gcc/config/avr/elf.h
+++ b/gcc/config/avr/elf.h
@@ -22,9 +22,6 @@
#undef PCC_BITFIELD_TYPE_MATTERS
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT (32768 * 8)
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 698dd87..3287e49 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -53,6 +53,7 @@
#include "hw-doloop.h"
#include "dumpfile.h"
#include "builtins.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -1046,7 +1047,7 @@ bfin_load_pic_reg (rtx dest)
if (local_info_node && local_info_node->local)
return pic_offset_table_rtx;
- if (global_options_set.x_bfin_library_id)
+ if (OPTION_SET_P (bfin_library_id))
addr = plus_constant (Pmode, pic_offset_table_rtx,
-4 - bfin_library_id * 4);
else
@@ -2369,7 +2370,7 @@ bfin_option_override (void)
#endif
/* Library identification */
- if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
+ if (OPTION_SET_P (bfin_library_id) && ! TARGET_ID_SHARED_LIBRARY)
error ("%<-mshared-library-id=%> specified without "
"%<-mid-shared-library%>");
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 1ec0bbb..8b311f3 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -138,8 +138,7 @@
;; Distinguish a 32-bit version of an insn from a 16-bit version.
(UNSPEC_32BIT 11)
(UNSPEC_NOP 12)
- (UNSPEC_ONES 13)
- (UNSPEC_ATOMIC 14)])
+ (UNSPEC_ATOMIC 13)])
(define_constants
[(UNSPEC_VOLATILE_CSYNC 1)
@@ -1398,12 +1397,32 @@
(define_insn "ones"
[(set (match_operand:HI 0 "register_operand" "=d")
- (unspec:HI [(match_operand:SI 1 "register_operand" "d")]
- UNSPEC_ONES))]
+ (truncate:HI
+ (popcount:SI (match_operand:SI 1 "register_operand" "d"))))]
""
"%h0 = ONES %1;"
[(set_attr "type" "alu0")])
+(define_expand "popcountsi2"
+ [(set (match_dup 2)
+ (truncate:HI (popcount:SI (match_operand:SI 1 "register_operand" ""))))
+ (set (match_operand:SI 0 "register_operand")
+ (zero_extend:SI (match_dup 2)))]
+ ""
+{
+ operands[2] = gen_reg_rtx (HImode);
+})
+
+(define_expand "popcounthi2"
+ [(set (match_dup 2)
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))
+ (set (match_operand:HI 0 "register_operand")
+ (truncate:HI (popcount:SI (match_dup 2))))]
+ ""
+{
+ operands[2] = gen_reg_rtx (SImode);
+})
+
(define_insn "smaxsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(smax:SI (match_operand:SI 1 "register_operand" "d")
diff --git a/gcc/config/bpf/bpf-opts.h b/gcc/config/bpf/bpf-opts.h
index 1bc930c..456e39c 100644
--- a/gcc/config/bpf/bpf-opts.h
+++ b/gcc/config/bpf/bpf-opts.h
@@ -53,4 +53,11 @@ enum bpf_kernel_version
LINUX_NATIVE,
};
+enum bpf_isa_version
+{
+ ISA_V1,
+ ISA_V2,
+ ISA_V3,
+};
+
#endif /* ! BPF_OPTS_H */
diff --git a/gcc/config/bpf/bpf-passes.def b/gcc/config/bpf/bpf-passes.def
new file mode 100644
index 0000000..3e96165
--- /dev/null
+++ b/gcc/config/bpf/bpf-passes.def
@@ -0,0 +1,20 @@
+/* Declaration of target-specific passes for eBPF.
+ Copyright (C) 2021 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/>. */
+
+INSERT_PASS_AFTER (pass_df_initialize_opt, 1, pass_bpf_core_attr);
diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
index aeb5126..e6bb901 100644
--- a/gcc/config/bpf/bpf-protos.h
+++ b/gcc/config/bpf/bpf-protos.h
@@ -29,5 +29,8 @@ extern void bpf_print_operand (FILE *, rtx, int);
extern void bpf_print_operand_address (FILE *, rtx);
extern void bpf_expand_prologue (void);
extern void bpf_expand_epilogue (void);
+extern void bpf_expand_cbranch (machine_mode, rtx *);
+
+rtl_opt_pass * make_pass_bpf_core_attr (gcc::context *);
#endif /* ! GCC_BPF_PROTOS_H */
diff --git a/gcc/config/bpf/bpf.c b/gcc/config/bpf/bpf.c
index e635f9e..82bb698 100644
--- a/gcc/config/bpf/bpf.c
+++ b/gcc/config/bpf/bpf.c
@@ -54,6 +54,25 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "predict.h"
#include "langhooks.h"
+#include "flags.h"
+
+#include "cfg.h" /* needed for struct control_flow_graph used in BB macros */
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "tree-pass.h"
+#include "tree-iterator.h"
+
+#include "context.h"
+#include "pass_manager.h"
+
+#include "gimplify.h"
+#include "gimplify-me.h"
+
+#include "ctfc.h"
+#include "btf.h"
+
+#include "coreout.h"
/* Per-function machine data. */
struct GTY(()) machine_function
@@ -104,6 +123,27 @@ bpf_handle_fndecl_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle preserve_access_index attribute, which can be applied to structs,
+ unions and classes. Actually adding the attribute to the TYPE_DECL is
+ taken care of for us, so just warn for types that aren't supported. */
+
+static tree
+bpf_handle_preserve_access_index_attribute (tree *node, tree name,
+ tree args,
+ int flags,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute only applies to structure, union and class types",
+ name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Target-specific attributes. */
static const struct attribute_spec bpf_attribute_table[] =
@@ -116,6 +156,11 @@ static const struct attribute_spec bpf_attribute_table[] =
{ "kernel_helper", 1, 1, true, false, false, false,
bpf_handle_fndecl_attribute, NULL },
+ /* CO-RE support: attribute to mark that all accesses to the declared
+ struct/union/array should be recorded. */
+ { "preserve_access_index", 0, -1, false, true, false, true,
+ bpf_handle_preserve_access_index_attribute, NULL },
+
/* The last attribute spec is set to be NULL. */
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -136,11 +181,18 @@ enum bpf_builtins
BPF_BUILTIN_LOAD_BYTE,
BPF_BUILTIN_LOAD_HALF,
BPF_BUILTIN_LOAD_WORD,
+
+ /* Compile Once - Run Everywhere (CO-RE) support. */
+ BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
+
BPF_BUILTIN_MAX,
};
static GTY (()) tree bpf_builtins[(int) BPF_BUILTIN_MAX];
+
+void bpf_register_coreattr_pass (void);
+
/* Initialize the per-function machine status. */
static struct machine_function *
@@ -158,11 +210,92 @@ bpf_option_override (void)
{
/* Set the initializer for the per-function status structure. */
init_machine_status = bpf_init_machine_status;
+
+ /* BPF CO-RE support requires BTF debug info generation. */
+ if (TARGET_BPF_CORE && !btf_debuginfo_p ())
+ error ("BPF CO-RE requires BTF debugging information, use %<-gbtf%>");
+
+ /* To support the portability needs of BPF CO-RE approach, BTF debug
+ information includes the BPF CO-RE relocations. */
+ if (TARGET_BPF_CORE)
+ write_symbols |= BTF_WITH_CORE_DEBUG;
+
+ /* Unlike much of the other BTF debug information, the information necessary
+ for CO-RE relocations is added to the CTF container by the BPF backend.
+ Enabling LTO adds some complications in the generation of the BPF CO-RE
+ relocations because if LTO is in effect, the relocations need to be
+ generated late in the LTO link phase. This poses a new challenge for the
+ compiler to now provide means to combine the early BTF and late BTF CO-RE
+ debug info, similar to DWARF debug info. BTF/CO-RE debug info is not
+ amenable to such a split generation and a later merging.
+
+ In any case, in absence of linker support for BTF sections at this time,
+ it is acceptable to simply disallow LTO for BPF CO-RE compilations. */
+
+ if (flag_lto && TARGET_BPF_CORE)
+ sorry ("BPF CO-RE does not support LTO");
+
+ /* -gbtf implies -mcore when using the BPF backend, unless -mno-co-re
+ is specified. */
+ if (btf_debuginfo_p () && !(target_flags_explicit & MASK_BPF_CORE))
+ {
+ target_flags |= MASK_BPF_CORE;
+ write_symbols |= BTF_WITH_CORE_DEBUG;
+ }
+
+ /* Determine available features from ISA setting (-mcpu=). */
+ if (bpf_has_jmpext == -1)
+ bpf_has_jmpext = (bpf_isa >= ISA_V2);
+
+ if (bpf_has_alu32 == -1)
+ bpf_has_alu32 = (bpf_isa >= ISA_V3);
+
+ if (bpf_has_jmp32 == -1)
+ bpf_has_jmp32 = (bpf_isa >= ISA_V3);
+
}
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE bpf_option_override
+/* Return FALSE iff -mcore has been specified. */
+
+static bool
+ctfc_debuginfo_early_finish_p (void)
+{
+ if (TARGET_BPF_CORE)
+ return false;
+ else
+ return true;
+}
+
+#undef TARGET_CTFC_DEBUGINFO_EARLY_FINISH_P
+#define TARGET_CTFC_DEBUGINFO_EARLY_FINISH_P ctfc_debuginfo_early_finish_p
+
+/* Implement TARGET_ASM_INIT_SECTIONS. */
+
+static void
+bpf_asm_init_sections (void)
+{
+ if (TARGET_BPF_CORE)
+ btf_ext_init ();
+}
+
+#undef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS bpf_asm_init_sections
+
+/* Implement TARGET_ASM_FILE_END. */
+
+static void
+bpf_file_end (void)
+{
+ if (TARGET_BPF_CORE)
+ btf_ext_output ();
+}
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END bpf_file_end
+
/* Define target-specific CPP macros. This function in used in the
definition of TARGET_CPU_CPP_BUILTINS in bpf.h */
@@ -418,6 +551,36 @@ bpf_expand_epilogue (void)
emit_jump_insn (gen_exit ());
}
+/* Expand to the instructions for a conditional branch. This function
+ is called when expanding the 'cbranch<mode>4' pattern in bpf.md. */
+
+void
+bpf_expand_cbranch (machine_mode mode, rtx *operands)
+{
+ /* If all jump instructions are available, nothing special to do here. */
+ if (bpf_has_jmpext)
+ return;
+
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ /* Without the conditional branch instructions jslt, jsle, jlt, jle, we need
+ to convert conditional branches that would use them to an available
+ operation instead by reversing the comparison. */
+ if ((code == LT || code == LE || code == LTU || code == LEU))
+ {
+ /* Reverse the condition. */
+ PUT_CODE (operands[0], reverse_condition (code));
+
+ /* Swap the operands, and ensure that the first is a register. */
+ if (!register_operand (operands[2], mode))
+ operands[2] = force_reg (mode, operands[2]);
+
+ rtx tmp = operands[1];
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+}
+
/* Return the initial difference between the specified pair of
registers. The registers that can figure in FROM, and TO, are
specified by ELIMINABLE_REGS in bpf.h.
@@ -812,11 +975,18 @@ bpf_init_builtins (void)
build_function_type_list (ullt, ullt, 0));
def_builtin ("__builtin_bpf_load_word", BPF_BUILTIN_LOAD_WORD,
build_function_type_list (ullt, ullt, 0));
+ def_builtin ("__builtin_preserve_access_index",
+ BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
+ build_function_type_list (ptr_type_node, ptr_type_node, 0));
}
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS bpf_init_builtins
+static tree bpf_core_compute (tree, vec<unsigned int> *);
+static int bpf_core_get_index (const tree);
+static bool is_attr_preserve_access (tree);
+
/* Expand a call to a BPF-specific built-in function that was set up
with bpf_init_builtins. */
@@ -867,7 +1037,75 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
/* The result of the load is in R0. */
return gen_rtx_REG (ops[0].mode, BPF_R0);
}
+ else if (code == -1)
+ {
+ /* A resolved overloaded builtin, e.g. __bpf_preserve_access_index_si */
+ tree arg = CALL_EXPR_ARG (exp, 0);
+ if (arg == NULL_TREE)
+ return NULL_RTX;
+
+ auto_vec<unsigned int, 16> accessors;
+ tree container;
+
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (arg);
+
+ if (is_gimple_assign (def_stmt))
+ arg = gimple_assign_rhs1 (def_stmt);
+ else
+ return expand_normal (arg);
+ }
+
+ /* Avoid double-recording information if the argument is an access to
+ a struct/union marked __attribute__((preserve_access_index)). This
+ Will be handled by the attribute handling pass. */
+ if (is_attr_preserve_access (arg))
+ return expand_normal (arg);
+
+ container = bpf_core_compute (arg, &accessors);
+
+ /* Any valid use of the builtin must have at least one access. Otherwise,
+ there is nothing to record and nothing to do. This is primarily a
+ guard against optimizations leading to unexpected expressions in the
+ argument of the builtin. For example, if the builtin is used to read
+ a field of a structure which can be statically determined to hold a
+ constant value, the argument to the builtin will be optimized to that
+ constant. This is OK, and means the builtin call is superfluous.
+ e.g.
+ struct S foo;
+ foo.a = 5;
+ int x = __preserve_access_index (foo.a);
+ ... do stuff with x
+ 'foo.a' in the builtin argument will be optimized to '5' with -01+.
+ This sequence does not warrant recording a CO-RE relocation. */
+
+ if (accessors.length () < 1)
+ return expand_normal (arg);
+
+ accessors.reverse ();
+
+ container = TREE_TYPE (container);
+
+ rtx_code_label *label = gen_label_rtx ();
+ LABEL_PRESERVE_P (label) = 1;
+ emit_label (label);
+
+ /* Determine what output section this relocation will apply to.
+ If this function is associated with a section, use that. Otherwise,
+ fall back on '.text'. */
+ const char * section_name;
+ if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
+ section_name = DECL_SECTION_NAME (current_function_decl);
+ else
+ section_name = ".text";
+
+ /* Add the CO-RE relocation information to the BTF container. */
+ bpf_core_reloc_add (container, section_name, &accessors, label);
+
+ return expand_normal (arg);
+ }
gcc_unreachable ();
}
@@ -921,6 +1159,425 @@ bpf_debug_unwind_info ()
#undef TARGET_ASM_ALIGNED_DI_OP
#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
+
+/* BPF Compile Once - Run Everywhere (CO-RE) support routines.
+
+ BPF CO-RE is supported in two forms:
+ - A target builtin, __builtin_preserve_access_index
+
+ This builtin accepts a single argument. Any access to an aggregate data
+ structure (struct, union or array) within the argument will be recorded by
+ the CO-RE machinery, resulting in a relocation record being placed in the
+ .BTF.ext section of the output.
+
+ It is implemented in bpf_resolve_overloaded_builtin () and
+ bpf_expand_builtin (), using the supporting routines below.
+
+ - An attribute, __attribute__((preserve_access_index))
+
+ This attribute can be applied to struct and union types. Any access to a
+ type with this attribute will be recorded by the CO-RE machinery.
+
+ The pass pass_bpf_core_attr, below, implements support for
+ this attribute. */
+
+/* Traverse the subtree under NODE, which is expected to be some form of
+ aggregate access the CO-RE machinery cares about (like a read of a member of
+ a struct or union), collecting access indices for the components and storing
+ them in the vector referenced by ACCESSORS.
+
+ Return the ultimate (top-level) container of the aggregate access. In general,
+ this will be a VAR_DECL or some kind of REF.
+
+ Note that the accessors are computed *in reverse order* of how the BPF
+ CO-RE machinery defines them. The vector needs to be reversed (or simply
+ output in reverse order) for the .BTF.ext relocation information. */
+
+static tree
+bpf_core_compute (tree node, vec<unsigned int> *accessors)
+{
+
+ if (TREE_CODE (node) == ADDR_EXPR)
+ node = TREE_OPERAND (node, 0);
+
+ else if (TREE_CODE (node) == INDIRECT_REF
+ || TREE_CODE (node) == POINTER_PLUS_EXPR)
+ {
+ accessors->safe_push (0);
+ return TREE_OPERAND (node, 0);
+ }
+
+ while (1)
+ {
+ switch (TREE_CODE (node))
+ {
+ case COMPONENT_REF:
+ accessors->safe_push (bpf_core_get_index (TREE_OPERAND (node, 1)));
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ accessors->safe_push (bpf_core_get_index (node));
+ break;
+
+ case MEM_REF:
+ accessors->safe_push (bpf_core_get_index (node));
+ if (TREE_CODE (TREE_OPERAND (node, 0)) == ADDR_EXPR)
+ node = TREE_OPERAND (TREE_OPERAND (node, 0), 0);
+ goto done;
+
+ default:
+ goto done;
+ }
+ node = TREE_OPERAND (node, 0);
+ }
+ done:
+ return node;
+
+}
+
+/* Compute the index of the NODE in its immediate container.
+ NODE should be a FIELD_DECL (i.e. of struct or union), or an ARRAY_REF. */
+static int
+bpf_core_get_index (const tree node)
+{
+ enum tree_code code = TREE_CODE (node);
+
+ if (code == FIELD_DECL)
+ {
+ /* Lookup the index from the BTF information. Some struct/union members
+ may not be emitted in BTF; only the BTF container has enough
+ information to compute the correct index. */
+ int idx = bpf_core_get_sou_member_index (ctf_get_tu_ctfc (), node);
+ if (idx >= 0)
+ return idx;
+ }
+
+ else if (code == ARRAY_REF || code == ARRAY_RANGE_REF || code == MEM_REF)
+ {
+ /* For array accesses, the index is operand 1. */
+ tree index = TREE_OPERAND (node, 1);
+
+ /* If the indexing operand is a constant, extracting is trivial. */
+ if (TREE_CODE (index) == INTEGER_CST && tree_fits_shwi_p (index))
+ return tree_to_shwi (index);
+ }
+
+ return -1;
+}
+
+/* Synthesize a new builtin function declaration at LOC with signature TYPE.
+ Used by bpf_resolve_overloaded_builtin to resolve calls to
+ __builtin_preserve_access_index. */
+
+static tree
+bpf_core_newdecl (location_t loc, tree type)
+{
+ tree rettype = build_function_type_list (type, type, NULL);
+ tree newdecl = NULL_TREE;
+ char name[80];
+ int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
+
+ static unsigned long cnt = 0;
+ len = snprintf (name + len, sizeof (name) - len, "%lu", cnt++);
+
+ return add_builtin_function_ext_scope (name, rettype, -1, BUILT_IN_MD, NULL,
+ NULL_TREE);
+}
+
+/* Return whether EXPR could access some aggregate data structure that
+ BPF CO-RE support needs to know about. */
+
+static int
+bpf_core_is_maybe_aggregate_access (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+ if (code == COMPONENT_REF || code == ARRAY_REF)
+ return 1;
+
+ if (code == ADDR_EXPR)
+ return bpf_core_is_maybe_aggregate_access (TREE_OPERAND (expr, 0));
+
+ return 0;
+}
+
+/* Callback function used with walk_tree from bpf_resolve_overloaded_builtin. */
+
+static tree
+bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
+{
+ location_t loc = *((location_t *) data);
+
+ /* If this is a type, don't do anything. */
+ if (TYPE_P (*tp))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (bpf_core_is_maybe_aggregate_access (*tp))
+ {
+ tree newdecl = bpf_core_newdecl (loc, TREE_TYPE (*tp));
+ tree newcall = build_call_expr_loc (loc, newdecl, 1, *tp);
+ *tp = newcall;
+ *walk_subtrees = 0;
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN (see gccint manual section
+ Target Macros::Misc.).
+ We use this for the __builtin_preserve_access_index builtin for CO-RE
+ support.
+
+ FNDECL is the declaration of the builtin, and ARGLIST is the list of
+ arguments passed to it, and is really a vec<tree,_> *.
+
+ In this case, the 'operation' implemented by the builtin is a no-op;
+ the builtin is just a marker. So, the result is simply the argument. */
+
+static tree
+bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
+{
+ if (DECL_MD_FUNCTION_CODE (fndecl) != BPF_BUILTIN_PRESERVE_ACCESS_INDEX)
+ return NULL_TREE;
+
+ /* We only expect one argument, but it may be an arbitrarily-complicated
+ statement-expression. */
+ vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (arglist);
+ unsigned n_params = params ? params->length() : 0;
+
+ if (n_params != 1)
+ {
+ error_at (loc, "expected exactly 1 argument");
+ return NULL_TREE;
+ }
+
+ tree param = (*params)[0];
+
+ /* If not generating BPF_CORE information, the builtin does nothing. */
+ if (!TARGET_BPF_CORE)
+ return param;
+
+ /* Do remove_c_maybe_const_expr for the arg.
+ TODO: WHY do we have to do this here? Why doesn't c-typeck take care
+ of it before or after this hook? */
+ if (TREE_CODE (param) == C_MAYBE_CONST_EXPR)
+ param = C_MAYBE_CONST_EXPR_EXPR (param);
+
+ /* Construct a new function declaration with the correct type, and return
+ a call to it.
+
+ Calls with statement-expressions, for example:
+ _(({ foo->a = 1; foo->u[2].b = 2; }))
+ require special handling.
+
+ We rearrange this into a new block scope in which each statement
+ becomes a unique builtin call:
+ {
+ _ ({ foo->a = 1;});
+ _ ({ foo->u[2].b = 2;});
+ }
+
+ This ensures that all the relevant information remains within the
+ expression trees the builtin finally gets. */
+
+ walk_tree (&param, bpf_core_walk, (void *) &loc, NULL);
+
+ return param;
+}
+
+#undef TARGET_RESOLVE_OVERLOADED_BUILTIN
+#define TARGET_RESOLVE_OVERLOADED_BUILTIN bpf_resolve_overloaded_builtin
+
+
+/* Handling for __attribute__((preserve_access_index)) for BPF CO-RE support.
+
+ This attribute marks a structure/union/array type as "preseve", so that
+ every access to that type should be recorded and replayed by the BPF loader;
+ this is just the same functionality as __builtin_preserve_access_index,
+ but in the form of an attribute for an entire aggregate type.
+
+ Note also that nested structs behave as though they all have the attribute.
+ For example:
+ struct X { int a; };
+ struct Y { struct X bar} __attribute__((preserve_access_index));
+ struct Y foo;
+ foo.bar.a;
+ will record access all the way to 'a', even though struct X does not have
+ the preserve_access_index attribute.
+
+ This is to follow LLVM behavior.
+
+ This pass finds all accesses to objects of types marked with the attribute,
+ and wraps them in the same "low-level" builtins used by the builtin version.
+ All logic afterwards is therefore identical to the builtin version of
+ preserve_access_index. */
+
+/* True iff tree T accesses any member of a struct/union/class which is marked
+ with the PRESERVE_ACCESS_INDEX attribute. */
+
+static bool
+is_attr_preserve_access (tree t)
+{
+ if (t == NULL_TREE)
+ return false;
+
+ poly_int64 bitsize, bitpos;
+ tree var_off;
+ machine_mode mode;
+ int sign, reverse, vol;
+
+ tree base = get_inner_reference (t, &bitsize, &bitpos, &var_off, &mode,
+ &sign, &reverse, &vol);
+
+ if (TREE_CODE (base) == MEM_REF)
+ {
+ return lookup_attribute ("preserve_access_index",
+ TYPE_ATTRIBUTES (TREE_TYPE (base)));
+ }
+
+ if (TREE_CODE (t) == COMPONENT_REF)
+ {
+ /* preserve_access_index propegates into nested structures,
+ so check whether this is a component of another component
+ which in turn is part of such a struct. */
+
+ const tree op = TREE_OPERAND (t, 0);
+
+ if (TREE_CODE (op) == COMPONENT_REF)
+ return is_attr_preserve_access (op);
+
+ const tree container = DECL_CONTEXT (TREE_OPERAND (t, 1));
+
+ return lookup_attribute ("preserve_access_index",
+ TYPE_ATTRIBUTES (container));
+ }
+
+ else if (TREE_CODE (t) == ADDR_EXPR)
+ return is_attr_preserve_access (TREE_OPERAND (t, 0));
+
+ return false;
+}
+
+/* The body of pass_bpf_core_attr. Scan RTL for accesses to structs/unions
+ marked with __attribute__((preserve_access_index)) and generate a CO-RE
+ relocation for any such access. */
+
+static void
+handle_attr_preserve (function *fn)
+{
+ basic_block bb;
+ rtx_insn *insn;
+ rtx_code_label *label;
+ FOR_EACH_BB_FN (bb, fn)
+ {
+ FOR_BB_INSNS (bb, insn)
+ {
+ if (!NONJUMP_INSN_P (insn))
+ continue;
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) != SET)
+ continue;
+
+ start_sequence();
+
+ for (int i = 0; i < 2; i++)
+ {
+ rtx mem = XEXP (pat, i);
+ if (MEM_P (mem))
+ {
+ tree expr = MEM_EXPR (mem);
+ if (!expr)
+ continue;
+
+ if (TREE_CODE (expr) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (expr, 0));
+ if (is_gimple_assign (def_stmt))
+ expr = gimple_assign_rhs1 (def_stmt);
+ }
+
+ if (is_attr_preserve_access (expr))
+ {
+ auto_vec<unsigned int, 16> accessors;
+ tree container = bpf_core_compute (expr, &accessors);
+ if (accessors.length () < 1)
+ continue;
+ accessors.reverse ();
+
+ container = TREE_TYPE (container);
+ const char * section_name;
+ if (DECL_SECTION_NAME (fn->decl))
+ section_name = DECL_SECTION_NAME (fn->decl);
+ else
+ section_name = ".text";
+
+ label = gen_label_rtx ();
+ LABEL_PRESERVE_P (label) = 1;
+ emit_label (label);
+
+ /* Add the CO-RE relocation information to the BTF container. */
+ bpf_core_reloc_add (container, section_name, &accessors, label);
+ }
+ }
+ }
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ emit_insn_before (seq, insn);
+ }
+ }
+}
+
+
+/* This pass finds accesses to structures marked with the BPF target attribute
+ __attribute__((preserve_access_index)). For every such access, a CO-RE
+ relocation record is generated, to be output in the .BTF.ext section. */
+
+namespace {
+
+const pass_data pass_data_bpf_core_attr =
+{
+ RTL_PASS, /* type */
+ "bpf_core_attr", /* 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_bpf_core_attr : public rtl_opt_pass
+{
+public:
+ pass_bpf_core_attr (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_bpf_core_attr, ctxt)
+ {}
+
+ virtual bool gate (function *) { return TARGET_BPF_CORE; }
+ virtual unsigned int execute (function *);
+};
+
+unsigned int
+pass_bpf_core_attr::execute (function *fn)
+{
+ handle_attr_preserve (fn);
+ return 0;
+}
+
+} /* Anonymous namespace. */
+
+rtl_opt_pass *
+make_pass_bpf_core_attr (gcc::context *ctxt)
+{
+ return new pass_bpf_core_attr (ctxt);
+}
+
/* Finally, build the GCC target. */
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 03830cc..436c8df 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -100,9 +100,9 @@
;; insns, with the proper modes.
;;
;; 32-bit arithmetic (for SI modes) is implemented using the alu32
-;; instructions.
+;; instructions, if available.
-(define_mode_iterator AM [SI DI])
+(define_mode_iterator AM [(SI "bpf_has_alu32") DI])
;;; Addition
(define_insn "add<AM:mode>3"
@@ -241,22 +241,24 @@
;; the ldx{bhwdw} instructions to load the values in registers.
(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "0,r,m")))]
""
"@
and\t%0,0xffff
+ mov\t%0,%1\;and\t%0,0xffff
ldxh\t%0,%1"
- [(set_attr "type" "alu,ldx")])
+ [(set_attr "type" "alu,alu,ldx")])
(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "0,r,m")))]
""
"@
and\t%0,0xff
+ mov\t%0,%1\;and\t%0,0xff
ldxb\t%0,%1"
- [(set_attr "type" "alu,ldx")])
+ [(set_attr "type" "alu,alu,ldx")])
(define_insn "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
@@ -264,7 +266,7 @@
(match_operand:SI 1 "nonimmediate_operand" "r,m")))]
""
"@
- mov32\t%0,%1
+ * return bpf_has_alu32 ? \"mov32\t%0,%1\" : \"mov\t%0,%1\;and\t%0,0xffffffff\";
ldxw\t%0,%1"
[(set_attr "type" "alu,ldx")])
@@ -313,7 +315,7 @@
;;;; Shifts
-(define_mode_iterator SIM [SI DI])
+(define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
(define_insn "ashr<SIM:mode>3"
[(set (match_operand:SIM 0 "register_operand" "=r,r")
@@ -344,24 +346,28 @@
;; The eBPF jump instructions use 64-bit arithmetic when evaluating
;; the jump conditions. Therefore we use DI modes below.
-(define_expand "cbranchdi4"
+(define_mode_iterator JM [(SI "bpf_has_jmp32") DI])
+
+(define_expand "cbranch<JM:mode>4"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "reg_or_imm_operand")])
+ [(match_operand:JM 1 "register_operand")
+ (match_operand:JM 2 "reg_or_imm_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
""
{
if (!ordered_comparison_operator (operands[0], VOIDmode))
FAIL;
+
+ bpf_expand_cbranch (<JM:MODE>mode, operands);
})
-(define_insn "*branch_on_di"
+(define_insn "*branch_on_<JM:mode>"
[(set (pc)
(if_then_else (match_operator 3 "ordered_comparison_operator"
- [(match_operand:DI 0 "register_operand" "r")
- (match_operand:DI 1 "reg_or_imm_operand" "rI")])
+ [(match_operand:JM 0 "register_operand" "r")
+ (match_operand:JM 1 "reg_or_imm_operand" "rI")])
(label_ref (match_operand 2 "" ""))
(pc)))]
""
@@ -370,16 +376,16 @@
switch (code)
{
- case EQ: return "jeq\t%0,%1,%2"; break;
- case NE: return "jne\t%0,%1,%2"; break;
- case LT: return "jslt\t%0,%1,%2"; break;
- case LE: return "jsle\t%0,%1,%2"; break;
- case GT: return "jsgt\t%0,%1,%2"; break;
- case GE: return "jsge\t%0,%1,%2"; break;
- case LTU: return "jlt\t%0,%1,%2"; break;
- case LEU: return "jle\t%0,%1,%2"; break;
- case GTU: return "jgt\t%0,%1,%2"; break;
- case GEU: return "jge\t%0,%1,%2"; break;
+ case EQ: return "jeq<msuffix>\t%0,%1,%2"; break;
+ case NE: return "jne<msuffix>\t%0,%1,%2"; break;
+ case LT: return "jslt<msuffix>\t%0,%1,%2"; break;
+ case LE: return "jsle<msuffix>\t%0,%1,%2"; break;
+ case GT: return "jsgt<msuffix>\t%0,%1,%2"; break;
+ case GE: return "jsge<msuffix>\t%0,%1,%2"; break;
+ case LTU: return "jlt<msuffix>\t%0,%1,%2"; break;
+ case LEU: return "jle<msuffix>\t%0,%1,%2"; break;
+ case GTU: return "jgt<msuffix>\t%0,%1,%2"; break;
+ case GEU: return "jge<msuffix>\t%0,%1,%2"; break;
default:
gcc_unreachable ();
return "";
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index 916b53c..e8b728c 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -127,3 +127,36 @@ Generate little-endian eBPF.
mframe-limit=
Target Joined RejectNegative UInteger IntegerRange(0, 32767) Var(bpf_frame_limit) Init(512)
Set a hard limit for the size of each stack frame, in bytes.
+
+mco-re
+Target Mask(BPF_CORE)
+Generate all necessary information for BPF Compile Once - Run Everywhere.
+
+; Selecting BPF ISA features and versions
+
+mjmpext
+Target Var(bpf_has_jmpext) Init(-1)
+Enable extra conditional-branch instructions j(s)lt and j(s)le.
+
+malu32
+Target Var(bpf_has_alu32) Init(-1)
+Enable 32-bit ALU instructions.
+
+mjmp32
+Target Var(bpf_has_jmp32) Init(-1)
+Enable 32-bit jump instructions.
+
+mcpu=
+Target RejectNegative Joined Var(bpf_isa) Enum(bpf_isa) Init(ISA_V3)
+
+Enum
+Name(bpf_isa) Type(enum bpf_isa_version)
+
+EnumValue
+Enum(bpf_isa) String(v1) Value(ISA_V1)
+
+EnumValue
+Enum(bpf_isa) String(v2) Value(ISA_V2)
+
+EnumValue
+Enum(bpf_isa) String(v3) Value(ISA_V3)
diff --git a/gcc/config/bpf/coreout.c b/gcc/config/bpf/coreout.c
new file mode 100644
index 0000000..d5486b4
--- /dev/null
+++ b/gcc/config/bpf/coreout.c
@@ -0,0 +1,356 @@
+/* BPF Compile Once - Run Everywhere (CO-RE) support.
+ Copyright (C) 2021 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "output.h"
+#include "dwarf2asm.h"
+#include "ctfc.h"
+#include "btf.h"
+#include "rtl.h"
+
+#include "coreout.h"
+
+/* This file contains data structures and routines for construction and output
+ of BPF Compile Once - Run Everywhere (BPF CO-RE) information.
+
+ eBPF programs written in C usually include Linux kernel headers, so that
+ they may interact with kernel data structures in a useful way. This
+ intrudces two major portability issues:
+
+ 1. Kernel data structures regularly change, with fields added, moved or
+ deleted between versions. An eBPF program cannot in general be expected
+ to run on any systems which does not share an identical kernel version to
+ the system on which it was compiled.
+
+ 2. Included kernel headers (and used data structures) may be internal, not
+ exposed in an userspace API, and therefore target-specific. An eBPF
+ program compiled on an x86_64 machine will include x86_64 kernel headers.
+ The resulting program may not run well (or at all) in machines of
+ another architecture.
+
+ BPF CO-RE is designed to solve the first issue by leveraging the BPF loader
+ to adjust references to kernel data structures made by the program as-needed
+ according to versions of structures actually present on the host kernel.
+
+ To achieve this, additional information is placed in a ".BTF.ext" section.
+ This information tells the loader which references will require adjusting,
+ and how to perform each necessary adjustment.
+
+ For any access to a data structure which may require load-time adjustment,
+ the following information is recorded (making up a CO-RE relocation record):
+ - The BTF type ID of the outermost structure which is accessed.
+ - An access string encoding the accessed member via a series of member and
+ array indexes. These indexes are used to look up detailed BTF information
+ about the member.
+ - The offset of the appropriate instruction to patch in the BPF program.
+ - An integer specifying what kind of relocation to perform.
+
+ A CO-RE-capable BPF loader reads this information together with the BTF
+ information of the program, compares it against BTF information of the host
+ kernel, and determines the appropriate way to patch the specified
+ instruction.
+
+ Once all CO-RE relocations are resolved, the program is loaded and verified
+ as usual. The process can be summarized with the following diagram:
+
+ +------------+
+ | C compiler |
+ +-----+------+
+ | BPF + BTF + CO-RE relocations
+ v
+ +------------+
+ +--->| BPF loader |
+ | +-----+------+
+ | | BPF (adapted)
+ BTF | v
+ | +------------+
+ +----+ Kernel |
+ +------------+
+
+ Note that a single ELF object may contain multiple eBPF programs. As a
+ result, a single .BTF.ext section can contain CO-RE relocations for multiple
+ programs in distinct sections. */
+
+/* Internal representation of a BPF CO-RE relocation record. */
+
+typedef struct GTY (()) bpf_core_reloc {
+ unsigned int bpfcr_type; /* BTF type ID of container. */
+ unsigned int bpfcr_astr_off; /* Offset of access string in .BTF
+ string table. */
+ rtx_code_label * bpfcr_insn_label; /* RTX label attached to instruction
+ to patch. */
+ enum btf_core_reloc_kind bpfcr_kind; /* Kind of relocation to perform. */
+} bpf_core_reloc_t;
+
+typedef bpf_core_reloc_t * bpf_core_reloc_ref;
+
+/* Internal representation of a CO-RE relocation (sub)section of the
+ .BTF.ext information. One such section is generated for each ELF section
+ in the output object having relocations that a BPF loader must resolve. */
+
+typedef struct GTY (()) bpf_core_section {
+ /* Name of ELF section to which these CO-RE relocations apply. */
+ const char * name;
+
+ /* Offset of section name in .BTF string table. */
+ uint32_t name_offset;
+
+ /* Relocations in the section. */
+ vec <bpf_core_reloc_ref, va_gc> * GTY (()) relocs;
+} bpf_core_section_t;
+
+typedef bpf_core_section_t * bpf_core_section_ref;
+
+/* BTF.ext debug info section. */
+
+static GTY (()) section * btf_ext_info_section;
+
+static int btf_ext_label_num;
+
+#ifndef BTF_EXT_INFO_SECTION_NAME
+#define BTF_EXT_INFO_SECTION_NAME ".BTF.ext"
+#endif
+
+#define BTF_EXT_INFO_SECTION_FLAGS (SECTION_DEBUG)
+
+#define MAX_BTF_EXT_LABEL_BYTES 40
+
+static char btf_ext_info_section_label[MAX_BTF_EXT_LABEL_BYTES];
+
+#ifndef BTF_EXT_INFO_SECTION_LABEL
+#define BTF_EXT_INFO_SECTION_LABEL "Lbtfext"
+#endif
+
+static GTY (()) vec<bpf_core_section_ref, va_gc> *bpf_core_sections;
+
+
+/* Create a new BPF CO-RE relocation record, and add it to the appropriate
+ CO-RE section. */
+
+void
+bpf_core_reloc_add (const tree type, const char * section_name,
+ vec<unsigned int> *accessors, rtx_code_label *label)
+{
+ char buf[40];
+ unsigned int i, n = 0;
+
+ /* A valid CO-RE access must have at least one accessor. */
+ if (accessors->length () < 1)
+ return;
+
+ for (i = 0; i < accessors->length () - 1; i++)
+ n += snprintf (buf + n, sizeof (buf) - n, "%u:", (*accessors)[i]);
+ snprintf (buf + n, sizeof (buf) - n, "%u", (*accessors)[i]);
+
+ bpf_core_reloc_ref bpfcr = ggc_cleared_alloc<bpf_core_reloc_t> ();
+ ctf_container_ref ctfc = ctf_get_tu_ctfc ();
+
+ /* Buffer the access string in the auxiliary strtab. Since the two string
+ tables are concatenated, add the length of the first to the offset. */
+ size_t strtab_len = ctfc_get_strtab_len (ctfc, CTF_STRTAB);
+ ctf_add_string (ctfc, buf, &(bpfcr->bpfcr_astr_off), CTF_AUX_STRTAB);
+ bpfcr->bpfcr_astr_off += strtab_len;
+
+ bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type));
+ bpfcr->bpfcr_insn_label = label;
+ bpfcr->bpfcr_kind = BPF_RELO_FIELD_BYTE_OFFSET;
+
+ /* Add the CO-RE reloc to the appropriate section. */
+ bpf_core_section_ref sec;
+ FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec)
+ if (strcmp (sec->name, section_name) == 0)
+ {
+ vec_safe_push (sec->relocs, bpfcr);
+ return;
+ }
+
+ /* If the CO-RE section does not yet exist, create it. */
+ sec = ggc_cleared_alloc<bpf_core_section_t> ();
+
+ ctf_add_string (ctfc, section_name, &sec->name_offset, CTF_AUX_STRTAB);
+ sec->name_offset += strtab_len;
+ if (strcmp (section_name, ""))
+ ctfc->ctfc_aux_strlen += strlen (section_name) + 1;
+
+ sec->name = section_name;
+ vec_alloc (sec->relocs, 1);
+ vec_safe_push (sec->relocs, bpfcr);
+
+ vec_safe_push (bpf_core_sections, sec);
+}
+
+/* Return the 0-based index of the field NODE in its containing struct or union
+ type. */
+
+int
+bpf_core_get_sou_member_index (ctf_container_ref ctfc, const tree node)
+{
+ if (TREE_CODE (node) == FIELD_DECL)
+ {
+ const tree container = DECL_CONTEXT (node);
+ const char * name = IDENTIFIER_POINTER (DECL_NAME (node));
+
+ /* Lookup the CTF type info for the containing type. */
+ dw_die_ref die = lookup_type_die (container);
+ if (die == NULL)
+ return -1;
+
+ ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die);
+ if (dtd == NULL)
+ return -1;
+
+ unsigned int kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info);
+ if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+ return -1;
+
+ int i = 0;
+ ctf_dmdef_t * dmd;
+ for (dmd = dtd->dtd_u.dtu_members;
+ dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+ {
+ if (get_btf_id (dmd->dmd_type) > BTF_MAX_TYPE)
+ continue;
+ if (strcmp (dmd->dmd_name, name) == 0)
+ return i;
+ i++;
+ }
+ }
+ return -1;
+}
+
+/* Compute and output the header of a .BTF.ext debug info section. */
+
+static void
+output_btfext_header (void)
+{
+ switch_to_section (btf_ext_info_section);
+ ASM_OUTPUT_LABEL (asm_out_file, btf_ext_info_section_label);
+
+ dw2_asm_output_data (2, BTF_MAGIC, "btf_magic");
+ dw2_asm_output_data (1, BTF_VERSION, "btfext_version");
+ dw2_asm_output_data (1, 0, "btfext_flags");
+ dw2_asm_output_data (4, sizeof (struct btf_ext_header), "btfext_hdr_len");
+
+ uint32_t func_info_off = 0, func_info_len = 0;
+ uint32_t line_info_off = 0, line_info_len = 0;
+ uint32_t core_relo_off = 0, core_relo_len = 0;
+
+ /* Header core_relo_len is the sum total length in bytes of all CO-RE
+ relocation sections. */
+ size_t i;
+ bpf_core_section_ref sec;
+ core_relo_len += vec_safe_length (bpf_core_sections)
+ * sizeof (struct btf_ext_section_header);
+
+ FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec)
+ core_relo_len +=
+ vec_safe_length (sec->relocs) * sizeof (struct btf_ext_reloc);
+
+ dw2_asm_output_data (4, func_info_off, "func_info_offset");
+ dw2_asm_output_data (4, func_info_len, "func_info_len");
+
+ dw2_asm_output_data (4, line_info_off, "line_info_offset");
+ dw2_asm_output_data (4, line_info_len, "line_info_len");
+
+ dw2_asm_output_data (4, core_relo_off, "core_relo_offset");
+ dw2_asm_output_data (4, core_relo_len, "core_relo_len");
+}
+
+/* Output a single CO-RE relocation record. */
+
+static void
+output_asm_btfext_core_reloc (bpf_core_reloc_ref bpfcr)
+{
+ dw2_assemble_integer (4, gen_rtx_LABEL_REF (Pmode, bpfcr->bpfcr_insn_label));
+ fprintf (asm_out_file, "\t%s bpfcr_insn\n", ASM_COMMENT_START);
+
+ dw2_asm_output_data (4, bpfcr->bpfcr_type, "bpfcr_type");
+ dw2_asm_output_data (4, bpfcr->bpfcr_astr_off, "bpfcr_astr_off");
+ dw2_asm_output_data (4, bpfcr->bpfcr_kind, "bpfcr_kind");
+}
+
+/* Output all CO-RE relocation records for a section. */
+
+static void
+output_btfext_core_relocs (bpf_core_section_ref sec)
+{
+ size_t i;
+ bpf_core_reloc_ref bpfcr;
+ FOR_EACH_VEC_ELT (*(sec->relocs), i, bpfcr)
+ output_asm_btfext_core_reloc (bpfcr);
+}
+
+/* Output all CO-RE relocation sections. */
+
+static void
+output_btfext_core_sections (void)
+{
+ size_t i;
+ bpf_core_section_ref sec;
+ FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec)
+ {
+ /* BTF Ext section info. */
+ dw2_asm_output_data (4, sizeof (struct btf_ext_reloc),
+ "btfext_secinfo_rec_size");
+
+ /* Section name offset, refers to the offset of a string with the name of
+ the section to which these CORE relocations refer, e.g. '.text'.
+ The string is buffered in the BTF strings table. */
+ dw2_asm_output_data (4, sec->name_offset, "btfext_secinfo_sec_name_off");
+ dw2_asm_output_data (4, vec_safe_length (sec->relocs),
+ "btfext_secinfo_num_recs");
+
+ output_btfext_core_relocs (sec);
+ }
+}
+
+/* Initialize sections, labels, and data structures for BTF.ext output. */
+
+void
+btf_ext_init (void)
+{
+ btf_ext_info_section = get_section (BTF_EXT_INFO_SECTION_NAME,
+ BTF_EXT_INFO_SECTION_FLAGS, NULL);
+
+ ASM_GENERATE_INTERNAL_LABEL (btf_ext_info_section_label,
+ BTF_EXT_INFO_SECTION_LABEL,
+ btf_ext_label_num++);
+
+ vec_alloc (bpf_core_sections, 1);
+}
+
+/* Output the entire .BTF.ext section. */
+
+void
+btf_ext_output (void)
+{
+ output_btfext_header ();
+ output_btfext_core_sections ();
+
+ bpf_core_sections = NULL;
+}
+
+#include "gt-coreout.h"
diff --git a/gcc/config/bpf/coreout.h b/gcc/config/bpf/coreout.h
new file mode 100644
index 0000000..82c203d
--- /dev/null
+++ b/gcc/config/bpf/coreout.h
@@ -0,0 +1,114 @@
+/* coreout.h - Declarations and definitions related to
+ BPF Compile Once - Run Everywhere (CO-RE) support.
+ Copyright (C) 2021 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 __COREOUT_H
+#define __COREOUT_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* .BTF.ext information. */
+
+struct btf_ext_section_header
+{
+ uint32_t kind;
+ uint32_t sec_name_off;
+ uint32_t num_records;
+};
+
+/* A funcinfo record, in the .BTF.ext funcinfo section. */
+struct btf_ext_funcinfo
+{
+ uint32_t insn_off; /* Offset of the first instruction of the function. */
+ uint32_t type; /* Type ID of a BTF_KIND_FUNC type. */
+};
+
+/* A lineinfo record, in the .BTF.ext lineinfo section. */
+struct btf_ext_lineinfo
+{
+ uint32_t insn_off; /* Offset of the instruction. */
+ uint32_t file_name_off; /* Offset of file name in BTF string table. */
+ uint32_t line_off; /* Offset of source line in BTF string table. */
+ uint32_t line_col; /* Line number (bits 31-11) and column (11-0). */
+};
+
+enum btf_core_reloc_kind
+{
+ BPF_RELO_FIELD_BYTE_OFFSET = 0,
+ BPF_RELO_FIELD_BYTE_SIZE = 1,
+ BPF_RELO_FIELD_EXISTS = 2,
+ BPF_RELO_FIELD_SIGNED = 3,
+ BPF_RELO_FIELD_LSHIFT_U64 = 4,
+ BPF_RELO_FIELD_RSHIFT_U64 = 5,
+ BPF_RELO_TYPE_ID_LOCAL = 6,
+ BPF_RELO_TYPE_ID_TARGET = 7,
+ BPF_RELO_TYPE_EXISTS = 8,
+ BPF_RELO_TYPE_SIZE = 9,
+ BPF_RELO_ENUMVAL_EXISTS = 10,
+ BPF_RELO_ENUMVAL_VALUE = 11
+};
+
+struct btf_ext_reloc
+{
+ uint32_t insn_off; /* Offset of instruction to be patched. A
+ section-relative label at compile time. */
+ uint32_t type_id; /* Type ID of the outermost containing entity, e.g.
+ the containing structure. */
+ uint32_t access_str_off; /* Offset of CO-RE accessor string in .BTF strings
+ section. */
+ uint32_t kind; /* An enum btf_core_reloc_kind. Note that it always
+ takes 32 bits. */
+};
+
+struct btf_ext_header
+{
+ uint16_t magic; /* Magic number (BTF_MAGIC). */
+ uint8_t version; /* Data format version (BTF_VERSION). */
+ uint8_t flags; /* Flags. Currently unused. */
+ uint32_t hdr_len; /* Length of this header in bytes. */
+
+ /* Following offsets are relative to the end of this header, in bytes.
+ Following lengths are in bytes. */
+ uint32_t func_info_off; /* Offset of funcinfo section. */
+ uint32_t func_info_len; /* Length of funcinfo section. */
+ uint32_t line_info_off; /* Offset of lineinfo section. */
+ uint32_t line_info_len; /* Length of lineinfo section. */
+
+ uint32_t core_relo_off; /* Offset of CO-RE relocation section. */
+ uint32_t core_relo_len; /* Length of CO-RE relocation section. */
+};
+
+extern void btf_ext_init (void);
+extern void btf_ext_output (void);
+
+extern void bpf_core_reloc_add (const tree, const char *, vec<unsigned int> *,
+ rtx_code_label *);
+extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __COREOUT_H */
diff --git a/gcc/config/bpf/t-bpf b/gcc/config/bpf/t-bpf
index e69de29..b37bf85 100644
--- a/gcc/config/bpf/t-bpf
+++ b/gcc/config/bpf/t-bpf
@@ -0,0 +1,8 @@
+
+TM_H += $(srcdir)/config/bpf/coreout.h
+
+coreout.o: $(srcdir)/config/bpf/coreout.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+PASSES_EXTRA += $(srcdir)/config/bpf/bpf-passes.def
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index ce49495..4854371 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -60,6 +60,7 @@
#include "dumpfile.h"
#include "builtins.h"
#include "flags.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -221,7 +222,7 @@ c6x_option_override (void)
{
unsigned i;
- if (global_options_set.x_c6x_arch_option)
+ if (OPTION_SET_P (c6x_arch_option))
{
c6x_arch = all_isas[c6x_arch_option].type;
c6x_insn_mask &= ~C6X_INSNS_ALL_CPU_BITS;
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 1ab830e..4276b6a7 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -901,24 +901,6 @@ struct cum_args {int regs;};
/* FIXME: Investigate DEBUGGER_AUTO_OFFSET, DEBUGGER_ARG_OFFSET. */
-/* Node: DBX Options */
-
-/* Is this correct? Check later. */
-#define DBX_NO_XREFS
-
-#define DBX_CONTIN_LENGTH 0
-
-/* FIXME: Is this needed when we have 0 DBX_CONTIN_LENGTH? */
-#define DBX_CONTIN_CHAR '?'
-
-
-/* Node: DBX Hooks */
-/* (no definitions) */
-
-/* Node: File names and DBX */
-/* (no definitions) */
-
-
/* Node: DWARF */
/* (no definitions) */
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
index e55821f..487288b 100644
--- a/gcc/config/csky/csky.c
+++ b/gcc/config/csky/csky.c
@@ -67,6 +67,7 @@
#include "pass_manager.h"
#include "tree-pass.h"
#include "context.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -2757,15 +2758,15 @@ csky_option_override (void)
#ifdef ENABLE_TPF_DEBUG
/* Don't emit DWARF4 unless specifically selected. The TPF
debuggers do not yet support DWARF 3/4. */
- if (!global_options_set.x_dwarf_strict)
+ if (!OPTION_SET_P (dwarf_strict))
dwarf_strict = 1;
- if (!global_options_set.x_dwarf_version)
+ if (!OPTION_SET_P (dwarf_version))
dwarf_version = 3;
#endif
/* Don't run the scheduler before reload by default,
since it tends to increase register pressure. */
- if (!global_options_set.x_flag_schedule_insns)
+ if (!OPTION_SET_P (flag_schedule_insns))
flag_schedule_insns = 0;
csky_add_gc_roots ();
diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c
index 3d7768f..a036e09 100644
--- a/gcc/config/darwin-driver.c
+++ b/gcc/config/darwin-driver.c
@@ -143,7 +143,7 @@ darwin_find_version_from_kernel (void)
if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion,
&osversion_len, NULL, 0) == -1)
{
- warning (0, "sysctl for kern.osversion failed: %m");
+ warning (0, "%<sysctl%> for %<kern.osversion%> failed: %m");
return NULL;
}
@@ -189,7 +189,7 @@ darwin_find_version_from_kernel (void)
return new_flag;
parse_failed:
- warning (0, "couldn%'t understand kern.osversion %q.*s",
+ warning (0, "could not understand %<kern.osversion%> %q.*s",
(int) osversion_len, osversion);
return NULL;
}
@@ -229,7 +229,7 @@ darwin_default_min_version (void)
const char *checked = validate_macosx_version_min (new_flag);
if (checked == NULL)
{
- warning (0, "could not understand version %s", new_flag);
+ warning (0, "could not understand version %qs", new_flag);
return NULL;
}
new_flag = xstrndup (checked, strlen (checked));
@@ -259,14 +259,11 @@ maybe_get_sysroot_from_sdkroot ()
return xstrndup (maybe_sysroot, strlen (maybe_sysroot));
}
-/* Translate -filelist and -framework options in *DECODED_OPTIONS
- (size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
- considered to be linker inputs in the case that no other inputs are
- specified. Handling these options in DRIVER_SELF_SPECS does not
- suffice because specs are too late to add linker inputs, and
- handling them in LINK_SPEC does not suffice because the linker will
- not be called if there are no other inputs. When native, also
- default the -mmacosx-version-min flag. */
+/* Handle the deduction of m32/m64 from -arch flags and the interactions
+ between them (i.e. try to warn a user who thinks that they have a driver
+ that can produce multi-slice "FAT" outputs with more than one arch).
+ Default the -mmacosx-version-min flag, which requires a system call on
+ native hosts. */
void
darwin_driver_init (unsigned int *decoded_options_count,
@@ -305,7 +302,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
else if (!strcmp ((*decoded_options)[i].arg, "ppc64"))
seenPPC64 = true;
else
- error ("this compiler does not support %s",
+ error ("this compiler does not support %qs",
(*decoded_options)[i].arg);
/* Now we've examined it, drop the -arch arg. */
if (*decoded_options_count > i) {
@@ -326,23 +323,6 @@ darwin_driver_init (unsigned int *decoded_options_count,
seenM64 = true;
break;
- case OPT_filelist:
- case OPT_framework:
- ++*decoded_options_count;
- *decoded_options = XRESIZEVEC (struct cl_decoded_option,
- *decoded_options,
- *decoded_options_count);
- memmove (*decoded_options + i + 2,
- *decoded_options + i + 1,
- ((*decoded_options_count - i - 2)
- * sizeof (struct cl_decoded_option)));
- generate_option (OPT_Xlinker, (*decoded_options)[i].arg, 1,
- CL_DRIVER, &(*decoded_options)[i + 1]);
- generate_option (OPT_Xlinker,
- (*decoded_options)[i].canonical_option[0], 1,
- CL_DRIVER, &(*decoded_options)[i]);
- break;
-
case OPT_mmacosx_version_min_:
seen_version_min = true;
vers_string =
@@ -377,45 +357,53 @@ darwin_driver_init (unsigned int *decoded_options_count,
/* Turn -arch xxxx into the appropriate -m32/-m64 flag.
If the User tried to specify multiple arch flags (which is possible with
some Darwin compilers) warn that this mode is not supported by this
- compiler (and ignore the arch flags, which means that the default multi-
- lib will be generated). */
+ compiler. We take arch specifiers that agree with the default multilib
+ as the first choice and reject others. */
/* TODO: determine if these warnings would better be errors. */
#if DARWIN_X86
if (seenPPC || seenPPC64)
- warning (0, "this compiler does not support PowerPC (arch flags ignored)");
+ warning (0, "this compiler does not support PowerPC"
+ " (%<-arch%> option ignored)");
if (seenX86)
{
if (seenX86_64 || seenM64)
- warning (0, "%s conflicts with i386 (arch flags ignored)",
- (seenX86_64? "x86_64": "m64"));
- else if (! seenM32) /* Add -m32 if the User didn't. */
+ {
+ const char *op = (seenX86_64? "-arch x86_64": "-m64");
+ warning (0, "%qs conflicts with %<-arch i386%> (%qs ignored)",
+ op, op);
+ }
+ if (! seenM32) /* Add -m32 if the User didn't. */
appendM32 = true;
}
else if (seenX86_64)
{
- if (seenX86 || seenM32)
- warning (0, "%s conflicts with x86_64 (arch flags ignored)",
- (seenX86? "i386": "m32"));
- else if (! seenM64) /* Add -m64 if the User didn't. */
+ if (seenM32)
+ warning (0, "%<-m32%> conflicts with %<-arch x86_64%>"
+ " (%<-m32%> ignored)");
+ if (! seenM64) /* Add -m64 if the User didn't. */
appendM64 = true;
}
#elif DARWIN_PPC
if (seenX86 || seenX86_64)
- warning (0, "this compiler does not support X86 (arch flags ignored)");
+ warning (0, "this compiler does not support x86"
+ " (%<-arch%> option ignored)");
if (seenPPC)
{
if (seenPPC64 || seenM64)
- warning (0, "%s conflicts with ppc (arch flags ignored)",
- (seenPPC64? "ppc64": "m64"));
- else if (! seenM32) /* Add -m32 if the User didn't. */
+ {
+ const char *op = (seenPPC64? "-arch ppc64": "-m64");
+ warning (0, "%qs conflicts with %<-arch ppc%> (%qs ignored)",
+ op, op);
+ }
+ if (! seenM32) /* Add -m32 if the User didn't. */
appendM32 = true;
}
else if (seenPPC64)
{
- if (seenPPC || seenM32)
- warning (0, "%s conflicts with ppc64 (arch flags ignored)",
- (seenPPC? "ppc": "m32"));
- else if (! seenM64) /* Add -m64 if the User didn't. */
+ if (seenM32)
+ warning (0, "%<-m32%> conflicts with %<-arch ppc64%>"
+ " (%<-m32%> ignored)");
+ if (! seenM64) /* Add -m64 if the User didn't. */
appendM64 = true;
}
#endif
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 5d1d13c..28dc55d 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -42,11 +42,13 @@ along with GCC; see the file COPYING3. If not see
#include "explow.h"
#include "expr.h"
#include "langhooks.h"
+#include "targhooks.h"
#include "toplev.h"
#include "lto-section-names.h"
#include "intl.h"
#include "optabs.h"
#include "flags.h"
+#include "opts.h"
/* Fix and Continue.
@@ -109,6 +111,9 @@ static bool ld_uses_coal_sects = false;
each FDE. */
static bool ld_needs_eh_markers = false;
+/* Emit a section-start symbol for mod init and term sections. */
+static bool ld_init_term_start_labels = false;
+
/* Section names. */
section * darwin_sections[NUM_DARWIN_SECTIONS];
@@ -1838,6 +1843,11 @@ finalize_ctors ()
else
switch_to_section (darwin_sections[constructor_section]);
+ /* Where needed, provide a linker-visible section-start symbol so that we
+ have stable output between debug and non-debug. */
+ if (ld_init_term_start_labels)
+ fputs (MACHOPIC_INDIRECT ? "_Mod.init:\n" : "_CTOR.sect:\n", asm_out_file);
+
if (vec_safe_length (ctors) > 1)
ctors->qsort (sort_cdtor_records);
FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
@@ -1858,6 +1868,11 @@ finalize_dtors ()
else
switch_to_section (darwin_sections[destructor_section]);
+ /* Where needed, provide a linker-visible section-start symbol so that we
+ have stable output between debug and non-debug. */
+ if (ld_init_term_start_labels)
+ fputs (MACHOPIC_INDIRECT ? "_Mod.term:\n" : "_DTOR.sect:\n", asm_out_file);
+
if (vec_safe_length (dtors) > 1)
dtors->qsort (sort_cdtor_records);
FOR_EACH_VEC_SAFE_ELT (dtors, i, elt)
@@ -3228,11 +3243,25 @@ darwin_override_options (void)
/* Earlier versions are not specifically accounted, until required. */
}
- /* Older Darwin ld could not coalesce weak entities without them being
- placed in special sections. */
- if (darwin_target_linker
- && (strverscmp (darwin_target_linker, MIN_LD64_NO_COAL_SECTS) < 0))
- ld_uses_coal_sects = true;
+ /* Some codegen needs to account for the capabilities of the target
+ linker. */
+ if (darwin_target_linker)
+ {
+ /* Older Darwin ld could not coalesce weak entities without them being
+ placed in special sections. */
+ if (strverscmp (darwin_target_linker, MIN_LD64_NO_COAL_SECTS) < 0)
+ ld_uses_coal_sects = true;
+
+ /* Some newer assemblers emit section start temp symbols for mod init
+ and term sections if there is no suitable symbol present already.
+ The temp symbols are linker visible and therefore appear in the
+ symbol tables. Since the temp symbol number can vary when debug is
+ enabled, that causes compare-debug fails. The solution is to provide
+ a stable linker-visible symbol. */
+ if (strverscmp (darwin_target_linker,
+ MIN_LD64_INIT_TERM_START_LABELS) >= 0)
+ ld_init_term_start_labels = true;
+ }
/* In principle, this should be c-family only. However, we really need to
set sensible defaults for LTO as well, since the section selection stuff
@@ -3254,7 +3283,7 @@ darwin_override_options (void)
}
/* Unless set, force ABI=2 for NeXT and m64, 0 otherwise. */
- if (!global_options_set.x_flag_objc_abi)
+ if (!OPTION_SET_P (flag_objc_abi))
global_options.x_flag_objc_abi
= (!flag_next_runtime)
? 0
@@ -3262,7 +3291,7 @@ darwin_override_options (void)
: (generating_for_darwin_version >= 9) ? 1
: 0);
- if (global_options_set.x_flag_objc_abi && flag_next_runtime)
+ if (OPTION_SET_P (flag_objc_abi) && flag_next_runtime)
{
if (TARGET_64BIT && global_options.x_flag_objc_abi != 2)
/* The Objective-C family ABI 2 is the only valid version NeXT/m64. */
@@ -3279,23 +3308,23 @@ darwin_override_options (void)
/* Don't emit DWARF3/4 unless specifically selected. This is a
workaround for tool bugs. */
- if (!global_options_set.x_dwarf_strict)
+ if (!OPTION_SET_P (dwarf_strict))
dwarf_strict = 1;
- if (!global_options_set.x_dwarf_version)
+ if (!OPTION_SET_P (dwarf_version))
dwarf_version = 2;
- if (global_options_set.x_dwarf_split_debug_info)
+ if (OPTION_SET_P (dwarf_split_debug_info))
{
inform (input_location,
"%<-gsplit-dwarf%> is not supported on this platform, ignored");
dwarf_split_debug_info = 0;
- global_options_set.x_dwarf_split_debug_info = 0;
+ OPTION_SET_P (dwarf_split_debug_info) = 0;
}
/* Do not allow unwind tables to be generated by default for m32.
fnon-call-exceptions will override this, regardless of what we do. */
if (generating_for_darwin_version < 10
- && !global_options_set.x_flag_asynchronous_unwind_tables
+ && !OPTION_SET_P (flag_asynchronous_unwind_tables)
&& !TARGET_64BIT)
global_options.x_flag_asynchronous_unwind_tables = 0;
@@ -3306,15 +3335,15 @@ darwin_override_options (void)
will be generated". If the User specifically sets flags... we assume
(s)he knows why... */
if (generating_for_darwin_version < 9
- && global_options_set.x_flag_reorder_blocks_and_partition
+ && OPTION_SET_P (flag_reorder_blocks_and_partition)
&& ((global_options.x_flag_exceptions /* User, c++, java */
- && !global_options_set.x_flag_exceptions) /* User specified... */
+ && !OPTION_SET_P (flag_exceptions)) /* User specified... */
|| (global_options.x_flag_unwind_tables
- && !global_options_set.x_flag_unwind_tables)
+ && !OPTION_SET_P (flag_unwind_tables))
|| (global_options.x_flag_non_call_exceptions
- && !global_options_set.x_flag_non_call_exceptions)
+ && !OPTION_SET_P (flag_non_call_exceptions))
|| (global_options.x_flag_asynchronous_unwind_tables
- && !global_options_set.x_flag_asynchronous_unwind_tables)))
+ && !OPTION_SET_P (flag_asynchronous_unwind_tables))))
{
inform (input_location,
"%<-freorder-blocks-and-partition%> does not work with "
@@ -3325,12 +3354,12 @@ darwin_override_options (void)
/* FIXME: flag_objc_sjlj_exceptions is no longer needed since there is only
one valid choice of exception scheme for each runtime. */
- if (!global_options_set.x_flag_objc_sjlj_exceptions)
+ if (!OPTION_SET_P (flag_objc_sjlj_exceptions))
global_options.x_flag_objc_sjlj_exceptions =
flag_next_runtime && !TARGET_64BIT;
/* FIXME: and this could be eliminated then too. */
- if (!global_options_set.x_flag_exceptions
+ if (!OPTION_SET_P (flag_exceptions)
&& flag_objc_exceptions
&& TARGET_64BIT)
flag_exceptions = 1;
@@ -3386,7 +3415,7 @@ darwin_override_options (void)
Linkers that don't need stubs, don't need the EH symbol markers either.
*/
- if (!global_options_set.x_darwin_symbol_stubs)
+ if (!OPTION_SET_P (darwin_symbol_stubs))
{
if (darwin_target_linker)
{
@@ -3634,19 +3663,22 @@ darwin_rename_builtins (void)
}
}
+/* Implementation for the TARGET_LIBC_HAS_FUNCTION hook. */
+
bool
darwin_libc_has_function (enum function_class fn_class,
tree type ATTRIBUTE_UNUSED)
{
- if (fn_class == function_sincos)
+ if (fn_class == function_sincos && darwin_macosx_version_min)
return (strverscmp (darwin_macosx_version_min, "10.9") >= 0);
-
+#if DARWIN_PPC && SUPPORT_DARWIN_LEGACY
if (fn_class == function_c99_math_complex
|| fn_class == function_c99_misc)
return (TARGET_64BIT
- || strverscmp (darwin_macosx_version_min, "10.3") >= 0);
-
- return true;
+ || (darwin_macosx_version_min &&
+ strverscmp (darwin_macosx_version_min, "10.3") >= 0));
+#endif
+ return default_libc_has_function (fn_class, type);
}
hashval_t
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index b1be561..27cb3e4 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -118,25 +118,164 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* True if pragma ms_struct is in effect. */
extern GTY(()) int darwin_ms_struct;
-/* The majority of Darwin's special driver opts are direct access to ld flags
- (to save the user typing -Wl,xxxxx or Xlinker xxxxx) but we can't process
- them here, since doing so will make it appear that there are linker infiles
- and the linker will invoked even when it is not necessary.
+/* Darwin has a user convenience feature where some linker options are exposed
+ at the driver level (so one can type "-all_load" instead of "-Wl,-all_load"
+ or "-Xlinker -all_load"). We retain this, but now these options are all
+ marked as 'Driver' and we process them as early as possible so that they
+ get allocated to the right toolchain command. There are a couple of special
+ cases where these driver opts are used multiple times, or to control
+ operations on more than one command (e.g. dynamiclib). These are handled
+ specially and we then add %<xxxx specs for the commands that _don't_ need
+ them. NOTE: the order of 'shared' and 'dynamiclib' is significant, hence
+ they are placed out of alphabetical order at the start. Likewise, we keep
+ a couple of cases where a negative option originally appeared after the
+ positive alternate, potentially overriding it.
+ When we report an error with %e, it seems necessary to strip the option
+ before doing so, otherwise it survives to the cc1 command line (%e doesn't
+ appear to abort the program before this).
+ Right now there's no mechanism to split up the "variable portion" (%*) of
+ the matched spec string, so where we have some driver specs that take 2
+ or 3 arguments, these cannot be processed here, but are deferred until the
+ LINK_SPEC, where they are copied verbatim.
+ We have a "safe" version of the MacOS version string, that's been sanity-
+ checked and truncated to minor version. If the 'tiny' (3rd) portion of the
+ value is not significant, it's better to use this in version-compare(). */
- However, a few can be handled and we can elide options that are silently-
- ignored defaults, plus warn on obsolete ones that no longer function. */
#undef SUBTARGET_DRIVER_SELF_SPECS
#define SUBTARGET_DRIVER_SELF_SPECS \
-"%{fapple-kext|mkernel:-static}", \
-"%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull", \
-"%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
- %<gsplit-dwarf", \
-"%{gused:-g -feliminate-unused-debug-symbols} %<gused", \
-"%{rpath*: -Xlinker -rpath -Xlinker %*}", \
-"%{shared:-Zdynamiclib} %<shared", \
-"%{static:%{Zdynamic:%e conflicting code gen style switches are used}}",\
-"%{y*:%nthe y option is obsolete and ignored} %<y*", \
-"%<Mach "
+ "%{shared:%{!dynamiclib:-dynamiclib}} %<shared", \
+ "%{static:%{dynamic|dynamiclib:%econflicting code generation switches}}",\
+ "%{dynamiclib:-Xlinker -dylib \
+ %{allowable_client*:-Xlinker -allowable_client -Xlinker %*} \
+ %<allowable_client* \
+ %{bundle_loader*: %<bundle_loader* \
+ %e-bundle_loader not allowed with -dynamiclib} \
+ %{client_name*: %<client_name* \
+ %e-client_name not allowed with -dynamiclib} \
+ %{compatibility_version*:\
+ -Xlinker -dylib_compatibility_version -Xlinker %*} \
+ %<compatibility_version* \
+ %{current_version*:-Xlinker -dylib_current_version -Xlinker %*} \
+ %<current_version* \
+ %{install_name*:-Xlinker -dylib_install_name -Xlinker %* } \
+ %<install_name* \
+ %{keep_private_externs: %<keep_private_externs \
+ %e-keep_private_externs not allowed with -dynamiclib} \
+ %{private_bundle: %<private_bundle \
+ %e-private_bundle not allowed with -dynamiclib} \
+ }", \
+ "%{!dynamiclib: \
+ %{bundle_loader*:-Xlinker -bundle_loader -Xlinker %*} \
+ %<bundle_loader* \
+ %{client_name*:-Xlinker -client_name -Xlinker %*} \
+ %<client_name* \
+ %{compatibility_version*: %<compatibility_version* \
+ %e-compatibility_version only allowed with -dynamiclib} \
+ %{current_version*: %<current_version* \
+ %e-current_version only allowed with -dynamiclib} \
+ %{install_name*: %<install_name* \
+ %e-install_name only allowed with -dynamiclib} \
+ %{keep_private_externs:-Xlinker -keep_private_externs} \
+ %<keep_private_externs \
+ %{private_bundle:-Xlinker -private_bundle} \
+ %<private_bundle \
+ }", \
+ "%{all_load:-Xlinker -all_load} %<all_load", \
+ "%{arch_errors_fatal:-Xlinker -arch_errors_fatal} \
+ %<arch_errors_fatal", \
+ "%{bind_at_load:-Xlinker -bind_at_load} %<bind_at_load", \
+ "%{bundle:%{!dynamiclib:-Xlinker -bundle; \
+ :%e-bundle not allowed with -dynamiclib}}", \
+ "%{dead_strip:-Xlinker -dead_strip} %<dead_strip", \
+ "%{dylib_file*:-Xlinker -dylib_file -Xlinker %*} %<dylib_file*", \
+ "%{dylinker:-Xlinker -dylinker} %<dylinker", \
+ "%{dylinker_install_name*:-Xlinker -dylinker_install_name -Xlinker %*}\
+ %<dylinker_install_name*", \
+ "%{exported_symbols_list*:-Xlinker -exported_symbols_list -Xlinker %*}\
+ %<exported_symbols_list", \
+ "%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls", \
+ "%{fterminated-vtables: -fapple-kext} %<fterminated-vtables", \
+ "%{fapple-kext|mkernel:-static}", \
+ "%{filelist*:-Xlinker -filelist -Xlinker %*} %<filelist*", \
+ "%{flat_namespace:-Xlinker -flat_namespace} %<flat_namespace", \
+ "%{force_cpusubtype_ALL:-Xassembler -force_cpusubtype_ALL} ", \
+ "%{force_flat_namespace: \
+ %{!dynamiclib:-Xlinker -force_flat_namespace; \
+ :%e-force_flat_namespace not allowed with -dynamiclib}} \
+ %<force_flat_namespace", \
+ "%{framework*:-Xlinker -framework -Xlinker %*} %<framework*", \
+ "%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull", \
+ "%{gused:-g -feliminate-unused-debug-symbols} %<gused", \
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
+ %<gsplit-dwarf", \
+ "%{headerpad_max_install_names:-Xlinker -headerpad_max_install_names}\
+ %<headerpad_max_install_names", \
+ "%{image_base*:-Xlinker -image_base -Xlinker %*} %<image_base*", \
+ "%{init*:-Xlinker -init -Xlinker %*} %<init*", \
+ "%{multi_module:-Xlinker -multi_module} %<multi_module", \
+ "%{multiply_defined*:-Xlinker -multiply_defined -Xlinker %*; \
+ :%{shared-libgcc: \
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -multiply_defined) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= suppress)}} \
+ %<multiply_defined*", \
+ "%{multiplydefinedunused*:\
+ -Xlinker -multiply_defined_unused -Xlinker %*} \
+ %<multiplydefinedunused* ", \
+ "%{no_dead_strip_inits_and_terms:\
+ -Xlinker -no_dead_strip_inits_and_terms} \
+ %<no_dead_strip_inits_and_terms", \
+ "%{nofixprebinding:-Xlinker -nofixprebinding} %<nofixprebinding", \
+ "%{nomultidefs:-Xlinker -nomultidefs} %<nomultidefs", \
+ "%{pagezero_size*:-Xlinker -pagezero_size -Xlinker %*} \
+ %<pagezero_size", \
+ "%{prebind:-Xlinker -prebind} %<prebind", \
+ "%{noprebind:-Xlinker -noprebind} %<noprebind", \
+ "%{prebind_all_twolevel_modules:\
+ -Xlinker -prebind_all_twolevel_modules} \
+ %<prebind_all_twolevel_modules", \
+ "%{preload:-Xlinker -preload} %<preload", \
+ "%{read_only_relocs*:-Xlinker -read_only_relocs -Xlinker %*} \
+ %<read_only_relocs*", \
+ "%{rpath*: -Xlinker -rpath -Xlinker %*}", \
+ "%{seg_addr_table_filename*: \
+ -Xlinker -seg_addr_table_filename -Xlinker %*} \
+ %<seg_addr_table_filename*", \
+ "%{seg_addr_table*:-Xlinker -seg_addr_table -Xlinker %*} \
+ %<seg_addr_table*", \
+ "%{seg1addr*:-Xlinker -image_base -Xlinker %*} %<seg1addr*", \
+ "%{seglinkedit:-Xlinker -seglinkedit} %<seglinkedit", \
+ "%{noseglinkedit:-Xlinker -noseglinkedit} %<noseglinkedit", \
+ "%{segs_read_only_addr*:-Xlinker -segs_read_only_addr -Xlinker %*} \
+ %<segs_read_only_addr*", \
+ "%{segs_read_write_addr*:-Xlinker -segs_read_write_addr -Xlinker %*} \
+ %<segs_read_write_addr*", \
+ "%{single_module:-Xlinker -single_module} %<single_module", \
+ "%{sub_library*:-Xlinker -sub_library -Xlinker %*} %<sub_library*", \
+ "%{sub_umbrella*:-Xlinker -sub_umbrella -Xlinker %*} %<sub_umbrella*",\
+ "%{twolevel_namespace:-Xlinker -twolevel_namespace} \
+ %<twolevel_namespace", \
+ "%{twolevel_namespace_hints:-Xlinker -twolevel_namespace_hints} \
+ %<twolevel_namespace_hints", \
+ "%{umbrella*:-Xlinker -umbrella -Xlinker %*} %<umbrella*", \
+ "%{undefined*:-Xlinker -undefined -Xlinker %*} %<undefined*", \
+ "%{unexported_symbols_list*:\
+ -Xlinker -unexported_symbols_list -Xlinker %*} \
+ %<unexported_symbols_list*", \
+ "%{!weak_reference_mismatches*:\
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -weak_reference_mismatches) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= non-weak)}", \
+ "%{weak_reference_mismatches*:\
+ -Xlinker -weak_reference_mismatches -Xlinker %*} \
+ %<weak_reference_mismatches*", \
+ "%{whyload:-Xlinker -whyload} %<whyload", \
+ "%{whatsloaded:-Xlinker -whatsloaded} %<whatsloaded", \
+ "%{w:-Xlinker -w}", \
+ "%<y*", \
+ "%<Mach "
#if LD64_HAS_EXPORT_DYNAMIC
#define DARWIN_RDYNAMIC "%{rdynamic:-export_dynamic}"
@@ -157,9 +296,7 @@ extern GTY(()) int darwin_ms_struct;
%:version-compare(>= 10.7 mmacosx-version-min= -no_pie) }"
#define DARWIN_CC1_SPEC \
- "%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls " \
- "%{fterminated-vtables: -fapple-kext} %<fterminated-vtables " \
- "%<filelist* %<framework*"
+ "%<dynamic %<dynamiclib %<force_cpusubtype_ALL "
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
do { \
@@ -184,7 +321,7 @@ extern GTY(()) int darwin_ms_struct;
#undef CPP_SPEC
#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" \
- " %{pthread:-D_REENTRANT}"
+ " %{pthread:-D_REENTRANT} "
/* This is a fix for PR41260 by passing -no_compact_unwind on darwin10 and
later until the assembler, linker and libunwind are able to deal with the
@@ -212,7 +349,7 @@ extern GTY(()) int darwin_ms_struct;
linkers, and for positional arguments like libraries. */
#define LINK_COMMAND_SPEC_A \
- "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ "%{!c:%{!E:%{!S:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*: \
%(linker)" \
LINK_PLUGIN_SPEC \
"%{flto*:%<fcompare-debug*} \
@@ -221,20 +358,23 @@ extern GTY(()) int darwin_ms_struct;
"%X %{s} %{t} %{Z} %{u*} \
%{e*} %{r} \
%{o*}%{!o:-o a.out} \
- %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \
- %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
- %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): \
- %{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \
- %{fgnu-tm: \
- %{static|static-libgcc|static-libstdc++|static-libgfortran: libitm.a%s; : -litm } } \
- %{!nostdlib:%{!r:%{!nodefaultlibs:\
+ %{!r:%{!nostdlib:%{!nostartfiles:%S}}} \
+ %{L*} %(link_libgcc) %o \
+ %{!r:%{!nostdlib:%{!nodefaultlibs:\
+ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
+ %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): \
+ %{static|static-libgcc|static-libstdc++|static-libgfortran: \
+ libgomp.a%s; : -lgomp }} \
+ %{fgnu-tm: \
+ %{static|static-libgcc|static-libstdc++|static-libgfortran: \
+ libitm.a%s; : -litm }} \
%{%:sanitize(address): -lasan } \
%{%:sanitize(undefined): -lubsan } \
%(link_ssp) \
- %:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef.o) \
+ %:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef) \
%(link_gcc_c_sequence) \
}}}\
- %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} %{F*} "\
+ %{!r:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} "\
DARWIN_PIE_SPEC \
DARWIN_NOPIE_SPEC \
DARWIN_RDYNAMIC \
@@ -247,12 +387,12 @@ extern GTY(()) int darwin_ms_struct;
enabled). */
#define DSYMUTIL_SPEC \
- "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
- %{v} \
- %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}}}\
- %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\
- .f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
- %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}}}"
+ "%{!c:%{!E:%{!S:%{!r:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*:\
+ %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym \
+ %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\
+ .f95|.f03|.f77|.for|.F|.F90|.F95|.F03|.d: -dsym }\
+ }}}}}\
+ }}}}}}}}"
#define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC
@@ -274,101 +414,38 @@ extern GTY(()) int darwin_ms_struct;
#define HAVE_LD_SYSROOT 1
/* It seems the only (working) way to get a space after %R is to append a
dangling '/'. */
-#define SYSROOT_SPEC "%{!isysroot*:-syslibroot %R/ }"
+#define SYSROOT_SPEC "%{!isysroot*:-syslibroot %R/ } "
/* Do the same as clang, for now, and insert the sysroot for ld when an
isysroot is specified. */
-#define LINK_SYSROOT_SPEC "%{isysroot*:-syslibroot %*}"
+#define LINK_SYSROOT_SPEC "%{isysroot*:-syslibroot %*} "
/* Suppress the addition of extra prefix paths when a sysroot is in use. */
#define STANDARD_STARTFILE_PREFIX_1 ""
#define STANDARD_STARTFILE_PREFIX_2 ""
-/* Please keep the random linker options in alphabetical order (modulo
- 'Z' and 'no' prefixes). Note that options taking arguments may appear
- multiple times on a command line with different arguments each time,
- so put a * after their names so all of them get passed. */
+
+/* Please keep the random linker options in alphabetical order.
+ Note that options taking arguments may appear multiple times on a command
+ line with different arguments each time, so put a * after their names so
+ all of them get passed. */
#define LINK_SPEC \
- "%{static}%{!static:-dynamic} \
+ "%{static}%{!static:%{!dynamic:-dynamic}} \
%:remove-outfile(-ldl) \
%:remove-outfile(-lm) \
%:remove-outfile(-lpthread) \
%{fgnu-runtime: %{static|static-libgcc: \
%:replace-outfile(-lobjc libobjc-gnu.a%s); \
- :%:replace-outfile(-lobjc -lobjc-gnu ) } }\
+ :%:replace-outfile(-lobjc -lobjc-gnu )}}\
%{static|static-libgcc|static-libgfortran:%:replace-outfile(-lgfortran libgfortran.a%s)}\
%{static|static-libgcc|static-libstdc++|static-libgfortran:%:replace-outfile(-lgomp libgomp.a%s)}\
%{static|static-libgcc|static-libstdc++:%:replace-outfile(-lstdc++ libstdc++.a%s)}\
- %{!Zdynamiclib: \
- %{Zforce_cpusubtype_ALL:-arch %(darwin_arch) -force_cpusubtype_ALL} \
- %{!Zforce_cpusubtype_ALL:-arch %(darwin_subarch)} \
- %{Zbundle:-bundle} \
- %{Zbundle_loader*:-bundle_loader %*} \
- %{client_name*} \
- %{compatibility_version*:%e-compatibility_version only allowed with -dynamiclib\
-} \
- %{current_version*:%e-current_version only allowed with -dynamiclib} \
- %{Zforce_flat_namespace:-force_flat_namespace} \
- %{Zinstall_name*:%e-install_name only allowed with -dynamiclib} \
- %{keep_private_externs} \
- %{private_bundle} \
- } \
- %{Zdynamiclib: -dylib \
- %{Zbundle:%e-bundle not allowed with -dynamiclib} \
- %{Zbundle_loader*:%e-bundle_loader not allowed with -dynamiclib} \
- %{client_name*:%e-client_name not allowed with -dynamiclib} \
- %{compatibility_version*:-dylib_compatibility_version %*} \
- %{current_version*:-dylib_current_version %*} \
- %{Zforce_cpusubtype_ALL:-arch %(darwin_arch)} \
- %{!Zforce_cpusubtype_ALL: -arch %(darwin_subarch)} \
- %{Zforce_flat_namespace:%e-force_flat_namespace not allowed with -dynamiclib} \
- %{Zinstall_name*:-dylib_install_name %*} \
- %{keep_private_externs:%e-keep_private_externs not allowed with -dynamiclib} \
- %{private_bundle:%e-private_bundle not allowed with -dynamiclib} \
- } \
- %{Zall_load:-all_load} \
- %{Zallowable_client*:-allowable_client %*} \
- %{Zbind_at_load:-bind_at_load} \
- %{Zarch_errors_fatal:-arch_errors_fatal} \
- %{Zdead_strip:-dead_strip} \
- %{Zno_dead_strip_inits_and_terms:-no_dead_strip_inits_and_terms} \
- %{Zdylib_file*:-dylib_file %*} \
- %{Zdynamic:-dynamic}\
- %{Zexported_symbols_list*:-exported_symbols_list %*} \
- %{Zflat_namespace:-flat_namespace} \
- %{headerpad_max_install_names} \
- %{Zimage_base*:-image_base %*} \
- %{Zinit*:-init %*} \
- %{mmacosx-version-min=*:-macosx_version_min %*} \
- %{nomultidefs} \
- %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \
- %{Zmultiply_defined*:-multiply_defined %*} \
- %{!Zmultiply_defined*:%{shared-libgcc: \
- %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \
- %:version-compare(< 10.5 mmacosx-version-min= suppress)}} \
- %{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
- %{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \
- %{read_only_relocs} \
- %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} \
- %{Zsegaddr*:-segaddr %*} \
- %{Zsegs_read_only_addr*:-segs_read_only_addr %*} \
- %{Zsegs_read_write_addr*:-segs_read_write_addr %*} \
- %{Zseg_addr_table*: -seg_addr_table %*} \
- %{Zfn_seg_addr_table_filename*:-seg_addr_table_filename %*} \
- %{sub_library*} %{sub_umbrella*} \
- " LINK_SYSROOT_SPEC " \
- %{twolevel_namespace} %{twolevel_namespace_hints} \
- %{Zumbrella*: -umbrella %*} \
- %{undefined*} \
- %{Zunexported_symbols_list*:-unexported_symbols_list %*} \
- %{Zweak_reference_mismatches*:-weak_reference_mismatches %*} \
- %{!Zweak_reference_mismatches*:-weak_reference_mismatches non-weak} \
- %{w} \
- %{pagezero_size*} %{segs_read_*} %{seglinkedit} %{noseglinkedit} \
- %{sectalign*} %{sectobjectsymbols*} %{segcreate*} %{whyload} \
- %{whatsloaded} %{dylinker_install_name*} \
- %{dylinker} "
-
+ %{force_cpusubtype_ALL:-arch %(darwin_arch)} \
+ %{!force_cpusubtype_ALL:-arch %(darwin_subarch)} "\
+ LINK_SYSROOT_SPEC \
+ "%{mmacosx-version-min=*:-macosx_version_min %*} \
+ %{sectalign*} %{sectcreate*} %{sectobjectsymbols*} %{sectorder*} \
+ %{segaddr*} %{segcreate*} %{segprot*} "
/* Machine dependent libraries. */
@@ -410,9 +487,9 @@ extern GTY(()) int darwin_ms_struct;
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
-"%{Zdynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
- %{!Zdynamiclib:%{Zbundle:%(darwin_bundle1)} \
- %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
+"%{dynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
+ %{!dynamiclib:%{bundle:%(darwin_bundle1)} \
+ %{!bundle:%{pg:%{static:-lgcrt0.o} \
%{!static:%{object:-lgcrt0.o} \
%{!object:%{preload:-lgcrt0.o} \
%{!preload:-lgcrt1.o \
@@ -423,7 +500,7 @@ extern GTY(()) int darwin_ms_struct;
%{!object:%{preload:-lcrt0.o} \
%{!preload: %(darwin_crt1) \
%(darwin_crt2)}}}}}} \
- %(darwin_crt3)"
+ %(darwin_crt3) %<dynamiclib "
/* We want a destructor last in the list. */
#define TM_DESTRUCTOR "%{fgnu-tm: -lcrttme.o}"
@@ -463,24 +540,25 @@ extern GTY(()) int darwin_ms_struct;
#ifdef HAVE_AS_MMACOSX_VERSION_MIN_OPTION
/* Emit macosx version (but only major). */
#define ASM_MMACOSX_VERSION_MIN_SPEC \
- " %{asm_macosx_version_min=*: -mmacosx-version-min=%*} %<asm_macosx_version_min=*"
+"%{asm_macosx_version_min=*: -mmacosx-version-min=%* } \
+ %<asm_macosx_version_min=* "
#else
-#define ASM_MMACOSX_VERSION_MIN_SPEC " %<asm_macosx_version_min=*"
+#define ASM_MMACOSX_VERSION_MIN_SPEC " %<asm_macosx_version_min=* "
#endif
-/* When we detect that we're cctools or llvm as, we need to insert the right
- additional options. */
#if HAVE_GNU_AS
+/* The options are added in gcc.c for this case. */
#define ASM_OPTIONS ""
#else
+/* When we detect that we're cctools or llvm as, we need to insert the right
+ additional options. Actually, currently these are the same as GAS. */
#define ASM_OPTIONS "%{v} %{w:-W} %{I*}"
#endif
/* Default Darwin ASM_SPEC, very simple. */
-#define ASM_SPEC "-arch %(darwin_arch) \
- " ASM_OPTIONS " \
- %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
- %{static}" ASM_MMACOSX_VERSION_MIN_SPEC
+#define ASM_SPEC \
+"%{static} -arch %(darwin_arch) " \
+ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC
#ifdef HAVE_AS_STABS_DIRECTIVE
/* We only pass a debug option to the assembler if that supports stabs, since
@@ -494,14 +572,14 @@ extern GTY(()) int darwin_ms_struct;
#define ASM_DEBUG_OPTION_SPEC ""
#define ASM_FINAL_SPEC \
- "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} %<gsplit-dwarf"
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
+ %<gsplit-dwarf"
/* We now require C++11 to bootstrap and newer tools than those based on
stabs, so require DWARF-2, even if stabs is supported by the assembler. */
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-#define DARWIN_PREFER_DWARF
#define DWARF2_DEBUGGING_INFO 1
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
#ifdef HAVE_AS_STABS_DIRECTIVE
#define DBX_DEBUGGING_INFO 1
@@ -1104,6 +1182,9 @@ extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **);
needed, and there is no need for the compiler to emit them. */
#define MIN_LD64_OMIT_STUBS "62.1"
+/* Emit start labels for init and term sections from this version. */
+#define MIN_LD64_INIT_TERM_START_LABELS "136.0"
+
/* If we have no definition for the linker version, pick the minimum version
that will bootstrap the compiler. */
#ifndef LD64_VERSION
diff --git a/gcc/config/darwin.opt b/gcc/config/darwin.opt
index 23f3593..d1d1f81 100644
--- a/gcc/config/darwin.opt
+++ b/gcc/config/darwin.opt
@@ -90,11 +90,11 @@ Target RejectNegative Joined Separate Var(darwin_target_linker) Init(LD64_VERSIO
; Driver options.
all_load
-Driver RejectNegative Alias(Zall_load)
+Driver RejectNegative
Load all members of archive libraries, rather than only those that satisfy undefined symbols.
allowable_client
-Driver RejectNegative Separate Alias(Zallowable_client)
+Driver RejectNegative Separate
-allowable_client <name> The output dylib is private to the client <name>.
arch
@@ -102,7 +102,7 @@ Driver RejectNegative Separate
-arch <name> Generate output for architecture <name>.
arch_errors_fatal
-Driver RejectNegative Alias(Zarch_errors_fatal)
+Driver RejectNegative
Mismatches between file architecture and one specified by \"-arch\" are errors instead of warnings.
asm_macosx_version_min=
@@ -110,15 +110,15 @@ Driver RejectNegative Joined
The earliest macOS version on which this program will run (formatted for the assembler).
bind_at_load
-Driver RejectNegative Alias(Zbind_at_load)
+Driver RejectNegative
Generate an output executable that binds symbols on load, rather than lazily.
bundle
-Driver RejectNegative Alias(Zbundle)
+Driver RejectNegative
Generate a Mach-O bundle (file type MH_BUNDLE).
bundle_loader
-Driver RejectNegative Separate Alias(Zbundle_loader)
+Driver RejectNegative Separate
-bundle_loader <executable> Treat <executable> (that will be loading this bundle) as if it was one of the dynamic libraries the bundle is linked against for symbol resolution.
client_name
@@ -134,11 +134,12 @@ Driver RejectNegative Separate
-current_version <number> Set the current version for the library to <number>.
dead_strip
-Driver RejectNegative Alias(Zdead_strip)
+Driver RejectNegative
Remove code and data that is unreachable from any exported symbol (including the entry point).
dylib_file
-Driver Separate Alias(Zdylib_file)
+Driver RejectNegative Separate
+-dylib_file install_name:file_name This allows linking of a dylib with \"install_name\" but to be found in a different install position \"file_name\"
dylinker
Driver RejectNegative
@@ -149,15 +150,15 @@ Driver RejectNegative Separate
-dylinker_install_name <path> Only used for building dyld.
dynamic
-Driver RejectNegative Alias(Zdynamic)
+Driver RejectNegative
The default (and opposite of -static), implied by user mode executables, shared libraries and bundles.
dynamiclib
-Driver RejectNegative Alias(Zdynamiclib)
+Driver RejectNegative
Produce a Mach-O shared library (file type MH_DYLIB), synonym for \"-shared\".
exported_symbols_list
-Driver RejectNegative Separate Alias(Zexported_symbols_list)
+Driver RejectNegative Separate
-exported_symbols_list <filename> Export global symbols in <filename> in linked output file; any symbols not mentioned will be treated as \"hidden\".
filelist
@@ -169,15 +170,15 @@ Driver RejectNegative
Used for generating code for some older kernel revisions.
flat_namespace
-Driver RejectNegative Alias(Zflat_namespace)
+Driver RejectNegative
Ignore the normal two-level namespace; resolve symbols in command line order and do not record which library provided the resolved symbol.
force_cpusubtype_ALL
-Driver RejectNegative Alias(Zforce_cpusubtype_ALL)
+Driver RejectNegative
For the assembler (and linker) permit any architecture sub-variant to be used without error.
force_flat_namespace
-Driver RejectNegative Alias(Zforce_flat_namespace)
+Driver RejectNegative
Set the output object such that, on loading, dyld will ignore any two-level namespace information and resolve symbols in the discovery order for loaded libs.
framework
@@ -201,15 +202,15 @@ Driver RejectNegative
Automatically adds space for longer path names in load commands (up to MAXPATHLEN).
image_base
-Driver RejectNegative Separate Alias(Zimage_base)
+Driver RejectNegative Separate
-image_base <address> Specify <address> as the base address for a dylib or bundle.
init
-Driver RejectNegative Separate Alias(Zinit)
+Driver RejectNegative Separate
-init <symbol_name> The symbol <symbol_name> will be used as the first initialiser for a dylib.
install_name
-Driver RejectNegative Separate Alias(Zinstall_name)
+Driver RejectNegative Separate
-install_name <name> Set the install name for a dylib.
keep_private_externs
@@ -217,19 +218,19 @@ Driver RejectNegative
Usually \"private extern\" (hidden) symbols are made local when linking, this command suppresses that such that they remain exported.
multi_module
-Driver RejectNegative Alias(Zmulti_module)
+Driver RejectNegative
(Obsolete after 10.4) Multi modules are ignored at runtime since macOS 10.4.
multiply_defined
-Driver RejectNegative Separate Alias(Zmultiply_defined)
+Driver RejectNegative Separate
(Obsolete after 10.4) -multiply_defined <treatment> Provided a mechanism for warning about symbols defined in multiple dylibs.
multiply_defined_unused
-Driver RejectNegative Separate Alias(Zmultiplydefinedunused)
+Driver RejectNegative Separate
(Obsolete after 10.4) -multiply_defined_unused <treatment> Provided a mechanism for warning about symbols defined in the current executable also being defined in linked dylibs.
no_dead_strip_inits_and_terms
-Driver RejectNegative Alias(Zno_dead_strip_inits_and_terms)
+Driver RejectNegative
(Obsolete) Current linkers never dead-strip these items, so the option is not needed.
nofixprebinding
@@ -299,12 +300,12 @@ Driver RejectNegative Separate Args(3)
(Obsolete) -sectorder <segname> <sectname> <orderfile> Replaced by a more general option \"-order_file\".
seg_addr_table
-Driver RejectNegative Separate Alias(Zseg_addr_table)
+Driver RejectNegative Separate
-seg_addr_table <file> Specify the base addresses for dynamic libraries; <file> contains a line for each library.
; This is only usable by the ld_classic linker.
seg_addr_table_filename
-Driver RejectNegative Separate Alias(Zfn_seg_addr_table_filename)
+Driver RejectNegative Separate
(Obsolete, ld_classic only) -seg_addr_table_filename <path>.
seg1addr
@@ -312,7 +313,7 @@ Driver RejectNegative Separate
Synonym for \"image_base\".
segaddr
-Driver RejectNegative Separate Args(2) Alias(Zsegaddr)
+Driver RejectNegative Separate Args(2)
-segaddr <name> <address> Set the base address of segment <name> to <address> which must be aligned to a page boundary (currently 4kb).
; This is only usable by the ld_classic linker.
@@ -329,15 +330,15 @@ Driver RejectNegative Separate Args(3)
-segprot <segname> <max_prot> <init_prot> The virtual memory protections for segment <segname> have maximum and initial values <max_prot> and <init_prot> respectively. The specified values may contain \"r\", \"w\", \"x\" or \"-\" the latter meaning \"no access\".
segs_read_only_addr
-Driver RejectNegative Separate Alias(Zsegs_read_only_addr)
+Driver RejectNegative Separate
-segs_read_only_addr <address> Specify that <address> is the base address of the read-only segments of a dylib.
segs_read_write_addr
-Driver RejectNegative Separate Alias(Zsegs_read_write_addr)
+Driver RejectNegative Separate
-segs_read_write_addr <address> Specify that <address> is the base address address of the read-write segments of a dylib.
single_module
-Driver RejectNegative Alias(Zsingle_module)
+Driver RejectNegative
(Obsolete) This is the default.
sub_library
@@ -357,7 +358,7 @@ Driver RejectNegative
Add extra information to the executable that can speed up dynamic loading (provided that dependent libraries are unchanged).
umbrella
-Driver RejectNegative Separate Alias(Zumbrella)
+Driver RejectNegative
-umbrella <framework> The specified framework will be re-exported.
undefined
@@ -365,11 +366,11 @@ Driver RejectNegative Separate
-undefined <treatment> Specify the handling for undefined symbols (default is error).
unexported_symbols_list
-Driver RejectNegative Separate Alias(Zunexported_symbols_list)
+Driver RejectNegative Separate
-unexported_symbols_list <filename> Do not export the global symbols listed in <filename>.
weak_reference_mismatches
-Driver RejectNegative Separate Alias(Zweak_reference_mismatches)
+Driver RejectNegative Separate
-weak_reference_mismatches <treatment> Specifies what to do if a symbol import conflicts between file (weak in one and not in another) the default is to treat the symbol as non-weak.
whatsloaded
@@ -391,97 +392,3 @@ Driver RejectNegative Joined
Mach
Driver RejectNegative
(Obsolete and unhandled by ld64, ignored) ld should produce an executable (only handled by ld_classic).
-
-;; These are not "real" options, but placeholders used to hide the real options
-;; from generic options processing... FIXME: they can be eliminated now.
-
-Zall_load
-Driver
-
-Zallowable_client
-Driver Separate
-
-Zarch_errors_fatal
-Driver
-
-Zbind_at_load
-Driver
-
-Zbundle
-Driver
-
-Zbundle_loader
-Driver Separate
-
-Zdead_strip
-Driver
-
-Zdylib_file
-Driver Separate
-
-Zdynamic
-Driver
-
-Zdynamiclib
-Driver
-
-Zexported_symbols_list
-Driver Separate
-
-Zfn_seg_addr_table_filename
-Driver Separate
-
-Zflat_namespace
-Driver
-
-Zforce_cpusubtype_ALL
-Driver
-
-Zforce_flat_namespace
-Driver
-
-Zimage_base
-Driver Separate
-
-Zinit
-Driver Separate
-
-Zinstall_name
-Driver Separate
-
-Zmulti_module
-Driver
-
-Zmultiply_defined
-Driver Separate
-
-Zmultiplydefinedunused
-Driver Separate
-
-Zno_dead_strip_inits_and_terms
-Driver
-
-Zseg_addr_table
-Driver Separate
-
-Zsegaddr
-Driver Separate Args(2)
-
-Zsegs_read_only_addr
-Driver Separate
-
-Zsegs_read_write_addr
-Driver Separate
-
-Zsingle_module
-Driver
-
-Zumbrella
-Driver Separate
-
-Zunexported_symbols_list
-Driver Separate
-
-Zweak_reference_mismatches
-Driver Separate
-
diff --git a/gcc/config/dbx.h b/gcc/config/dbx.h
deleted file mode 100644
index b270a07..0000000
--- a/gcc/config/dbx.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Prefer DBX (stabs) debugging information.
- Copyright (C) 1996-2021 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/>. */
-
-/* This file causes gcc to prefer using DBX (stabs) debugging
- information. The configure script will add a #include of this file
- to tm.h when --with-stabs is used for certain targets. */
-
-#define DBX_DEBUGGING_INFO 1
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
diff --git a/gcc/config/dbxcoff.h b/gcc/config/dbxcoff.h
index d491cff..bd705f9 100644
--- a/gcc/config/dbxcoff.h
+++ b/gcc/config/dbxcoff.h
@@ -25,12 +25,6 @@ along with GCC; see the file COPYING3. If not see
#define DBX_DEBUGGING_INFO 1
-/* Generate DBX debugging information by default. */
-
-#ifndef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#endif
-
/* Be function-relative for block and source line stab directives. */
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index a7f7f08..02cd07c 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "ifcvt.h"
#include "rtl-iter.h"
#include "calls.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -664,7 +665,7 @@ frv_option_override (void)
if (!flag_pic) /* -fPIC */
flag_pic = 2;
- if (!global_options_set.x_g_switch_value) /* -G0 */
+ if (!OPTION_SET_P (g_switch_value)) /* -G0 */
{
g_switch_value = 0;
}
@@ -757,7 +758,7 @@ frv_option_override (void)
}
/* Check for small data option */
- if (!global_options_set.x_g_switch_value && !TARGET_LIBPIC)
+ if (!OPTION_SET_P (g_switch_value) && !TARGET_LIBPIC)
g_switch_value = SDATA_DEFAULT_SIZE;
/* There is no single unaligned SI op for PIC code. Sometimes we
diff --git a/gcc/config/gcn/gcn-hsa.h b/gcc/config/gcn/gcn-hsa.h
index fc99c8d..4fd2f07 100644
--- a/gcc/config/gcn/gcn-hsa.h
+++ b/gcc/config/gcn/gcn-hsa.h
@@ -75,25 +75,55 @@ extern unsigned int gcn_local_sym_hash (const char *name);
supported for gcn. */
#define GOMP_SELF_SPECS ""
-#ifdef HAVE_GCN_SRAM_ECC_FIJI
-#define A_FIJI
+#ifdef HAVE_GCN_XNACK_FIJI
+#define X_FIJI
#else
-#define A_FIJI "!march=*:;march=fiji:;"
+#define X_FIJI "!march=*:;march=fiji:;"
#endif
-#ifdef HAVE_GCN_SRAM_ECC_GFX900
-#define A_900
+#ifdef HAVE_GCN_XNACK_GFX900
+#define X_900
#else
-#define A_900 "march=gfx900:;"
+#define X_900 "march=gfx900:;"
#endif
-#ifdef HAVE_GCN_SRAM_ECC_GFX906
-#define A_906
+#ifdef HAVE_GCN_XNACK_GFX906
+#define X_906
#else
-#define A_906 "march=gfx906:;"
+#define X_906 "march=gfx906:;"
#endif
+#ifdef HAVE_GCN_XNACK_GFX908
+#define X_908
+#else
+#define X_908 "march=gfx908:;"
+#endif
+
+/* These targets can't have SRAM-ECC, even if a broken assembler allows it. */
+#define S_FIJI "!march=*:;march=fiji:;"
+#define S_900 "march=gfx900:;"
+#define S_906 "march=gfx906:;"
#ifdef HAVE_GCN_SRAM_ECC_GFX908
-#define A_908
+#define S_908
+#else
+#define S_908 "march=gfx908:;"
+#endif
+
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+#define SRAMOPT "!msram-ecc=off:-mattr=+sram-ecc;:-mattr=-sram-ecc"
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+/* In HSACOv4 no attribute setting means the binary supports "any" hardware
+ configuration. The name of the attribute also changed. */
+#define SRAMOPT "msram-ecc=on:-mattr=+sramecc;msram-ecc=off:-mattr=-sramecc"
+#endif
+#if !defined(SRAMOPT) && !defined(IN_LIBGCC2)
+#error "No assembler syntax configured"
+#endif
+
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+/* FIJI cards don't seem to support drivers new enough to allow HSACOv4. */
+#define HSACO3_SELECT_OPT \
+ "%{!march=*|march=fiji:--amdhsa-code-object-version=3} "
#else
-#define A_908 "march=gfx908:;"
+#define HSACO3_SELECT_OPT
#endif
/* These targets can't have SRAM-ECC, even if a broken assembler allows it. */
@@ -103,10 +133,10 @@ extern unsigned int gcn_local_sym_hash (const char *name);
/* Use LLVM assembler and linker options. */
#define ASM_SPEC "-triple=amdgcn--amdhsa " \
"%:last_arg(%{march=*:-mcpu=%*}) " \
- "-mattr=%{mxnack:+xnack;:-xnack} " \
- /* FIXME: support "any" when we move to HSACOv4. */ \
- "-mattr=%{" A_FIJI A_900 A_906 A_908 \
- "!msram-ecc=off:+sram-ecc;:-sram-ecc} " \
+ HSACO3_SELECT_OPT \
+ "%{" X_FIJI X_900 X_906 X_908 \
+ "mxnack:-mattr=+xnack;:-mattr=-xnack} " \
+ "%{" S_FIJI S_900 S_906 S_908 SRAMOPT "} " \
"-filetype=obj"
#define LINK_SPEC "--pie --export-dynamic"
#define LIB_SPEC "-lc"
diff --git a/gcc/config/gcn/gcn-protos.h b/gcc/config/gcn/gcn-protos.h
index 5d62a84..2d385e0 100644
--- a/gcc/config/gcn/gcn-protos.h
+++ b/gcc/config/gcn/gcn-protos.h
@@ -41,7 +41,8 @@ extern bool gcn_global_address_p (rtx);
extern tree gcn_goacc_adjust_private_decl (location_t, tree var, int level);
extern tree gcn_goacc_create_worker_broadcast_record (tree record_type,
bool sender,
- const char *name);
+ const char *name,
+ unsigned HOST_WIDE_INT offset);
extern void gcn_goacc_reduction (gcall *call);
extern bool gcn_hard_regno_rename_ok (unsigned int from_reg,
unsigned int to_reg);
diff --git a/gcc/config/gcn/gcn-tree.c b/gcc/config/gcn/gcn-tree.c
index f722d2d..d8b913b 100644
--- a/gcc/config/gcn/gcn-tree.c
+++ b/gcc/config/gcn/gcn-tree.c
@@ -309,7 +309,6 @@ static tree
gcn_goacc_get_worker_red_decl (tree type, unsigned offset)
{
machine_function *machfun = cfun->machine;
- tree existing_decl;
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
@@ -319,31 +318,12 @@ gcn_goacc_get_worker_red_decl (tree type, unsigned offset)
(TYPE_QUALS (type)
| ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_LDS)));
- if (machfun->reduc_decls
- && offset < machfun->reduc_decls->length ()
- && (existing_decl = (*machfun->reduc_decls)[offset]))
- {
- gcc_assert (TREE_TYPE (existing_decl) == var_type);
- return existing_decl;
- }
- else
- {
- char name[50];
- sprintf (name, ".oacc_reduction_%u", offset);
- tree decl = create_tmp_var_raw (var_type, name);
-
- DECL_CONTEXT (decl) = NULL_TREE;
- TREE_STATIC (decl) = 1;
-
- varpool_node::finalize_decl (decl);
-
- vec_safe_grow_cleared (machfun->reduc_decls, offset + 1, true);
- (*machfun->reduc_decls)[offset] = decl;
+ gcc_assert (offset
+ < (machfun->reduction_limit - machfun->reduction_base));
+ tree ptr_type = build_pointer_type (var_type);
+ tree addr = build_int_cst (ptr_type, machfun->reduction_base + offset);
- return decl;
- }
-
- return NULL_TREE;
+ return build_simple_mem_ref (addr);
}
/* Expand IFN_GOACC_REDUCTION_SETUP. */
@@ -500,7 +480,7 @@ gcn_goacc_reduction_teardown (gcall *call)
}
if (lhs)
- gimplify_assign (lhs, var, &seq);
+ gimplify_assign (lhs, unshare_expr (var), &seq);
pop_gimplify_context (NULL);
@@ -581,27 +561,24 @@ gcn_goacc_adjust_private_decl (location_t, tree var, int level)
tree
gcn_goacc_create_worker_broadcast_record (tree record_type, bool sender,
- const char *name)
+ const char *name,
+ unsigned HOST_WIDE_INT offset)
{
- tree type = record_type;
-
- TYPE_ADDR_SPACE (type) = ADDR_SPACE_LDS;
+ tree type = build_qualified_type (record_type,
+ TYPE_QUALS_NO_ADDR_SPACE (record_type)
+ | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_LDS));
if (!sender)
- type = build_pointer_type (type);
-
- tree decl = create_tmp_var_raw (type, name);
-
- if (sender)
{
- DECL_CONTEXT (decl) = NULL_TREE;
- TREE_STATIC (decl) = 1;
+ tree ptr_type = build_pointer_type (type);
+ return create_tmp_var_raw (ptr_type, name);
}
- if (sender)
- varpool_node::finalize_decl (decl);
+ if (record_type == char_type_node)
+ offset = 1;
- return decl;
+ tree ptr_type = build_pointer_type (type);
+ return build_int_cst (ptr_type, offset);
}
/* }}} */
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 84ff675..01fdce6 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -827,8 +827,12 @@
/* Work around assembler bug in which a 64-bit register is expected,
but a 32-bit value would be correct. */
int reg = REGNO (operands[2]) - FIRST_VGPR_REG;
- sprintf (buf, "global_load%%o0\t%%0, v[%d:%d], %%1 offset:%%3%s\;"
- "s_waitcnt\tvmcnt(0)", reg, reg + 1, glc);
+ if (HAVE_GCN_ASM_GLOBAL_LOAD_FIXED)
+ sprintf (buf, "global_load%%o0\t%%0, v%d, %%1 offset:%%3%s\;"
+ "s_waitcnt\tvmcnt(0)", reg, glc);
+ else
+ sprintf (buf, "global_load%%o0\t%%0, v[%d:%d], %%1 offset:%%3%s\;"
+ "s_waitcnt\tvmcnt(0)", reg, reg + 1, glc);
}
else
gcc_unreachable ();
@@ -958,8 +962,12 @@
/* Work around assembler bug in which a 64-bit register is expected,
but a 32-bit value would be correct. */
int reg = REGNO (operands[1]) - FIRST_VGPR_REG;
- sprintf (buf, "global_store%%s3\tv[%d:%d], %%3, %%0 offset:%%2%s",
- reg, reg + 1, glc);
+ if (HAVE_GCN_ASM_GLOBAL_LOAD_FIXED)
+ sprintf (buf, "global_store%%s3\tv%d, %%3, %%0 offset:%%2%s",
+ reg, glc);
+ else
+ sprintf (buf, "global_store%%s3\tv[%d:%d], %%3, %%0 offset:%%2%s",
+ reg, reg + 1, glc);
}
else
gcc_unreachable ();
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 9df2827..75a9c57 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -51,6 +51,7 @@
#include "intl.h"
#include "rtl-iter.h"
#include "dwarf2.h"
+#include "gimple.h"
/* This file should be included last. */
#include "target-def.h"
@@ -73,14 +74,21 @@ int gcn_isa = 3; /* Default to GCN3. */
We want to permit full occupancy, so size accordingly. */
+/* Use this as a default, but allow it to grow if the user requests a large
+ amount of gang-private shared-memory space. */
+static int acc_lds_size = 0x600;
+
#define OMP_LDS_SIZE 0x600 /* 0x600 is 1/40 total, rounded down. */
-#define ACC_LDS_SIZE 32768 /* Half of the total should be fine. */
+#define ACC_LDS_SIZE acc_lds_size
#define OTHER_LDS_SIZE 65536 /* If in doubt, reserve all of it. */
#define LDS_SIZE (flag_openacc ? ACC_LDS_SIZE \
: flag_openmp ? OMP_LDS_SIZE \
: OTHER_LDS_SIZE)
+static int gang_private_hwm = 32;
+static hash_map<tree, int> lds_allocs;
+
/* The number of registers usable by normal non-kernel functions.
The SGPR count includes any special extra registers such as VCC. */
@@ -99,13 +107,6 @@ gcn_init_machine_status (void)
f = ggc_cleared_alloc<machine_function> ();
- /* Set up LDS allocation for broadcasting for this function. */
- f->lds_allocated = 32;
- f->lds_allocs = hash_map<tree, int>::create_ggc (64);
-
- /* And LDS temporary decls for worker reductions. */
- vec_alloc (f->reduc_decls, 0);
-
if (TARGET_GCN3)
f->use_flat_addressing = true;
@@ -145,6 +146,24 @@ gcn_option_override (void)
stack_size_opt = 1048576;
}
+ /* Reserve 1Kb (somewhat arbitrarily) of LDS space for reduction results and
+ worker broadcasts. */
+ if (gang_private_size_opt == -1)
+ gang_private_size_opt = 512;
+ else if (gang_private_size_opt < gang_private_hwm)
+ gang_private_size_opt = gang_private_hwm;
+ else if (gang_private_size_opt >= acc_lds_size - 1024)
+ {
+ /* We need some space for reductions and worker broadcasting. If the
+ user requests a large amount of gang-private LDS space, we might not
+ have enough left for the former. Increase the LDS allocation in that
+ case, although this may reduce the maximum occupancy on the
+ hardware. */
+ acc_lds_size = gang_private_size_opt + 1024;
+ if (acc_lds_size > 32768)
+ acc_lds_size = 32768;
+ }
+
/* The xnack option is a placeholder, for now. */
if (flag_xnack)
sorry ("XNACK support");
@@ -3066,7 +3085,7 @@ gcn_expand_prologue ()
The low-part is the address of the topmost addressable byte, which is
size-1. The high-part is an offset and should be zero. */
emit_move_insn (gen_rtx_REG (SImode, M0_REG),
- gen_int_mode (LDS_SIZE-1, SImode));
+ gen_int_mode (LDS_SIZE, SImode));
emit_insn (gen_prologue_use (gen_rtx_REG (SImode, M0_REG)));
@@ -5115,10 +5134,14 @@ gcn_oacc_dim_pos (int dim)
/* Implement TARGET_GOACC_FORK_JOIN. */
static bool
-gcn_fork_join (gcall *ARG_UNUSED (call), const int *ARG_UNUSED (dims),
- bool ARG_UNUSED (is_fork))
+gcn_fork_join (gcall *call, const int dims[], bool is_fork)
{
- /* GCN does not need to expand fork/join markers at the RTL level. */
+ tree arg = gimple_call_arg (call, 2);
+ unsigned axis = TREE_INT_CST_LOW (arg);
+
+ if (!is_fork && axis == GOMP_DIM_WORKER && dims[axis] != 1)
+ return true;
+
return false;
}
@@ -5161,6 +5184,28 @@ gcn_fixup_accel_lto_options (tree fndecl)
}
}
+/* Implement TARGET_GOACC_SHARED_MEM_LAYOUT hook. */
+
+static void
+gcn_shared_mem_layout (unsigned HOST_WIDE_INT *lo,
+ unsigned HOST_WIDE_INT *hi,
+ int ARG_UNUSED (dims[GOMP_DIM_MAX]),
+ unsigned HOST_WIDE_INT
+ ARG_UNUSED (private_size[GOMP_DIM_MAX]),
+ unsigned HOST_WIDE_INT reduction_size[GOMP_DIM_MAX])
+{
+ *lo = gang_private_size_opt + reduction_size[GOMP_DIM_WORKER];
+ /* !!! We can maybe use dims[] to estimate the maximum number of work
+ groups/wavefronts/etc. we will launch, and therefore tune the maximum
+ amount of LDS we should use. For now, use a minimal amount to try to
+ maximise occupancy. */
+ *hi = acc_lds_size;
+ machine_function *machfun = cfun->machine;
+ machfun->reduction_base = gang_private_size_opt;
+ machfun->reduction_limit
+ = gang_private_size_opt + reduction_size[GOMP_DIM_WORKER];
+}
+
/* }}} */
/* {{{ ASM Output. */
@@ -5172,42 +5217,70 @@ static void
output_file_start (void)
{
const char *cpu;
- bool use_sram = flag_sram_ecc;
+ bool use_xnack_attr = true;
+ bool use_sram_attr = true;
switch (gcn_arch)
{
case PROCESSOR_FIJI:
cpu = "gfx803";
-#ifndef HAVE_GCN_SRAM_ECC_FIJI
- use_sram = false;
+#ifndef HAVE_GCN_XNACK_FIJI
+ use_xnack_attr = false;
#endif
+ use_sram_attr = false;
break;
case PROCESSOR_VEGA10:
cpu = "gfx900";
-#ifndef HAVE_GCN_SRAM_ECC_GFX900
- use_sram = false;
+#ifndef HAVE_GCN_XNACK_GFX900
+ use_xnack_attr = false;
#endif
+ use_sram_attr = false;
break;
case PROCESSOR_VEGA20:
cpu = "gfx906";
-#ifndef HAVE_GCN_SRAM_ECC_GFX906
- use_sram = false;
+#ifndef HAVE_GCN_XNACK_GFX906
+ use_xnack_attr = false;
#endif
+ use_sram_attr = false;
break;
case PROCESSOR_GFX908:
cpu = "gfx908";
+#ifndef HAVE_GCN_XNACK_GFX908
+ use_xnack_attr = false;
+#endif
#ifndef HAVE_GCN_SRAM_ECC_GFX908
- use_sram = false;
+ use_sram_attr = false;
#endif
break;
default: gcc_unreachable ();
}
+#if HAVE_GCN_ASM_V3_SYNTAX
const char *xnack = (flag_xnack ? "+xnack" : "");
- /* FIXME: support "any" when we move to HSACOv4. */
- const char *sram_ecc = (use_sram ? "+sram-ecc" : "");
+ const char *sram_ecc = (flag_sram_ecc ? "+sram-ecc" : "");
+#endif
+#if HAVE_GCN_ASM_V4_SYNTAX
+ /* In HSACOv4 no attribute setting means the binary supports "any" hardware
+ configuration. In GCC binaries, this is true for SRAM ECC, but not
+ XNACK. */
+ const char *xnack = (flag_xnack ? ":xnack+" : ":xnack-");
+ const char *sram_ecc = (flag_sram_ecc == SRAM_ECC_ON ? ":sramecc+"
+ : flag_sram_ecc == SRAM_ECC_OFF ? ":sramecc-"
+ : "");
+#endif
+ if (!use_xnack_attr)
+ xnack = "";
+ if (!use_sram_attr)
+ sram_ecc = "";
fprintf(asm_out_file, "\t.amdgcn_target \"amdgcn-unknown-amdhsa--%s%s%s\"\n",
- cpu, xnack, sram_ecc);
+ cpu,
+#if HAVE_GCN_ASM_V3_SYNTAX
+ xnack, sram_ecc
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+ sram_ecc, xnack
+#endif
+ );
}
/* Implement ASM_DECLARE_FUNCTION_NAME via gcn-hsa.h.
@@ -5488,17 +5561,18 @@ gcn_section_type_flags (tree decl, const char *name, int reloc)
/* Helper function for gcn_asm_output_symbol_ref.
- FIXME: If we want to have propagation blocks allocated separately and
- statically like this, it would be better done via symbol refs and the
- assembler/linker. This is a temporary hack. */
+ FIXME: This function is used to lay out gang-private variables in LDS
+ on a per-CU basis.
+ There may be cases in which gang-private variables in different compilation
+ units could clobber each other. In that case we should be relying on the
+ linker to lay out gang-private LDS space, but that doesn't appear to be
+ possible at present. */
static void
gcn_print_lds_decl (FILE *f, tree var)
{
int *offset;
- machine_function *machfun = cfun->machine;
-
- if ((offset = machfun->lds_allocs->get (var)))
+ if ((offset = lds_allocs.get (var)))
fprintf (f, "%u", (unsigned) *offset);
else
{
@@ -5508,14 +5582,14 @@ gcn_print_lds_decl (FILE *f, tree var)
if (size > align && size > 4 && align < 8)
align = 8;
- machfun->lds_allocated = ((machfun->lds_allocated + align - 1)
- & ~(align - 1));
+ gang_private_hwm = ((gang_private_hwm + align - 1) & ~(align - 1));
- machfun->lds_allocs->put (var, machfun->lds_allocated);
- fprintf (f, "%u", machfun->lds_allocated);
- machfun->lds_allocated += size;
- if (machfun->lds_allocated > LDS_SIZE)
- error ("local data-share memory exhausted");
+ lds_allocs.put (var, gang_private_hwm);
+ fprintf (f, "%u", gang_private_hwm);
+ gang_private_hwm += size;
+ if (gang_private_hwm > gang_private_size_opt)
+ error ("gang-private data-share memory exhausted (increase with "
+ "%<-mgang-private-size=<number>%>)");
}
}
@@ -6515,6 +6589,8 @@ gcn_dwarf_register_span (rtx rtl)
#define TARGET_GOACC_REDUCTION gcn_goacc_reduction
#undef TARGET_GOACC_VALIDATE_DIMS
#define TARGET_GOACC_VALIDATE_DIMS gcn_goacc_validate_dims
+#undef TARGET_GOACC_SHARED_MEM_LAYOUT
+#define TARGET_GOACC_SHARED_MEM_LAYOUT gcn_shared_mem_layout
#undef TARGET_HARD_REGNO_MODE_OK
#define TARGET_HARD_REGNO_MODE_OK gcn_hard_regno_mode_ok
#undef TARGET_HARD_REGNO_NREGS
diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
index 5822ec3..b97ec48 100644
--- a/gcc/config/gcn/gcn.h
+++ b/gcc/config/gcn/gcn.h
@@ -576,10 +576,8 @@ struct GTY(()) machine_function
HOST_WIDE_INT local_vars;
HOST_WIDE_INT callee_saves;
- unsigned lds_allocated;
- hash_map<tree, int> *lds_allocs;
-
- vec<tree, va_gc> *reduc_decls;
+ unsigned HOST_WIDE_INT reduction_base;
+ unsigned HOST_WIDE_INT reduction_limit;
bool use_flat_addressing;
};
diff --git a/gcc/config/gcn/gcn.opt b/gcc/config/gcn/gcn.opt
index 6faacca..09cf191 100644
--- a/gcc/config/gcn/gcn.opt
+++ b/gcc/config/gcn/gcn.opt
@@ -68,6 +68,12 @@ mstack-size=
Target RejectNegative Joined UInteger Var(stack_size_opt) Init(-1)
-mstack-size=<number> Set the private segment size per wave-front, in bytes.
+int gang_private_size_opt = -1
+
+mgang-private-size=
+Target RejectNegative Joined UInteger Var(gang_private_size_opt) Init(-1)
+Amount of local data-share (LDS) memory to reserve for gang-private variables.
+
Wopenacc-dims
Target Var(warn_openacc_dims) Warning
Warn about invalid OpenACC dimensions.
diff --git a/gcc/config/gcn/mkoffload.c b/gcc/config/gcn/mkoffload.c
index 732bdfd..b2e71ea 100644
--- a/gcc/config/gcn/mkoffload.c
+++ b/gcc/config/gcn/mkoffload.c
@@ -42,8 +42,10 @@
#undef ELFOSABI_AMDGPU_HSA
#define ELFOSABI_AMDGPU_HSA 64
-#undef ELFABIVERSION_AMDGPU_HSA
-#define ELFABIVERSION_AMDGPU_HSA 1
+#undef ELFABIVERSION_AMDGPU_HSA_V3
+#define ELFABIVERSION_AMDGPU_HSA_V3 1
+#undef ELFABIVERSION_AMDGPU_HSA_V4
+#define ELFABIVERSION_AMDGPU_HSA_V4 2
#undef EF_AMDGPU_MACH_AMDGCN_GFX803
#define EF_AMDGPU_MACH_AMDGCN_GFX803 0x2a
@@ -54,8 +56,55 @@
#undef EF_AMDGPU_MACH_AMDGCN_GFX908
#define EF_AMDGPU_MACH_AMDGCN_GFX908 0x30
-#define EF_AMDGPU_XNACK 0x100
-#define EF_AMDGPU_SRAM_ECC 0x200
+#define EF_AMDGPU_XNACK_V3 0x100
+#define EF_AMDGPU_SRAM_ECC_V3 0x200
+
+#define EF_AMDGPU_FEATURE_XNACK_V4 0x300 /* Mask. */
+#define EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 0x000
+#define EF_AMDGPU_FEATURE_XNACK_ANY_V4 0x100
+#define EF_AMDGPU_FEATURE_XNACK_OFF_V4 0x200
+#define EF_AMDGPU_FEATURE_XNACK_ON_V4 0x300
+
+#define EF_AMDGPU_FEATURE_SRAMECC_V4 0xc00 /* Mask. */
+#define EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 0x000
+#define EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 0x400
+#define EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 0x800
+#define EF_AMDGPU_FEATURE_SRAMECC_ON_V4 0xc00
+
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+#define SET_XNACK_ON(VAR) VAR |= EF_AMDGPU_XNACK_V3
+#define SET_XNACK_OFF(VAR) VAR &= ~EF_AMDGPU_XNACK_V3
+#define TEST_XNACK(VAR) (VAR & EF_AMDGPU_XNACK_V3)
+
+#define SET_SRAM_ECC_ON(VAR) VAR |= EF_AMDGPU_SRAM_ECC_V3
+#define SET_SRAM_ECC_ANY(VAR) SET_SRAM_ECC_ON (VAR)
+#define SET_SRAM_ECC_OFF(VAR) VAR &= ~EF_AMDGPU_SRAM_ECC_V3
+#define SET_SRAM_ECC_UNSUPPORTED(VAR) SET_SRAM_ECC_OFF (VAR)
+#define TEST_SRAM_ECC_ANY(VAR) 0 /* Not supported. */
+#define TEST_SRAM_ECC_ON(VAR) (VAR & EF_AMDGPU_SRAM_ECC_V3)
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+#define SET_XNACK_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
+ | EF_AMDGPU_FEATURE_XNACK_ON_V4)
+#define SET_XNACK_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
+ | EF_AMDGPU_FEATURE_XNACK_OFF_V4)
+#define TEST_XNACK(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) \
+ == EF_AMDGPU_FEATURE_XNACK_ON_V4)
+
+#define SET_SRAM_ECC_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
+#define SET_SRAM_ECC_ANY(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
+#define SET_SRAM_ECC_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_OFF_V4)
+#define SET_SRAM_ECC_UNSUPPORTED(VAR) \
+ VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ | EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4)
+#define TEST_SRAM_ECC_ANY(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
+#define TEST_SRAM_ECC_ON(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
+ == EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
+#endif
#ifndef R_AMDGPU_NONE
#define R_AMDGPU_NONE 0
@@ -80,7 +129,13 @@ static struct obstack files_to_cleanup;
enum offload_abi offload_abi = OFFLOAD_ABI_UNSET;
uint32_t elf_arch = EF_AMDGPU_MACH_AMDGCN_GFX803; // Default GPU architecture.
-uint32_t elf_flags = 0;
+uint32_t elf_flags =
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+ 0;
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+ (EF_AMDGPU_FEATURE_XNACK_ANY_V4 | EF_AMDGPU_FEATURE_SRAMECC_ANY_V4);
+#endif
/* Delete tempfiles. */
@@ -297,12 +352,27 @@ copy_early_debug_info (const char *infile, const char *outfile)
/* We only support host relocations of x86_64, for now. */
gcc_assert (ehdr.e_machine == EM_X86_64);
+ /* Fiji devices use HSACOv3 regardless of the assembler. */
+ uint32_t elf_flags_actual = (elf_arch == EF_AMDGPU_MACH_AMDGCN_GFX803
+ ? 0 : elf_flags);
+ /* GFX900 devices don't support the sramecc attribute even if
+ a buggy assembler thinks it does. This must match gcn-hsa.h */
+ if (elf_arch == EF_AMDGPU_MACH_AMDGCN_GFX900)
+ SET_SRAM_ECC_UNSUPPORTED (elf_flags_actual);
+
/* Patch the correct elf architecture flag into the file. */
ehdr.e_ident[7] = ELFOSABI_AMDGPU_HSA;
- ehdr.e_ident[8] = ELFABIVERSION_AMDGPU_HSA;
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+ ehdr.e_ident[8] = ELFABIVERSION_AMDGPU_HSA_V3;
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+ ehdr.e_ident[8] = (elf_arch == EF_AMDGPU_MACH_AMDGCN_GFX803
+ ? ELFABIVERSION_AMDGPU_HSA_V3
+ : ELFABIVERSION_AMDGPU_HSA_V4);
+#endif
ehdr.e_type = ET_REL;
ehdr.e_machine = EM_AMDGPU;
- ehdr.e_flags = elf_arch | elf_flags;
+ ehdr.e_flags = elf_arch | elf_flags_actual;
/* Load the section headers so we can walk them later. */
Elf64_Shdr *sections = (Elf64_Shdr *)xmalloc (sizeof (Elf64_Shdr)
@@ -851,23 +921,22 @@ main (int argc, char **argv)
else if (strcmp (argv[i], "-fpic") == 0)
fpic = true;
else if (strcmp (argv[i], "-mxnack") == 0)
- elf_flags |= EF_AMDGPU_XNACK;
+ SET_XNACK_ON (elf_flags);
else if (strcmp (argv[i], "-mno-xnack") == 0)
- elf_flags &= ~EF_AMDGPU_XNACK;
+ SET_XNACK_OFF (elf_flags);
else if (strcmp (argv[i], "-msram-ecc=on") == 0)
{
- elf_flags |= EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_ON (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-msram-ecc=any") == 0)
{
- /* FIXME: change this when we move to HSACOv4. */
- elf_flags |= EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_ANY (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-msram-ecc=off") == 0)
{
- elf_flags &= ~EF_AMDGPU_SRAM_ECC;
+ SET_SRAM_ECC_OFF (elf_flags);
sram_seen = true;
}
else if (strcmp (argv[i], "-save-temps") == 0)
@@ -890,23 +959,27 @@ main (int argc, char **argv)
if (!(fopenacc ^ fopenmp))
fatal_error (input_location, "either -fopenacc or -fopenmp must be set");
- /* The SRAM-ECC feature defaults to "any" on GPUs where the feature is
- available. */
if (!sram_seen)
- switch (elf_arch)
- {
- case EF_AMDGPU_MACH_AMDGCN_GFX803:
- case EF_AMDGPU_MACH_AMDGCN_GFX900:
- case EF_AMDGPU_MACH_AMDGCN_GFX906:
+ {
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+ /* For HSACOv3, the SRAM-ECC feature defaults to "on" on GPUs where the
+ feature is available.
+ (HSACOv4 has elf_flags initialsed to "any" in all cases.) */
+ switch (elf_arch)
+ {
+ case EF_AMDGPU_MACH_AMDGCN_GFX803:
+ case EF_AMDGPU_MACH_AMDGCN_GFX900:
+ case EF_AMDGPU_MACH_AMDGCN_GFX906:
#ifndef HAVE_GCN_SRAM_ECC_GFX908
- case EF_AMDGPU_MACH_AMDGCN_GFX908:
+ case EF_AMDGPU_MACH_AMDGCN_GFX908:
#endif
- break;
- default:
- /* FIXME: change this when we move to HSACOv4. */
- elf_flags |= EF_AMDGPU_SRAM_ECC;
- break;
- }
+ break;
+ default:
+ SET_SRAM_ECC_ON (elf_flags);
+ break;
+ }
+#endif
+ }
const char *abi;
switch (offload_abi)
@@ -935,12 +1008,6 @@ main (int argc, char **argv)
obstack_ptr_grow (&cc_argv_obstack, "-xlto");
if (fopenmp)
obstack_ptr_grow (&cc_argv_obstack, "-mgomp");
- obstack_ptr_grow (&cc_argv_obstack,
- (elf_flags & EF_AMDGPU_XNACK
- ? "-mxnack" : "-mno-xnack"));
- obstack_ptr_grow (&cc_argv_obstack,
- (elf_flags & EF_AMDGPU_SRAM_ECC
- ? "-msram-ecc=on" : "-msram-ecc=off"));
for (int ix = 1; ix != argc; ix++)
{
@@ -1043,11 +1110,12 @@ main (int argc, char **argv)
obstack_ptr_grow (&ld_argv_obstack, gcn_s2_name);
obstack_ptr_grow (&ld_argv_obstack, "-lgomp");
obstack_ptr_grow (&ld_argv_obstack,
- (elf_flags & EF_AMDGPU_XNACK
+ (TEST_XNACK (elf_flags)
? "-mxnack" : "-mno-xnack"));
obstack_ptr_grow (&ld_argv_obstack,
- (elf_flags & EF_AMDGPU_SRAM_ECC
- ? "-msram-ecc=on" : "-msram-ecc=off"));
+ (TEST_SRAM_ECC_ON (elf_flags) ? "-msram-ecc=on"
+ : TEST_SRAM_ECC_ANY (elf_flags) ? "-msram-ecc=any"
+ : "-msram-ecc=off"));
if (verbose)
obstack_ptr_grow (&ld_argv_obstack, "-v");
diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md
index 82cb161..0d28c75 100644
--- a/gcc/config/h8300/bitfield.md
+++ b/gcc/config/h8300/bitfield.md
@@ -338,17 +338,6 @@
}
[(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)]))]
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 3d34401..4a9624f 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -45,7 +45,6 @@ extern int compute_a_shift_cc (rtx *, rtx_code);
#ifdef HAVE_ATTR_cc
extern enum attr_cc compute_plussi_cc (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, rtx_code);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 5f7251a..a63c322 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -3256,30 +3256,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_
return length;
}
-
#if 0
-/* Expand a conditional branch. */
-
-void
-h8300_expand_branch (rtx operands[])
-{
- enum rtx_code code = GET_CODE (operands[0]);
- rtx op0 = operands[1];
- rtx op1 = operands[2];
- rtx label = operands[3];
- rtx tmp;
-
- tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
- emit_insn (gen_rtx_SET (cc0_rtx, tmp));
-
- tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
-}
-
-
+
/* Expand a conditional store. */
void
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 7f49e42..e81e21b 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -223,6 +223,7 @@
(define_mode_iterator HSI [HI SI])
(define_mode_iterator QHSI [QI HI SI])
+(define_mode_iterator QHSI2 [QI HI SI])
(define_mode_iterator QHSIF [QI HI SI SF])
@@ -233,6 +234,14 @@
(define_code_iterator logicals [ior xor and])
(define_code_iterator ors [ior xor])
+
+(define_code_iterator eqne [eq ne])
+
+;; For storing the C flag, map from the unsigned comparison to the right
+;; code for testing the C bit.
+(define_code_iterator geultu [geu ltu])
+(define_code_attr geultu_to_c [(geu "eq") (ltu "ne")])
+
(include "movepush.md")
(include "mova.md")
diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md
index 2919053..0ee3e36 100644
--- a/gcc/config/h8300/testcompare.md
+++ b/gcc/config/h8300/testcompare.md
@@ -70,6 +70,22 @@
"mov.w %e0,%e0"
[(set_attr "length" "2")])
+(define_insn "*cmp<mode>_c"
+ [(set (reg:CCC CC_REG)
+ (ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ")
+ (match_operand:QHSI 1 "h8300_src_operand" "rQi")))]
+ "reload_completed"
+ {
+ if (<MODE>mode == QImode)
+ return "cmp.b %X1,%X0";
+ else if (<MODE>mode == HImode)
+ return "cmp.w %T1,%T0";
+ else if (<MODE>mode == SImode)
+ return "cmp.l %S1,%S0";
+ gcc_unreachable ();
+ }
+ [(set_attr "length_table" "add")])
+
(define_insn "*cmpqi"
[(set (reg:CC CC_REG)
(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
@@ -144,3 +160,183 @@
[(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])])
+;; This exists solely to convince ifcvt to try some store-flag sequences.
+;;
+;; Essentially we don't want to expose a general store-flag capability.
+;; The only generally useful/profitable case is when we want to test the
+;; C bit. In that case we can use addx, subx, bst, or bist to get the bit
+;; into a GPR.
+;;
+;; Others could be handled with stc, shifts and masking, but it likely isn't
+;; profitable.
+;;
+(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"))]
+ ""
+ {
+ FAIL;
+ })
+
+;; Storing the C bit is pretty simple since there are many ways to
+;; introduce it into a GPR. addx, subx and a variety of bit manipulation
+;; instructions
+;;
+(define_insn "*store_c_<mode>"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (eqne:QHSI (reg:CCC CC_REG) (const_int 0)))]
+ "reload_completed"
+ {
+ if (<CODE> == NE)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bst\t#0,%X0";
+ else if (<MODE>mode == HImode)
+ return "xor.w\t%T0,%T0\;bst\t#0,%s0";
+ else if (<MODE>mode == SImode)
+ return "xor.l\t%S0,%S0\;bst\t#0,%w0";
+ gcc_unreachable ();
+ }
+ else if (<CODE> == EQ)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bist\t#0,%X0";
+ else if (<MODE>mode == HImode)
+ return "xor.w\t%T0,%T0\;bist\t#0,%s0";
+ else if (<MODE>mode == SImode)
+ return "xor.l\t%S0,%S0\;bist\t#0,%w0";
+ gcc_unreachable ();
+ }
+ }
+ [(set (attr "length") (symbol_ref "<MODE>mode == SImode ? 6 : 4"))])
+
+;; Similarly, but with a negated result
+(define_insn "*store_neg_c_<mode>"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))]
+ "reload_completed"
+ {
+ if (<MODE>mode == QImode)
+ return "subx\t%X0,%X0";
+ else if (<MODE>mode == HImode)
+ return "subx\t%X0,%X0\;exts.w\t%T0";
+ else if (<MODE>mode == SImode)
+ return "subx\t%X0,%X0\;exts.w\t%T0\;exts.l\t%S0";
+ gcc_unreachable ();
+ }
+ [(set
+ (attr "length")
+ (symbol_ref "(<MODE>mode == SImode ? 6 : <MODE>mode == HImode ? 4 : 2)"))])
+
+;; Using b[i]st we can store the C bit into any of the low 16 bits of
+;; a destination. We can also rotate it up into the high bit of a 32 bit
+;; destination.
+(define_insn "*store_shifted_c<mode>"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (ashift:QHSI (eqne:QHSI (reg:CCC CC_REG) (const_int 0))
+ (match_operand 1 "immediate_operand" "n")))]
+ "(reload_completed
+ && (INTVAL (operands[1]) == 31 || INTVAL (operands[1]) <= 15))"
+ {
+ if (<CODE> == NE)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bst\t%1,%X0";
+ else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
+ return "xor.w\t%T0,%T0\;bst\t%1,%X0";
+ else if (<MODE>mode == HImode)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ output_asm_insn ("xor.w\t%T0,%T0\;bst\t%1,%t0", operands);
+ return "";
+ }
+ else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
+ return "xor.l\t%S0,%S0\;rotxr.l\t%S0";
+ else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
+ return "xor.l\t%S0,%S0\;bst\t%1,%X0";
+ else if (<MODE>mode == SImode)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ output_asm_insn ("xor.l\t%S0,%S0\;bst\t%1,%t0", operands);
+ return "";
+ }
+ gcc_unreachable ();
+ }
+ else if (<CODE> == EQ)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bist\t%1,%X0";
+ else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
+ return "xor.w\t%T0,%T0\;bist\t%1,%X0";
+ else if (<MODE>mode == HImode)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ output_asm_insn ("xor.w\t%T0,%T0\;bist\t%1,%t0", operands);
+ return "";
+ }
+ else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
+ return "xor.l\t%S0,%S0\;bixor\t#0,%X0\;rotxr.l\t%S0";
+ else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
+ return "xor.l\t%S0,%S0\;bist\t%1,%X0";
+ else if (<MODE>mode == SImode)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ output_asm_insn ("xor.l\t%S0,%S0\;bist\t%1,%t0", operands);
+ return "";
+ }
+ gcc_unreachable ();
+ }
+ gcc_unreachable ();
+ }
+ [(set
+ (attr "length")
+ (symbol_ref "(<MODE>mode == QImode ? 4
+ : <MODE>mode == HImode ? 4
+ : <CODE> == NE ? 6
+ : INTVAL (operands[1]) == 31 ? 8 : 6)"))])
+
+;; Recognize this scc and generate code we can match
+(define_insn_and_split "*store_c"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
+ (match_operand:QHSI2 2 "register_operand" "r")))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (reg:CCC CC_REG)
+ (ltu:CCC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0)))])
+
+;; We can fold in negation of the result and generate better code than
+;; what the generic bits would do when testing for C == 1
+(define_insn_and_split "*store_neg_c"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (neg:QHSI
+ (ltu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
+ (match_operand:QHSI2 2 "register_operand" "r"))))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (reg:CCC CC_REG)
+ (ltu:CCC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))])
+
+;; We can use rotates and bst/bist to put the C bit into various places
+;; in the destination.
+(define_insn_and_split "*store_shifted_c"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (ashift:QHSI (geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
+ (match_operand:QHSI2 2 "register_operand" "r"))
+ (match_operand 3 "immediate_operand" "n")))]
+ "INTVAL (operands[3]) == 31 || INTVAL (operands[3]) <= 15"
+ "#"
+ "&& reload_completed"
+ [(set (reg:CCC CC_REG) (ltu:CCC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (ashift:QHSI (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0))
+ (match_dup 3)))])
+
diff --git a/gcc/config/i386/amxbf16intrin.h b/gcc/config/i386/amxbf16intrin.h
index 8c24cdd..1d60e8e 100644
--- a/gcc/config/i386/amxbf16intrin.h
+++ b/gcc/config/i386/amxbf16intrin.h
@@ -34,7 +34,7 @@
#define __DISABLE_AMX_BF16__
#endif /* __AMX_BF16__ */
-#if defined(__x86_64__) && defined(__AMX_BF16__)
+#if defined(__x86_64__)
#define _tile_dpbf16ps_internal(dst,src1,src2) \
__asm__ volatile\
("{tdpbf16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpbf16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
diff --git a/gcc/config/i386/amxint8intrin.h b/gcc/config/i386/amxint8intrin.h
index 180c243..dbb7b6c 100644
--- a/gcc/config/i386/amxint8intrin.h
+++ b/gcc/config/i386/amxint8intrin.h
@@ -34,7 +34,7 @@
#define __DISABLE_AMX_INT8__
#endif /* __AMX_INT8__ */
-#if defined(__x86_64__) && defined(__AMX_INT8__)
+#if defined(__x86_64__)
#define _tile_int8_dp_internal(name,dst,src1,src2) \
__asm__ volatile \
("{"#name"\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|"#name"\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
diff --git a/gcc/config/i386/amxtileintrin.h b/gcc/config/i386/amxtileintrin.h
index 16c8b6e..75d784a 100644
--- a/gcc/config/i386/amxtileintrin.h
+++ b/gcc/config/i386/amxtileintrin.h
@@ -34,7 +34,7 @@
#define __DISABLE_AMX_TILE__
#endif /* __AMX_TILE__ */
-#if defined(__x86_64__) && defined(__AMX_TILE__)
+#if defined(__x86_64__)
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
_tile_loadconfig (const void *__config)
diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h
new file mode 100644
index 0000000..5e49447
--- /dev/null
+++ b/gcc/config/i386/avx512fp16intrin.h
@@ -0,0 +1,7157 @@
+/* Copyright (C) 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.
+
+ 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 <avx512fp16intrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512FP16INTRIN_H_INCLUDED
+#define __AVX512FP16INTRIN_H_INCLUDED
+
+#ifndef __AVX512FP16__
+#pragma GCC push_options
+#pragma GCC target("avx512fp16")
+#define __DISABLE_AVX512FP16__
+#endif /* __AVX512FP16__ */
+
+/* Internal data types for implementing the intrinsics. */
+typedef _Float16 __v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 __v16hf __attribute__ ((__vector_size__ (32)));
+typedef _Float16 __v32hf __attribute__ ((__vector_size__ (64)));
+
+/* The Intel API is flexible enough that we must allow aliasing with other
+ vector types, and their scalar components. */
+typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef _Float16 __m256h __attribute__ ((__vector_size__ (32), __may_alias__));
+typedef _Float16 __m512h __attribute__ ((__vector_size__ (64), __may_alias__));
+
+/* Unaligned version of the same type. */
+typedef _Float16 __m128h_u __attribute__ ((__vector_size__ (16), \
+ __may_alias__, __aligned__ (1)));
+typedef _Float16 __m256h_u __attribute__ ((__vector_size__ (32), \
+ __may_alias__, __aligned__ (1)));
+typedef _Float16 __m512h_u __attribute__ ((__vector_size__ (64), \
+ __may_alias__, __aligned__ (1)));
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_ph (_Float16 __A7, _Float16 __A6, _Float16 __A5,
+ _Float16 __A4, _Float16 __A3, _Float16 __A2,
+ _Float16 __A1, _Float16 __A0)
+{
+ return __extension__ (__m128h)(__v8hf){ __A0, __A1, __A2, __A3,
+ __A4, __A5, __A6, __A7 };
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_set_ph (_Float16 __A15, _Float16 __A14, _Float16 __A13,
+ _Float16 __A12, _Float16 __A11, _Float16 __A10,
+ _Float16 __A9, _Float16 __A8, _Float16 __A7,
+ _Float16 __A6, _Float16 __A5, _Float16 __A4,
+ _Float16 __A3, _Float16 __A2, _Float16 __A1,
+ _Float16 __A0)
+{
+ return __extension__ (__m256h)(__v16hf){ __A0, __A1, __A2, __A3,
+ __A4, __A5, __A6, __A7,
+ __A8, __A9, __A10, __A11,
+ __A12, __A13, __A14, __A15 };
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_set_ph (_Float16 __A31, _Float16 __A30, _Float16 __A29,
+ _Float16 __A28, _Float16 __A27, _Float16 __A26,
+ _Float16 __A25, _Float16 __A24, _Float16 __A23,
+ _Float16 __A22, _Float16 __A21, _Float16 __A20,
+ _Float16 __A19, _Float16 __A18, _Float16 __A17,
+ _Float16 __A16, _Float16 __A15, _Float16 __A14,
+ _Float16 __A13, _Float16 __A12, _Float16 __A11,
+ _Float16 __A10, _Float16 __A9, _Float16 __A8,
+ _Float16 __A7, _Float16 __A6, _Float16 __A5,
+ _Float16 __A4, _Float16 __A3, _Float16 __A2,
+ _Float16 __A1, _Float16 __A0)
+{
+ return __extension__ (__m512h)(__v32hf){ __A0, __A1, __A2, __A3,
+ __A4, __A5, __A6, __A7,
+ __A8, __A9, __A10, __A11,
+ __A12, __A13, __A14, __A15,
+ __A16, __A17, __A18, __A19,
+ __A20, __A21, __A22, __A23,
+ __A24, __A25, __A26, __A27,
+ __A28, __A29, __A30, __A31 };
+}
+
+/* Create vectors of elements in the reversed order from _mm_set_ph,
+ _mm256_set_ph and _mm512_set_ph functions. */
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2,
+ _Float16 __A3, _Float16 __A4, _Float16 __A5,
+ _Float16 __A6, _Float16 __A7)
+{
+ return _mm_set_ph (__A7, __A6, __A5, __A4, __A3, __A2, __A1, __A0);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2,
+ _Float16 __A3, _Float16 __A4, _Float16 __A5,
+ _Float16 __A6, _Float16 __A7, _Float16 __A8,
+ _Float16 __A9, _Float16 __A10, _Float16 __A11,
+ _Float16 __A12, _Float16 __A13, _Float16 __A14,
+ _Float16 __A15)
+{
+ return _mm256_set_ph (__A15, __A14, __A13, __A12, __A11, __A10, __A9,
+ __A8, __A7, __A6, __A5, __A4, __A3, __A2, __A1,
+ __A0);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_setr_ph (_Float16 __A0, _Float16 __A1, _Float16 __A2,
+ _Float16 __A3, _Float16 __A4, _Float16 __A5,
+ _Float16 __A6, _Float16 __A7, _Float16 __A8,
+ _Float16 __A9, _Float16 __A10, _Float16 __A11,
+ _Float16 __A12, _Float16 __A13, _Float16 __A14,
+ _Float16 __A15, _Float16 __A16, _Float16 __A17,
+ _Float16 __A18, _Float16 __A19, _Float16 __A20,
+ _Float16 __A21, _Float16 __A22, _Float16 __A23,
+ _Float16 __A24, _Float16 __A25, _Float16 __A26,
+ _Float16 __A27, _Float16 __A28, _Float16 __A29,
+ _Float16 __A30, _Float16 __A31)
+
+{
+ return _mm512_set_ph (__A31, __A30, __A29, __A28, __A27, __A26, __A25,
+ __A24, __A23, __A22, __A21, __A20, __A19, __A18,
+ __A17, __A16, __A15, __A14, __A13, __A12, __A11,
+ __A10, __A9, __A8, __A7, __A6, __A5, __A4, __A3,
+ __A2, __A1, __A0);
+}
+
+/* Broadcast _Float16 to vector. */
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set1_ph (_Float16 __A)
+{
+ return _mm_set_ph (__A, __A, __A, __A, __A, __A, __A, __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_set1_ph (_Float16 __A)
+{
+ return _mm256_set_ph (__A, __A, __A, __A, __A, __A, __A, __A,
+ __A, __A, __A, __A, __A, __A, __A, __A);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_set1_ph (_Float16 __A)
+{
+ return _mm512_set_ph (__A, __A, __A, __A, __A, __A, __A, __A,
+ __A, __A, __A, __A, __A, __A, __A, __A,
+ __A, __A, __A, __A, __A, __A, __A, __A,
+ __A, __A, __A, __A, __A, __A, __A, __A);
+}
+
+/* Create a vector with all zeros. */
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setzero_ph (void)
+{
+ return _mm_set1_ph (0.0f);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_setzero_ph (void)
+{
+ return _mm256_set1_ph (0.0f);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_setzero_ph (void)
+{
+ return _mm512_set1_ph (0.0f);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_undefined_ph (void)
+{
+ __m128h __Y = __Y;
+ return __Y;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_undefined_ph (void)
+{
+ __m256h __Y = __Y;
+ return __Y;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_undefined_ph (void)
+{
+ __m512h __Y = __Y;
+ return __Y;
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_h (__m128h __A)
+{
+ return __A[0];
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtsh_h (__m256h __A)
+{
+ return __A[0];
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtsh_h (__m512h __A)
+{
+ return __A[0];
+}
+
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph_ps (__m512h __a)
+{
+ return (__m512) __a;
+}
+
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph_pd (__m512h __a)
+{
+ return (__m512d) __a;
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph_si512 (__m512h __a)
+{
+ return (__m512i) __a;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph512_ph128 (__m512h __A)
+{
+ union
+ {
+ __m128h a[4];
+ __m512h v;
+ } u = { .v = __A };
+ return u.a[0];
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph512_ph256 (__m512h __A)
+{
+ union
+ {
+ __m256h a[2];
+ __m512h v;
+ } u = { .v = __A };
+ return u.a[0];
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph128_ph512 (__m128h __A)
+{
+ union
+ {
+ __m128h a[4];
+ __m512h v;
+ } u;
+ u.a[0] = __A;
+ return u.v;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castph256_ph512 (__m256h __A)
+{
+ union
+ {
+ __m256h a[2];
+ __m512h v;
+ } u;
+ u.a[0] = __A;
+ return u.v;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_zextph128_ph512 (__m128h __A)
+{
+ return (__m512h) _mm512_insertf32x4 (_mm512_setzero_ps (),
+ (__m128) __A, 0);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_zextph256_ph512 (__m256h __A)
+{
+ return (__m512h) _mm512_insertf64x4 (_mm512_setzero_pd (),
+ (__m256d) __A, 0);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castps_ph (__m512 __a)
+{
+ return (__m512h) __a;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castpd_ph (__m512d __a)
+{
+ return (__m512h) __a;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_castsi512_ph (__m512i __a)
+{
+ return (__m512h) __a;
+}
+
+/* Create a vector with element 0 as F and the rest zero. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_sh (_Float16 __F)
+{
+ return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, __F);
+}
+
+/* Create a vector with element 0 as *P and the rest zero. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_load_sh (void const *__P)
+{
+ return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ *(_Float16 const *) __P);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_load_ph (void const *__P)
+{
+ return *(const __m512h *) __P;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_load_ph (void const *__P)
+{
+ return *(const __m256h *) __P;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_load_ph (void const *__P)
+{
+ return *(const __m128h *) __P;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_loadu_ph (void const *__P)
+{
+ return *(const __m512h_u *) __P;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_loadu_ph (void const *__P)
+{
+ return *(const __m256h_u *) __P;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_loadu_ph (void const *__P)
+{
+ return *(const __m128h_u *) __P;
+}
+
+/* Stores the lower _Float16 value. */
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_store_sh (void *__P, __m128h __A)
+{
+ *(_Float16 *) __P = ((__v8hf)__A)[0];
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_store_ph (void *__P, __m512h __A)
+{
+ *(__m512h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_store_ph (void *__P, __m256h __A)
+{
+ *(__m256h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_store_ph (void *__P, __m128h __A)
+{
+ *(__m128h *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_storeu_ph (void *__P, __m512h __A)
+{
+ *(__m512h_u *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_storeu_ph (void *__P, __m256h __A)
+{
+ *(__m256h_u *) __P = __A;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_storeu_ph (void *__P, __m128h __A)
+{
+ *(__m128h_u *) __P = __A;
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_abs_ph (__m512h __A)
+{
+ return (__m512h) _mm512_and_epi32 ( _mm512_set1_epi32 (0x7FFF7FFF),
+ (__m512i) __A);
+}
+
+/* Intrinsics v[add,sub,mul,div]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_add_ph (__m512h __A, __m512h __B)
+{
+ return (__m512h) ((__v32hf) __A + (__v32hf) __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_add_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_addph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_add_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_addph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_sub_ph (__m512h __A, __m512h __B)
+{
+ return (__m512h) ((__v32hf) __A - (__v32hf) __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_sub_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_subph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_sub_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_subph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mul_ph (__m512h __A, __m512h __B)
+{
+ return (__m512h) ((__v32hf) __A * (__v32hf) __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_mul_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_mulph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_mul_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_mulph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_div_ph (__m512h __A, __m512h __B)
+{
+ return (__m512h) ((__v32hf) __A / (__v32hf) __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_div_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_divph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_div_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_divph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_add_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_addph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_add_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_addph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_add_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_addph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_sub_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_subph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_sub_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_subph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_sub_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_subph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mul_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_mulph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_mul_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_mulph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_mul_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_mulph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_div_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_divph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_div_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_divph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_div_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_divph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+#else
+#define _mm512_add_round_ph(A, B, C) \
+ ((__m512h)__builtin_ia32_addph512_mask_round((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_add_round_ph(A, B, C, D, E) \
+ ((__m512h)__builtin_ia32_addph512_mask_round((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_add_round_ph(A, B, C, D) \
+ ((__m512h)__builtin_ia32_addph512_mask_round((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#define _mm512_sub_round_ph(A, B, C) \
+ ((__m512h)__builtin_ia32_subph512_mask_round((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_sub_round_ph(A, B, C, D, E) \
+ ((__m512h)__builtin_ia32_subph512_mask_round((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_sub_round_ph(A, B, C, D) \
+ ((__m512h)__builtin_ia32_subph512_mask_round((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#define _mm512_mul_round_ph(A, B, C) \
+ ((__m512h)__builtin_ia32_mulph512_mask_round((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_mul_round_ph(A, B, C, D, E) \
+ ((__m512h)__builtin_ia32_mulph512_mask_round((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_mul_round_ph(A, B, C, D) \
+ ((__m512h)__builtin_ia32_mulph512_mask_round((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#define _mm512_div_round_ph(A, B, C) \
+ ((__m512h)__builtin_ia32_divph512_mask_round((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_div_round_ph(A, B, C, D, E) \
+ ((__m512h)__builtin_ia32_divph512_mask_round((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_div_round_ph(A, B, C, D) \
+ ((__m512h)__builtin_ia32_divph512_mask_round((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+#endif /* __OPTIMIZE__ */
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_conj_pch (__m512h __A)
+{
+ return (__m512h) _mm512_xor_epi32 ((__m512i) __A, _mm512_set1_epi32 (1<<31));
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_conj_pch (__m512h __W, __mmask16 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A),
+ (__v16sf) __W,
+ (__mmask16) __U);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_conj_pch (__mmask16 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_movaps512_mask ((__v16sf) _mm512_conj_pch (__A),
+ (__v16sf) _mm512_setzero_ps (),
+ (__mmask16) __U);
+}
+
+/* Intrinsics of v[add,sub,mul,div]sh. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_sh (__m128h __A, __m128h __B)
+{
+ __A[0] += __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_add_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_addsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_add_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_addsh_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_sh (__m128h __A, __m128h __B)
+{
+ __A[0] -= __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sub_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_subsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sub_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_subsh_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mul_sh (__m128h __A, __m128h __B)
+{
+ __A[0] *= __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_mul_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_mulsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_mul_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_mulsh_mask (__B, __C, _mm_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_div_sh (__m128h __A, __m128h __B)
+{
+ __A[0] /= __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_div_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_divsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_div_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_divsh_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_addsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_add_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_addsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_add_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_addsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_subsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sub_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_subsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sub_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_subsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mul_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_mulsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_mul_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_mulsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_mul_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_mulsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_div_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_divsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_div_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_divsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_div_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_divsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+#else
+#define _mm_add_round_sh(A, B, C) \
+ ((__m128h)__builtin_ia32_addsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_add_round_sh(A, B, C, D, E) \
+ ((__m128h)__builtin_ia32_addsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_add_round_sh(A, B, C, D) \
+ ((__m128h)__builtin_ia32_addsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#define _mm_sub_round_sh(A, B, C) \
+ ((__m128h)__builtin_ia32_subsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_sub_round_sh(A, B, C, D, E) \
+ ((__m128h)__builtin_ia32_subsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_sub_round_sh(A, B, C, D) \
+ ((__m128h)__builtin_ia32_subsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#define _mm_mul_round_sh(A, B, C) \
+ ((__m128h)__builtin_ia32_mulsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_mul_round_sh(A, B, C, D, E) \
+ ((__m128h)__builtin_ia32_mulsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_mul_round_sh(A, B, C, D) \
+ ((__m128h)__builtin_ia32_mulsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#define _mm_div_round_sh(A, B, C) \
+ ((__m128h)__builtin_ia32_divsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_div_round_sh(A, B, C, D, E) \
+ ((__m128h)__builtin_ia32_divsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_div_round_sh(A, B, C, D) \
+ ((__m128h)__builtin_ia32_divsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsic vmaxph vminph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_max_ph (__m512h __A, __m512h __B)
+{
+ return __builtin_ia32_maxph512_mask (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_max_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_maxph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_max_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_maxph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_min_ph (__m512h __A, __m512h __B)
+{
+ return __builtin_ia32_minph512_mask (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_min_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_minph512_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_min_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_minph512_mask (__B, __C,
+ _mm512_setzero_ph (), __A);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_max_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_maxph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_max_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_maxph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_max_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_maxph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_min_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_minph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_min_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_minph512_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_min_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_minph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm512_max_round_ph(A, B, C) \
+ (__builtin_ia32_maxph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_max_round_ph(A, B, C, D, E) \
+ (__builtin_ia32_maxph512_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_max_round_ph(A, B, C, D) \
+ (__builtin_ia32_maxph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#define _mm512_min_round_ph(A, B, C) \
+ (__builtin_ia32_minph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_min_round_ph(A, B, C, D, E) \
+ (__builtin_ia32_minph512_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_min_round_ph(A, B, C, D) \
+ (__builtin_ia32_minph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsic vmaxsh vminsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_sh (__m128h __A, __m128h __B)
+{
+ __A[0] = __A[0] > __B[0] ? __A[0] : __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_max_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_maxsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_max_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_maxsh_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_sh (__m128h __A, __m128h __B)
+{
+ __A[0] = __A[0] < __B[0] ? __A[0] : __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_min_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_minsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_min_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_minsh_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_maxsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_max_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_maxsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_max_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_maxsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_minsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_min_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_minsh_mask_round (__C, __D, __A, __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_min_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_minsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm_max_round_sh(A, B, C) \
+ (__builtin_ia32_maxsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_max_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_maxsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_max_round_sh(A, B, C, D) \
+ (__builtin_ia32_maxsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#define _mm_min_round_sh(A, B, C) \
+ (__builtin_ia32_minsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_min_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_minsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_min_round_sh(A, B, C, D) \
+ (__builtin_ia32_minsh_mask_round ((B), (C), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* vcmpph */
+#ifdef __OPTIMIZE
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cmp_ph_mask (__m512h __A, __m512h __B, const int __C)
+{
+ return (__mmask32) __builtin_ia32_cmpph512_mask (__A, __B, __C,
+ (__mmask32) -1);
+}
+
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cmp_ph_mask (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return (__mmask32) __builtin_ia32_cmpph512_mask (__B, __C, __D,
+ __A);
+}
+
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cmp_round_ph_mask (__m512h __A, __m512h __B, const int __C,
+ const int __D)
+{
+ return (__mmask32) __builtin_ia32_cmpph512_mask_round (__A, __B,
+ __C, (__mmask32) -1,
+ __D);
+}
+
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cmp_round_ph_mask (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D, const int __E)
+{
+ return (__mmask32) __builtin_ia32_cmpph512_mask_round (__B, __C,
+ __D, __A,
+ __E);
+}
+
+#else
+#define _mm512_cmp_ph_mask(A, B, C) \
+ (__builtin_ia32_cmpph512_mask ((A), (B), (C), (-1)))
+
+#define _mm512_mask_cmp_ph_mask(A, B, C, D) \
+ (__builtin_ia32_cmpph512_mask ((B), (C), (D), (A)))
+
+#define _mm512_cmp_round_ph_mask(A, B, C, D) \
+ (__builtin_ia32_cmpph512_mask_round ((A), (B), (C), (-1), (D)))
+
+#define _mm512_mask_cmp_round_ph_mask(A, B, C, D, E) \
+ (__builtin_ia32_cmpph512_mask_round ((B), (C), (D), (A), (E)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcmpsh. */
+#ifdef __OPTIMIZE__
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmp_sh_mask (__m128h __A, __m128h __B, const int __C)
+{
+ return (__mmask8)
+ __builtin_ia32_cmpsh_mask_round (__A, __B,
+ __C, (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cmp_sh_mask (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return (__mmask8)
+ __builtin_ia32_cmpsh_mask_round (__B, __C,
+ __D, __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmp_round_sh_mask (__m128h __A, __m128h __B, const int __C,
+ const int __D)
+{
+ return (__mmask8) __builtin_ia32_cmpsh_mask_round (__A, __B,
+ __C, (__mmask8) -1,
+ __D);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cmp_round_sh_mask (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D, const int __E)
+{
+ return (__mmask8) __builtin_ia32_cmpsh_mask_round (__B, __C,
+ __D, __A,
+ __E);
+}
+
+#else
+#define _mm_cmp_sh_mask(A, B, C) \
+ (__builtin_ia32_cmpsh_mask_round ((A), (B), (C), (-1), \
+ (_MM_FROUND_CUR_DIRECTION)))
+
+#define _mm_mask_cmp_sh_mask(A, B, C, D) \
+ (__builtin_ia32_cmpsh_mask_round ((B), (C), (D), (A), \
+ (_MM_FROUND_CUR_DIRECTION)))
+
+#define _mm_cmp_round_sh_mask(A, B, C, D) \
+ (__builtin_ia32_cmpsh_mask_round ((A), (B), (C), (-1), (D)))
+
+#define _mm_mask_cmp_round_sh_mask(A, B, C, D, E) \
+ (__builtin_ia32_cmpsh_mask_round ((B), (C), (D), (A), (E)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcomish. */
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comieq_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_EQ_OS,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comilt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LT_OS,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comile_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LE_OS,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comigt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GT_OS,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comige_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GE_OS,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comineq_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_NEQ_US,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomieq_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_EQ_OQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomilt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LT_OQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomile_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_LE_OQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomigt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GT_OQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomige_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_GE_OQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_ucomineq_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, _CMP_NEQ_UQ,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comi_sh (__m128h __A, __m128h __B, const int __P)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, __P,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_comi_round_sh (__m128h __A, __m128h __B, const int __P, const int __R)
+{
+ return __builtin_ia32_cmpsh_mask_round (__A, __B, __P,
+ (__mmask8) -1,__R);
+}
+
+#else
+#define _mm_comi_round_sh(A, B, P, R) \
+ (__builtin_ia32_cmpsh_mask_round ((A), (B), (P), (__mmask8) (-1), (R)))
+#define _mm_comi_sh(A, B, P) \
+ (__builtin_ia32_cmpsh_mask_round ((A), (B), (P), (__mmask8) (-1), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vsqrtph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_sqrt_ph (__m512h __A)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__A,
+ _mm512_setzero_ph(),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_sqrt_ph (__m512h __A, __mmask32 __B, __m512h __C)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_sqrt_ph (__mmask32 __A, __m512h __B)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__B,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_sqrt_round_ph (__m512h __A, const int __B)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__A,
+ _mm512_setzero_ph(),
+ (__mmask32) -1, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_sqrt_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_sqrt_round_ph (__mmask32 __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_sqrtph512_mask_round (__B,
+ _mm512_setzero_ph (),
+ __A, __C);
+}
+
+#else
+#define _mm512_sqrt_round_ph(A, B) \
+ (__builtin_ia32_sqrtph512_mask_round ((A), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (B)))
+
+#define _mm512_mask_sqrt_round_ph(A, B, C, D) \
+ (__builtin_ia32_sqrtph512_mask_round ((C), (A), (B), (D)))
+
+#define _mm512_maskz_sqrt_round_ph(A, B, C) \
+ (__builtin_ia32_sqrtph512_mask_round ((B), \
+ _mm512_setzero_ph (), \
+ (A), (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vrsqrtph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_rsqrt_ph (__m512h __A)
+{
+ return __builtin_ia32_rsqrtph512_mask (__A, _mm512_setzero_ph (),
+ (__mmask32) -1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_rsqrt_ph (__m512h __A, __mmask32 __B, __m512h __C)
+{
+ return __builtin_ia32_rsqrtph512_mask (__C, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_rsqrt_ph (__mmask32 __A, __m512h __B)
+{
+ return __builtin_ia32_rsqrtph512_mask (__B, _mm512_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vrsqrtsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_rsqrt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_rsqrtsh_mask (__B, __A, _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_rsqrt_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_rsqrtsh_mask (__D, __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_rsqrt_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_rsqrtsh_mask (__C, __B, _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vsqrtsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sqrt_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sqrt_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__D, __C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sqrt_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sqrt_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sqrt_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__D, __C, __A, __B,
+ __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sqrt_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_sqrtsh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm_sqrt_round_sh(A, B, C) \
+ (__builtin_ia32_sqrtsh_mask_round ((B), (A), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_sqrt_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_sqrtsh_mask_round ((D), (C), (A), (B), (E)))
+
+#define _mm_maskz_sqrt_round_sh(A, B, C, D) \
+ (__builtin_ia32_sqrtsh_mask_round ((C), (B), \
+ _mm_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vrcpph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_rcp_ph (__m512h __A)
+{
+ return __builtin_ia32_rcpph512_mask (__A, _mm512_setzero_ph (),
+ (__mmask32) -1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_rcp_ph (__m512h __A, __mmask32 __B, __m512h __C)
+{
+ return __builtin_ia32_rcpph512_mask (__C, __A, __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_rcp_ph (__mmask32 __A, __m512h __B)
+{
+ return __builtin_ia32_rcpph512_mask (__B, _mm512_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vrcpsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_rcp_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_rcpsh_mask (__B, __A, _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_rcp_sh (__m128h __A, __mmask32 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_rcpsh_mask (__D, __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_rcp_sh (__mmask32 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_rcpsh_mask (__C, __B, _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vscalefph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_scalef_ph (__m512h __A, __m512h __B)
+{
+ return __builtin_ia32_scalefph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_scalef_ph (__m512h __A, __mmask32 __B, __m512h __C, __m512h __D)
+{
+ return __builtin_ia32_scalefph512_mask_round (__C, __D, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_scalef_ph (__mmask32 __A, __m512h __B, __m512h __C)
+{
+ return __builtin_ia32_scalefph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_scalef_round_ph (__m512h __A, __m512h __B, const int __C)
+{
+ return __builtin_ia32_scalefph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_scalef_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return __builtin_ia32_scalefph512_mask_round (__C, __D, __A, __B,
+ __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_scalef_round_ph (__mmask32 __A, __m512h __B, __m512h __C,
+ const int __D)
+{
+ return __builtin_ia32_scalefph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm512_scalef_round_ph(A, B, C) \
+ (__builtin_ia32_scalefph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_scalef_round_ph(A, B, C, D, E) \
+ (__builtin_ia32_scalefph512_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_scalef_round_ph(A, B, C, D) \
+ (__builtin_ia32_scalefph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vscalefsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_scalef_sh (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_scalefsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_scalef_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_scalefsh_mask_round (__C, __D, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_scalef_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_scalefsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_scalef_round_sh (__m128h __A, __m128h __B, const int __C)
+{
+ return __builtin_ia32_scalefsh_mask_round (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_scalef_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return __builtin_ia32_scalefsh_mask_round (__C, __D, __A, __B,
+ __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_scalef_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return __builtin_ia32_scalefsh_mask_round (__B, __C,
+ _mm_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm_scalef_round_sh(A, B, C) \
+ (__builtin_ia32_scalefsh_mask_round ((A), (B), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (C)))
+
+#define _mm_mask_scalef_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_scalefsh_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm_maskz_scalef_round_sh(A, B, C, D) \
+ (__builtin_ia32_scalefsh_mask_round ((B), (C), _mm_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vreduceph. */
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_ph (__m512h __A, int __B)
+{
+ return __builtin_ia32_reduceph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_reduce_ph (__m512h __A, __mmask32 __B, __m512h __C, int __D)
+{
+ return __builtin_ia32_reduceph512_mask_round (__C, __D, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_reduce_ph (__mmask32 __A, __m512h __B, int __C)
+{
+ return __builtin_ia32_reduceph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_round_ph (__m512h __A, int __B, const int __C)
+{
+ return __builtin_ia32_reduceph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_reduce_round_ph (__m512h __A, __mmask32 __B, __m512h __C,
+ int __D, const int __E)
+{
+ return __builtin_ia32_reduceph512_mask_round (__C, __D, __A, __B,
+ __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_reduce_round_ph (__mmask32 __A, __m512h __B, int __C,
+ const int __D)
+{
+ return __builtin_ia32_reduceph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm512_reduce_ph(A, B) \
+ (__builtin_ia32_reduceph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_mask_reduce_ph(A, B, C, D) \
+ (__builtin_ia32_reduceph512_mask_round ((C), (D), (A), (B), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_maskz_reduce_ph(A, B, C) \
+ (__builtin_ia32_reduceph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_reduce_round_ph(A, B, C) \
+ (__builtin_ia32_reduceph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_reduce_round_ph(A, B, C, D, E) \
+ (__builtin_ia32_reduceph512_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_reduce_round_ph(A, B, C, D) \
+ (__builtin_ia32_reduceph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vreducesh. */
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_sh (__m128h __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_reducesh_mask_round (__A, __B, __C,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_reduce_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, int __E)
+{
+ return __builtin_ia32_reducesh_mask_round (__C, __D, __E, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_reduce_sh (__mmask8 __A, __m128h __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_reducesh_mask_round (__B, __C, __D,
+ _mm_setzero_ph (), __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_round_sh (__m128h __A, __m128h __B, int __C, const int __D)
+{
+ return __builtin_ia32_reducesh_mask_round (__A, __B, __C,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_reduce_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, int __E, const int __F)
+{
+ return __builtin_ia32_reducesh_mask_round (__C, __D, __E, __A,
+ __B, __F);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_reduce_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ int __D, const int __E)
+{
+ return __builtin_ia32_reducesh_mask_round (__B, __C, __D,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm_reduce_sh(A, B, C) \
+ (__builtin_ia32_reducesh_mask_round ((A), (B), (C), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_mask_reduce_sh(A, B, C, D, E) \
+ (__builtin_ia32_reducesh_mask_round ((C), (D), (E), (A), (B), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_maskz_reduce_sh(A, B, C, D) \
+ (__builtin_ia32_reducesh_mask_round ((B), (C), (D), \
+ _mm_setzero_ph (), \
+ (A), _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_reduce_round_sh(A, B, C, D) \
+ (__builtin_ia32_reducesh_mask_round ((A), (B), (C), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (D)))
+
+#define _mm_mask_reduce_round_sh(A, B, C, D, E, F) \
+ (__builtin_ia32_reducesh_mask_round ((C), (D), (E), (A), (B), (F)))
+
+#define _mm_maskz_reduce_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_reducesh_mask_round ((B), (C), (D), \
+ _mm_setzero_ph (), \
+ (A), (E)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vrndscaleph. */
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_roundscale_ph (__m512h __A, int __B)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_roundscale_ph (__m512h __A, __mmask32 __B,
+ __m512h __C, int __D)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__C, __D, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_roundscale_ph (__mmask32 __A, __m512h __B, int __C)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_roundscale_round_ph (__m512h __A, int __B, const int __C)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__A, __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ __C);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_roundscale_round_ph (__m512h __A, __mmask32 __B,
+ __m512h __C, int __D, const int __E)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__C, __D, __A,
+ __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_roundscale_round_ph (__mmask32 __A, __m512h __B, int __C,
+ const int __D)
+{
+ return __builtin_ia32_rndscaleph512_mask_round (__B, __C,
+ _mm512_setzero_ph (),
+ __A, __D);
+}
+
+#else
+#define _mm512_roundscale_ph(A, B) \
+ (__builtin_ia32_rndscaleph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_mask_roundscale_ph(A, B, C, D) \
+ (__builtin_ia32_rndscaleph512_mask_round ((C), (D), (A), (B), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_maskz_roundscale_ph(A, B, C) \
+ (__builtin_ia32_rndscaleph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), \
+ _MM_FROUND_CUR_DIRECTION))
+#define _mm512_roundscale_round_ph(A, B, C) \
+ (__builtin_ia32_rndscaleph512_mask_round ((A), (B), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, (C)))
+
+#define _mm512_mask_roundscale_round_ph(A, B, C, D, E) \
+ (__builtin_ia32_rndscaleph512_mask_round ((C), (D), (A), (B), (E)))
+
+#define _mm512_maskz_roundscale_round_ph(A, B, C, D) \
+ (__builtin_ia32_rndscaleph512_mask_round ((B), (C), \
+ _mm512_setzero_ph (), \
+ (A), (D)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vrndscalesh. */
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_roundscale_sh (__m128h __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__A, __B, __C,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_roundscale_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, int __E)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__C, __D, __E, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_roundscale_sh (__mmask8 __A, __m128h __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__B, __C, __D,
+ _mm_setzero_ph (), __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_roundscale_round_sh (__m128h __A, __m128h __B, int __C, const int __D)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__A, __B, __C,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_roundscale_round_sh (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, int __E, const int __F)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__C, __D, __E,
+ __A, __B, __F);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_roundscale_round_sh (__mmask8 __A, __m128h __B, __m128h __C,
+ int __D, const int __E)
+{
+ return __builtin_ia32_rndscalesh_mask_round (__B, __C, __D,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm_roundscale_sh(A, B, C) \
+ (__builtin_ia32_rndscalesh_mask_round ((A), (B), (C), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_mask_roundscale_sh(A, B, C, D, E) \
+ (__builtin_ia32_rndscalesh_mask_round ((C), (D), (E), (A), (B), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_maskz_roundscale_sh(A, B, C, D) \
+ (__builtin_ia32_rndscalesh_mask_round ((B), (C), (D), \
+ _mm_setzero_ph (), \
+ (A), _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_roundscale_round_sh(A, B, C, D) \
+ (__builtin_ia32_rndscalesh_mask_round ((A), (B), (C), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (D)))
+
+#define _mm_mask_roundscale_round_sh(A, B, C, D, E, F) \
+ (__builtin_ia32_rndscalesh_mask_round ((C), (D), (E), (A), (B), (F)))
+
+#define _mm_maskz_roundscale_round_sh(A, B, C, D, E) \
+ (__builtin_ia32_rndscalesh_mask_round ((B), (C), (D), \
+ _mm_setzero_ph (), \
+ (A), (E)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfpclasssh. */
+#ifdef __OPTIMIZE__
+extern __inline __mmask8
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fpclass_sh_mask (__m128h __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) __A, __imm,
+ (__mmask8) -1);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fpclass_sh_mask (__mmask8 __U, __m128h __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) __A, __imm, __U);
+}
+
+#else
+#define _mm_fpclass_sh_mask(X, C) \
+ ((__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) (__m128h) (X), \
+ (int) (C), (__mmask8) (-1))) \
+
+#define _mm_mask_fpclass_sh_mask(U, X, C) \
+ ((__mmask8) __builtin_ia32_fpclasssh_mask ((__v8hf) (__m128h) (X), \
+ (int) (C), (__mmask8) (U)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfpclassph. */
+#ifdef __OPTIMIZE__
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fpclass_ph_mask (__mmask32 __U, __m512h __A,
+ const int __imm)
+{
+ return (__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) __A,
+ __imm, __U);
+}
+
+extern __inline __mmask32
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fpclass_ph_mask (__m512h __A, const int __imm)
+{
+ return (__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) __A,
+ __imm,
+ (__mmask32) -1);
+}
+
+#else
+#define _mm512_mask_fpclass_ph_mask(u, x, c) \
+ ((__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) (__m512h) (x), \
+ (int) (c),(__mmask8)(u)))
+
+#define _mm512_fpclass_ph_mask(x, c) \
+ ((__mmask32) __builtin_ia32_fpclassph512_mask ((__v32hf) (__m512h) (x), \
+ (int) (c),(__mmask8)-1))
+#endif /* __OPIMTIZE__ */
+
+/* Intrinsics vgetexpph, vgetexpsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getexp_sh (__m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__v8hf) _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__v8hf) __W, (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_sh (__mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_getexpsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__v8hf) _mm_setzero_ph (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_getexp_ph (__m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_getexpph512_mask ((__v32hf) __A,
+ (__v32hf) _mm512_setzero_ph (),
+ (__mmask32) -1, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_getexp_ph (__m512h __W, __mmask32 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_getexpph512_mask ((__v32hf) __A, (__v32hf) __W,
+ (__mmask32) __U, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_getexp_ph (__mmask32 __U, __m512h __A)
+{
+ return (__m512h)
+ __builtin_ia32_getexpph512_mask ((__v32hf) __A,
+ (__v32hf) _mm512_setzero_ph (),
+ (__mmask32) __U, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getexp_round_sh (__m128h __A, __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_round_sh (__m128h __W, __mmask8 __U, __m128h __A,
+ __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __W,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_round_sh (__mmask8 __U, __m128h __A, __m128h __B,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_getexpsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf)
+ _mm_setzero_ph (),
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_getexp_round_ph (__m512h __A, const int __R)
+{
+ return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A,
+ (__v32hf)
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_getexp_round_ph (__m512h __W, __mmask32 __U, __m512h __A,
+ const int __R)
+{
+ return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A,
+ (__v32hf) __W,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_getexp_round_ph (__mmask32 __U, __m512h __A, const int __R)
+{
+ return (__m512h) __builtin_ia32_getexpph512_mask ((__v32hf) __A,
+ (__v32hf)
+ _mm512_setzero_ph (),
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm_getexp_round_sh(A, B, R) \
+ ((__m128h)__builtin_ia32_getexpsh_mask_round((__v8hf)(__m128h)(A), \
+ (__v8hf)(__m128h)(B), \
+ (__v8hf)_mm_setzero_ph(), \
+ (__mmask8)-1, R))
+
+#define _mm_mask_getexp_round_sh(W, U, A, B, C) \
+ (__m128h)__builtin_ia32_getexpsh_mask_round(A, B, W, U, C)
+
+#define _mm_maskz_getexp_round_sh(U, A, B, C) \
+ (__m128h)__builtin_ia32_getexpsh_mask_round(A, B, \
+ (__v8hf)_mm_setzero_ph(), \
+ U, C)
+
+#define _mm512_getexp_round_ph(A, R) \
+ ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \
+ (__v32hf)_mm512_setzero_ph(), (__mmask32)-1, R))
+
+#define _mm512_mask_getexp_round_ph(W, U, A, R) \
+ ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \
+ (__v32hf)(__m512h)(W), (__mmask32)(U), R))
+
+#define _mm512_maskz_getexp_round_ph(U, A, R) \
+ ((__m512h)__builtin_ia32_getexpph512_mask((__v32hf)(__m512h)(A), \
+ (__v32hf)_mm512_setzero_ph(), (__mmask32)(U), R))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vgetmantph, vgetmantsh. */
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getmant_sh (__m128h __A, __m128h __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128h)
+ __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__D << 2) | __C, _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_sh (__m128h __W, __mmask8 __U, __m128h __A,
+ __m128h __B, _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128h)
+ __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__D << 2) | __C, (__v8hf) __W,
+ __U, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_sh (__mmask8 __U, __m128h __A, __m128h __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128h)
+ __builtin_ia32_getmantsh_mask_round ((__v8hf) __A, (__v8hf) __B,
+ (__D << 2) | __C,
+ (__v8hf) _mm_setzero_ph(),
+ __U, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_getmant_ph (__m512h __A, _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_getmant_ph (__m512h __W, __mmask32 __U, __m512h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ (__v32hf) __W, __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_getmant_ph (__mmask32 __U, __m512h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ (__v32hf)
+ _mm512_setzero_ph (),
+ __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getmant_round_sh (__m128h __A, __m128h __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__D << 2) | __C,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_round_sh (__m128h __W, __mmask8 __U, __m128h __A,
+ __m128h __B, _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__D << 2) | __C,
+ (__v8hf) __W,
+ __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_round_sh (__mmask8 __U, __m128h __A, __m128h __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128h) __builtin_ia32_getmantsh_mask_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__D << 2) | __C,
+ (__v8hf)
+ _mm_setzero_ph(),
+ __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_getmant_round_ph (__m512h __A, _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ _mm512_setzero_ph (),
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_getmant_round_ph (__m512h __W, __mmask32 __U, __m512h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ (__v32hf) __W, __U,
+ __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_getmant_round_ph (__mmask32 __U, __m512h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_getmantph512_mask ((__v32hf) __A,
+ (__C << 2) | __B,
+ (__v32hf)
+ _mm512_setzero_ph (),
+ __U, __R);
+}
+
+#else
+#define _mm512_getmant_ph(X, B, C) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h) \
+ _mm512_setzero_ph(), \
+ (__mmask32)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_mask_getmant_ph(W, U, X, B, C) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h)(W), \
+ (__mmask32)(U), \
+ _MM_FROUND_CUR_DIRECTION))
+
+
+#define _mm512_maskz_getmant_ph(U, X, B, C) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h) \
+ _mm512_setzero_ph(), \
+ (__mmask32)(U), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_getmant_sh(X, Y, C, D) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h) \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_mask_getmant_sh(W, U, X, Y, C, D) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h)(W), \
+ (__mmask8)(U), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_maskz_getmant_sh(U, X, Y, C, D) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h) \
+ _mm_setzero_ph(), \
+ (__mmask8)(U), \
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm512_getmant_round_ph(X, B, C, R) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h) \
+ _mm512_setzero_ph(), \
+ (__mmask32)-1, \
+ (R)))
+
+#define _mm512_mask_getmant_round_ph(W, U, X, B, C, R) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h)(W), \
+ (__mmask32)(U), \
+ (R)))
+
+
+#define _mm512_maskz_getmant_round_ph(U, X, B, C, R) \
+ ((__m512h)__builtin_ia32_getmantph512_mask ((__v32hf)(__m512h)(X), \
+ (int)(((C)<<2) | (B)), \
+ (__v32hf)(__m512h) \
+ _mm512_setzero_ph(), \
+ (__mmask32)(U), \
+ (R)))
+
+#define _mm_getmant_round_sh(X, Y, C, D, R) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h) \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ (R)))
+
+#define _mm_mask_getmant_round_sh(W, U, X, Y, C, D, R) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h)(W), \
+ (__mmask8)(U), \
+ (R)))
+
+#define _mm_maskz_getmant_round_sh(U, X, Y, C, D, R) \
+ ((__m128h)__builtin_ia32_getmantsh_mask_round ((__v8hf)(__m128h)(X), \
+ (__v8hf)(__m128h)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v8hf)(__m128h) \
+ _mm_setzero_ph(), \
+ (__mmask8)(U), \
+ (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vmovw. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi16_si128 (short __A)
+{
+ return _mm_set_epi16 (0, 0, 0, 0, 0, 0, 0, __A);
+}
+
+extern __inline short
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi128_si16 (__m128i __A)
+{
+ return __builtin_ia32_vec_ext_v8hi ((__v8hi)__A, 0);
+}
+
+/* Intrinsics vmovsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_load_sh (__m128h __A, __mmask8 __B, _Float16 const* __C)
+{
+ return __builtin_ia32_loadsh_mask (__C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_load_sh (__mmask8 __A, _Float16 const* __B)
+{
+ return __builtin_ia32_loadsh_mask (__B, _mm_setzero_ph (), __A);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_store_sh (_Float16 const* __A, __mmask8 __B, __m128h __C)
+{
+ __builtin_ia32_storesh_mask (__A, __C, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_move_sh (__m128h __A, __m128h __B)
+{
+ __A[0] = __B[0];
+ return __A;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_move_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_vmovsh_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_move_sh (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_vmovsh_mask (__B, __C, _mm_setzero_ph (), __A);
+}
+
+/* Intrinsics vcvtph2dq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epi32 (__m256h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epi32 (__m512i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epi32 (__mmask16 __A, __m256h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epi32 (__m256h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epi32 (__m512i __A, __mmask16 __B, __m256h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epi32 (__mmask16 __A, __m256h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2dq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epi32(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2dq512_mask_round ((A), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (__mmask16)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_epi32(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2dq512_mask_round ((C), (__v16si)(A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_epi32(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2dq512_mask_round ((B), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2udq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epu32 (__m256h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epu32 (__m512i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epu32 (__mmask16 __A, __m256h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epu32 (__m256h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epu32 (__m512i __A, __mmask16 __B, __m256h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epu32 (__mmask16 __A, __m256h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2udq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epu32(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2udq512_mask_round ((A), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (__mmask16)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_epu32(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2udq512_mask_round ((C), (__v16si)(A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_epu32(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2udq512_mask_round ((B), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2dq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epi32 (__m256h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epi32 (__m512i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epi32 (__mmask16 __A, __m256h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epi32 (__m256h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epi32 (__m512i __A, __mmask16 __B,
+ __m256h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epi32 (__mmask16 __A, __m256h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2dq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epi32(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2dq512_mask_round ((A), \
+ (__v16si) \
+ (_mm512_setzero_si512 ()), \
+ (__mmask16)(-1), (B)))
+
+#define _mm512_mask_cvtt_roundph_epi32(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2dq512_mask_round ((C), \
+ (__v16si)(A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvtt_roundph_epi32(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2dq512_mask_round ((B), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2udq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epu32 (__m256h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epu32 (__m512i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epu32 (__mmask16 __A, __m256h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epu32 (__m256h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__A,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epu32 (__m512i __A, __mmask16 __B,
+ __m256h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__C,
+ (__v16si) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epu32 (__mmask16 __A, __m256h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2udq512_mask_round (__B,
+ (__v16si)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epu32(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2udq512_mask_round ((A), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (__mmask16)-1, \
+ (B)))
+
+#define _mm512_mask_cvtt_roundph_epu32(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2udq512_mask_round ((C), \
+ (__v16si)(A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvtt_roundph_epu32(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2udq512_mask_round ((B), \
+ (__v16si) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtdq2ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtepi32_ph (__m512i __A)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepi32_ph (__m256h __A, __mmask16 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepi32_ph (__mmask16 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __B,
+ _mm256_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepi32_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepi32_ph (__m256h __A, __mmask16 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepi32_ph (__mmask16 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtdq2ph512_mask_round ((__v16si) __B,
+ _mm256_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepi32_ph(A, B) \
+ (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(A), \
+ _mm256_setzero_ph (), \
+ (__mmask16)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundepi32_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(C), \
+ (A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvt_roundepi32_ph(A, B, C) \
+ (__builtin_ia32_vcvtdq2ph512_mask_round ((__v16si)(B), \
+ _mm256_setzero_ph (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtudq2ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtepu32_ph (__m512i __A)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepu32_ph (__m256h __A, __mmask16 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepu32_ph (__mmask16 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __B,
+ _mm256_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepu32_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepu32_ph (__m256h __A, __mmask16 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepu32_ph (__mmask16 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtudq2ph512_mask_round ((__v16si) __B,
+ _mm256_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepu32_ph(A, B) \
+ (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)(A), \
+ _mm256_setzero_ph (), \
+ (__mmask16)-1, \
+ B))
+
+#define _mm512_mask_cvt_roundepu32_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)C, \
+ A, \
+ B, \
+ D))
+
+#define _mm512_maskz_cvt_roundepu32_ph(A, B, C) \
+ (__builtin_ia32_vcvtudq2ph512_mask_round ((__v16si)B, \
+ _mm256_setzero_ph (), \
+ A, \
+ C))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2qq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epi64 (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epi64 (__m512i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epi64 (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epi64 (__m512i __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epi64 (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_vcvtph2qq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epi64(A, B) \
+ (__builtin_ia32_vcvtph2qq512_mask_round ((A), \
+ _mm512_setzero_si512 (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_epi64(A, B, C, D) \
+ (__builtin_ia32_vcvtph2qq512_mask_round ((C), (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_epi64(A, B, C) \
+ (__builtin_ia32_vcvtph2qq512_mask_round ((B), \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2uqq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epu64 (__m512i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epu64 (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epu64 (__m512i __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epu64 (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_vcvtph2uqq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epu64(A, B) \
+ (__builtin_ia32_vcvtph2uqq512_mask_round ((A), \
+ _mm512_setzero_si512 (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_epu64(A, B, C, D) \
+ (__builtin_ia32_vcvtph2uqq512_mask_round ((C), (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_epu64(A, B, C) \
+ (__builtin_ia32_vcvtph2uqq512_mask_round ((B), \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2qq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epi64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epi64 (__m512i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epi64 (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epi64 (__m512i __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epi64 (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_vcvttph2qq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epi64(A, B) \
+ (__builtin_ia32_vcvttph2qq512_mask_round ((A), \
+ _mm512_setzero_si512 (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvtt_roundph_epi64(A, B, C, D) \
+ __builtin_ia32_vcvttph2qq512_mask_round ((C), (A), (B), (D))
+
+#define _mm512_maskz_cvtt_roundph_epi64(A, B, C) \
+ (__builtin_ia32_vcvttph2qq512_mask_round ((B), \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2uqq. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epu64 (__m512i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epu64 (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__A,
+ _mm512_setzero_si512 (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epu64 (__m512i __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epu64 (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_vcvttph2uqq512_mask_round (__B,
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epu64(A, B) \
+ (__builtin_ia32_vcvttph2uqq512_mask_round ((A), \
+ _mm512_setzero_si512 (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvtt_roundph_epu64(A, B, C, D) \
+ __builtin_ia32_vcvttph2uqq512_mask_round ((C), (A), (B), (D))
+
+#define _mm512_maskz_cvtt_roundph_epu64(A, B, C) \
+ (__builtin_ia32_vcvttph2uqq512_mask_round ((B), \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtqq2ph. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtepi64_ph (__m512i __A)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepi64_ph (__mmask8 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __B,
+ _mm_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepi64_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepi64_ph (__m128h __A, __mmask8 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepi64_ph (__mmask8 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtqq2ph512_mask_round ((__v8di) __B,
+ _mm_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepi64_ph(A, B) \
+ (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(A), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundepi64_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(C), (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundepi64_ph(A, B, C) \
+ (__builtin_ia32_vcvtqq2ph512_mask_round ((__v8di)(B), \
+ _mm_setzero_ph (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtuqq2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtepu64_ph (__m512i __A)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepu64_ph (__mmask8 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __B,
+ _mm_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepu64_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepu64_ph (__m128h __A, __mmask8 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepu64_ph (__mmask8 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di) __B,
+ _mm_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepu64_ph(A, B) \
+ (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(A), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundepu64_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(C), (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundepu64_ph(A, B, C) \
+ (__builtin_ia32_vcvtuqq2ph512_mask_round ((__v8di)(B), \
+ _mm_setzero_ph (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2w. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epi16 (__m512h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epi16 (__m512i __A, __mmask32 __B, __m512h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epi16 (__mmask32 __A, __m512h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epi16 (__m512h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epi16 (__m512i __A, __mmask32 __B, __m512h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epi16 (__mmask32 __A, __m512h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2w512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epi16(A, B) \
+ ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((A), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (__mmask32)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_epi16(A, B, C, D) \
+ ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((C), \
+ (__v32hi)(A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvt_roundph_epi16(A, B, C) \
+ ((__m512i)__builtin_ia32_vcvtph2w512_mask_round ((B), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2uw. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_epu16 (__m512h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_epu16 (__m512i __A, __mmask32 __B, __m512h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__C, (__v32hi) __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_epu16 (__mmask32 __A, __m512h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_epu16 (__m512h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_epu16 (__m512i __A, __mmask32 __B, __m512h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__C, (__v32hi) __A, __B, __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_epu16 (__mmask32 __A, __m512h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvtph2uw512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_epu16(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2uw512_mask_round ((A), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (__mmask32)-1, (B)))
+
+#define _mm512_mask_cvt_roundph_epu16(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2uw512_mask_round ((C), (__v32hi)(A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_epu16(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvtph2uw512_mask_round ((B), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2w. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epi16 (__m512h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epi16 (__m512i __A, __mmask32 __B, __m512h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epi16 (__mmask32 __A, __m512h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epi16 (__m512h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epi16 (__m512i __A, __mmask32 __B,
+ __m512h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epi16 (__mmask32 __A, __m512h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2w512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epi16(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2w512_mask_round ((A), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (__mmask32)-1, \
+ (B)))
+
+#define _mm512_mask_cvtt_roundph_epi16(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2w512_mask_round ((C), \
+ (__v32hi)(A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvtt_roundph_epi16(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2w512_mask_round ((B), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvttph2uw. */
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvttph_epu16 (__m512h __A)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvttph_epu16 (__m512i __A, __mmask32 __B, __m512h __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvttph_epu16 (__mmask32 __A, __m512h __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtt_roundph_epu16 (__m512h __A, int __B)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__A,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtt_roundph_epu16 (__m512i __A, __mmask32 __B,
+ __m512h __C, int __D)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__C,
+ (__v32hi) __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtt_roundph_epu16 (__mmask32 __A, __m512h __B, int __C)
+{
+ return (__m512i)
+ __builtin_ia32_vcvttph2uw512_mask_round (__B,
+ (__v32hi)
+ _mm512_setzero_si512 (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtt_roundph_epu16(A, B) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2uw512_mask_round ((A), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (__mmask32)-1, \
+ (B)))
+
+#define _mm512_mask_cvtt_roundph_epu16(A, B, C, D) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2uw512_mask_round ((C), \
+ (__v32hi)(A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvtt_roundph_epu16(A, B, C) \
+ ((__m512i) \
+ __builtin_ia32_vcvttph2uw512_mask_round ((B), \
+ (__v32hi) \
+ _mm512_setzero_si512 (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtw2ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtepi16_ph (__m512i __A)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __A,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepi16_ph (__m512h __A, __mmask32 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepi16_ph (__mmask32 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __B,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepi16_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __A,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepi16_ph (__m512h __A, __mmask32 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepi16_ph (__mmask32 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtw2ph512_mask_round ((__v32hi) __B,
+ _mm512_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepi16_ph(A, B) \
+ (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(A), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundepi16_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(C), \
+ (A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvt_roundepi16_ph(A, B, C) \
+ (__builtin_ia32_vcvtw2ph512_mask_round ((__v32hi)(B), \
+ _mm512_setzero_ph (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtuw2ph. */
+ extern __inline __m512h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+ _mm512_cvtepu16_ph (__m512i __A)
+ {
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __A,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+ }
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtepu16_ph (__m512h __A, __mmask32 __B, __m512i __C)
+{
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __C,
+ __A,
+ __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtepu16_ph (__mmask32 __A, __m512i __B)
+{
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __B,
+ _mm512_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundepu16_ph (__m512i __A, int __B)
+{
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __A,
+ _mm512_setzero_ph (),
+ (__mmask32) -1,
+ __B);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundepu16_ph (__m512h __A, __mmask32 __B, __m512i __C, int __D)
+{
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __C,
+ __A,
+ __B,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundepu16_ph (__mmask32 __A, __m512i __B, int __C)
+{
+ return __builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi) __B,
+ _mm512_setzero_ph (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundepu16_ph(A, B) \
+ (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(A), \
+ _mm512_setzero_ph (), \
+ (__mmask32)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundepu16_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(C), \
+ (A), \
+ (B), \
+ (D)))
+
+#define _mm512_maskz_cvt_roundepu16_ph(A, B, C) \
+ (__builtin_ia32_vcvtuw2ph512_mask_round ((__v32hi)(B), \
+ _mm512_setzero_ph (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtsh2si, vcvtsh2us. */
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_i32 (__m128h __A)
+{
+ return (int) __builtin_ia32_vcvtsh2si32_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline unsigned
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_u32 (__m128h __A)
+{
+ return (int) __builtin_ia32_vcvtsh2usi32_round (__A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_i32 (__m128h __A, const int __R)
+{
+ return (int) __builtin_ia32_vcvtsh2si32_round (__A, __R);
+}
+
+extern __inline unsigned
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_u32 (__m128h __A, const int __R)
+{
+ return (int) __builtin_ia32_vcvtsh2usi32_round (__A, __R);
+}
+
+#else
+#define _mm_cvt_roundsh_i32(A, B) \
+ ((int)__builtin_ia32_vcvtsh2si32_round ((A), (B)))
+#define _mm_cvt_roundsh_u32(A, B) \
+ ((int)__builtin_ia32_vcvtsh2usi32_round ((A), (B)))
+
+#endif /* __OPTIMIZE__ */
+
+#ifdef __x86_64__
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_i64 (__m128h __A)
+{
+ return (long long)
+ __builtin_ia32_vcvtsh2si64_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline unsigned long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_u64 (__m128h __A)
+{
+ return (long long)
+ __builtin_ia32_vcvtsh2usi64_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_i64 (__m128h __A, const int __R)
+{
+ return (long long) __builtin_ia32_vcvtsh2si64_round (__A, __R);
+}
+
+extern __inline unsigned long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_u64 (__m128h __A, const int __R)
+{
+ return (long long) __builtin_ia32_vcvtsh2usi64_round (__A, __R);
+}
+
+#else
+#define _mm_cvt_roundsh_i64(A, B) \
+ ((long long)__builtin_ia32_vcvtsh2si64_round ((A), (B)))
+#define _mm_cvt_roundsh_u64(A, B) \
+ ((long long)__builtin_ia32_vcvtsh2usi64_round ((A), (B)))
+
+#endif /* __OPTIMIZE__ */
+#endif /* __x86_64__ */
+
+/* Intrinsics vcvttsh2si, vcvttsh2us. */
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttsh_i32 (__m128h __A)
+{
+ return (int)
+ __builtin_ia32_vcvttsh2si32_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline unsigned
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttsh_u32 (__m128h __A)
+{
+ return (int)
+ __builtin_ia32_vcvttsh2usi32_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline int
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtt_roundsh_i32 (__m128h __A, const int __R)
+{
+ return (int) __builtin_ia32_vcvttsh2si32_round (__A, __R);
+}
+
+extern __inline unsigned
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtt_roundsh_u32 (__m128h __A, const int __R)
+{
+ return (int) __builtin_ia32_vcvttsh2usi32_round (__A, __R);
+}
+
+#else
+#define _mm_cvtt_roundsh_i32(A, B) \
+ ((int)__builtin_ia32_vcvttsh2si32_round ((A), (B)))
+#define _mm_cvtt_roundsh_u32(A, B) \
+ ((int)__builtin_ia32_vcvttsh2usi32_round ((A), (B)))
+
+#endif /* __OPTIMIZE__ */
+
+#ifdef __x86_64__
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttsh_i64 (__m128h __A)
+{
+ return (long long)
+ __builtin_ia32_vcvttsh2si64_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline unsigned long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttsh_u64 (__m128h __A)
+{
+ return (long long)
+ __builtin_ia32_vcvttsh2usi64_round (__A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtt_roundsh_i64 (__m128h __A, const int __R)
+{
+ return (long long) __builtin_ia32_vcvttsh2si64_round (__A, __R);
+}
+
+extern __inline unsigned long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtt_roundsh_u64 (__m128h __A, const int __R)
+{
+ return (long long) __builtin_ia32_vcvttsh2usi64_round (__A, __R);
+}
+
+#else
+#define _mm_cvtt_roundsh_i64(A, B) \
+ ((long long)__builtin_ia32_vcvttsh2si64_round ((A), (B)))
+#define _mm_cvtt_roundsh_u64(A, B) \
+ ((long long)__builtin_ia32_vcvttsh2usi64_round ((A), (B)))
+
+#endif /* __OPTIMIZE__ */
+#endif /* __x86_64__ */
+
+/* Intrinsics vcvtsi2sh, vcvtusi2sh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvti32_sh (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvtsi2sh32_round (__A, __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtu32_sh (__m128h __A, unsigned int __B)
+{
+ return __builtin_ia32_vcvtusi2sh32_round (__A, __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundi32_sh (__m128h __A, int __B, const int __R)
+{
+ return __builtin_ia32_vcvtsi2sh32_round (__A, __B, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundu32_sh (__m128h __A, unsigned int __B, const int __R)
+{
+ return __builtin_ia32_vcvtusi2sh32_round (__A, __B, __R);
+}
+
+#else
+#define _mm_cvt_roundi32_sh(A, B, C) \
+ (__builtin_ia32_vcvtsi2sh32_round ((A), (B), (C)))
+#define _mm_cvt_roundu32_sh(A, B, C) \
+ (__builtin_ia32_vcvtusi2sh32_round ((A), (B), (C)))
+
+#endif /* __OPTIMIZE__ */
+
+#ifdef __x86_64__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvti64_sh (__m128h __A, long long __B)
+{
+ return __builtin_ia32_vcvtsi2sh64_round (__A, __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtu64_sh (__m128h __A, unsigned long long __B)
+{
+ return __builtin_ia32_vcvtusi2sh64_round (__A, __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundi64_sh (__m128h __A, long long __B, const int __R)
+{
+ return __builtin_ia32_vcvtsi2sh64_round (__A, __B, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundu64_sh (__m128h __A, unsigned long long __B, const int __R)
+{
+ return __builtin_ia32_vcvtusi2sh64_round (__A, __B, __R);
+}
+
+#else
+#define _mm_cvt_roundi64_sh(A, B, C) \
+ (__builtin_ia32_vcvtsi2sh64_round ((A), (B), (C)))
+#define _mm_cvt_roundu64_sh(A, B, C) \
+ (__builtin_ia32_vcvtusi2sh64_round ((A), (B), (C)))
+
+#endif /* __OPTIMIZE__ */
+#endif /* __x86_64__ */
+
+/* Intrinsics vcvtph2pd. */
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtph_pd (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__A,
+ _mm512_setzero_pd (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtph_pd (__m512d __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtph_pd (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__B,
+ _mm512_setzero_pd (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundph_pd (__m128h __A, int __B)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__A,
+ _mm512_setzero_pd (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundph_pd (__m512d __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundph_pd (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_vcvtph2pd512_mask_round (__B,
+ _mm512_setzero_pd (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvt_roundph_pd(A, B) \
+ (__builtin_ia32_vcvtph2pd512_mask_round ((A), \
+ _mm512_setzero_pd (), \
+ (__mmask8)-1, \
+ (B)))
+
+#define _mm512_mask_cvt_roundph_pd(A, B, C, D) \
+ (__builtin_ia32_vcvtph2pd512_mask_round ((C), (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundph_pd(A, B, C) \
+ (__builtin_ia32_vcvtph2pd512_mask_round ((B), \
+ _mm512_setzero_pd (), \
+ (A), \
+ (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2psx. */
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtxph_ps (__m256h __A)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__A,
+ _mm512_setzero_ps (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtxph_ps (__m512 __A, __mmask16 __B, __m256h __C)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtxph_ps (__mmask16 __A, __m256h __B)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__B,
+ _mm512_setzero_ps (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtx_roundph_ps (__m256h __A, int __B)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__A,
+ _mm512_setzero_ps (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtx_roundph_ps (__m512 __A, __mmask16 __B, __m256h __C, int __D)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__C, __A, __B, __D);
+}
+
+extern __inline __m512
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtx_roundph_ps (__mmask16 __A, __m256h __B, int __C)
+{
+ return __builtin_ia32_vcvtph2psx512_mask_round (__B,
+ _mm512_setzero_ps (),
+ __A,
+ __C);
+}
+
+#else
+#define _mm512_cvtx_roundph_ps(A, B) \
+ (__builtin_ia32_vcvtph2psx512_mask_round ((A), \
+ _mm512_setzero_ps (), \
+ (__mmask16)-1, \
+ (B)))
+
+#define _mm512_mask_cvtx_roundph_ps(A, B, C, D) \
+ (__builtin_ia32_vcvtph2psx512_mask_round ((C), (A), (B), (D)))
+
+#define _mm512_maskz_cvtx_roundph_ps(A, B, C) \
+ (__builtin_ia32_vcvtph2psx512_mask_round ((B), \
+ _mm512_setzero_ps (), \
+ (A), \
+ (C)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtps2ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtxps_ph (__m512 __A)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtxps_ph (__m256h __A, __mmask16 __B, __m512 __C)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __C,
+ __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtxps_ph (__mmask16 __A, __m512 __B)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __B,
+ _mm256_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtx_roundps_ph (__m512 __A, int __B)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1,
+ __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtx_roundps_ph (__m256h __A, __mmask16 __B, __m512 __C, int __D)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __C,
+ __A, __B, __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtx_roundps_ph (__mmask16 __A, __m512 __B, int __C)
+{
+ return __builtin_ia32_vcvtps2phx512_mask_round ((__v16sf) __B,
+ _mm256_setzero_ph (),
+ __A, __C);
+}
+
+#else
+#define _mm512_cvtx_roundps_ph(A, B) \
+ (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(A), \
+ _mm256_setzero_ph (),\
+ (__mmask16)-1, (B)))
+
+#define _mm512_mask_cvtx_roundps_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(C), \
+ (A), (B), (D)))
+
+#define _mm512_maskz_cvtx_roundps_ph(A, B, C) \
+ (__builtin_ia32_vcvtps2phx512_mask_round ((__v16sf)(B), \
+ _mm256_setzero_ph (),\
+ (A), (C)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtpd2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvtpd_ph (__m512d __A)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m512d __C)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __C,
+ __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvtpd_ph (__mmask8 __A, __m512d __B)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __B,
+ _mm_setzero_ph (),
+ __A,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_cvt_roundpd_ph (__m512d __A, int __B)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_cvt_roundpd_ph (__m128h __A, __mmask8 __B, __m512d __C, int __D)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __C,
+ __A, __B, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_cvt_roundpd_ph (__mmask8 __A, __m512d __B, int __C)
+{
+ return __builtin_ia32_vcvtpd2ph512_mask_round ((__v8df) __B,
+ _mm_setzero_ph (),
+ __A, __C);
+}
+
+#else
+#define _mm512_cvt_roundpd_ph(A, B) \
+ (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(A), \
+ _mm_setzero_ph (), \
+ (__mmask8)-1, (B)))
+
+#define _mm512_mask_cvt_roundpd_ph(A, B, C, D) \
+ (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(C), \
+ (A), (B), (D)))
+
+#define _mm512_maskz_cvt_roundpd_ph(A, B, C) \
+ (__builtin_ia32_vcvtpd2ph512_mask_round ((__v8df)(B), \
+ _mm_setzero_ph (), \
+ (A), (C)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtsh2ss, vcvtsh2sd. */
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_ss (__m128 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__B, __A,
+ _mm_setzero_ps (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtsh_ss (__m128 __A, __mmask8 __B, __m128 __C,
+ __m128h __D)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__D, __C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtsh_ss (__mmask8 __A, __m128 __B,
+ __m128h __C)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__C, __B,
+ _mm_setzero_ps (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsh_sd (__m128d __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__B, __A,
+ _mm_setzero_pd (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtsh_sd (__m128d __A, __mmask8 __B, __m128d __C,
+ __m128h __D)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__D, __C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtsh_sd (__mmask8 __A, __m128d __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__C, __B,
+ _mm_setzero_pd (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_ss (__m128 __A, __m128h __B, const int __R)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__B, __A,
+ _mm_setzero_ps (),
+ (__mmask8) -1, __R);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvt_roundsh_ss (__m128 __A, __mmask8 __B, __m128 __C,
+ __m128h __D, const int __R)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__D, __C, __A, __B, __R);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvt_roundsh_ss (__mmask8 __A, __m128 __B,
+ __m128h __C, const int __R)
+{
+ return __builtin_ia32_vcvtsh2ss_mask_round (__C, __B,
+ _mm_setzero_ps (),
+ __A, __R);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsh_sd (__m128d __A, __m128h __B, const int __R)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__B, __A,
+ _mm_setzero_pd (),
+ (__mmask8) -1, __R);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvt_roundsh_sd (__m128d __A, __mmask8 __B, __m128d __C,
+ __m128h __D, const int __R)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__D, __C, __A, __B, __R);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvt_roundsh_sd (__mmask8 __A, __m128d __B, __m128h __C, const int __R)
+{
+ return __builtin_ia32_vcvtsh2sd_mask_round (__C, __B,
+ _mm_setzero_pd (),
+ __A, __R);
+}
+
+#else
+#define _mm_cvt_roundsh_ss(A, B, R) \
+ (__builtin_ia32_vcvtsh2ss_mask_round ((B), (A), \
+ _mm_setzero_ps (), \
+ (__mmask8) -1, (R)))
+
+#define _mm_mask_cvt_roundsh_ss(A, B, C, D, R) \
+ (__builtin_ia32_vcvtsh2ss_mask_round ((D), (C), (A), (B), (R)))
+
+#define _mm_maskz_cvt_roundsh_ss(A, B, C, R) \
+ (__builtin_ia32_vcvtsh2ss_mask_round ((C), (B), \
+ _mm_setzero_ps (), \
+ (A), (R)))
+
+#define _mm_cvt_roundsh_sd(A, B, R) \
+ (__builtin_ia32_vcvtsh2sd_mask_round ((B), (A), \
+ _mm_setzero_pd (), \
+ (__mmask8) -1, (R)))
+
+#define _mm_mask_cvt_roundsh_sd(A, B, C, D, R) \
+ (__builtin_ia32_vcvtsh2sd_mask_round ((D), (C), (A), (B), (R)))
+
+#define _mm_maskz_cvt_roundsh_sd(A, B, C, R) \
+ (__builtin_ia32_vcvtsh2sd_mask_round ((C), (B), \
+ _mm_setzero_pd (), \
+ (A), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtss2sh, vcvtsd2sh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtss_sh (__m128h __A, __m128 __B)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtss_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128 __D)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__D, __C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtss_sh (__mmask8 __A, __m128h __B, __m128 __C)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsd_sh (__m128h __A, __m128d __B)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtsd_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128d __D)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__D, __C, __A, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtsd_sh (__mmask8 __A, __m128h __B, __m128d __C)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundss_sh (__m128h __A, __m128 __B, const int __R)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvt_roundss_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128 __D,
+ const int __R)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__D, __C, __A, __B, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvt_roundss_sh (__mmask8 __A, __m128h __B, __m128 __C,
+ const int __R)
+{
+ return __builtin_ia32_vcvtss2sh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvt_roundsd_sh (__m128h __A, __m128d __B, const int __R)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__B, __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvt_roundsd_sh (__m128h __A, __mmask8 __B, __m128h __C, __m128d __D,
+ const int __R)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__D, __C, __A, __B, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvt_roundsd_sh (__mmask8 __A, __m128h __B, __m128d __C,
+ const int __R)
+{
+ return __builtin_ia32_vcvtsd2sh_mask_round (__C, __B,
+ _mm_setzero_ph (),
+ __A, __R);
+}
+
+#else
+#define _mm_cvt_roundss_sh(A, B, R) \
+ (__builtin_ia32_vcvtss2sh_mask_round ((B), (A), \
+ _mm_setzero_ph (), \
+ (__mmask8) -1, R))
+
+#define _mm_mask_cvt_roundss_sh(A, B, C, D, R) \
+ (__builtin_ia32_vcvtss2sh_mask_round ((D), (C), (A), (B), (R)))
+
+#define _mm_maskz_cvt_roundss_sh(A, B, C, R) \
+ (__builtin_ia32_vcvtss2sh_mask_round ((C), (B), \
+ _mm_setzero_ph (), \
+ A, R))
+
+#define _mm_cvt_roundsd_sh(A, B, R) \
+ (__builtin_ia32_vcvtsd2sh_mask_round ((B), (A), \
+ _mm_setzero_ph (), \
+ (__mmask8) -1, R))
+
+#define _mm_mask_cvt_roundsd_sh(A, B, C, D, R) \
+ (__builtin_ia32_vcvtsd2sh_mask_round ((D), (C), (A), (B), (R)))
+
+#define _mm_maskz_cvt_roundsd_sh(A, B, C, R) \
+ (__builtin_ia32_vcvtsd2sh_mask_round ((C), (B), \
+ _mm_setzero_ph (), \
+ (A), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmaddsub[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmaddsub_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmaddsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmaddsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmaddsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmaddsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmaddsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmaddsub_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmaddsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fmaddsub_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddsubph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fmaddsub_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddsubph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fmaddsub_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfmaddsubph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fmaddsub_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddsubph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmsubadd[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+ _mm512_fmsubadd_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmsubadd_ph (__m512h __A, __mmask32 __U,
+ __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmsubadd_ph (__m512h __A, __m512h __B,
+ __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmsubadd_ph (__mmask32 __U, __m512h __A,
+ __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmsubadd_round_ph (__m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmsubadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmsubadd_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmsubadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fmsubadd_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubaddph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fmsubadd_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubaddph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fmsubadd_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfmsubaddph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fmsubadd_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubaddph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmadd[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+ _mm512_fmadd_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fmadd_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fmadd_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fmadd_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfmaddph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fmadd_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmaddph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfnmadd[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fnmadd_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fnmadd_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fnmadd_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fnmadd_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fnmadd_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fnmadd_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmaddph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fnmadd_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmaddph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fnmadd_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmaddph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fnmadd_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmaddph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fnmadd_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmaddph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fnmadd_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfnmaddph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fnmadd_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmaddph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmsub[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmsub_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmsub_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfmsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fmsub_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fmsub_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fmsub_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfmsubph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fmsub_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfmsubph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfnmsub[132,213,231]ph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fnmsub_ph (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fnmsub_ph (__m512h __A, __mmask32 __U, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fnmsub_ph (__m512h __A, __m512h __B, __m512h __C, __mmask32 __U)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fnmsub_ph (__mmask32 __U, __m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfnmsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fnmsub_round_ph (__m512h __A, __m512h __B, __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) -1, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fnmsub_round_ph (__m512h __A, __mmask32 __U, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmsubph512_mask ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fnmsub_round_ph (__m512h __A, __m512h __B, __m512h __C,
+ __mmask32 __U, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmsubph512_mask3 ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fnmsub_round_ph (__mmask32 __U, __m512h __A, __m512h __B,
+ __m512h __C, const int __R)
+{
+ return (__m512h) __builtin_ia32_vfnmsubph512_maskz ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ (__mmask32) __U, __R);
+}
+
+#else
+#define _mm512_fnmsub_round_ph(A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmsubph512_mask ((A), (B), (C), -1, (R)))
+
+#define _mm512_mask_fnmsub_round_ph(A, U, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmsubph512_mask ((A), (B), (C), (U), (R)))
+
+#define _mm512_mask3_fnmsub_round_ph(A, B, C, U, R) \
+ ((__m512h)__builtin_ia32_vfnmsubph512_mask3 ((A), (B), (C), (U), (R)))
+
+#define _mm512_maskz_fnmsub_round_ph(U, A, B, C, R) \
+ ((__m512h)__builtin_ia32_vfnmsubph512_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmadd[132,213,231]sh. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_sh (__m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_round_sh (__mmask8 __U, __m128h __W, __m128h __A,
+ __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+#else
+#define _mm_fmadd_round_sh(A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), (C), (-1), (R)))
+#define _mm_mask_fmadd_round_sh(A, U, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), (C), (U), (R)))
+#define _mm_mask3_fmadd_round_sh(A, B, C, U, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask3 ((A), (B), (C), (U), (R)))
+#define _mm_maskz_fmadd_round_sh(U, A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfnmadd[132,213,231]sh. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmadd_sh (__m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmadd_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmadd_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmadd_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmadd_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmadd_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmadd_round_sh (__mmask8 __U, __m128h __W, __m128h __A,
+ __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfnmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+#else
+#define _mm_fnmadd_round_sh(A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfnmaddsh3_mask ((A), (B), (C), (-1), (R)))
+#define _mm_mask_fnmadd_round_sh(A, U, B, C, R) \
+ ((__m128h) __builtin_ia32_vfnmaddsh3_mask ((A), (B), (C), (U), (R)))
+#define _mm_mask3_fnmadd_round_sh(A, B, C, U, R) \
+ ((__m128h) __builtin_ia32_vfnmaddsh3_mask3 ((A), (B), (C), (U), (R)))
+#define _mm_maskz_fnmadd_round_sh(U, A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfnmaddsh3_maskz ((A), (B), (C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfmsub[132,213,231]sh. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmsub_sh (__m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmsub_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmsub_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmsub_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmsub_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W,
+ (__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmsub_round_sh (__mmask8 __U, __m128h __W, __m128h __A,
+ __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ (__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+#else
+#define _mm_fmsub_round_sh(A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), -(C), (-1), (R)))
+#define _mm_mask_fmsub_round_sh(A, U, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), (B), -(C), (U), (R)))
+#define _mm_mask3_fmsub_round_sh(A, B, C, U, R) \
+ ((__m128h) __builtin_ia32_vfmsubsh3_mask3 ((A), (B), (C), (U), (R)))
+#define _mm_maskz_fmsub_round_sh(U, A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), (B), -(C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfnmsub[132,213,231]sh. */
+extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmsub_sh (__m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmsub_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmsub_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W,
+ -(__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmsub_sh (__mmask8 __U, __m128h __W, __m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) -1,
+ __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmsub_round_sh (__m128h __W, __mmask8 __U, __m128h __A, __m128h __B,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_mask ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmsub_round_sh (__m128h __W, __m128h __A, __m128h __B, __mmask8 __U,
+ const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmsubsh3_mask3 ((__v8hf) __W,
+ -(__v8hf) __A,
+ (__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmsub_round_sh (__mmask8 __U, __m128h __W, __m128h __A,
+ __m128h __B, const int __R)
+{
+ return (__m128h) __builtin_ia32_vfmaddsh3_maskz ((__v8hf) __W,
+ -(__v8hf) __A,
+ -(__v8hf) __B,
+ (__mmask8) __U, __R);
+}
+
+#else
+#define _mm_fnmsub_round_sh(A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), -(B), -(C), (-1), (R)))
+#define _mm_mask_fnmsub_round_sh(A, U, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_mask ((A), -(B), -(C), (U), (R)))
+#define _mm_mask3_fnmsub_round_sh(A, B, C, U, R) \
+ ((__m128h) __builtin_ia32_vfmsubsh3_mask3 ((A), -(B), (C), (U), (R)))
+#define _mm_maskz_fnmsub_round_sh(U, A, B, C, R) \
+ ((__m128h) __builtin_ia32_vfmaddsh3_maskz ((A), -(B), -(C), (U), (R)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]maddcph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fcmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask3_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmadd_pch (__m512h __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_pch (__m512h __A, __m512h __B, __m512h __C, __mmask16 __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask3_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_pch (__mmask16 __A, __m512h __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fcmadd_round_pch (__m512h __A, __m512h __B, __m512h __C,
+ __mmask16 __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_mask3_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmadd_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) __A,
+ (__v32hf) __C,
+ (__v32hf) __D, __B,
+ __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask3_fmadd_round_pch (__m512h __A, __m512h __B, __m512h __C,
+ __mmask16 __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_mask3_round ((__v32hf) __A,
+ (__v32hf) __B,
+ (__v32hf) __C,
+ __D, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmadd_round_pch (__mmask16 __A, __m512h __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmaddcph512_maskz_round ((__v32hf) __B,
+ (__v32hf) __C,
+ (__v32hf) __D,
+ __A, __E);
+}
+
+#else
+#define _mm512_fcmadd_round_pch(A, B, C, D) \
+ (__m512h) __builtin_ia32_vfcmaddcph512_round ((A), (B), (C), (D))
+
+#define _mm512_mask_fcmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) \
+ __builtin_ia32_vfcmaddcph512_mask_round ((__v32hf) (A), \
+ (__v32hf) (C), \
+ (__v32hf) (D), \
+ (B), (E)))
+
+
+#define _mm512_mask3_fcmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) \
+ __builtin_ia32_vfcmaddcph512_mask3_round ((A), (B), (C), (D), (E)))
+
+#define _mm512_maskz_fcmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfcmaddcph512_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm512_fmadd_round_pch(A, B, C, D) \
+ (__m512h) __builtin_ia32_vfmaddcph512_round ((A), (B), (C), (D))
+
+#define _mm512_mask_fmadd_round_pch(A, B, C, D, E) \
+ ((__m512h) \
+ __builtin_ia32_vfmaddcph512_mask_round ((__v32hf) (A), \
+ (__v32hf) (C), \
+ (__v32hf) (D), \
+ (B), (E)))
+
+#define _mm512_mask3_fmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfmaddcph512_mask3_round ((A), (B), (C), (D), (E))
+
+#define _mm512_maskz_fmadd_round_pch(A, B, C, D, E) \
+ (__m512h) \
+ __builtin_ia32_vfmaddcph512_maskz_round ((B), (C), (D), (A), (E))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]mulcph. */
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmul_pch (__m512h __A, __m512h __B)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmul_pch (__mmask16 __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmul_pch (__m512h __A, __m512h __B)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmul_pch (__m512h __A, __mmask16 __B, __m512h __C, __m512h __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmul_pch (__mmask16 __A, __m512h __B, __m512h __C)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fcmul_round_pch (__m512h __A, __m512h __B, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B, __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fcmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fcmul_round_pch (__mmask16 __A, __m512h __B,
+ __m512h __C, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfcmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_fmul_round_pch (__m512h __A, __m512h __B, const int __D)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_round ((__v32hf) __A,
+ (__v32hf) __B,
+ __D);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_fmul_round_pch (__m512h __A, __mmask16 __B, __m512h __C,
+ __m512h __D, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __C,
+ (__v32hf) __D,
+ (__v32hf) __A,
+ __B, __E);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_maskz_fmul_round_pch (__mmask16 __A, __m512h __B,
+ __m512h __C, const int __E)
+{
+ return (__m512h)
+ __builtin_ia32_vfmulcph512_mask_round ((__v32hf) __B,
+ (__v32hf) __C,
+ _mm512_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm512_fcmul_round_pch(A, B, D) \
+ (__m512h) __builtin_ia32_vfcmulcph512_round ((A), (B), (D))
+
+#define _mm512_mask_fcmul_round_pch(A, B, C, D, E) \
+ (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((C), (D), (A), (B), (E))
+
+#define _mm512_maskz_fcmul_round_pch(A, B, C, E) \
+ (__m512h) __builtin_ia32_vfcmulcph512_mask_round ((B), (C), \
+ (__v32hf) \
+ _mm512_setzero_ph (), \
+ (A), (E))
+
+#define _mm512_fmul_round_pch(A, B, D) \
+ (__m512h) __builtin_ia32_vfmulcph512_round ((A), (B), (D))
+
+#define _mm512_mask_fmul_round_pch(A, B, C, D, E) \
+ (__m512h) __builtin_ia32_vfmulcph512_mask_round ((C), (D), (A), (B), (E))
+
+#define _mm512_maskz_fmul_round_pch(A, B, C, E) \
+ (__m512h) __builtin_ia32_vfmulcph512_mask_round ((B), (C), \
+ (__v32hf) \
+ _mm512_setzero_ph (), \
+ (A), (E))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]maddcsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_sch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_sch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_sch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_sch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_maskz_round ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D,
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_round_sch (__m128h __A, __m128h __B, __m128h __C, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ __D);
+}
+#else
+#define _mm_mask_fcmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) \
+ __builtin_ia32_vfcmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)))
+
+
+#define _mm_mask3_fcmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) \
+ __builtin_ia32_vfcmaddcsh_mask3_round ((__v8hf) (A), \
+ (__v8hf) (B), \
+ (__v8hf) (C), \
+ (D), (E)))
+
+#define _mm_maskz_fcmadd_round_sch(A, B, C, D, E) \
+ __builtin_ia32_vfcmaddcsh_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm_fcmadd_round_sch(A, B, C, D) \
+ __builtin_ia32_vfcmaddcsh_round ((A), (B), (C), (D))
+
+#define _mm_mask_fmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) \
+ __builtin_ia32_vfmaddcsh_mask_round ((__v8hf) (A), \
+ (__v8hf) (C), \
+ (__v8hf) (D), \
+ (B), (E)))
+
+#define _mm_mask3_fmadd_round_sch(A, B, C, D, E) \
+ ((__m128h) \
+ __builtin_ia32_vfmaddcsh_mask3_round ((__v8hf) (A), \
+ (__v8hf) (B), \
+ (__v8hf) (C), \
+ (D), (E)))
+
+#define _mm_maskz_fmadd_round_sch(A, B, C, D, E) \
+ __builtin_ia32_vfmaddcsh_maskz_round ((B), (C), (D), (A), (E))
+
+#define _mm_fmadd_round_sch(A, B, C, D) \
+ __builtin_ia32_vfmaddcsh_round ((A), (B), (C), (D))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vf[,c]mulcsh. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_sch (__m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_sch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_sch (__m128h __A, __m128h __B)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_sch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_sch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, _MM_FROUND_CUR_DIRECTION);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_round_sch (__m128h __A, __m128h __B, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B,
+ __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_round_sch (__m128h __A, __m128h __B, const int __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_round ((__v8hf) __A,
+ (__v8hf) __B, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_round_sch (__m128h __A, __mmask8 __B, __m128h __C,
+ __m128h __D, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A,
+ __B, __E);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_round_sch (__mmask8 __A, __m128h __B, __m128h __C, const int __E)
+{
+ return (__m128h)
+ __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A, __E);
+}
+
+#else
+#define _mm_fcmul_round_sch(__A, __B, __D) \
+ (__m128h) __builtin_ia32_vfcmulcsh_round ((__v8hf) __A, \
+ (__v8hf) __B, __D)
+
+#define _mm_mask_fcmul_round_sch(__A, __B, __C, __D, __E) \
+ (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __C, \
+ (__v8hf) __D, \
+ (__v8hf) __A, \
+ __B, __E)
+
+#define _mm_maskz_fcmul_round_sch(__A, __B, __C, __E) \
+ (__m128h) __builtin_ia32_vfcmulcsh_mask_round ((__v8hf) __B, \
+ (__v8hf) __C, \
+ _mm_setzero_ph (), \
+ __A, __E)
+
+#define _mm_fmul_round_sch(__A, __B, __D) \
+ (__m128h) __builtin_ia32_vfmulcsh_round ((__v8hf) __A, \
+ (__v8hf) __B, __D)
+
+#define _mm_mask_fmul_round_sch(__A, __B, __C, __D, __E) \
+ (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __C, \
+ (__v8hf) __D, \
+ (__v8hf) __A, \
+ __B, __E)
+
+#define _mm_maskz_fmul_round_sch(__A, __B, __C, __E) \
+ (__m128h) __builtin_ia32_vfmulcsh_mask_round ((__v8hf) __B, \
+ (__v8hf) __C, \
+ _mm_setzero_ph (), \
+ __A, __E)
+
+#endif /* __OPTIMIZE__ */
+
+#define _MM512_REDUCE_OP(op) \
+ __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \
+ __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \
+ __m256h __T3 = (__T1 op __T2); \
+ __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \
+ __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \
+ __m128h __T6 = (__T4 op __T5); \
+ __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T8 = (__T6 op __T7); \
+ __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \
+ (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T10 = __T8 op __T9; \
+ return __T10[0] op __T10[1]
+
+// TODO reduce
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_add_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_mul_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (*);
+}
+
+#undef _MM512_REDUCE_OP
+
+#ifdef __AVX512VL__
+
+#define _MM512_REDUCE_OP(op) \
+ __m256h __T1 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 0); \
+ __m256h __T2 = (__m256h) _mm512_extractf64x4_pd ((__m512d) __A, 1); \
+ __m256h __T3 = __builtin_ia32_##op##ph256_mask (__T1, __T2, \
+ _mm256_setzero_ph (), (__mmask16) -1); \
+ __m128h __T4 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 0); \
+ __m128h __T5 = (__m128h) _mm256_extractf128_pd ((__m256d) __T3, 1); \
+ __m128h __T6 = __builtin_ia32_##op##ph128_mask \
+ (__T4, __T5, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T7 = (__m128h) __builtin_shuffle ((__m128h)__T6, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T8 = (__m128h) __builtin_ia32_##op##ph128_mask \
+ (__T6, __T7, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T9 = (__m128h) __builtin_shuffle ((__m128h)__T8, \
+ (__v8hi) { 4, 5 }); \
+ __m128h __T10 = __builtin_ia32_##op##ph128_mask \
+ (__T8, __T9, _mm_setzero_ph (),(__mmask8) -1); \
+ __m128h __T11 = (__m128h) __builtin_shuffle (__T10, \
+ (__v8hi) { 1, 0 }); \
+ __m128h __T12 = __builtin_ia32_##op##ph128_mask \
+ (__T10, __T11, _mm_setzero_ph (),(__mmask8) -1); \
+ return __T12[0]
+
+#else
+
+#define _MM512_REDUCE_OP(op) \
+ __m512h __T1 = (__m512h) __builtin_shuffle ((__m512d) __A, \
+ (__v8di) { 4, 5, 6, 7, 0, 0, 0, 0 }); \
+ __m512h __T2 = _mm512_##op##_ph (__A, __T1); \
+ __m512h __T3 = (__m512h) __builtin_shuffle ((__m512d) __T2, \
+ (__v8di) { 2, 3, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T4 = _mm512_##op##_ph (__T2, __T3); \
+ __m512h __T5 = (__m512h) __builtin_shuffle ((__m512d) __T4, \
+ (__v8di) { 1, 0, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T6 = _mm512_##op##_ph (__T4, __T5); \
+ __m512h __T7 = (__m512h) __builtin_shuffle ((__m512) __T6, \
+ (__v16si) { 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }); \
+ __m512h __T8 = _mm512_##op##_ph (__T6, __T7); \
+ __m512h __T9 = (__m512h) __builtin_shuffle (__T8, \
+ (__v32hi) { 1, 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 }); \
+ __m512h __T10 = _mm512_##op##_ph (__T8, __T9); \
+ return __T10[0]
+#endif
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_min_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (min);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_reduce_max_ph (__m512h __A)
+{
+ _MM512_REDUCE_OP (max);
+}
+
+#undef _MM512_REDUCE_OP
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_mask_blend_ph (__mmask32 __U, __m512h __A, __m512h __W)
+{
+ return (__m512h) __builtin_ia32_movdquhi512_mask ((__v32hi) __W,
+ (__v32hi) __A,
+ (__mmask32) __U);
+
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_permutex2var_ph (__m512h __A, __m512i __I, __m512h __B)
+{
+ return (__m512h) __builtin_ia32_vpermi2varhi512_mask ((__v32hi) __A,
+ (__v32hi) __I,
+ (__v32hi) __B,
+ (__mmask32)-1);
+}
+
+extern __inline __m512h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_permutexvar_ph (__m512i __A, __m512h __B)
+{
+ return (__m512h) __builtin_ia32_permvarhi512_mask ((__v32hi) __B,
+ (__v32hi) __A,
+ (__v32hi)
+ (_mm512_setzero_ph ()),
+ (__mmask32)-1);
+}
+
+#ifdef __DISABLE_AVX512FP16__
+#undef __DISABLE_AVX512FP16__
+#pragma GCC pop_options
+#endif /* __DISABLE_AVX512FP16__ */
+
+#endif /* __AVX512FP16INTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/avx512fp16vlintrin.h b/gcc/config/i386/avx512fp16vlintrin.h
new file mode 100644
index 0000000..0b1f1cb
--- /dev/null
+++ b/gcc/config/i386/avx512fp16vlintrin.h
@@ -0,0 +1,3319 @@
+/* Copyright (C) 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.
+
+ 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 <avx512fp16vlintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __AVX512FP16VLINTRIN_H_INCLUDED
+#define __AVX512FP16VLINTRIN_H_INCLUDED
+
+#if !defined(__AVX512VL__) || !defined(__AVX512FP16__)
+#pragma GCC push_options
+#pragma GCC target("avx512fp16,avx512vl")
+#define __DISABLE_AVX512FP16VL__
+#endif /* __AVX512FP16VL__ */
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castph_ps (__m128h __a)
+{
+ return (__m128) __a;
+}
+
+extern __inline __m256
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castph_ps (__m256h __a)
+{
+ return (__m256) __a;
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castph_pd (__m128h __a)
+{
+ return (__m128d) __a;
+}
+
+extern __inline __m256d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castph_pd (__m256h __a)
+{
+ return (__m256d) __a;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castph_si128 (__m128h __a)
+{
+ return (__m128i) __a;
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castph_si256 (__m256h __a)
+{
+ return (__m256i) __a;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castps_ph (__m128 __a)
+{
+ return (__m128h) __a;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castps_ph (__m256 __a)
+{
+ return (__m256h) __a;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castpd_ph (__m128d __a)
+{
+ return (__m128h) __a;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castpd_ph (__m256d __a)
+{
+ return (__m256h) __a;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_castsi128_ph (__m128i __a)
+{
+ return (__m128h) __a;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castsi256_ph (__m256i __a)
+{
+ return (__m256h) __a;
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castph256_ph128 (__m256h __A)
+{
+ union
+ {
+ __m128h a[2];
+ __m256h v;
+ } u = { .v = __A };
+ return u.a[0];
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_castph128_ph256 (__m128h __A)
+{
+ union
+ {
+ __m128h a[2];
+ __m256h v;
+ } u;
+ u.a[0] = __A;
+ return u.v;
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_zextph128_ph256 (__m128h __A)
+{
+ return (__m256h) _mm256_insertf128_ps (_mm256_setzero_ps (),
+ (__m128) __A, 0);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_conj_pch (__m256h __A)
+{
+ return (__m256h) _mm256_xor_epi32 ((__m256i) __A, _mm256_set1_epi32 (1<<31));
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_conj_pch (__m256h __W, __mmask8 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf)
+ _mm256_conj_pch (__A),
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_conj_pch (__mmask8 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_movaps256_mask ((__v8sf)
+ _mm256_conj_pch (__A),
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_conj_pch (__m128h __A)
+{
+ return (__m128h) _mm_xor_epi32 ((__m128i) __A, _mm_set1_epi32 (1<<31));
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_conj_pch (__m128h __W, __mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A),
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_conj_pch (__mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_movaps128_mask ((__v4sf) _mm_conj_pch (__A),
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+/* Intrinsics v[add,sub,mul,div]ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_ph (__m128h __A, __m128h __B)
+{
+ return (__m128h) ((__v8hf) __A + (__v8hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_add_ph (__m256h __A, __m256h __B)
+{
+ return (__m256h) ((__v16hf) __A + (__v16hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_add_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_addph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_add_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_addph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_add_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_addph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_add_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_addph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_ph (__m128h __A, __m128h __B)
+{
+ return (__m128h) ((__v8hf) __A - (__v8hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_sub_ph (__m256h __A, __m256h __B)
+{
+ return (__m256h) ((__v16hf) __A - (__v16hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sub_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_subph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_sub_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_subph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sub_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_subph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_sub_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_subph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mul_ph (__m128h __A, __m128h __B)
+{
+ return (__m128h) ((__v8hf) __A * (__v8hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mul_ph (__m256h __A, __m256h __B)
+{
+ return (__m256h) ((__v16hf) __A * (__v16hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_mul_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_mulph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_mul_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_mulph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_mul_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_mulph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_mul_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_mulph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_div_ph (__m128h __A, __m128h __B)
+{
+ return (__m128h) ((__v8hf) __A / (__v8hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_div_ph (__m256h __A, __m256h __B)
+{
+ return (__m256h) ((__v16hf) __A / (__v16hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_div_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_divph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_div_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_divph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_div_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_divph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_div_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_divph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+/* Intrinsics v[max,min]ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_ph (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_maxph128_mask (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_max_ph (__m256h __A, __m256h __B)
+{
+ return __builtin_ia32_maxph256_mask (__A, __B,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_max_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_maxph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_max_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_maxph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_max_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_maxph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_max_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_maxph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_ph (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_minph128_mask (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_min_ph (__m256h __A, __m256h __B)
+{
+ return __builtin_ia32_minph256_mask (__A, __B,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_min_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_minph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_min_ph (__m256h __A, __mmask16 __B, __m256h __C, __m256h __D)
+{
+ return __builtin_ia32_minph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_min_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_minph128_mask (__B, __C, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_min_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_minph256_mask (__B, __C,
+ _mm256_setzero_ph (), __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_abs_ph (__m128h __A)
+{
+ return (__m128h) _mm_and_si128 ( _mm_set1_epi32 (0x7FFF7FFF),
+ (__m128i) __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_abs_ph (__m256h __A)
+{
+ return (__m256h) _mm256_and_si256 ( _mm256_set1_epi32 (0x7FFF7FFF),
+ (__m256i) __A);
+}
+
+/* vcmpph */
+#ifdef __OPTIMIZE
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmp_ph_mask (__m128h __A, __m128h __B, const int __C)
+{
+ return (__mmask8) __builtin_ia32_cmpph128_mask (__A, __B, __C,
+ (__mmask8) -1);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cmp_ph_mask (__mmask8 __A, __m128h __B, __m128h __C,
+ const int __D)
+{
+ return (__mmask8) __builtin_ia32_cmpph128_mask (__B, __C, __D, __A);
+}
+
+extern __inline __mmask16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmp_ph_mask (__m256h __A, __m256h __B, const int __C)
+{
+ return (__mmask16) __builtin_ia32_cmpph256_mask (__A, __B, __C,
+ (__mmask16) -1);
+}
+
+extern __inline __mmask16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cmp_ph_mask (__mmask16 __A, __m256h __B, __m256h __C,
+ const int __D)
+{
+ return (__mmask16) __builtin_ia32_cmpph256_mask (__B, __C, __D,
+ __A);
+}
+
+#else
+#define _mm_cmp_ph_mask(A, B, C) \
+ (__builtin_ia32_cmpph128_mask ((A), (B), (C), (-1)))
+
+#define _mm_mask_cmp_ph_mask(A, B, C, D) \
+ (__builtin_ia32_cmpph128_mask ((B), (C), (D), (A)))
+
+#define _mm256_cmp_ph_mask(A, B, C) \
+ (__builtin_ia32_cmpph256_mask ((A), (B), (C), (-1)))
+
+#define _mm256_mask_cmp_ph_mask(A, B, C, D) \
+ (__builtin_ia32_cmpph256_mask ((B), (C), (D), (A)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vsqrtph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sqrt_ph (__m128h __A)
+{
+ return __builtin_ia32_sqrtph128_mask (__A, _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_sqrt_ph (__m256h __A)
+{
+ return __builtin_ia32_sqrtph256_mask (__A, _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_sqrt_ph (__m128h __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_sqrtph128_mask (__C, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_sqrt_ph (__m256h __A, __mmask16 __B, __m256h __C)
+{
+ return __builtin_ia32_sqrtph256_mask (__C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_sqrt_ph (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_sqrtph128_mask (__B, _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_sqrt_ph (__mmask16 __A, __m256h __B)
+{
+ return __builtin_ia32_sqrtph256_mask (__B, _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vrsqrtph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_rsqrt_ph (__m128h __A)
+{
+ return __builtin_ia32_rsqrtph128_mask (__A, _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_rsqrt_ph (__m256h __A)
+{
+ return __builtin_ia32_rsqrtph256_mask (__A, _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_rsqrt_ph (__m128h __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_rsqrtph128_mask (__C, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_rsqrt_ph (__m256h __A, __mmask16 __B, __m256h __C)
+{
+ return __builtin_ia32_rsqrtph256_mask (__C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_rsqrt_ph (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_rsqrtph128_mask (__B, _mm_setzero_ph (), __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_rsqrt_ph (__mmask16 __A, __m256h __B)
+{
+ return __builtin_ia32_rsqrtph256_mask (__B, _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vrcpph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_rcp_ph (__m128h __A)
+{
+ return __builtin_ia32_rcpph128_mask (__A, _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_rcp_ph (__m256h __A)
+{
+ return __builtin_ia32_rcpph256_mask (__A, _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_rcp_ph (__m128h __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_rcpph128_mask (__C, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_rcp_ph (__m256h __A, __mmask16 __B, __m256h __C)
+{
+ return __builtin_ia32_rcpph256_mask (__C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_rcp_ph (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_rcpph128_mask (__B, _mm_setzero_ph (), __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_rcp_ph (__mmask16 __A, __m256h __B)
+{
+ return __builtin_ia32_rcpph256_mask (__B, _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vscalefph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_scalef_ph (__m128h __A, __m128h __B)
+{
+ return __builtin_ia32_scalefph128_mask (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_scalef_ph (__m256h __A, __m256h __B)
+{
+ return __builtin_ia32_scalefph256_mask (__A, __B,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_scalef_ph (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return __builtin_ia32_scalefph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_scalef_ph (__m256h __A, __mmask16 __B, __m256h __C,
+ __m256h __D)
+{
+ return __builtin_ia32_scalefph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_scalef_ph (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return __builtin_ia32_scalefph128_mask (__B, __C,
+ _mm_setzero_ph (), __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_scalef_ph (__mmask16 __A, __m256h __B, __m256h __C)
+{
+ return __builtin_ia32_scalefph256_mask (__B, __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vreduceph. */
+#ifdef __OPTIMIZE__
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_ph (__m128h __A, int __B)
+{
+ return __builtin_ia32_reduceph128_mask (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_reduce_ph (__m128h __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_reduceph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_reduce_ph (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_reduceph128_mask (__B, __C,
+ _mm_setzero_ph (), __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_ph (__m256h __A, int __B)
+{
+ return __builtin_ia32_reduceph256_mask (__A, __B,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_reduce_ph (__m256h __A, __mmask16 __B, __m256h __C, int __D)
+{
+ return __builtin_ia32_reduceph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_reduce_ph (__mmask16 __A, __m256h __B, int __C)
+{
+ return __builtin_ia32_reduceph256_mask (__B, __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+#else
+#define _mm_reduce_ph(A, B) \
+ (__builtin_ia32_reduceph128_mask ((A), (B), \
+ _mm_setzero_ph (), \
+ ((__mmask8)-1)))
+
+#define _mm_mask_reduce_ph(A, B, C, D) \
+ (__builtin_ia32_reduceph128_mask ((C), (D), (A), (B)))
+
+#define _mm_maskz_reduce_ph(A, B, C) \
+ (__builtin_ia32_reduceph128_mask ((B), (C), _mm_setzero_ph (), (A)))
+
+#define _mm256_reduce_ph(A, B) \
+ (__builtin_ia32_reduceph256_mask ((A), (B), \
+ _mm256_setzero_ph (), \
+ ((__mmask16)-1)))
+
+#define _mm256_mask_reduce_ph(A, B, C, D) \
+ (__builtin_ia32_reduceph256_mask ((C), (D), (A), (B)))
+
+#define _mm256_maskz_reduce_ph(A, B, C) \
+ (__builtin_ia32_reduceph256_mask ((B), (C), _mm256_setzero_ph (), (A)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vrndscaleph. */
+#ifdef __OPTIMIZE__
+ extern __inline __m128h
+ __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+ _mm_roundscale_ph (__m128h __A, int __B)
+ {
+ return __builtin_ia32_rndscaleph128_mask (__A, __B,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+ }
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_roundscale_ph (__m128h __A, __mmask8 __B, __m128h __C, int __D)
+{
+ return __builtin_ia32_rndscaleph128_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_roundscale_ph (__mmask8 __A, __m128h __B, int __C)
+{
+ return __builtin_ia32_rndscaleph128_mask (__B, __C,
+ _mm_setzero_ph (), __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_roundscale_ph (__m256h __A, int __B)
+{
+ return __builtin_ia32_rndscaleph256_mask (__A, __B,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_roundscale_ph (__m256h __A, __mmask16 __B, __m256h __C,
+ int __D)
+{
+ return __builtin_ia32_rndscaleph256_mask (__C, __D, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_roundscale_ph (__mmask16 __A, __m256h __B, int __C)
+{
+ return __builtin_ia32_rndscaleph256_mask (__B, __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+#else
+#define _mm_roundscale_ph(A, B) \
+ (__builtin_ia32_rndscaleph128_mask ((A), (B), _mm_setzero_ph (), \
+ ((__mmask8)-1)))
+
+#define _mm_mask_roundscale_ph(A, B, C, D) \
+ (__builtin_ia32_rndscaleph128_mask ((C), (D), (A), (B)))
+
+#define _mm_maskz_roundscale_ph(A, B, C) \
+ (__builtin_ia32_rndscaleph128_mask ((B), (C), _mm_setzero_ph (), (A)))
+
+#define _mm256_roundscale_ph(A, B) \
+ (__builtin_ia32_rndscaleph256_mask ((A), (B), \
+ _mm256_setzero_ph(), \
+ ((__mmask16)-1)))
+
+#define _mm256_mask_roundscale_ph(A, B, C, D) \
+ (__builtin_ia32_rndscaleph256_mask ((C), (D), (A), (B)))
+
+#define _mm256_maskz_roundscale_ph(A, B, C) \
+ (__builtin_ia32_rndscaleph256_mask ((B), (C), \
+ _mm256_setzero_ph (), (A)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vfpclassph. */
+#ifdef __OPTIMIZE__
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+ _mm_mask_fpclass_ph_mask (__mmask8 __U, __m128h __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) __A,
+ __imm, __U);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fpclass_ph_mask (__m128h __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) __A,
+ __imm,
+ (__mmask8) -1);
+}
+
+extern __inline __mmask16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fpclass_ph_mask (__mmask16 __U, __m256h __A, const int __imm)
+{
+ return (__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) __A,
+ __imm, __U);
+}
+
+extern __inline __mmask16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fpclass_ph_mask (__m256h __A, const int __imm)
+{
+ return (__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) __A,
+ __imm,
+ (__mmask16) -1);
+}
+
+#else
+#define _mm_fpclass_ph_mask(X, C) \
+ ((__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) (__m128h) (X), \
+ (int) (C),(__mmask8)-1))
+
+#define _mm_mask_fpclass_ph_mask(u, X, C) \
+ ((__mmask8) __builtin_ia32_fpclassph128_mask ((__v8hf) (__m128h) (X), \
+ (int) (C),(__mmask8)(u)))
+
+#define _mm256_fpclass_ph_mask(X, C) \
+ ((__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) (__m256h) (X), \
+ (int) (C),(__mmask16)-1))
+
+#define _mm256_mask_fpclass_ph_mask(u, X, C) \
+ ((__mmask16) __builtin_ia32_fpclassph256_mask ((__v16hf) (__m256h) (X), \
+ (int) (C),(__mmask16)(u)))
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vgetexpph, vgetexpsh. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_getexp_ph (__m256h __A)
+{
+ return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A,
+ (__v16hf)
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_getexp_ph (__m256h __W, __mmask16 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A,
+ (__v16hf) __W,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_getexp_ph (__mmask16 __U, __m256h __A)
+{
+ return (__m256h) __builtin_ia32_getexpph256_mask ((__v16hf) __A,
+ (__v16hf)
+ _mm256_setzero_ph (),
+ (__mmask16) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getexp_ph (__m128h __A)
+{
+ return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A,
+ (__v8hf)
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_ph (__m128h __W, __mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A,
+ (__v8hf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_ph (__mmask8 __U, __m128h __A)
+{
+ return (__m128h) __builtin_ia32_getexpph128_mask ((__v8hf) __A,
+ (__v8hf)
+ _mm_setzero_ph (),
+ (__mmask8) __U);
+}
+
+
+/* Intrinsics vgetmantph, vgetmantsh. */
+#ifdef __OPTIMIZE__
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_getmant_ph (__m256h __A, _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A,
+ (__C << 2) | __B,
+ (__v16hf)
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_getmant_ph (__m256h __W, __mmask16 __U, __m256h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A,
+ (__C << 2) | __B,
+ (__v16hf) __W,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_getmant_ph (__mmask16 __U, __m256h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m256h) __builtin_ia32_getmantph256_mask ((__v16hf) __A,
+ (__C << 2) | __B,
+ (__v16hf)
+ _mm256_setzero_ph (),
+ (__mmask16) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_getmant_ph (__m128h __A, _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A,
+ (__C << 2) | __B,
+ (__v8hf)
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_ph (__m128h __W, __mmask8 __U, __m128h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A,
+ (__C << 2) | __B,
+ (__v8hf) __W,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_ph (__mmask8 __U, __m128h __A,
+ _MM_MANTISSA_NORM_ENUM __B,
+ _MM_MANTISSA_SIGN_ENUM __C)
+{
+ return (__m128h) __builtin_ia32_getmantph128_mask ((__v8hf) __A,
+ (__C << 2) | __B,
+ (__v8hf)
+ _mm_setzero_ph (),
+ (__mmask8) __U);
+}
+
+#else
+#define _mm256_getmant_ph(X, B, C) \
+ ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v16hf)(__m256h)_mm256_setzero_ph (), \
+ (__mmask16)-1))
+
+#define _mm256_mask_getmant_ph(W, U, X, B, C) \
+ ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v16hf)(__m256h)(W), \
+ (__mmask16)(U)))
+
+#define _mm256_maskz_getmant_ph(U, X, B, C) \
+ ((__m256h) __builtin_ia32_getmantph256_mask ((__v16hf)(__m256h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v16hf)(__m256h)_mm256_setzero_ph (), \
+ (__mmask16)(U)))
+
+#define _mm_getmant_ph(X, B, C) \
+ ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v8hf)(__m128h)_mm_setzero_ph (), \
+ (__mmask8)-1))
+
+#define _mm_mask_getmant_ph(W, U, X, B, C) \
+ ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v8hf)(__m128h)(W), \
+ (__mmask8)(U)))
+
+#define _mm_maskz_getmant_ph(U, X, B, C) \
+ ((__m128h) __builtin_ia32_getmantph128_mask ((__v8hf)(__m128h) (X), \
+ (int)(((C)<<2) | (B)), \
+ (__v8hf)(__m128h)_mm_setzero_ph (), \
+ (__mmask8)(U)))
+
+#endif /* __OPTIMIZE__ */
+
+/* Intrinsics vcvtph2dq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epi32 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2dq128_mask (__A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epi32 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2dq128_mask (__C, ( __v4si) __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epi32 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2dq128_mask (__B,
+ (__v4si) _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epi32 (__m128h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2dq256_mask (__A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epi32 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2dq256_mask (__C, ( __v8si) __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epi32 (__mmask8 __A, __m128h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2dq256_mask (__B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtph2udq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epu32 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2udq128_mask (__A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epu32 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2udq128_mask (__C, ( __v4si) __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epu32 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2udq128_mask (__B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epu32 (__m128h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2udq256_mask (__A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epu32 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2udq256_mask (__C, ( __v8si) __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epu32 (__mmask8 __A, __m128h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2udq256_mask (__B,
+ (__v8si) _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2dq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epi32 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2dq128_mask (__A,
+ (__v4si) _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epi32 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)__builtin_ia32_vcvttph2dq128_mask (__C,
+ ( __v4si) __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epi32 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2dq128_mask (__B,
+ (__v4si) _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epi32 (__m128h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2dq256_mask (__A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epi32 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2dq256_mask (__C,
+ ( __v8si) __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epi32 (__mmask8 __A, __m128h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2dq256_mask (__B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2udq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epu32 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2udq128_mask (__A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epu32 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2udq128_mask (__C,
+ ( __v4si) __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epu32 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2udq128_mask (__B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epu32 (__m128h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2udq256_mask (__A,
+ (__v8si)
+ _mm256_setzero_si256 (), (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epu32 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2udq256_mask (__C,
+ ( __v8si) __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epu32 (__mmask8 __A, __m128h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2udq256_mask (__B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtdq2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi32_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepi32_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepi32_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtdq2ph128_mask ((__v4si) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepi32_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepi32_ph (__m128h __A, __mmask8 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepi32_ph (__mmask8 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtdq2ph256_mask ((__v8si) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtudq2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu32_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepu32_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __C,
+ __A,
+ __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepu32_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtudq2ph128_mask ((__v4si) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepu32_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepu32_ph (__m128h __A, __mmask8 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepu32_ph (__mmask8 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtudq2ph256_mask ((__v8si) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtph2qq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epi64 (__m128h __A)
+{
+ return
+ __builtin_ia32_vcvtph2qq128_mask (__A,
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epi64 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2qq128_mask (__C, __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2qq128_mask (__B,
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epi64 (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2qq256_mask (__A,
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epi64 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2qq256_mask (__C, __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2qq256_mask (__B,
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtph2uqq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2uqq128_mask (__A,
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epu64 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2uqq128_mask (__C, __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2uqq128_mask (__B,
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2uqq256_mask (__A,
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epu64 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2uqq256_mask (__C, __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2uqq256_mask (__B,
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2qq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epi64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2qq128_mask (__A,
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epi64 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2qq128_mask (__C,
+ __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2qq128_mask (__B,
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epi64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2qq256_mask (__A,
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epi64 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2qq256_mask (__C,
+ __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epi64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2qq256_mask (__B,
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2uqq. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2uqq128_mask (__A,
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epu64 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2uqq128_mask (__C,
+ __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2uqq128_mask (__B,
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epu64 (__m128h __A)
+{
+ return __builtin_ia32_vcvttph2uqq256_mask (__A,
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epu64 (__m256i __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvttph2uqq256_mask (__C,
+ __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epu64 (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvttph2uqq256_mask (__B,
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtqq2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi64_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepi64_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtqq2ph128_mask ((__v2di) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepi64_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepi64_ph (__m128h __A, __mmask8 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepi64_ph (__mmask8 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtqq2ph256_mask ((__v4di) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtuqq2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu64_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepu64_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtuqq2ph128_mask ((__v2di) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepu64_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepu64_ph (__m128h __A, __mmask8 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepu64_ph (__mmask8 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtuqq2ph256_mask ((__v4di) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtph2w. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epi16 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2w128_mask (__A,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epi16 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2w128_mask (__C, ( __v8hi) __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epi16 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2w128_mask (__B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epi16 (__m256h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2w256_mask (__A,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epi16 (__m256i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2w256_mask (__C, ( __v16hi) __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epi16 (__mmask16 __A, __m256h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2w256_mask (__B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtph2uw. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_epu16 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2uw128_mask (__A,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_epu16 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2uw128_mask (__C, ( __v8hi) __A, __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_epu16 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvtph2uw128_mask (__B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_epu16 (__m256h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2uw256_mask (__A,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_epu16 (__m256i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2uw256_mask (__C, ( __v16hi) __A, __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_epu16 (__mmask16 __A, __m256h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvtph2uw256_mask (__B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2w. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epi16 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2w128_mask (__A,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epi16 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2w128_mask (__C,
+ ( __v8hi) __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epi16 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2w128_mask (__B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epi16 (__m256h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2w256_mask (__A,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epi16 (__m256i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2w256_mask (__C,
+ ( __v16hi) __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epi16 (__mmask16 __A, __m256h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2w256_mask (__B,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvttph2uw. */
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvttph_epu16 (__m128h __A)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2uw128_mask (__A,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvttph_epu16 (__m128i __A, __mmask8 __B, __m128h __C)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2uw128_mask (__C,
+ ( __v8hi) __A,
+ __B);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvttph_epu16 (__mmask8 __A, __m128h __B)
+{
+ return (__m128i)
+ __builtin_ia32_vcvttph2uw128_mask (__B,
+ (__v8hi)
+ _mm_setzero_si128 (),
+ __A);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvttph_epu16 (__m256h __A)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2uw256_mask (__A,
+ (__v16hi)
+ _mm256_setzero_si256 (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvttph_epu16 (__m256i __A, __mmask16 __B, __m256h __C)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2uw256_mask (__C,
+ ( __v16hi) __A,
+ __B);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvttph_epu16 (__mmask16 __A, __m256h __B)
+{
+ return (__m256i)
+ __builtin_ia32_vcvttph2uw256_mask (__B,
+ (__v16hi) _mm256_setzero_si256 (),
+ __A);
+}
+
+/* Intrinsics vcvtw2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi16_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepi16_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __C,
+ __A,
+ __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepi16_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtw2ph128_mask ((__v8hi) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepi16_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepi16_ph (__m256h __A, __mmask16 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __C,
+ __A,
+ __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepi16_ph (__mmask16 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtw2ph256_mask ((__v16hi) __B,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtuw2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu16_ph (__m128i __A)
+{
+ return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtepu16_ph (__m128h __A, __mmask8 __B, __m128i __C)
+{
+ return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtepu16_ph (__mmask8 __A, __m128i __B)
+{
+ return __builtin_ia32_vcvtuw2ph128_mask ((__v8hi) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtepu16_ph (__m256i __A)
+{
+ return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __A,
+ _mm256_setzero_ph (),
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtepu16_ph (__m256h __A, __mmask16 __B, __m256i __C)
+{
+ return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __C, __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtepu16_ph (__mmask16 __A, __m256i __B)
+{
+ return __builtin_ia32_vcvtuw2ph256_mask ((__v16hi) __B,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtph2pd. */
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_pd (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2pd128_mask (__A,
+ _mm_setzero_pd (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtph_pd (__m128d __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2pd128_mask (__C, __A, __B);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtph_pd (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2pd128_mask (__B, _mm_setzero_pd (), __A);
+}
+
+extern __inline __m256d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_pd (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2pd256_mask (__A,
+ _mm256_setzero_pd (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtph_pd (__m256d __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2pd256_mask (__C, __A, __B);
+}
+
+extern __inline __m256d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtph_pd (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2pd256_mask (__B,
+ _mm256_setzero_pd (),
+ __A);
+}
+
+/* Intrinsics vcvtph2ps. */
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtxph_ps (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2psx128_mask (__A,
+ _mm_setzero_ps (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtxph_ps (__m128 __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2psx128_mask (__C, __A, __B);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtxph_ps (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2psx128_mask (__B, _mm_setzero_ps (), __A);
+}
+
+extern __inline __m256
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtxph_ps (__m128h __A)
+{
+ return __builtin_ia32_vcvtph2psx256_mask (__A,
+ _mm256_setzero_ps (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtxph_ps (__m256 __A, __mmask8 __B, __m128h __C)
+{
+ return __builtin_ia32_vcvtph2psx256_mask (__C, __A, __B);
+}
+
+extern __inline __m256
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtxph_ps (__mmask8 __A, __m128h __B)
+{
+ return __builtin_ia32_vcvtph2psx256_mask (__B,
+ _mm256_setzero_ps (),
+ __A);
+}
+
+/* Intrinsics vcvtxps2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtxps_ph (__m128 __A)
+{
+ return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtxps_ph (__m128h __A, __mmask8 __B, __m128 __C)
+{
+ return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtxps_ph (__mmask8 __A, __m128 __B)
+{
+ return __builtin_ia32_vcvtps2phx128_mask ((__v4sf) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtxps_ph (__m256 __A)
+{
+ return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtxps_ph (__m128h __A, __mmask8 __B, __m256 __C)
+{
+ return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtxps_ph (__mmask8 __A, __m256 __B)
+{
+ return __builtin_ia32_vcvtps2phx256_mask ((__v8sf) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vcvtpd2ph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtpd_ph (__m128d __A)
+{
+ return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m128d __C)
+{
+ return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_cvtpd_ph (__mmask8 __A, __m128d __B)
+{
+ return __builtin_ia32_vcvtpd2ph128_mask ((__v2df) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtpd_ph (__m256d __A)
+{
+ return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __A,
+ _mm_setzero_ph (),
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_cvtpd_ph (__m128h __A, __mmask8 __B, __m256d __C)
+{
+ return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __C, __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_cvtpd_ph (__mmask8 __A, __m256d __B)
+{
+ return __builtin_ia32_vcvtpd2ph256_mask ((__v4df) __B,
+ _mm_setzero_ph (),
+ __A);
+}
+
+/* Intrinsics vfmaddsub[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmaddsub_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h)__builtin_ia32_vfmaddsubph256_mask ((__v16hf)__A,
+ (__v16hf)__B,
+ (__v16hf)__C,
+ (__mmask16)-1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmaddsub_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddsubph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmaddsub_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfmaddsubph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmaddsub_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddsubph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmaddsub_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h)__builtin_ia32_vfmaddsubph128_mask ((__v8hf)__A,
+ (__v8hf)__B,
+ (__v8hf)__C,
+ (__mmask8)-1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmaddsub_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddsubph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmaddsub_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmaddsubph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmaddsub_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddsubph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vfmsubadd[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmsubadd_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmsubadd_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmsubadd_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfmsubaddph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmsubadd_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubaddph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmsubadd_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmsubadd_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmsubadd_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmsubaddph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmsubadd_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubaddph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vfmadd[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmadd_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmadd_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmadd_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfmaddph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmadd_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmaddph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vfnmadd[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fnmadd_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fnmadd_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmaddph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fnmadd_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfnmaddph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fnmadd_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmaddph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmadd_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmadd_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmaddph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmadd_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfnmaddph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmadd_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmaddph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vfmsub[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmsub_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmsub_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmsub_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfmsubph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmsub_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmsubph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmsub_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmsub_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmsub_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfmsubph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmsub_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmsubph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vfnmsub[132,213,231]ph. */
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fnmsub_ph (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmsubph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) -1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fnmsub_ph (__m256h __A, __mmask16 __U, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmsubph256_mask ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16) __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fnmsub_ph (__m256h __A, __m256h __B, __m256h __C,
+ __mmask16 __U)
+{
+ return (__m256h) __builtin_ia32_vfnmsubph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fnmsub_ph (__mmask16 __U, __m256h __A, __m256h __B,
+ __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfnmsubph256_maskz ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C,
+ (__mmask16)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fnmsub_ph (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmsubph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) -1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fnmsub_ph (__m128h __A, __mmask8 __U, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmsubph128_mask ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8) __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fnmsub_ph (__m128h __A, __m128h __B, __m128h __C,
+ __mmask8 __U)
+{
+ return (__m128h) __builtin_ia32_vfnmsubph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fnmsub_ph (__mmask8 __U, __m128h __A, __m128h __B,
+ __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfnmsubph128_maskz ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C,
+ (__mmask8)
+ __U);
+}
+
+/* Intrinsics vf[,c]maddcph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmadd_pch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmaddcph128 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfmaddcph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfmaddcph128_maskz ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D, __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmadd_pch (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmaddcph256 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h)
+ __builtin_ia32_vfmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __C,
+ (__v16hf) __D, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D)
+{
+ return (__m256h)
+ __builtin_ia32_vfmaddcph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C, __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D)
+{
+ return (__m256h)__builtin_ia32_vfmaddcph256_maskz ((__v16hf) __B,
+ (__v16hf) __C,
+ (__v16hf) __D, __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfcmaddcph128 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmadd_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcph128_mask ((__v8hf) __A,
+ (__v8hf) __C,
+ (__v8hf) __D, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask3_fcmadd_pch (__m128h __A, __m128h __B, __m128h __C, __mmask8 __D)
+{
+ return (__m128h)
+ __builtin_ia32_vfcmaddcph128_mask3 ((__v8hf) __A,
+ (__v8hf) __B,
+ (__v8hf) __C, __D);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmadd_pch (__mmask8 __A, __m128h __B, __m128h __C, __m128h __D)
+{
+ return (__m128h)__builtin_ia32_vfcmaddcph128_maskz ((__v8hf) __B,
+ (__v8hf) __C,
+ (__v8hf) __D, __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfcmaddcph256 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fcmadd_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h)
+ __builtin_ia32_vfcmaddcph256_mask ((__v16hf) __A,
+ (__v16hf) __C,
+ (__v16hf) __D, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask3_fcmadd_pch (__m256h __A, __m256h __B, __m256h __C, __mmask8 __D)
+{
+ return (__m256h)
+ __builtin_ia32_vfcmaddcph256_mask3 ((__v16hf) __A,
+ (__v16hf) __B,
+ (__v16hf) __C, __D);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fcmadd_pch (__mmask8 __A, __m256h __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfcmaddcph256_maskz ((__v16hf) __B,
+ (__v16hf) __C,
+ (__v16hf) __D, __A);
+}
+
+/* Intrinsics vf[,c]mulcph. */
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fmul_pch (__m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128 ((__v8hf) __A, (__v8hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fmul_pch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfmulcph128_mask ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fmul_pch (__m256h __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256 ((__v16hf) __A,
+ (__v16hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __C,
+ (__v16hf) __D,
+ (__v16hf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fmul_pch (__mmask8 __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfmulcph256_mask ((__v16hf) __B,
+ (__v16hf) __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_fcmul_pch (__m128h __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128 ((__v8hf) __A,
+ (__v8hf) __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fcmul_pch (__m128h __A, __mmask8 __B, __m128h __C, __m128h __D)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __C,
+ (__v8hf) __D,
+ (__v8hf) __A, __B);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_fcmul_pch (__mmask8 __A, __m128h __B, __m128h __C)
+{
+ return (__m128h) __builtin_ia32_vfcmulcph128_mask ((__v8hf) __B,
+ (__v8hf) __C,
+ _mm_setzero_ph (),
+ __A);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_fcmul_pch (__m256h __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256 ((__v16hf) __A, (__v16hf) __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_fcmul_pch (__m256h __A, __mmask8 __B, __m256h __C, __m256h __D)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __C,
+ (__v16hf) __D,
+ (__v16hf) __A, __B);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_maskz_fcmul_pch (__mmask8 __A, __m256h __B, __m256h __C)
+{
+ return (__m256h) __builtin_ia32_vfcmulcph256_mask ((__v16hf) __B,
+ (__v16hf) __C,
+ _mm256_setzero_ph (),
+ __A);
+}
+
+#define _MM256_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 0); \
+ __m128h __T2 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 1); \
+ __m128h __T3 = (__T1 op __T2); \
+ __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T5 = (__T3) op (__T4); \
+ __m128h __T6 = (__m128h) __builtin_shuffle (__T5, \
+ (__v8hi) { 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T7 = __T5 op __T6; \
+ return __T7[0] op __T7[1]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_add_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_mul_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (*);
+}
+
+#undef _MM256_REDUCE_OP
+#define _MM256_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 0); \
+ __m128h __T2 = (__m128h) _mm256_extractf128_pd ((__m256d) __A, 1); \
+ __m128h __T3 = _mm_##op (__T1, __T2); \
+ __m128h __T4 = (__m128h) __builtin_shuffle (__T3, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T5 = _mm_##op (__T3, __T4); \
+ __m128h __T6 = (__m128h) __builtin_shuffle (__T5, (__v8hi) { 4, 5 }); \
+ __m128h __T7 = _mm_##op (__T5, __T6); \
+ __m128h __T8 = (__m128h) __builtin_shuffle (__T7, (__v8hi) { 1, 0 }); \
+ __m128h __T9 = _mm_##op (__T7, __T8); \
+ return __T9[0]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_min_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (min_ph);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_reduce_max_ph (__m256h __A)
+{
+ _MM256_REDUCE_OP (max_ph);
+}
+
+#define _MM_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) __builtin_shuffle (__A, \
+ (__v8hi) { 4, 5, 6, 7, 0, 1, 2, 3 }); \
+ __m128h __T2 = (__A) op (__T1); \
+ __m128h __T3 = (__m128h) __builtin_shuffle (__T2, \
+ (__v8hi){ 2, 3, 0, 1, 4, 5, 6, 7 }); \
+ __m128h __T4 = __T2 op __T3; \
+ return __T4[0] op __T4[1]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_add_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (+);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_mul_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (*);
+}
+
+#undef _MM_REDUCE_OP
+#define _MM_REDUCE_OP(op) \
+ __m128h __T1 = (__m128h) __builtin_shuffle (__A, \
+ (__v8hi) { 2, 3, 0, 1, 6, 7, 4, 5 }); \
+ __m128h __T2 = _mm_##op (__A, __T1); \
+ __m128h __T3 = (__m128h) __builtin_shuffle (__T2, (__v8hi){ 4, 5 }); \
+ __m128h __T4 = _mm_##op (__T2, __T3); \
+ __m128h __T5 = (__m128h) __builtin_shuffle (__T4, (__v8hi){ 1, 0 }); \
+ __m128h __T6 = _mm_##op (__T4, __T5); \
+ return __T6[0]
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_min_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (min_ph);
+}
+
+extern __inline _Float16
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_reduce_max_ph (__m128h __A)
+{
+ _MM_REDUCE_OP (max_ph);
+}
+
+#undef _MM256_REDUCE_OP
+#undef _MM_REDUCE_OP
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_mask_blend_ph (__mmask16 __U, __m256h __A, __m256h __W)
+{
+ return (__m256h) __builtin_ia32_movdquhi256_mask ((__v16hi) __W,
+ (__v16hi) __A,
+ (__mmask16) __U);
+
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutex2var_ph (__m256h __A, __m256i __I, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_vpermi2varhi256_mask ((__v16hi) __A,
+ (__v16hi) __I,
+ (__v16hi) __B,
+ (__mmask16)-1);
+}
+
+extern __inline __m256h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutexvar_ph (__m256i __A, __m256h __B)
+{
+ return (__m256h) __builtin_ia32_permvarhi256_mask ((__v16hi) __B,
+ (__v16hi) __A,
+ (__v16hi)
+ (_mm256_setzero_ph ()),
+ (__mmask16)-1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_blend_ph (__mmask8 __U, __m128h __A, __m128h __W)
+{
+ return (__m128h) __builtin_ia32_movdquhi128_mask ((__v8hi) __W,
+ (__v8hi) __A,
+ (__mmask8) __U);
+
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_permutex2var_ph (__m128h __A, __m128i __I, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_vpermi2varhi128_mask ((__v8hi) __A,
+ (__v8hi) __I,
+ (__v8hi) __B,
+ (__mmask8)-1);
+}
+
+extern __inline __m128h
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_permutexvar_ph (__m128i __A, __m128h __B)
+{
+ return (__m128h) __builtin_ia32_permvarhi128_mask ((__v8hi) __B,
+ (__v8hi) __A,
+ (__v8hi)
+ (_mm_setzero_ph ()),
+ (__mmask8)-1);
+}
+
+#ifdef __DISABLE_AVX512FP16VL__
+#undef __DISABLE_AVX512FP16VL__
+#pragma GCC pop_options
+#endif /* __DISABLE_AVX512FP16VL__ */
+
+#endif /* __AVX512FP16VLINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index aebc17c..82b8050 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -126,6 +126,7 @@
#define bit_AVX5124VNNIW (1 << 2)
#define bit_AVX5124FMAPS (1 << 3)
#define bit_AVX512VP2INTERSECT (1 << 8)
+#define bit_AVX512FP16 (1 << 23)
#define bit_IBT (1 << 20)
#define bit_UINTR (1 << 5)
#define bit_PCONFIG (1 << 18)
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index ac458cd..da872d1 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -18,17 +18,10 @@ 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 DBX_DEBUGGING_INFO 1
-#if TARGET_64BIT_DEFAULT || defined (HAVE_GAS_PE_SECREL32_RELOC)
#define DWARF2_DEBUGGING_INFO 1
-#endif
#undef PREFERRED_DEBUGGING_TYPE
-#if (DWARF2_DEBUGGING_INFO)
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-#else
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#endif
#undef TARGET_SEH
#define TARGET_SEH (TARGET_64BIT_MS_ABI && flag_unwind_tables)
@@ -97,7 +90,6 @@ along with GCC; see the file COPYING3. If not see
#undef DWARF_FRAME_REGISTERS
#define DWARF_FRAME_REGISTERS (TARGET_64BIT ? 33 : 17)
-#ifdef HAVE_GAS_PE_SECREL32_RELOC
/* Use section relative relocations for debugging offsets. Unlike
other targets that fake this by putting the section VMA at 0, PE
won't allow it. */
@@ -129,7 +121,6 @@ along with GCC; see the file COPYING3. If not see
gcc_unreachable (); \
} \
} while (0)
-#endif
#define TARGET_EXECUTABLE_SUFFIX ".exe"
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index 73b06e2..741f29a 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -128,15 +128,16 @@ along with GCC; see the file COPYING3. If not see
/* This is a workaround for a tool bug: see PR100340. */
#ifdef HAVE_AS_MLLVM_X86_PAD_FOR_ALIGN
-#define EXTRA_ASM_OPTS " -mllvm -x86-pad-for-align=false"
+#define EXTRA_ASM_OPTS " -mllvm -x86-pad-for-align=false "
#else
#define EXTRA_ASM_OPTS ""
#endif
#undef ASM_SPEC
-#define ASM_SPEC "-arch %(darwin_arch) \
- " ASM_OPTIONS " -force_cpusubtype_ALL \
- %{static}" ASM_MMACOSX_VERSION_MIN_SPEC EXTRA_ASM_OPTS
+#define ASM_SPEC \
+"%{static} -arch %(darwin_arch) " \
+ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC EXTRA_ASM_OPTS \
+"%{!force_cpusubtype_ALL:-force_cpusubtype_ALL} "
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
@@ -264,17 +265,6 @@ along with GCC; see the file COPYING3. If not see
target_flags &= ~MASK_MACHO_DYNAMIC_NO_PIC; \
} while (0)
-/* Darwin on x86_64 uses dwarf-2 by default. Pre-darwin9 32-bit
- compiles default to stabs+. darwin9+ defaults to dwarf-2. */
-#ifndef DARWIN_PREFER_DWARF
-#undef PREFERRED_DEBUGGING_TYPE
-#ifdef HAVE_AS_STABS_DIRECTIVE
-#define PREFERRED_DEBUGGING_TYPE (TARGET_64BIT ? DWARF2_DEBUG : DBX_DEBUG)
-#else
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-#endif
-#endif
-
/* Darwin uses the standard DWARF register numbers but the default
register numbers for STABS. Fortunately for 64-bit code the
default and the standard are the same. */
@@ -344,3 +334,8 @@ along with GCC; see the file COPYING3. If not see
#undef SUBTARGET_SHADOW_OFFSET
#define SUBTARGET_SHADOW_OFFSET \
(TARGET_LP64 ? HOST_WIDE_INT_1 << 44 : HOST_WIDE_INT_1 << 29)
+
+#undef CLEAR_INSN_CACHE
+#define CLEAR_INSN_CACHE(beg, end) \
+ extern void sys_icache_invalidate(void *start, size_t len); \
+ sys_icache_invalidate ((beg), (size_t)((end)-(beg)))
diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h
index 9decff7..f1afad9 100644
--- a/gcc/config/i386/djgpp.h
+++ b/gcc/config/i386/djgpp.h
@@ -147,7 +147,7 @@ along with GCC; see the file COPYING3. If not see
\
/* Don't emit DWARF3/4 unless specifically selected. */ \
/* DWARF3/4 currently does not work for DJGPP. */ \
- if (!global_options_set.x_dwarf_version) \
+ if (!OPTION_SET_P (dwarf_version)) \
dwarf_version = 2; \
\
} \
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 3ca313c..4c355c5 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -68,6 +68,7 @@ DEF_PRIMITIVE_TYPE (UINT8, unsigned_char_type_node)
DEF_PRIMITIVE_TYPE (UINT16, short_unsigned_type_node)
DEF_PRIMITIVE_TYPE (INT64, long_long_integer_type_node)
DEF_PRIMITIVE_TYPE (UINT64, long_long_unsigned_type_node)
+DEF_PRIMITIVE_TYPE (FLOAT16, ix86_float16_type_node)
DEF_PRIMITIVE_TYPE (FLOAT, float_type_node)
DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node)
DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node)
@@ -84,6 +85,7 @@ DEF_VECTOR_TYPE (V8QI, QI)
# SSE vectors
DEF_VECTOR_TYPE (V2DF, DOUBLE)
DEF_VECTOR_TYPE (V4SF, FLOAT)
+DEF_VECTOR_TYPE (V8HF, FLOAT16)
DEF_VECTOR_TYPE (V2DI, DI)
DEF_VECTOR_TYPE (V4SI, SI)
DEF_VECTOR_TYPE (V8HI, HI)
@@ -96,6 +98,7 @@ DEF_VECTOR_TYPE (V16UQI, UQI, V16QI)
# AVX vectors
DEF_VECTOR_TYPE (V4DF, DOUBLE)
DEF_VECTOR_TYPE (V8SF, FLOAT)
+DEF_VECTOR_TYPE (V16HF, FLOAT16)
DEF_VECTOR_TYPE (V4DI, DI)
DEF_VECTOR_TYPE (V8SI, SI)
DEF_VECTOR_TYPE (V16HI, HI)
@@ -106,6 +109,7 @@ DEF_VECTOR_TYPE (V16UHI, UHI, V16HI)
# AVX512F vectors
DEF_VECTOR_TYPE (V32SF, FLOAT)
+DEF_VECTOR_TYPE (V32HF, FLOAT16)
DEF_VECTOR_TYPE (V16SF, FLOAT)
DEF_VECTOR_TYPE (V8DF, DOUBLE)
DEF_VECTOR_TYPE (V8DI, DI)
@@ -130,6 +134,7 @@ DEF_POINTER_TYPE (PCVOID, VOID, CONST)
DEF_POINTER_TYPE (PVOID, VOID)
DEF_POINTER_TYPE (PDOUBLE, DOUBLE)
DEF_POINTER_TYPE (PFLOAT, FLOAT)
+DEF_POINTER_TYPE (PCFLOAT16, FLOAT16, CONST)
DEF_POINTER_TYPE (PSHORT, SHORT)
DEF_POINTER_TYPE (PUSHORT, USHORT)
DEF_POINTER_TYPE (PINT, INT)
@@ -1296,4 +1301,82 @@ 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
+DEF_FUNCTION_TYPE (UINT8, PV2DI, PCV2DI, PCVOID)
+
+# FP16 builtins
+DEF_FUNCTION_TYPE (V8HF, V8HI)
+DEF_FUNCTION_TYPE (QI, V8HF, INT, UQI)
+DEF_FUNCTION_TYPE (HI, V16HF, INT, UHI)
+DEF_FUNCTION_TYPE (SI, V32HF, INT, USI)
+DEF_FUNCTION_TYPE (INT, V8HF, INT)
+DEF_FUNCTION_TYPE (INT64, V8HF, INT)
+DEF_FUNCTION_TYPE (UINT, V8HF, INT)
+DEF_FUNCTION_TYPE (UINT64, V8HF, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF)
+DEF_FUNCTION_TYPE (VOID, PCFLOAT16, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, PCFLOAT16, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HF, INT, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, INT64, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, UINT, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, UINT64, INT)
+DEF_FUNCTION_TYPE (V2DI, V8HF, V2DI, UQI)
+DEF_FUNCTION_TYPE (V4DI, V8HF, V4DI, UQI)
+DEF_FUNCTION_TYPE (V2DF, V8HF, V2DF, UQI)
+DEF_FUNCTION_TYPE (V4DF, V8HF, V4DF, UQI)
+DEF_FUNCTION_TYPE (V4SI, V8HF, V4SI, UQI)
+DEF_FUNCTION_TYPE (V4SF, V8HF, V4SF, UQI)
+DEF_FUNCTION_TYPE (V8SI, V8HF, V8SI, UQI)
+DEF_FUNCTION_TYPE (V8SF, V8HF, V8SF, UQI)
+DEF_FUNCTION_TYPE (V8HI, V8HF, V8HI, UQI)
+DEF_FUNCTION_TYPE (V8HF, V4SI, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V4SF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8SI, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8SF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V2DI, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V4DI, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V2DF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V4DF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HI, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, INT, V8HF, UQI)
+DEF_FUNCTION_TYPE (UQI, V8HF, V8HF, INT, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF, UQI)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF, INT)
+DEF_FUNCTION_TYPE (UQI, V8HF, V8HF, INT, UQI, INT)
+DEF_FUNCTION_TYPE (V8DI, V8HF, V8DI, UQI, INT)
+DEF_FUNCTION_TYPE (V8DF, V8HF, V8DF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V8DI, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V8DF, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V2DF, V8HF, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V4SF, V8HF, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V2DF, V8HF, V2DF, V2DF, UQI, INT)
+DEF_FUNCTION_TYPE (V4SF, V8HF, V4SF, V4SF, UQI, INT)
+DEF_FUNCTION_TYPE (V8HF, V8HF, V8HF, INT, V8HF, UQI, INT)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF)
+DEF_FUNCTION_TYPE (V16HI, V16HF, V16HI, UHI)
+DEF_FUNCTION_TYPE (V16HF, V16HI, V16HF, UHI)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, UHI)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF)
+DEF_FUNCTION_TYPE (V16SI, V16HF, V16SI, UHI, INT)
+DEF_FUNCTION_TYPE (V16SF, V16HF, V16SF, UHI, INT)
+DEF_FUNCTION_TYPE (V16HF, V16HF, INT, V16HF, UHI)
+DEF_FUNCTION_TYPE (UHI, V16HF, V16HF, INT, UHI)
+DEF_FUNCTION_TYPE (V16HF, V16SI, V16HF, UHI, INT)
+DEF_FUNCTION_TYPE (V16HF, V16SF, V16HF, UHI, INT)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF, UQI)
+DEF_FUNCTION_TYPE (V16HF, V16HF, V16HF, V16HF, UHI)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, USI)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, INT)
+DEF_FUNCTION_TYPE (V32HI, V32HF, V32HI, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HI, V32HF, USI, INT)
+DEF_FUNCTION_TYPE (USI, V32HF, V32HF, INT, USI)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, USI)
+DEF_FUNCTION_TYPE (USI, V32HF, V32HF, INT, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, UHI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, V32HF, V32HF, USI, INT)
+DEF_FUNCTION_TYPE (V32HF, V32HF, INT, V32HF, USI, INT)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 4b1ae0e..99217d0 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -393,6 +393,10 @@ BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_us_truncatev32hiv32qi2_mas
BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_ss_truncatev32hiv32qi2_mask_store, "__builtin_ia32_pmovswb512mem_mask", IX86_BUILTIN_PMOVSWB512_MEM, UNKNOWN, (int) VOID_FTYPE_PV32QI_V32HI_USI)
BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_truncatev32hiv32qi2_mask_store, "__builtin_ia32_pmovwb512mem_mask", IX86_BUILTIN_PMOVWB512_MEM, UNKNOWN, (int) VOID_FTYPE_PV32QI_V32HI_USI)
+/* AVX512FP16 */
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_loadhf_mask, "__builtin_ia32_loadsh_mask", IX86_BUILTIN_LOADSH_MASK, UNKNOWN, (int) V8HF_FTYPE_PCFLOAT16_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_storehf_mask, "__builtin_ia32_storesh_mask", IX86_BUILTIN_STORESH_MASK, UNKNOWN, (int) VOID_FTYPE_PCFLOAT16_V8HF_UQI)
+
/* RDPKRU and WRPKRU. */
BDESC (OPTION_MASK_ISA_PKU, 0, CODE_FOR_rdpkru, "__builtin_ia32_rdpkru", IX86_BUILTIN_RDPKRU, UNKNOWN, (int) UNSIGNED_FTYPE_VOID)
BDESC (OPTION_MASK_ISA_PKU, 0, CODE_FOR_wrpkru, "__builtin_ia32_wrpkru", IX86_BUILTIN_WRPKRU, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
@@ -2774,6 +2778,164 @@ BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf, "__builti
BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_mask, "__builtin_ia32_dpbf16ps_v4sf_mask", IX86_BUILTIN_DPHI16PS_V4SF_MASK, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8HI_V8HI_UQI)
BDESC (0, OPTION_MASK_ISA2_AVX512BF16, CODE_FOR_avx512f_dpbf16ps_v4sf_maskz, "__builtin_ia32_dpbf16ps_v4sf_maskz", IX86_BUILTIN_DPHI16PS_V4SF_MASKZ, UNKNOWN, (int) V4SF_FTYPE_V4SF_V8HI_V8HI_UQI)
+/* AVX512FP16. */
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_addv8hf3_mask, "__builtin_ia32_addph128_mask", IX86_BUILTIN_ADDPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_addv16hf3_mask, "__builtin_ia32_addph256_mask", IX86_BUILTIN_ADDPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_addv32hf3_mask, "__builtin_ia32_addph512_mask", IX86_BUILTIN_ADDPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_subv8hf3_mask, "__builtin_ia32_subph128_mask", IX86_BUILTIN_SUBPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_subv16hf3_mask, "__builtin_ia32_subph256_mask", IX86_BUILTIN_SUBPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_subv32hf3_mask, "__builtin_ia32_subph512_mask", IX86_BUILTIN_SUBPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_mulv8hf3_mask, "__builtin_ia32_mulph128_mask", IX86_BUILTIN_MULPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_mulv16hf3_mask, "__builtin_ia32_mulph256_mask", IX86_BUILTIN_MULPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_mulv32hf3_mask, "__builtin_ia32_mulph512_mask", IX86_BUILTIN_MULPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_divv8hf3_mask, "__builtin_ia32_divph128_mask", IX86_BUILTIN_DIVPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_divv16hf3_mask, "__builtin_ia32_divph256_mask", IX86_BUILTIN_DIVPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_divv32hf3_mask, "__builtin_ia32_divph512_mask", IX86_BUILTIN_DIVPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmaddv8hf3_mask, "__builtin_ia32_addsh_mask", IX86_BUILTIN_ADDSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsubv8hf3_mask, "__builtin_ia32_subsh_mask", IX86_BUILTIN_SUBSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmmulv8hf3_mask, "__builtin_ia32_mulsh_mask", IX86_BUILTIN_MULSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmdivv8hf3_mask, "__builtin_ia32_divsh_mask", IX86_BUILTIN_DIVSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_smaxv8hf3_mask, "__builtin_ia32_maxph128_mask", IX86_BUILTIN_MAXPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_smaxv16hf3_mask, "__builtin_ia32_maxph256_mask", IX86_BUILTIN_MAXPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_smaxv32hf3_mask, "__builtin_ia32_maxph512_mask", IX86_BUILTIN_MAXPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_sminv8hf3_mask, "__builtin_ia32_minph128_mask", IX86_BUILTIN_MINPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_sminv16hf3_mask, "__builtin_ia32_minph256_mask", IX86_BUILTIN_MINPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_sminv32hf3_mask, "__builtin_ia32_minph512_mask", IX86_BUILTIN_MINPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsmaxv8hf3_mask, "__builtin_ia32_maxsh_mask", IX86_BUILTIN_MAXSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsminv8hf3_mask, "__builtin_ia32_minsh_mask", IX86_BUILTIN_MINSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_cmpv8hf3_mask, "__builtin_ia32_cmpph128_mask", IX86_BUILTIN_CMPPH128_MASK, UNKNOWN, (int) UQI_FTYPE_V8HF_V8HF_INT_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_cmpv16hf3_mask, "__builtin_ia32_cmpph256_mask", IX86_BUILTIN_CMPPH256_MASK, UNKNOWN, (int) UHI_FTYPE_V16HF_V16HF_INT_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_cmpv32hf3_mask, "__builtin_ia32_cmpph512_mask", IX86_BUILTIN_CMPPH512_MASK, UNKNOWN, (int) USI_FTYPE_V32HF_V32HF_INT_USI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_sqrtv8hf2_mask, "__builtin_ia32_sqrtph128_mask", IX86_BUILTIN_SQRTPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_sqrtv16hf2_mask, "__builtin_ia32_sqrtph256_mask", IX86_BUILTIN_SQRTPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rsqrtv8hf2_mask, "__builtin_ia32_rsqrtph128_mask", IX86_BUILTIN_RSQRTPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rsqrtv16hf2_mask, "__builtin_ia32_rsqrtph256_mask", IX86_BUILTIN_RSQRTPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rsqrtv32hf2_mask, "__builtin_ia32_rsqrtph512_mask", IX86_BUILTIN_RSQRTPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_USI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmrsqrtv8hf2_mask, "__builtin_ia32_rsqrtsh_mask", IX86_BUILTIN_RSQRTSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rcpv8hf2_mask, "__builtin_ia32_rcpph128_mask", IX86_BUILTIN_RCPPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rcpv16hf2_mask, "__builtin_ia32_rcpph256_mask", IX86_BUILTIN_RCPPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_UHI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rcpv32hf2_mask, "__builtin_ia32_rcpph512_mask", IX86_BUILTIN_RCPPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_USI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmrcpv8hf2_mask, "__builtin_ia32_rcpsh_mask", IX86_BUILTIN_RCPSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_scalefv8hf_mask, "__builtin_ia32_scalefph128_mask", IX86_BUILTIN_SCALEFPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_scalefv16hf_mask, "__builtin_ia32_scalefph256_mask", IX86_BUILTIN_SCALEFPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_reducepv8hf_mask, "__builtin_ia32_reduceph128_mask", IX86_BUILTIN_REDUCEPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_INT_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_reducepv16hf_mask, "__builtin_ia32_reduceph256_mask", IX86_BUILTIN_REDUCEPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_INT_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_rndscalev8hf_mask, "__builtin_ia32_rndscaleph128_mask", IX86_BUILTIN_RNDSCALEPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_INT_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_rndscalev16hf_mask, "__builtin_ia32_rndscaleph256_mask", IX86_BUILTIN_RNDSCALEPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_INT_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512dq_fpclassv16hf_mask, "__builtin_ia32_fpclassph256_mask", IX86_BUILTIN_FPCLASSPH256, UNKNOWN, (int) HI_FTYPE_V16HF_INT_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512dq_fpclassv8hf_mask, "__builtin_ia32_fpclassph128_mask", IX86_BUILTIN_FPCLASSPH128, UNKNOWN, (int) QI_FTYPE_V8HF_INT_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512dq_fpclassv32hf_mask, "__builtin_ia32_fpclassph512_mask", IX86_BUILTIN_FPCLASSPH512, UNKNOWN, (int) SI_FTYPE_V32HF_INT_USI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512dq_vmfpclassv8hf_mask, "__builtin_ia32_fpclasssh_mask", IX86_BUILTIN_FPCLASSSH_MASK, UNKNOWN, (int) QI_FTYPE_V8HF_INT_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_getexpv16hf_mask, "__builtin_ia32_getexpph256_mask", IX86_BUILTIN_GETEXPPH256, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_getexpv8hf_mask, "__builtin_ia32_getexpph128_mask", IX86_BUILTIN_GETEXPPH128, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_getmantv16hf_mask, "__builtin_ia32_getmantph256_mask", IX86_BUILTIN_GETMANTPH256, UNKNOWN, (int) V16HF_FTYPE_V16HF_INT_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_getmantv8hf_mask, "__builtin_ia32_getmantph128_mask", IX86_BUILTIN_GETMANTPH128, UNKNOWN, (int) V8HF_FTYPE_V8HF_INT_V8HF_UQI)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_movhf_mask, "__builtin_ia32_vmovsh_mask", IX86_BUILTIN_VMOVSH_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2dq_v4si_mask, "__builtin_ia32_vcvtph2dq128_mask", IX86_BUILTIN_VCVTPH2DQ128_MASK, UNKNOWN, (int) V4SI_FTYPE_V8HF_V4SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2dq_v8si_mask, "__builtin_ia32_vcvtph2dq256_mask", IX86_BUILTIN_VCVTPH2DQ256_MASK, UNKNOWN, (int) V8SI_FTYPE_V8HF_V8SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2udq_v4si_mask, "__builtin_ia32_vcvtph2udq128_mask", IX86_BUILTIN_VCVTPH2UDQ128_MASK, UNKNOWN, (int) V4SI_FTYPE_V8HF_V4SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2udq_v8si_mask, "__builtin_ia32_vcvtph2udq256_mask", IX86_BUILTIN_VCVTPH2UDQ256_MASK, UNKNOWN, (int) V8SI_FTYPE_V8HF_V8SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv4si2_mask, "__builtin_ia32_vcvttph2dq128_mask", IX86_BUILTIN_VCVTTPH2DQ128_MASK, UNKNOWN, (int) V4SI_FTYPE_V8HF_V4SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv8si2_mask, "__builtin_ia32_vcvttph2dq256_mask", IX86_BUILTIN_VCVTTPH2DQ256_MASK, UNKNOWN, (int) V8SI_FTYPE_V8HF_V8SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv4si2_mask, "__builtin_ia32_vcvttph2udq128_mask", IX86_BUILTIN_VCVTTPH2UDQ128_MASK, UNKNOWN, (int) V4SI_FTYPE_V8HF_V4SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv8si2_mask, "__builtin_ia32_vcvttph2udq256_mask", IX86_BUILTIN_VCVTTPH2UDQ256_MASK, UNKNOWN, (int) V8SI_FTYPE_V8HF_V8SI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2qq_v2di_mask, "__builtin_ia32_vcvtph2qq128_mask", IX86_BUILTIN_VCVTPH2QQ128_MASK, UNKNOWN, (int) V2DI_FTYPE_V8HF_V2DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2qq_v4di_mask, "__builtin_ia32_vcvtph2qq256_mask", IX86_BUILTIN_VCVTPH2QQ256_MASK, UNKNOWN, (int) V4DI_FTYPE_V8HF_V4DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uqq_v2di_mask, "__builtin_ia32_vcvtph2uqq128_mask", IX86_BUILTIN_VCVTPH2UQQ128_MASK, UNKNOWN, (int) V2DI_FTYPE_V8HF_V2DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uqq_v4di_mask, "__builtin_ia32_vcvtph2uqq256_mask", IX86_BUILTIN_VCVTPH2UQQ256_MASK, UNKNOWN, (int) V4DI_FTYPE_V8HF_V4DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv2di2_mask, "__builtin_ia32_vcvttph2qq128_mask", IX86_BUILTIN_VCVTTPH2QQ128_MASK, UNKNOWN, (int) V2DI_FTYPE_V8HF_V2DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv4di2_mask, "__builtin_ia32_vcvttph2qq256_mask", IX86_BUILTIN_VCVTTPH2QQ256_MASK, UNKNOWN, (int) V4DI_FTYPE_V8HF_V4DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv2di2_mask, "__builtin_ia32_vcvttph2uqq128_mask", IX86_BUILTIN_VCVTTPH2UQQ128_MASK, UNKNOWN, (int) V2DI_FTYPE_V8HF_V2DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv4di2_mask, "__builtin_ia32_vcvttph2uqq256_mask", IX86_BUILTIN_VCVTTPH2UQQ256_MASK, UNKNOWN, (int) V4DI_FTYPE_V8HF_V4DI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2w_v8hi_mask, "__builtin_ia32_vcvtph2w128_mask", IX86_BUILTIN_VCVTPH2W128_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HF_V8HI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2w_v16hi_mask, "__builtin_ia32_vcvtph2w256_mask", IX86_BUILTIN_VCVTPH2W256_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HF_V16HI_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uw_v8hi_mask, "__builtin_ia32_vcvtph2uw128_mask", IX86_BUILTIN_VCVTPH2UW128_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HF_V8HI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uw_v16hi_mask, "__builtin_ia32_vcvtph2uw256_mask", IX86_BUILTIN_VCVTPH2UW256_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HF_V16HI_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv8hi2_mask, "__builtin_ia32_vcvttph2w128_mask", IX86_BUILTIN_VCVTTPH2W128_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HF_V8HI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv16hi2_mask, "__builtin_ia32_vcvttph2w256_mask", IX86_BUILTIN_VCVTTPH2W256_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HF_V16HI_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv8hi2_mask, "__builtin_ia32_vcvttph2uw128_mask", IX86_BUILTIN_VCVTTPH2UW128_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HF_V8HI_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv16hi2_mask, "__builtin_ia32_vcvttph2uw256_mask", IX86_BUILTIN_VCVTTPH2UW256_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HF_V16HI_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtw2ph_v8hi_mask, "__builtin_ia32_vcvtw2ph128_mask", IX86_BUILTIN_VCVTW2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtw2ph_v16hi_mask, "__builtin_ia32_vcvtw2ph256_mask", IX86_BUILTIN_VCVTW2PH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HI_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuw2ph_v8hi_mask, "__builtin_ia32_vcvtuw2ph128_mask", IX86_BUILTIN_VCVTUW2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuw2ph_v16hi_mask, "__builtin_ia32_vcvtuw2ph256_mask", IX86_BUILTIN_VCVTUW2PH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HI_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtdq2ph_v4si_mask, "__builtin_ia32_vcvtdq2ph128_mask", IX86_BUILTIN_VCVTDQ2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V4SI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtdq2ph_v8si_mask, "__builtin_ia32_vcvtdq2ph256_mask", IX86_BUILTIN_VCVTDQ2PH256_MASK, UNKNOWN, (int) V8HF_FTYPE_V8SI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtudq2ph_v4si_mask, "__builtin_ia32_vcvtudq2ph128_mask", IX86_BUILTIN_VCVTUDQ2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V4SI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtudq2ph_v8si_mask, "__builtin_ia32_vcvtudq2ph256_mask", IX86_BUILTIN_VCVTUDQ2PH256_MASK, UNKNOWN, (int) V8HF_FTYPE_V8SI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtqq2ph_v2di_mask, "__builtin_ia32_vcvtqq2ph128_mask", IX86_BUILTIN_VCVTQQ2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V2DI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtqq2ph_v4di_mask, "__builtin_ia32_vcvtqq2ph256_mask", IX86_BUILTIN_VCVTQQ2PH256_MASK, UNKNOWN, (int) V8HF_FTYPE_V4DI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuqq2ph_v2di_mask, "__builtin_ia32_vcvtuqq2ph128_mask", IX86_BUILTIN_VCVTUQQ2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V2DI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuqq2ph_v4di_mask, "__builtin_ia32_vcvtuqq2ph256_mask", IX86_BUILTIN_VCVTUQQ2PH256_MASK, UNKNOWN, (int) V8HF_FTYPE_V4DI_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv2df2_mask, "__builtin_ia32_vcvtph2pd128_mask", IX86_BUILTIN_VCVTPH2PD128_MASK, UNKNOWN, (int) V2DF_FTYPE_V8HF_V2DF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv4df2_mask, "__builtin_ia32_vcvtph2pd256_mask", IX86_BUILTIN_VCVTPH2PD256_MASK, UNKNOWN, (int) V4DF_FTYPE_V8HF_V4DF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv4sf2_mask, "__builtin_ia32_vcvtph2psx128_mask", IX86_BUILTIN_VCVTPH2PSX128_MASK, UNKNOWN, (int) V4SF_FTYPE_V8HF_V4SF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv8sf2_mask, "__builtin_ia32_vcvtph2psx256_mask", IX86_BUILTIN_VCVTPH2PSX256_MASK, UNKNOWN, (int) V8SF_FTYPE_V8HF_V8SF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtps2ph_v4sf_mask, "__builtin_ia32_vcvtps2phx128_mask", IX86_BUILTIN_VCVTPS2PHX128_MASK, UNKNOWN, (int) V8HF_FTYPE_V4SF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtps2ph_v8sf_mask, "__builtin_ia32_vcvtps2phx256_mask", IX86_BUILTIN_VCVTPS2PHX256_MASK, UNKNOWN, (int) V8HF_FTYPE_V8SF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtpd2ph_v2df_mask, "__builtin_ia32_vcvtpd2ph128_mask", IX86_BUILTIN_VCVTPD2PH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V2DF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtpd2ph_v4df_mask, "__builtin_ia32_vcvtpd2ph256_mask", IX86_BUILTIN_VCVTPD2PH256_MASK, UNKNOWN, (int) V8HF_FTYPE_V4DF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddsub_v16hf_mask, "__builtin_ia32_vfmaddsubph256_mask", IX86_BUILTIN_VFMADDSUBPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddsub_v16hf_mask3, "__builtin_ia32_vfmaddsubph256_mask3", IX86_BUILTIN_VFMADDSUBPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddsub_v16hf_maskz, "__builtin_ia32_vfmaddsubph256_maskz", IX86_BUILTIN_VFMADDSUBPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddsub_v8hf_mask, "__builtin_ia32_vfmaddsubph128_mask", IX86_BUILTIN_VFMADDSUBPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddsub_v8hf_mask3, "__builtin_ia32_vfmaddsubph128_mask3", IX86_BUILTIN_VFMADDSUBPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddsub_v8hf_maskz, "__builtin_ia32_vfmaddsubph128_maskz", IX86_BUILTIN_VFMADDSUBPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsubadd_v16hf_mask, "__builtin_ia32_vfmsubaddph256_mask", IX86_BUILTIN_VFMSUBADDPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsubadd_v16hf_mask3, "__builtin_ia32_vfmsubaddph256_mask3", IX86_BUILTIN_VFMSUBADDPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsubadd_v16hf_maskz, "__builtin_ia32_vfmsubaddph256_maskz", IX86_BUILTIN_VFMSUBADDPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsubadd_v8hf_mask, "__builtin_ia32_vfmsubaddph128_mask", IX86_BUILTIN_VFMSUBADDPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsubadd_v8hf_mask3, "__builtin_ia32_vfmsubaddph128_mask3", IX86_BUILTIN_VFMSUBADDPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsubadd_v8hf_maskz, "__builtin_ia32_vfmsubaddph128_maskz", IX86_BUILTIN_VFMSUBADDPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmadd_v16hf_mask, "__builtin_ia32_vfmaddph256_mask", IX86_BUILTIN_VFMADDPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmadd_v16hf_mask3, "__builtin_ia32_vfmaddph256_mask3", IX86_BUILTIN_VFMADDPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmadd_v16hf_maskz, "__builtin_ia32_vfmaddph256_maskz", IX86_BUILTIN_VFMADDPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmadd_v8hf_mask, "__builtin_ia32_vfmaddph128_mask", IX86_BUILTIN_VFMADDPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmadd_v8hf_mask3, "__builtin_ia32_vfmaddph128_mask3", IX86_BUILTIN_VFMADDPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmadd_v8hf_maskz, "__builtin_ia32_vfmaddph128_maskz", IX86_BUILTIN_VFMADDPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmadd_v16hf_mask, "__builtin_ia32_vfnmaddph256_mask", IX86_BUILTIN_VFNMADDPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmadd_v16hf_mask3, "__builtin_ia32_vfnmaddph256_mask3", IX86_BUILTIN_VFNMADDPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmadd_v16hf_maskz, "__builtin_ia32_vfnmaddph256_maskz", IX86_BUILTIN_VFNMADDPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmadd_v8hf_mask, "__builtin_ia32_vfnmaddph128_mask", IX86_BUILTIN_VFNMADDPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmadd_v8hf_mask3, "__builtin_ia32_vfnmaddph128_mask3", IX86_BUILTIN_VFNMADDPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmadd_v8hf_maskz, "__builtin_ia32_vfnmaddph128_maskz", IX86_BUILTIN_VFNMADDPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsub_v16hf_mask, "__builtin_ia32_vfmsubph256_mask", IX86_BUILTIN_VFMSUBPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsub_v16hf_mask3, "__builtin_ia32_vfmsubph256_mask3", IX86_BUILTIN_VFMSUBPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmsub_v16hf_maskz, "__builtin_ia32_vfmsubph256_maskz", IX86_BUILTIN_VFMSUBPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsub_v8hf_mask, "__builtin_ia32_vfmsubph128_mask", IX86_BUILTIN_VFMSUBPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsub_v8hf_mask3, "__builtin_ia32_vfmsubph128_mask3", IX86_BUILTIN_VFMSUBPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmsub_v8hf_maskz, "__builtin_ia32_vfmsubph128_maskz", IX86_BUILTIN_VFMSUBPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmsub_v16hf_mask, "__builtin_ia32_vfnmsubph256_mask", IX86_BUILTIN_VFNMSUBPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmsub_v16hf_mask3, "__builtin_ia32_vfnmsubph256_mask3", IX86_BUILTIN_VFNMSUBPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fnmsub_v16hf_maskz, "__builtin_ia32_vfnmsubph256_maskz", IX86_BUILTIN_VFNMSUBPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UHI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_mask, "__builtin_ia32_vfnmsubph128_mask", IX86_BUILTIN_VFNMSUBPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_mask3, "__builtin_ia32_vfnmsubph128_mask3", IX86_BUILTIN_VFNMSUBPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fnmsub_v8hf_maskz, "__builtin_ia32_vfnmsubph128_maskz", IX86_BUILTIN_VFNMSUBPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v8hf, "__builtin_ia32_vfmaddcph128", IX86_BUILTIN_VFMADDCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddc_v8hf_mask1, "__builtin_ia32_vfmaddcph128_mask", IX86_BUILTIN_VFMADDCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddc_v8hf_mask, "__builtin_ia32_vfmaddcph128_mask3", IX86_BUILTIN_VFMADDCPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddc_v8hf_maskz, "__builtin_ia32_vfmaddcph128_maskz", IX86_BUILTIN_VFMADDCPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v16hf, "__builtin_ia32_vfmaddcph256", IX86_BUILTIN_VFMADDCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddc_v16hf_mask1, "__builtin_ia32_vfmaddcph256_mask", IX86_BUILTIN_VFMADDCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddc_v16hf_mask, "__builtin_ia32_vfmaddcph256_mask3", IX86_BUILTIN_VFMADDCPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmaddc_v16hf_maskz, "__builtin_ia32_vfmaddcph256_maskz", IX86_BUILTIN_VFMADDCPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v8hf, "__builtin_ia32_vfcmaddcph128", IX86_BUILTIN_VFCMADDCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddc_v8hf_mask1, "__builtin_ia32_vfcmaddcph128_mask", IX86_BUILTIN_VFCMADDCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddc_v8hf_mask, "__builtin_ia32_vfcmaddcph128_mask3", IX86_BUILTIN_VFCMADDCPH128_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddc_v8hf_maskz, "__builtin_ia32_vfcmaddcph128_maskz", IX86_BUILTIN_VFCMADDCPH128_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v16hf, "__builtin_ia32_vfcmaddcph256", IX86_BUILTIN_VFCMADDCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmaddc_v16hf_mask1, "__builtin_ia32_vfcmaddcph256_mask", IX86_BUILTIN_VFCMADDCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmaddc_v16hf_mask, "__builtin_ia32_vfcmaddcph256_mask3", IX86_BUILTIN_VFCMADDCPH256_MASK3, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmaddc_v16hf_maskz, "__builtin_ia32_vfcmaddcph256_maskz", IX86_BUILTIN_VFCMADDCPH256_MASKZ, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulc_v8hf, "__builtin_ia32_vfcmulcph128", IX86_BUILTIN_VFCMULCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulc_v8hf_mask, "__builtin_ia32_vfcmulcph128_mask", IX86_BUILTIN_VFCMULCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmulc_v16hf, "__builtin_ia32_vfcmulcph256", IX86_BUILTIN_VFCMULCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fcmulc_v16hf_mask, "__builtin_ia32_vfcmulcph256_mask", IX86_BUILTIN_VFCMULCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulc_v8hf, "__builtin_ia32_vfmulcph128", IX86_BUILTIN_VFMULCPH_V8HF, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulc_v8hf_mask, "__builtin_ia32_vfmulcph128_mask", IX86_BUILTIN_VFMULCPH128_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmulc_v16hf, "__builtin_ia32_vfmulcph256", IX86_BUILTIN_VFMULCPH_V16HF, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF)
+BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512vl_fmulc_v16hf_mask, "__builtin_ia32_vfmulcph256_mask", IX86_BUILTIN_VFMULCPH256_MASK, UNKNOWN, (int) V16HF_FTYPE_V16HF_V16HF_V16HF_UQI)
+
/* Builtins with rounding support. */
BDESC_END (ARGS, ROUND_ARGS)
@@ -2973,6 +3135,121 @@ BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_fixuns_truncv8dfv8di2_mask_round, "
BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_rangepv16sf_mask_round, "__builtin_ia32_rangeps512_mask", IX86_BUILTIN_RANGEPS512, UNKNOWN, (int) V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT)
BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_rangepv8df_mask_round, "__builtin_ia32_rangepd512_mask", IX86_BUILTIN_RANGEPD512, UNKNOWN, (int) V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT)
+/* AVX512FP16. */
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_addv32hf3_mask_round, "__builtin_ia32_addph512_mask_round", IX86_BUILTIN_ADDPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_subv32hf3_mask_round, "__builtin_ia32_subph512_mask_round", IX86_BUILTIN_SUBPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_mulv32hf3_mask_round, "__builtin_ia32_mulph512_mask_round", IX86_BUILTIN_MULPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_divv32hf3_mask_round, "__builtin_ia32_divph512_mask_round", IX86_BUILTIN_DIVPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmaddv8hf3_mask_round, "__builtin_ia32_addsh_mask_round", IX86_BUILTIN_ADDSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsubv8hf3_mask_round, "__builtin_ia32_subsh_mask_round", IX86_BUILTIN_SUBSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmmulv8hf3_mask_round, "__builtin_ia32_mulsh_mask_round", IX86_BUILTIN_MULSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmdivv8hf3_mask_round, "__builtin_ia32_divsh_mask_round", IX86_BUILTIN_DIVSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_smaxv32hf3_mask_round, "__builtin_ia32_maxph512_mask_round", IX86_BUILTIN_MAXPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_sminv32hf3_mask_round, "__builtin_ia32_minph512_mask_round", IX86_BUILTIN_MINPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsmaxv8hf3_mask_round, "__builtin_ia32_maxsh_mask_round", IX86_BUILTIN_MAXSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsminv8hf3_mask_round, "__builtin_ia32_minsh_mask_round", IX86_BUILTIN_MINSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_cmpv32hf3_mask_round, "__builtin_ia32_cmpph512_mask_round", IX86_BUILTIN_CMPPH512_MASK_ROUND, UNKNOWN, (int) USI_FTYPE_V32HF_V32HF_INT_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmcmpv8hf3_mask_round, "__builtin_ia32_cmpsh_mask_round", IX86_BUILTIN_CMPSH_MASK_ROUND, UNKNOWN, (int) UQI_FTYPE_V8HF_V8HF_INT_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_sqrtv32hf2_mask_round, "__builtin_ia32_sqrtph512_mask_round", IX86_BUILTIN_SQRTPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vmsqrtv8hf2_mask_round, "__builtin_ia32_sqrtsh_mask_round", IX86_BUILTIN_SQRTSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_scalefv32hf_mask_round, "__builtin_ia32_scalefph512_mask_round", IX86_BUILTIN_SCALEFPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmscalefv8hf_mask_round, "__builtin_ia32_scalefsh_mask_round", IX86_BUILTIN_SCALEFSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_reducepv32hf_mask_round, "__builtin_ia32_reduceph512_mask_round", IX86_BUILTIN_REDUCEPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_INT_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_reducesv8hf_mask_round, "__builtin_ia32_reducesh_mask_round", IX86_BUILTIN_REDUCESH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_rndscalev32hf_mask_round, "__builtin_ia32_rndscaleph512_mask_round", IX86_BUILTIN_RNDSCALEPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_INT_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_rndscalev8hf_mask_round, "__builtin_ia32_rndscalesh_mask_round", IX86_BUILTIN_RNDSCALESH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_getexpv32hf_mask_round, "__builtin_ia32_getexpph512_mask", IX86_BUILTIN_GETEXPPH512, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_sgetexpv8hf_mask_round, "__builtin_ia32_getexpsh_mask_round", IX86_BUILTIN_GETEXPSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_getmantv32hf_mask_round, "__builtin_ia32_getmantph512_mask", IX86_BUILTIN_GETMANTPH512, UNKNOWN, (int) V32HF_FTYPE_V32HF_INT_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vgetmantv8hf_mask_round, "__builtin_ia32_getmantsh_mask_round", IX86_BUILTIN_GETMANTSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2dq_v16si_mask_round, "__builtin_ia32_vcvtph2dq512_mask_round", IX86_BUILTIN_VCVTPH2DQ512_MASK_ROUND, UNKNOWN, (int) V16SI_FTYPE_V16HF_V16SI_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2udq_v16si_mask_round, "__builtin_ia32_vcvtph2udq512_mask_round", IX86_BUILTIN_VCVTPH2UDQ512_MASK_ROUND, UNKNOWN, (int) V16SI_FTYPE_V16HF_V16SI_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv16si2_mask_round, "__builtin_ia32_vcvttph2dq512_mask_round", IX86_BUILTIN_VCVTTPH2DQ512_MASK_ROUND, UNKNOWN, (int) V16SI_FTYPE_V16HF_V16SI_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv16si2_mask_round, "__builtin_ia32_vcvttph2udq512_mask_round", IX86_BUILTIN_VCVTTPH2UDQ512_MASK_ROUND, UNKNOWN, (int) V16SI_FTYPE_V16HF_V16SI_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2qq_v8di_mask_round, "__builtin_ia32_vcvtph2qq512_mask_round", IX86_BUILTIN_VCVTPH2QQ512_MASK_ROUND, UNKNOWN, (int) V8DI_FTYPE_V8HF_V8DI_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uqq_v8di_mask_round, "__builtin_ia32_vcvtph2uqq512_mask_round", IX86_BUILTIN_VCVTPH2UQQ512_MASK_ROUND, UNKNOWN, (int) V8DI_FTYPE_V8HF_V8DI_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv8di2_mask_round, "__builtin_ia32_vcvttph2qq512_mask_round", IX86_BUILTIN_VCVTTPH2QQ512_MASK_ROUND, UNKNOWN, (int) V8DI_FTYPE_V8HF_V8DI_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv8di2_mask_round, "__builtin_ia32_vcvttph2uqq512_mask_round", IX86_BUILTIN_VCVTTPH2UQQ512_MASK_ROUND, UNKNOWN, (int) V8DI_FTYPE_V8HF_V8DI_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2w_v32hi_mask_round, "__builtin_ia32_vcvtph2w512_mask_round", IX86_BUILTIN_VCVTPH2W512_MASK_ROUND, UNKNOWN, (int) V32HI_FTYPE_V32HF_V32HI_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtph2uw_v32hi_mask_round, "__builtin_ia32_vcvtph2uw512_mask_round", IX86_BUILTIN_VCVTPH2UW512_MASK_ROUND, UNKNOWN, (int) V32HI_FTYPE_V32HF_V32HI_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncv32hi2_mask_round, "__builtin_ia32_vcvttph2w512_mask_round", IX86_BUILTIN_VCVTTPH2W512_MASK_ROUND, UNKNOWN, (int) V32HI_FTYPE_V32HF_V32HI_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncv32hi2_mask_round, "__builtin_ia32_vcvttph2uw512_mask_round", IX86_BUILTIN_VCVTTPH2UW512_MASK_ROUND, UNKNOWN, (int) V32HI_FTYPE_V32HF_V32HI_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtw2ph_v32hi_mask_round, "__builtin_ia32_vcvtw2ph512_mask_round", IX86_BUILTIN_VCVTW2PH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HI_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuw2ph_v32hi_mask_round, "__builtin_ia32_vcvtuw2ph512_mask_round", IX86_BUILTIN_VCVTUW2PH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HI_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtdq2ph_v16si_mask_round, "__builtin_ia32_vcvtdq2ph512_mask_round", IX86_BUILTIN_VCVTDQ2PH512_MASK_ROUND, UNKNOWN, (int) V16HF_FTYPE_V16SI_V16HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtudq2ph_v16si_mask_round, "__builtin_ia32_vcvtudq2ph512_mask_round", IX86_BUILTIN_VCVTUDQ2PH512_MASK_ROUND, UNKNOWN, (int) V16HF_FTYPE_V16SI_V16HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtqq2ph_v8di_mask_round, "__builtin_ia32_vcvtqq2ph512_mask_round", IX86_BUILTIN_VCVTQQ2PH512_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8DI_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtuqq2ph_v8di_mask_round, "__builtin_ia32_vcvtuqq2ph512_mask_round", IX86_BUILTIN_VCVTUQQ2PH512_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8DI_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2si_round, "__builtin_ia32_vcvtsh2si32_round", IX86_BUILTIN_VCVTSH2SI32_ROUND, UNKNOWN, (int) INT_FTYPE_V8HF_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2siq_round, "__builtin_ia32_vcvtsh2si64_round", IX86_BUILTIN_VCVTSH2SI64_ROUND, UNKNOWN, (int) INT64_FTYPE_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2usi_round, "__builtin_ia32_vcvtsh2usi32_round", IX86_BUILTIN_VCVTSH2USI32_ROUND, UNKNOWN, (int) UINT_FTYPE_V8HF_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2usiq_round, "__builtin_ia32_vcvtsh2usi64_round", IX86_BUILTIN_VCVTSH2USI64_ROUND, UNKNOWN, (int) UINT64_FTYPE_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncsi2_round, "__builtin_ia32_vcvttsh2si32_round", IX86_BUILTIN_VCVTTSH2SI32_ROUND, UNKNOWN, (int) INT_FTYPE_V8HF_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fix_truncdi2_round, "__builtin_ia32_vcvttsh2si64_round", IX86_BUILTIN_VCVTTSH2SI64_ROUND, UNKNOWN, (int) INT64_FTYPE_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncsi2_round, "__builtin_ia32_vcvttsh2usi32_round", IX86_BUILTIN_VCVTTSH2USI32_ROUND, UNKNOWN, (int) UINT_FTYPE_V8HF_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fixuns_truncdi2_round, "__builtin_ia32_vcvttsh2usi64_round", IX86_BUILTIN_VCVTTSH2USI64_ROUND, UNKNOWN, (int) UINT64_FTYPE_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsi2sh_round, "__builtin_ia32_vcvtsi2sh32_round", IX86_BUILTIN_VCVTSI2SH32_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_INT_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsi2shq_round, "__builtin_ia32_vcvtsi2sh64_round", IX86_BUILTIN_VCVTSI2SH64_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_INT64_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtusi2sh_round, "__builtin_ia32_vcvtusi2sh32_round", IX86_BUILTIN_VCVTUSI2SH32_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_UINT_INT)
+BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtusi2shq_round, "__builtin_ia32_vcvtusi2sh64_round", IX86_BUILTIN_VCVTUSI2SH64_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_UINT64_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv8df2_mask_round, "__builtin_ia32_vcvtph2pd512_mask_round", IX86_BUILTIN_VCVTPH2PD512_MASK_ROUND, UNKNOWN, (int) V8DF_FTYPE_V8HF_V8DF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_float_extend_phv16sf2_mask_round, "__builtin_ia32_vcvtph2psx512_mask_round", IX86_BUILTIN_VCVTPH2PSX512_MASK_ROUND, UNKNOWN, (int) V16SF_FTYPE_V16HF_V16SF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtpd2ph_v8df_mask_round, "__builtin_ia32_vcvtpd2ph512_mask_round", IX86_BUILTIN_VCVTPD2PH512_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8DF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtps2ph_v16sf_mask_round, "__builtin_ia32_vcvtps2phx512_mask_round", IX86_BUILTIN_VCVTPS2PHX512_MASK_ROUND, UNKNOWN, (int) V16HF_FTYPE_V16SF_V16HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2ss_mask_round, "__builtin_ia32_vcvtsh2ss_mask_round", IX86_BUILTIN_VCVTSH2SS_MASK_ROUND, UNKNOWN, (int) V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsh2sd_mask_round, "__builtin_ia32_vcvtsh2sd_mask_round", IX86_BUILTIN_VCVTSH2SD_MASK_ROUND, UNKNOWN, (int) V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtss2sh_mask_round, "__builtin_ia32_vcvtss2sh_mask_round", IX86_BUILTIN_VCVTSS2SH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_vcvtsd2sh_mask_round, "__builtin_ia32_vcvtsd2sh_mask_round", IX86_BUILTIN_VCVTSD2SH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddsub_v32hf_mask_round, "__builtin_ia32_vfmaddsubph512_mask", IX86_BUILTIN_VFMADDSUBPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddsub_v32hf_mask3_round, "__builtin_ia32_vfmaddsubph512_mask3", IX86_BUILTIN_VFMADDSUBPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddsub_v32hf_maskz_round, "__builtin_ia32_vfmaddsubph512_maskz", IX86_BUILTIN_VFMADDSUBPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsubadd_v32hf_mask_round, "__builtin_ia32_vfmsubaddph512_mask", IX86_BUILTIN_VFMSUBADDPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsubadd_v32hf_mask3_round, "__builtin_ia32_vfmsubaddph512_mask3", IX86_BUILTIN_VFMSUBADDPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsubadd_v32hf_maskz_round, "__builtin_ia32_vfmsubaddph512_maskz", IX86_BUILTIN_VFMSUBADDPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmadd_v32hf_mask_round, "__builtin_ia32_vfmaddph512_mask", IX86_BUILTIN_VFMADDPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmadd_v32hf_mask3_round, "__builtin_ia32_vfmaddph512_mask3", IX86_BUILTIN_VFMADDPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmadd_v32hf_maskz_round, "__builtin_ia32_vfmaddph512_maskz", IX86_BUILTIN_VFMADDPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmadd_v32hf_mask_round, "__builtin_ia32_vfnmaddph512_mask", IX86_BUILTIN_VFNMADDPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmadd_v32hf_mask3_round, "__builtin_ia32_vfnmaddph512_mask3", IX86_BUILTIN_VFNMADDPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmadd_v32hf_maskz_round, "__builtin_ia32_vfnmaddph512_maskz", IX86_BUILTIN_VFNMADDPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsub_v32hf_mask_round, "__builtin_ia32_vfmsubph512_mask", IX86_BUILTIN_VFMSUBPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsub_v32hf_mask3_round, "__builtin_ia32_vfmsubph512_mask3", IX86_BUILTIN_VFMSUBPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmsub_v32hf_maskz_round, "__builtin_ia32_vfmsubph512_maskz", IX86_BUILTIN_VFMSUBPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmsub_v32hf_mask_round, "__builtin_ia32_vfnmsubph512_mask", IX86_BUILTIN_VFNMSUBPH512_MASK, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmsub_v32hf_mask3_round, "__builtin_ia32_vfnmsubph512_mask3", IX86_BUILTIN_VFNMSUBPH512_MASK3, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fnmsub_v32hf_maskz_round, "__builtin_ia32_vfnmsubph512_maskz", IX86_BUILTIN_VFNMSUBPH512_MASKZ, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfmadd_v8hf_mask_round, "__builtin_ia32_vfmaddsh3_mask", IX86_BUILTIN_VFMADDSH3_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfmadd_v8hf_mask3_round, "__builtin_ia32_vfmaddsh3_mask3", IX86_BUILTIN_VFMADDSH3_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfmadd_v8hf_maskz_round, "__builtin_ia32_vfmaddsh3_maskz", IX86_BUILTIN_VFMADDSH3_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_mask_round, "__builtin_ia32_vfnmaddsh3_mask", IX86_BUILTIN_VFNMADDSH3_MASK, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_mask3_round, "__builtin_ia32_vfnmaddsh3_mask3", IX86_BUILTIN_VFNMADDSH3_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfnmadd_v8hf_maskz_round, "__builtin_ia32_vfnmaddsh3_maskz", IX86_BUILTIN_VFNMADDSH3_MASKZ, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512f_vmfmsub_v8hf_mask3_round, "__builtin_ia32_vfmsubsh3_mask3", IX86_BUILTIN_VFMSUBSH3_MASK3, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fmaddc_v32hf_round, "__builtin_ia32_vfmaddcph512_round", IX86_BUILTIN_VFMADDCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round, "__builtin_ia32_vfmaddcph512_mask_round", IX86_BUILTIN_VFMADDCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddc_v32hf_mask_round, "__builtin_ia32_vfmaddcph512_mask3_round", IX86_BUILTIN_VFMADDCPH512_MASK3_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmaddc_v32hf_maskz_round, "__builtin_ia32_vfmaddcph512_maskz_round", IX86_BUILTIN_VFMADDCPH512_MASKZ_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_fma_fcmaddc_v32hf_round, "__builtin_ia32_vfcmaddcph512_round", IX86_BUILTIN_VFCMADDCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round, "__builtin_ia32_vfcmaddcph512_mask_round", IX86_BUILTIN_VFCMADDCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmaddc_v32hf_mask_round, "__builtin_ia32_vfcmaddcph512_mask3_round", IX86_BUILTIN_VFCMADDCPH512_MASK3_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmaddc_v32hf_maskz_round, "__builtin_ia32_vfcmaddcph512_maskz_round", IX86_BUILTIN_VFCMADDCPH512_MASKZ_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmulc_v32hf_round, "__builtin_ia32_vfcmulcph512_round", IX86_BUILTIN_VFCMULCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fcmulc_v32hf_mask_round, "__builtin_ia32_vfcmulcph512_mask_round", IX86_BUILTIN_VFCMULCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmulc_v32hf_round, "__builtin_ia32_vfmulcph512_round", IX86_BUILTIN_VFMULCPH512_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512bw_fmulc_v32hf_mask_round, "__builtin_ia32_vfmulcph512_mask_round", IX86_BUILTIN_VFMULCPH512_MASK_ROUND, UNKNOWN, (int) V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fma_fcmaddcsh_v8hf_round, "__builtin_ia32_vfcmaddcsh_round", IX86_BUILTIN_VFCMADDCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round, "__builtin_ia32_vfcmaddcsh_mask_round", IX86_BUILTIN_VFCMADDCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round, "__builtin_ia32_vfcmaddcsh_mask3_round", IX86_BUILTIN_VFCMADDCSH_MASK3_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmaddcsh_v8hf_maskz_round, "__builtin_ia32_vfcmaddcsh_maskz_round", IX86_BUILTIN_VFCMADDCSH_MASKZ_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fma_fmaddcsh_v8hf_round, "__builtin_ia32_vfmaddcsh_round", IX86_BUILTIN_VFMADDCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round, "__builtin_ia32_vfmaddcsh_mask_round", IX86_BUILTIN_VFMADDCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round, "__builtin_ia32_vfmaddcsh_mask3_round", IX86_BUILTIN_VFMADDCSH_MASK3_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmaddcsh_v8hf_maskz_round, "__builtin_ia32_vfmaddcsh_maskz_round", IX86_BUILTIN_VFMADDCSH_MASKZ_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulcsh_v8hf_round, "__builtin_ia32_vfcmulcsh_round", IX86_BUILTIN_VFCMULCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fcmulcsh_v8hf_mask_round, "__builtin_ia32_vfcmulcsh_mask_round", IX86_BUILTIN_VFCMULCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulcsh_v8hf_round, "__builtin_ia32_vfmulcsh_round", IX86_BUILTIN_VFMULCSH_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_INT)
+BDESC (0, OPTION_MASK_ISA2_AVX512FP16, CODE_FOR_avx512fp16_fmulcsh_v8hf_mask_round, "__builtin_ia32_vfmulcsh_mask_round", IX86_BUILTIN_VFMULCSH_MASK_ROUND, UNKNOWN, (int) V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT)
+
BDESC_END (ROUND_ARGS, MULTI_ARG)
/* FMA4 and XOP. */
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 204e290..11ce58b 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -125,6 +125,7 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX,
/* Table for the ix86 builtin non-function types. */
static GTY(()) tree ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1];
+tree ix86_float16_type_node = NULL_TREE;
/* Retrieve an element from the above table, building some of
the types lazily. */
@@ -1344,6 +1345,26 @@ ix86_init_builtins_va_builtins_abi (void)
}
static void
+ix86_register_float16_builtin_type (void)
+{
+ /* Provide the _Float16 type and float16_type_node if needed so that
+ it can be used in AVX512FP16 intrinsics and builtins. */
+ if (!float16_type_node)
+ {
+ ix86_float16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (ix86_float16_type_node) = 16;
+ SET_TYPE_MODE (ix86_float16_type_node, HFmode);
+ layout_type (ix86_float16_type_node);
+ }
+ else
+ ix86_float16_type_node = float16_type_node;
+
+ if (!maybe_get_identifier ("_Float16") && TARGET_SSE2)
+ lang_hooks.types.register_builtin_type (ix86_float16_type_node,
+ "_Float16");
+}
+
+static void
ix86_init_builtin_types (void)
{
tree float80_type_node, const_string_type_node;
@@ -1371,6 +1392,8 @@ ix86_init_builtin_types (void)
it. */
lang_hooks.types.register_builtin_type (float128_type_node, "__float128");
+ ix86_register_float16_builtin_type ();
+
const_string_type_node
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
@@ -1904,8 +1927,24 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
return 0;
new_target = TREE_TARGET_OPTION (target_node);
gcc_assert (new_target);
-
- if (new_target->arch_specified && new_target->arch > 0)
+ enum ix86_builtins builtin_fn = IX86_BUILTIN_CPU_IS;
+
+ /* Special case x86-64 micro-level architectures. */
+ const char *arch_name = attrs_str + strlen ("arch=");
+ if (startswith (arch_name, "x86-64"))
+ {
+ arg_str = arch_name;
+ builtin_fn = IX86_BUILTIN_CPU_SUPPORTS;
+ if (strcmp (arch_name, "x86-64") == 0)
+ priority = P_X86_64_BASELINE;
+ else if (strcmp (arch_name, "x86-64-v2") == 0)
+ priority = P_X86_64_V2;
+ else if (strcmp (arch_name, "x86-64-v3") == 0)
+ priority = P_X86_64_V3;
+ else if (strcmp (arch_name, "x86-64-v4") == 0)
+ priority = P_X86_64_V4;
+ }
+ else if (new_target->arch_specified && new_target->arch > 0)
for (i = 0; i < pta_size; i++)
if (processor_alias_table[i].processor == new_target->arch)
{
@@ -1975,7 +2014,7 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
if (predicate_list)
{
- predicate_decl = ix86_builtins [(int) IX86_BUILTIN_CPU_IS];
+ predicate_decl = ix86_builtins [(int) builtin_fn];
/* For a C string literal the length includes the trailing NULL. */
predicate_arg = build_string_literal (strlen (arg_str) + 1, arg_str);
predicate_chain = tree_cons (predicate_decl, predicate_arg,
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 5ed0de0..cc64f85 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -598,6 +598,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__PTWRITE__");
if (isa_flag2 & OPTION_MASK_ISA2_AVX512BF16)
def_or_undef (parse_in, "__AVX512BF16__");
+ if (isa_flag2 & OPTION_MASK_ISA2_AVX512FP16)
+ def_or_undef (parse_in, "__AVX512FP16__");
if (TARGET_MMX_WITH_SSE)
def_or_undef (parse_in, "__MMX_WITH_SSE__");
if (isa_flag2 & OPTION_MASK_ISA2_ENQCMD)
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 2500dbf..56dd99b 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -615,6 +615,16 @@ ix86_expand_vector_move (machine_mode mode, rtx operands[])
return;
}
+ /* If operand0 is a hard register, make operand1 a pseudo. */
+ if (can_create_pseudo_p ()
+ && !ix86_hardreg_mov_ok (op0, op1))
+ {
+ rtx tmp = gen_reg_rtx (GET_MODE (op0));
+ emit_move_insn (tmp, op1);
+ emit_move_insn (op0, tmp);
+ return;
+ }
+
/* Make operand1 a register if it isn't already. */
if (can_create_pseudo_p ()
&& !register_operand (op0, mode)
@@ -678,6 +688,10 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
extract = gen_avx_vextractf128v32qi;
mode = V16QImode;
break;
+ case E_V16HFmode:
+ extract = gen_avx_vextractf128v16hf;
+ mode = V8HFmode;
+ break;
case E_V8SFmode:
extract = gen_avx_vextractf128v8sf;
mode = V4SFmode;
@@ -1851,12 +1865,21 @@ ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
fp_lo = gen_reg_rtx (SFmode);
emit_insn (gen_floatsisf2 (fp_hi, int_hi));
emit_insn (gen_floatsisf2 (fp_lo, int_lo));
- fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
- 0, OPTAB_DIRECT);
- fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
- 0, OPTAB_DIRECT);
- if (!rtx_equal_p (target, fp_hi))
- emit_move_insn (target, fp_hi);
+ if (TARGET_FMA)
+ {
+ x = validize_mem (force_const_mem (SFmode, x));
+ fp_hi = gen_rtx_FMA (SFmode, fp_hi, x, fp_lo);
+ emit_move_insn (target, fp_hi);
+ }
+ else
+ {
+ fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
+ 0, OPTAB_DIRECT);
+ fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
+ 0, OPTAB_DIRECT);
+ if (!rtx_equal_p (target, fp_hi))
+ emit_move_insn (target, fp_hi);
+ }
}
/* floatunsv{4,8}siv{4,8}sf2 expander. Expand code to convert
@@ -1888,12 +1911,20 @@ ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
real_ldexp (&TWO16r, &dconst1, 16);
tmp[5] = const_double_from_real_value (TWO16r, SFmode);
tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
- tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5], NULL_RTX, 1,
- OPTAB_DIRECT);
- tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6], target, 1,
- OPTAB_DIRECT);
- if (tmp[7] != target)
- emit_move_insn (target, tmp[7]);
+ if (TARGET_FMA)
+ {
+ tmp[6] = gen_rtx_FMA (fltmode, tmp[4], tmp[5], tmp[3]);
+ emit_move_insn (target, tmp[6]);
+ }
+ else
+ {
+ tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5],
+ NULL_RTX, 1, OPTAB_DIRECT);
+ tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6],
+ target, 1, OPTAB_DIRECT);
+ if (tmp[7] != target)
+ emit_move_insn (target, tmp[7]);
+ }
}
/* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
@@ -1960,8 +1991,12 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
machine_mode vmode = mode;
rtvec par;
- if (vector_mode || mode == TFmode)
- use_sse = true;
+ if (vector_mode || mode == TFmode || mode == HFmode)
+ {
+ use_sse = true;
+ if (mode == HFmode)
+ vmode = V8HFmode;
+ }
else if (TARGET_SSE_MATH)
{
use_sse = SSE_FLOAT_MODE_P (mode);
@@ -2098,15 +2133,13 @@ void
ix86_expand_copysign (rtx operands[])
{
machine_mode mode, vmode;
- rtx dest, op0, op1, mask;
+ rtx dest, op0, op1, mask, op2, op3;
- dest = operands[0];
- op0 = operands[1];
- op1 = operands[2];
-
- mode = GET_MODE (dest);
+ mode = GET_MODE (operands[0]);
- if (mode == SFmode)
+ if (mode == HFmode)
+ vmode = V8HFmode;
+ else if (mode == SFmode)
vmode = V4SFmode;
else if (mode == DFmode)
vmode = V2DFmode;
@@ -2115,136 +2148,40 @@ ix86_expand_copysign (rtx operands[])
else
gcc_unreachable ();
- mask = ix86_build_signbit_mask (vmode, 0, 0);
-
- if (CONST_DOUBLE_P (op0))
- {
- if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
- op0 = simplify_unary_operation (ABS, mode, op0, mode);
-
- if (mode == SFmode || mode == DFmode)
- {
- if (op0 == CONST0_RTX (mode))
- op0 = CONST0_RTX (vmode);
- else
- {
- rtx v = ix86_build_const_vector (vmode, false, op0);
-
- op0 = force_reg (vmode, v);
- }
- }
- else if (op0 != CONST0_RTX (mode))
- op0 = force_reg (mode, op0);
-
- emit_insn (gen_copysign3_const (mode, dest, op0, op1, mask));
- }
- else
- {
- rtx nmask = ix86_build_signbit_mask (vmode, 0, 1);
-
- emit_insn (gen_copysign3_var
- (mode, dest, NULL_RTX, op0, op1, nmask, mask));
- }
-}
-
-/* Deconstruct a copysign operation into bit masks. Operand 0 is known to
- be a constant, and so has already been expanded into a vector constant. */
-
-void
-ix86_split_copysign_const (rtx operands[])
-{
- machine_mode mode, vmode;
- rtx dest, op0, mask, x;
-
- dest = operands[0];
- op0 = operands[1];
- mask = operands[3];
-
- mode = GET_MODE (dest);
- vmode = GET_MODE (mask);
-
- dest = lowpart_subreg (vmode, dest, mode);
- x = gen_rtx_AND (vmode, dest, mask);
- emit_insn (gen_rtx_SET (dest, x));
-
- if (op0 != CONST0_RTX (vmode))
- {
- x = gen_rtx_IOR (vmode, dest, op0);
- emit_insn (gen_rtx_SET (dest, x));
- }
-}
-
-/* Deconstruct a copysign operation into bit masks. Operand 0 is variable,
- so we have to do two masks. */
-
-void
-ix86_split_copysign_var (rtx operands[])
-{
- machine_mode mode, vmode;
- rtx dest, scratch, op0, op1, mask, nmask, x;
-
- dest = operands[0];
- scratch = operands[1];
- op0 = operands[2];
- op1 = operands[3];
- nmask = operands[4];
- mask = operands[5];
-
- mode = GET_MODE (dest);
- vmode = GET_MODE (mask);
-
- if (rtx_equal_p (op0, op1))
+ if (rtx_equal_p (operands[1], operands[2]))
{
- /* Shouldn't happen often (it's useless, obviously), but when it does
- we'd generate incorrect code if we continue below. */
- emit_move_insn (dest, op0);
+ emit_move_insn (operands[0], operands[1]);
return;
}
- if (REG_P (mask) && REGNO (dest) == REGNO (mask)) /* alternative 0 */
- {
- gcc_assert (REGNO (op1) == REGNO (scratch));
-
- x = gen_rtx_AND (vmode, scratch, mask);
- emit_insn (gen_rtx_SET (scratch, x));
+ dest = lowpart_subreg (vmode, operands[0], mode);
+ op1 = lowpart_subreg (vmode, operands[2], mode);
+ mask = ix86_build_signbit_mask (vmode, 0, 0);
- dest = mask;
- op0 = lowpart_subreg (vmode, op0, mode);
- x = gen_rtx_NOT (vmode, dest);
- x = gen_rtx_AND (vmode, x, op0);
- emit_insn (gen_rtx_SET (dest, x));
- }
- else
+ if (CONST_DOUBLE_P (operands[1]))
{
- if (REGNO (op1) == REGNO (scratch)) /* alternative 1,3 */
+ op0 = simplify_unary_operation (ABS, mode, operands[1], mode);
+ /* Optimize for 0, simplify b = copy_signf (0.0f, a) to b = mask & a. */
+ if (op0 == CONST0_RTX (mode))
{
- x = gen_rtx_AND (vmode, scratch, mask);
- }
- else /* alternative 2,4 */
- {
- gcc_assert (REGNO (mask) == REGNO (scratch));
- op1 = lowpart_subreg (vmode, op1, mode);
- x = gen_rtx_AND (vmode, scratch, op1);
+ emit_move_insn (dest, gen_rtx_AND (vmode, mask, op1));
+ return;
}
- emit_insn (gen_rtx_SET (scratch, x));
- if (REGNO (op0) == REGNO (dest)) /* alternative 1,2 */
- {
- dest = lowpart_subreg (vmode, op0, mode);
- x = gen_rtx_AND (vmode, dest, nmask);
- }
- else /* alternative 3,4 */
- {
- gcc_assert (REGNO (nmask) == REGNO (dest));
- dest = nmask;
- op0 = lowpart_subreg (vmode, op0, mode);
- x = gen_rtx_AND (vmode, dest, op0);
- }
- emit_insn (gen_rtx_SET (dest, x));
+ if (GET_MODE_SIZE (mode) < 16)
+ op0 = ix86_build_const_vector (vmode, false, op0);
+ op0 = force_reg (vmode, op0);
}
-
- x = gen_rtx_IOR (vmode, dest, scratch);
- emit_insn (gen_rtx_SET (dest, x));
+ else
+ op0 = lowpart_subreg (vmode, operands[1], mode);
+
+ op2 = gen_reg_rtx (vmode);
+ op3 = gen_reg_rtx (vmode);
+ emit_move_insn (op2, gen_rtx_AND (vmode,
+ gen_rtx_NOT (vmode, mask),
+ op0));
+ emit_move_insn (op3, gen_rtx_AND (vmode, mask, op1));
+ emit_move_insn (dest, gen_rtx_IOR (vmode, op2, op3));
}
/* Expand an xorsign operation. */
@@ -2253,7 +2190,7 @@ void
ix86_expand_xorsign (rtx operands[])
{
machine_mode mode, vmode;
- rtx dest, op0, op1, mask;
+ rtx dest, op0, op1, mask, x, temp;
dest = operands[0];
op0 = operands[1];
@@ -2261,39 +2198,26 @@ ix86_expand_xorsign (rtx operands[])
mode = GET_MODE (dest);
- if (mode == SFmode)
+ if (mode == HFmode)
+ vmode = V8HFmode;
+ else if (mode == SFmode)
vmode = V4SFmode;
else if (mode == DFmode)
vmode = V2DFmode;
else
gcc_unreachable ();
+ temp = gen_reg_rtx (vmode);
mask = ix86_build_signbit_mask (vmode, 0, 0);
- emit_insn (gen_xorsign3_1 (mode, dest, op0, op1, mask));
-}
-
-/* Deconstruct an xorsign operation into bit masks. */
-
-void
-ix86_split_xorsign (rtx operands[])
-{
- machine_mode mode, vmode;
- rtx dest, op0, mask, x;
+ op1 = lowpart_subreg (vmode, op1, mode);
+ x = gen_rtx_AND (vmode, op1, mask);
+ emit_insn (gen_rtx_SET (temp, x));
- dest = operands[0];
- op0 = operands[1];
- mask = operands[3];
-
- mode = GET_MODE (dest);
- vmode = GET_MODE (mask);
+ op0 = lowpart_subreg (vmode, op0, mode);
+ x = gen_rtx_XOR (vmode, temp, op0);
dest = lowpart_subreg (vmode, dest, mode);
- x = gen_rtx_AND (vmode, dest, mask);
- emit_insn (gen_rtx_SET (dest, x));
-
- op0 = lowpart_subreg (vmode, op0, mode);
- x = gen_rtx_XOR (vmode, dest, op0);
emit_insn (gen_rtx_SET (dest, x));
}
@@ -2331,6 +2255,7 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
switch (mode)
{
+ case E_HFmode:
case E_SFmode:
case E_DFmode:
case E_XFmode:
@@ -2644,7 +2569,7 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
bool unordered_compare = ix86_unordered_fp_compare (code);
rtx op0 = *pop0, op1 = *pop1;
machine_mode op_mode = GET_MODE (op0);
- bool is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P (op_mode);
+ bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HF_P (op_mode);
/* All of the unordered compare instructions only work on registers.
The same is true of the fcomi compare instructions. The XFmode
@@ -3698,6 +3623,10 @@ ix86_valid_mask_cmp_mode (machine_mode mode)
if (TARGET_XOP && !TARGET_AVX512F)
return false;
+ /* HFmode only supports vcmpsh whose dest is mask register. */
+ if (TARGET_AVX512FP16 && mode == HFmode)
+ return true;
+
/* AVX512F is needed for mask operation. */
if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
return false;
@@ -3719,10 +3648,14 @@ ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
{
int vector_size = GET_MODE_SIZE (mode);
- if (vector_size < 16)
+ if (cmp_mode == HFmode)
+ return true;
+ else if (vector_size < 16)
return false;
else if (vector_size == 64)
return true;
+ else if (GET_MODE_INNER (cmp_mode) == HFmode)
+ return true;
/* When op_true is NULL, op_false must be NULL, or vice versa. */
gcc_assert (!op_true == !op_false);
@@ -3833,7 +3766,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
&& GET_MODE_CLASS (cmpmode) == MODE_INT)
{
gcc_assert (ix86_valid_mask_cmp_mode (mode));
- /* Using vector move with mask register. */
+ /* Using scalar/vector move with mask register. */
cmp = force_reg (cmpmode, cmp);
/* Optimize for mask zero. */
op_true = (op_true != CONST0_RTX (mode)
@@ -3852,8 +3785,13 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
std::swap (op_true, op_false);
}
- rtx vec_merge = gen_rtx_VEC_MERGE (mode, op_true, op_false, cmp);
- emit_insn (gen_rtx_SET (dest, vec_merge));
+ if (mode == HFmode)
+ emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp));
+ else
+ {
+ rtx vec_merge = gen_rtx_VEC_MERGE (mode, op_true, op_false, cmp);
+ emit_insn (gen_rtx_SET (dest, vec_merge));
+ }
return;
}
else if (vector_all_ones_operand (op_true, mode)
@@ -3968,6 +3906,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
break;
case E_V16QImode:
case E_V8HImode:
+ case E_V8HFmode:
case E_V4SImode:
case E_V2DImode:
if (TARGET_SSE4_1)
@@ -3990,6 +3929,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
break;
case E_V32QImode:
case E_V16HImode:
+ case E_V16HFmode:
case E_V8SImode:
case E_V4DImode:
if (TARGET_AVX2)
@@ -4009,6 +3949,9 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
case E_V32HImode:
gen = gen_avx512bw_blendmv32hi;
break;
+ case E_V32HFmode:
+ gen = gen_avx512bw_blendmv32hf;
+ break;
case E_V16SImode:
gen = gen_avx512f_blendmv16si;
break;
@@ -4129,7 +4072,7 @@ ix86_expand_fp_movcc (rtx operands[])
rtx op0 = XEXP (operands[1], 0);
rtx op1 = XEXP (operands[1], 1);
- if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
{
machine_mode cmode;
@@ -4903,6 +4846,16 @@ ix86_expand_vec_perm (rtx operands[])
e = GET_MODE_UNIT_SIZE (mode);
gcc_assert (w <= 64);
+ /* For HF mode vector, convert it to HI using subreg. */
+ if (GET_MODE_INNER (mode) == HFmode)
+ {
+ machine_mode orig_mode = mode;
+ mode = mode_for_vector (HImode, w).require ();
+ target = lowpart_subreg (mode, target, orig_mode);
+ op0 = lowpart_subreg (mode, op0, orig_mode);
+ op1 = lowpart_subreg (mode, op1, orig_mode);
+ }
+
if (TARGET_AVX512F && one_operand_shuffle)
{
rtx (*gen) (rtx, rtx, rtx) = NULL;
@@ -9615,12 +9568,14 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case FLOAT128_FTYPE_FLOAT128_FLOAT128:
case V16QI_FTYPE_V16QI_V16QI:
case V16QI_FTYPE_V8HI_V8HI:
+ case V16HF_FTYPE_V16HF_V16HF:
case V16SF_FTYPE_V16SF_V16SF:
case V8QI_FTYPE_V8QI_V8QI:
case V8QI_FTYPE_V4HI_V4HI:
case V8HI_FTYPE_V8HI_V8HI:
case V8HI_FTYPE_V16QI_V16QI:
case V8HI_FTYPE_V4SI_V4SI:
+ case V8HF_FTYPE_V8HF_V8HF:
case V8SF_FTYPE_V8SF_V8SF:
case V8SF_FTYPE_V8SF_V8SI:
case V8DF_FTYPE_V8DF_V8DF:
@@ -9796,6 +9751,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V16HI_FTYPE_V16SI_V16HI_UHI:
case V16QI_FTYPE_V16SI_V16QI_UHI:
case V16QI_FTYPE_V8DI_V16QI_UQI:
+ case V32HF_FTYPE_V32HF_V32HF_USI:
case V16SF_FTYPE_V16SF_V16SF_UHI:
case V16SF_FTYPE_V4SF_V16SF_UHI:
case V16SI_FTYPE_SI_V16SI_UHI:
@@ -9825,20 +9781,41 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V16HI_FTYPE_HI_V16HI_UHI:
case V8HI_FTYPE_V8HI_V8HI_UQI:
case V8HI_FTYPE_HI_V8HI_UQI:
+ case V16HF_FTYPE_V16HF_V16HF_UHI:
case V8SF_FTYPE_V8HI_V8SF_UQI:
case V4SF_FTYPE_V8HI_V4SF_UQI:
+ case V8SI_FTYPE_V8HF_V8SI_UQI:
+ case V8SF_FTYPE_V8HF_V8SF_UQI:
case V8SI_FTYPE_V8SF_V8SI_UQI:
case V4SI_FTYPE_V4SF_V4SI_UQI:
+ case V4SI_FTYPE_V8HF_V4SI_UQI:
+ case V4SF_FTYPE_V8HF_V4SF_UQI:
+ case V4DI_FTYPE_V8HF_V4DI_UQI:
case V4DI_FTYPE_V4SF_V4DI_UQI:
+ case V2DI_FTYPE_V8HF_V2DI_UQI:
case V2DI_FTYPE_V4SF_V2DI_UQI:
+ case V8HF_FTYPE_V8HF_V8HF_UQI:
+ case V8HF_FTYPE_V8HF_V8HF_V8HF:
+ case V8HF_FTYPE_V8HI_V8HF_UQI:
+ case V8HF_FTYPE_V8SI_V8HF_UQI:
+ case V8HF_FTYPE_V8SF_V8HF_UQI:
+ case V8HF_FTYPE_V4SI_V8HF_UQI:
+ case V8HF_FTYPE_V4SF_V8HF_UQI:
+ case V8HF_FTYPE_V4DI_V8HF_UQI:
+ case V8HF_FTYPE_V4DF_V8HF_UQI:
+ case V8HF_FTYPE_V2DI_V8HF_UQI:
+ case V8HF_FTYPE_V2DF_V8HF_UQI:
case V4SF_FTYPE_V4DI_V4SF_UQI:
case V4SF_FTYPE_V2DI_V4SF_UQI:
case V4DF_FTYPE_V4DI_V4DF_UQI:
+ case V4DF_FTYPE_V8HF_V4DF_UQI:
+ case V2DF_FTYPE_V8HF_V2DF_UQI:
case V2DF_FTYPE_V2DI_V2DF_UQI:
case V16QI_FTYPE_V8HI_V16QI_UQI:
case V16QI_FTYPE_V16HI_V16QI_UHI:
case V16QI_FTYPE_V4SI_V16QI_UQI:
case V16QI_FTYPE_V8SI_V16QI_UQI:
+ case V8HI_FTYPE_V8HF_V8HI_UQI:
case V8HI_FTYPE_V4SI_V8HI_UQI:
case V8HI_FTYPE_V8SI_V8HI_UQI:
case V16QI_FTYPE_V2DI_V16QI_UQI:
@@ -9896,6 +9873,9 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V8DI_FTYPE_DI_V8DI_UQI:
case V16SF_FTYPE_V8SF_V16SF_UHI:
case V16SI_FTYPE_V8SI_V16SI_UHI:
+ case V16HF_FTYPE_V16HI_V16HF_UHI:
+ case V16HF_FTYPE_V16HF_V16HF_V16HF:
+ case V16HI_FTYPE_V16HF_V16HI_UHI:
case V16HI_FTYPE_V16HI_V16HI_UHI:
case V8HI_FTYPE_V16QI_V8HI_UQI:
case V16HI_FTYPE_V16QI_V16HI_UHI:
@@ -9996,6 +9976,9 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case HI_FTYPE_V16SF_INT_UHI:
case QI_FTYPE_V8SF_INT_UQI:
case QI_FTYPE_V4SF_INT_UQI:
+ case QI_FTYPE_V8HF_INT_UQI:
+ case HI_FTYPE_V16HF_INT_UHI:
+ case SI_FTYPE_V32HF_INT_USI:
case V4SI_FTYPE_V4SI_V4SI_UHI:
case V8SI_FTYPE_V8SI_V8SI_UHI:
nargs = 3;
@@ -10030,6 +10013,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
@@ -10047,6 +10031,8 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
+ case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
+ case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
@@ -10054,6 +10040,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
+ case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
@@ -10082,14 +10069,17 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case UQI_FTYPE_V8SI_V8SI_INT_UQI:
case QI_FTYPE_V4DF_V4DF_INT_UQI:
case QI_FTYPE_V8SF_V8SF_INT_UQI:
+ case UHI_FTYPE_V16HF_V16HF_INT_UHI:
case UQI_FTYPE_V2DI_V2DI_INT_UQI:
case UQI_FTYPE_V4SI_V4SI_INT_UQI:
case UQI_FTYPE_V2DF_V2DF_INT_UQI:
case UQI_FTYPE_V4SF_V4SF_INT_UQI:
+ case UQI_FTYPE_V8HF_V8HF_INT_UQI:
case UDI_FTYPE_V64QI_V64QI_INT_UDI:
case USI_FTYPE_V32QI_V32QI_INT_USI:
case UHI_FTYPE_V16QI_V16QI_INT_UHI:
case USI_FTYPE_V32HI_V32HI_INT_USI:
+ case USI_FTYPE_V32HF_V32HF_INT_USI:
case UHI_FTYPE_V16HI_V16HI_INT_UHI:
case UQI_FTYPE_V8HI_V8HI_INT_UQI:
nargs = 4;
@@ -10138,6 +10128,8 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
+ case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
+ case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
@@ -10309,8 +10301,10 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case CODE_FOR_avx_vpermilv4df_mask:
case CODE_FOR_avx512f_getmantv8df_mask:
case CODE_FOR_avx512f_getmantv16sf_mask:
+ case CODE_FOR_avx512vl_getmantv16hf_mask:
case CODE_FOR_avx512vl_getmantv8sf_mask:
case CODE_FOR_avx512vl_getmantv4df_mask:
+ case CODE_FOR_avx512fp16_getmantv8hf_mask:
case CODE_FOR_avx512vl_getmantv4sf_mask:
case CODE_FOR_avx512vl_getmantv2df_mask:
case CODE_FOR_avx512dq_rangepv8df_mask_round:
@@ -10373,6 +10367,9 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case CODE_FOR_avx512f_cmpv16sf3_mask:
case CODE_FOR_avx512f_vmcmpv2df3_mask:
case CODE_FOR_avx512f_vmcmpv4sf3_mask:
+ case CODE_FOR_avx512bw_cmpv32hf3_mask:
+ case CODE_FOR_avx512vl_cmpv16hf3_mask:
+ case CODE_FOR_avx512fp16_cmpv8hf3_mask:
error ("the last argument must be a 5-bit immediate");
return const0_rtx;
@@ -10722,14 +10719,24 @@ ix86_expand_round_builtin (const struct builtin_description *d,
{
case UINT64_FTYPE_V2DF_INT:
case UINT64_FTYPE_V4SF_INT:
+ case UINT64_FTYPE_V8HF_INT:
case UINT_FTYPE_V2DF_INT:
case UINT_FTYPE_V4SF_INT:
+ case UINT_FTYPE_V8HF_INT:
case INT64_FTYPE_V2DF_INT:
case INT64_FTYPE_V4SF_INT:
+ case INT64_FTYPE_V8HF_INT:
case INT_FTYPE_V2DF_INT:
case INT_FTYPE_V4SF_INT:
+ case INT_FTYPE_V8HF_INT:
nargs = 2;
break;
+ case V32HF_FTYPE_V32HF_V32HF_INT:
+ case V8HF_FTYPE_V8HF_V8HF_INT:
+ case V8HF_FTYPE_V8HF_INT_INT:
+ case V8HF_FTYPE_V8HF_UINT_INT:
+ case V8HF_FTYPE_V8HF_INT64_INT:
+ case V8HF_FTYPE_V8HF_UINT64_INT:
case V4SF_FTYPE_V4SF_UINT_INT:
case V4SF_FTYPE_V4SF_UINT64_INT:
case V2DF_FTYPE_V2DF_UINT64_INT:
@@ -10744,18 +10751,31 @@ ix86_expand_round_builtin (const struct builtin_description *d,
break;
case V8SF_FTYPE_V8DF_V8SF_QI_INT:
case V8DF_FTYPE_V8DF_V8DF_QI_INT:
+ case V32HI_FTYPE_V32HF_V32HI_USI_INT:
case V8SI_FTYPE_V8DF_V8SI_QI_INT:
+ case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
case V8DI_FTYPE_V8DF_V8DI_QI_INT:
case V8SF_FTYPE_V8DI_V8SF_QI_INT:
case V8DF_FTYPE_V8DI_V8DF_QI_INT:
+ case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
+ case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
+ case V32HF_FTYPE_V32HI_V32HF_USI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_USI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
case V16SF_FTYPE_V16SF_V16SF_HI_INT:
case V8DI_FTYPE_V8SF_V8DI_QI_INT:
case V16SF_FTYPE_V16SI_V16SF_HI_INT:
case V16SI_FTYPE_V16SF_V16SI_HI_INT:
+ case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
+ case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
case V8DF_FTYPE_V8SF_V8DF_QI_INT:
case V16SF_FTYPE_V16HI_V16SF_HI_INT:
case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
+ case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
+ case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
+ case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
+ case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
nargs = 4;
break;
case V4SF_FTYPE_V4SF_V4SF_INT_INT:
@@ -10769,15 +10789,23 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
+ case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
+ case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
+ case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
+ case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
+ case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
+ case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
nargs = 5;
break;
+ case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
@@ -10789,6 +10817,8 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
+ case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
+ case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
nargs_constant = 3;
nargs = 5;
break;
@@ -10798,6 +10828,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
+ case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
nargs = 6;
nargs_constant = 4;
break;
@@ -10834,16 +10865,20 @@ ix86_expand_round_builtin (const struct builtin_description *d,
{
case CODE_FOR_avx512f_getmantv8df_mask_round:
case CODE_FOR_avx512f_getmantv16sf_mask_round:
+ case CODE_FOR_avx512bw_getmantv32hf_mask_round:
case CODE_FOR_avx512f_vgetmantv2df_round:
case CODE_FOR_avx512f_vgetmantv2df_mask_round:
case CODE_FOR_avx512f_vgetmantv4sf_round:
case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
+ case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
error ("the immediate argument must be a 4-bit immediate");
return const0_rtx;
case CODE_FOR_avx512f_cmpv8df3_mask_round:
case CODE_FOR_avx512f_cmpv16sf3_mask_round:
case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
+ case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
+ case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
error ("the immediate argument must be a 5-bit immediate");
return const0_rtx;
default:
@@ -10862,7 +10897,27 @@ ix86_expand_round_builtin (const struct builtin_description *d,
/* If there is no rounding use normal version of the pattern. */
if (INTVAL (op) == NO_ROUND)
- redundant_embed_rnd = 1;
+ {
+ /* Skip erasing embedded rounding for below expanders who
+ generates multiple insns. In ix86_erase_embedded_rounding
+ the pattern will be transformed to a single set, and emit_insn
+ appends the set insead of insert it to chain. So the insns
+ emitted inside define_expander would be ignored. */
+ switch (icode)
+ {
+ case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
+ case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
+ case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
+ case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
+ case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
+ case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
+ redundant_embed_rnd = 0;
+ break;
+ default:
+ redundant_embed_rnd = 1;
+ break;
+ }
+ }
}
else
{
@@ -11139,6 +11194,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case VOID_FTYPE_PFLOAT_V16SF_UHI:
case VOID_FTYPE_PFLOAT_V8SF_UQI:
case VOID_FTYPE_PFLOAT_V4SF_UQI:
+ case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
case VOID_FTYPE_PV32QI_V32HI_USI:
case VOID_FTYPE_PV16QI_V16HI_UHI:
case VOID_FTYPE_PUDI_V8HI_UQI:
@@ -11211,6 +11267,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
+ case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
nargs = 3;
klass = load;
memory = 0;
@@ -14123,7 +14180,7 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
tmp1 = gen_reg_rtx (SImode);
emit_move_insn (tmp1, gen_lowpart (SImode, val));
- /* Insert the SImode value as low element of a V4SImode vector. */
+ /* Insert the SImode value as low element of a V4SImode vector. */
tmp2 = gen_reg_rtx (V4SImode);
emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
emit_move_insn (dperm.op0, gen_lowpart (mode, tmp2));
@@ -14207,6 +14264,11 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
}
return true;
+ case E_V8HFmode:
+ case E_V16HFmode:
+ case E_V32HFmode:
+ return ix86_vector_duplicate_value (mode, target, val);
+
default:
return false;
}
@@ -14243,6 +14305,8 @@ ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
break;
case E_V8HImode:
use_vector_set = TARGET_SSE2;
+ gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
+ ? gen_vec_setv8hi_0 : NULL;
break;
case E_V8QImode:
use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
@@ -14254,8 +14318,12 @@ ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
use_vector_set = TARGET_SSE4_1;
break;
case E_V32QImode:
+ use_vector_set = TARGET_AVX;
+ break;
case E_V16HImode:
use_vector_set = TARGET_AVX;
+ gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
+ ? gen_vec_setv16hi_0 : NULL;
break;
case E_V8SImode:
use_vector_set = TARGET_AVX;
@@ -14291,6 +14359,21 @@ ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
gen_vec_set_0 = gen_vec_setv8di_0;
break;
+ case E_V8HFmode:
+ use_vector_set = TARGET_AVX512FP16 && one_var == 0;
+ gen_vec_set_0 = gen_vec_setv8hf_0;
+ break;
+ case E_V16HFmode:
+ use_vector_set = TARGET_AVX512FP16 && one_var == 0;
+ gen_vec_set_0 = gen_vec_setv16hf_0;
+ break;
+ case E_V32HFmode:
+ use_vector_set = TARGET_AVX512FP16 && one_var == 0;
+ gen_vec_set_0 = gen_vec_setv32hf_0;
+ break;
+ case E_V32HImode:
+ use_vector_set = TARGET_AVX512FP16 && one_var == 0;
+ gen_vec_set_0 = gen_vec_setv32hi_0;
default:
break;
}
@@ -14440,6 +14523,8 @@ ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
if (!TARGET_64BIT)
return false;
/* FALLTHRU */
+ case E_V8HFmode:
+ case E_V16HFmode:
case E_V4DFmode:
case E_V8SFmode:
case E_V8SImode:
@@ -14520,6 +14605,9 @@ ix86_expand_vector_init_concat (machine_mode mode,
case 2:
switch (mode)
{
+ case E_V32HFmode:
+ half_mode = V16HFmode;
+ break;
case E_V16SImode:
half_mode = V8SImode;
break;
@@ -14532,6 +14620,9 @@ ix86_expand_vector_init_concat (machine_mode mode,
case E_V8DFmode:
half_mode = V4DFmode;
break;
+ case E_V16HFmode:
+ half_mode = V8HFmode;
+ break;
case E_V8SImode:
half_mode = V4SImode;
break;
@@ -14674,13 +14765,22 @@ ix86_expand_vector_init_interleave (machine_mode mode,
{
machine_mode first_imode, second_imode, third_imode, inner_mode;
int i, j;
- rtx op0, op1;
+ rtx op, op0, op1;
rtx (*gen_load_even) (rtx, rtx, rtx);
rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
switch (mode)
{
+ case E_V8HFmode:
+ gen_load_even = gen_vec_interleave_lowv8hf;
+ gen_interleave_first_low = gen_vec_interleave_lowv4si;
+ gen_interleave_second_low = gen_vec_interleave_lowv2di;
+ inner_mode = HFmode;
+ first_imode = V4SImode;
+ second_imode = V2DImode;
+ third_imode = VOIDmode;
+ break;
case E_V8HImode:
gen_load_even = gen_vec_setv8hi;
gen_interleave_first_low = gen_vec_interleave_lowv4si;
@@ -14705,28 +14805,43 @@ ix86_expand_vector_init_interleave (machine_mode mode,
for (i = 0; i < n; i++)
{
- /* Extend the odd elment to SImode using a paradoxical SUBREG. */
- op0 = gen_reg_rtx (SImode);
- emit_move_insn (op0, gen_lowpart (SImode, ops [i + i]));
+ op = ops [i + i];
+ if (inner_mode == HFmode)
+ {
+ rtx even, odd;
+ /* Use vpuncklwd to pack 2 HFmode. */
+ op0 = gen_reg_rtx (V8HFmode);
+ even = lowpart_subreg (V8HFmode, force_reg (HFmode, op), HFmode);
+ odd = lowpart_subreg (V8HFmode,
+ force_reg (HFmode, ops[i + i + 1]),
+ HFmode);
+ emit_insn (gen_load_even (op0, even, odd));
+ }
+ else
+ {
+ /* Extend the odd elment to SImode using a paradoxical SUBREG. */
+ op0 = gen_reg_rtx (SImode);
+ emit_move_insn (op0, gen_lowpart (SImode, op));
- /* Insert the SImode value as low element of V4SImode vector. */
- op1 = gen_reg_rtx (V4SImode);
- op0 = gen_rtx_VEC_MERGE (V4SImode,
- gen_rtx_VEC_DUPLICATE (V4SImode,
- op0),
- CONST0_RTX (V4SImode),
- const1_rtx);
- emit_insn (gen_rtx_SET (op1, op0));
+ /* Insert the SImode value as low element of V4SImode vector. */
+ op1 = gen_reg_rtx (V4SImode);
+ op0 = gen_rtx_VEC_MERGE (V4SImode,
+ gen_rtx_VEC_DUPLICATE (V4SImode,
+ op0),
+ CONST0_RTX (V4SImode),
+ const1_rtx);
+ emit_insn (gen_rtx_SET (op1, op0));
- /* Cast the V4SImode vector back to a vector in orignal mode. */
- op0 = gen_reg_rtx (mode);
- emit_move_insn (op0, gen_lowpart (mode, op1));
+ /* Cast the V4SImode vector back to a vector in orignal mode. */
+ op0 = gen_reg_rtx (mode);
+ emit_move_insn (op0, gen_lowpart (mode, op1));
- /* Load even elements into the second position. */
- emit_insn (gen_load_even (op0,
- force_reg (inner_mode,
- ops [i + i + 1]),
- const1_rtx));
+ /* Load even elements into the second position. */
+ emit_insn (gen_load_even (op0,
+ force_reg (inner_mode,
+ ops[i + i + 1]),
+ const1_rtx));
+ }
/* Cast vector to FIRST_IMODE vector. */
ops[i] = gen_reg_rtx (first_imode);
@@ -14844,6 +14959,10 @@ ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
half_mode = V8HImode;
goto half;
+ case E_V16HFmode:
+ half_mode = V8HFmode;
+ goto half;
+
half:
n = GET_MODE_NUNITS (mode);
for (i = 0; i < n; i++)
@@ -14867,6 +14986,11 @@ half:
half_mode = V16HImode;
goto quarter;
+ case E_V32HFmode:
+ quarter_mode = V8HFmode;
+ half_mode = V16HFmode;
+ goto quarter;
+
quarter:
n = GET_MODE_NUNITS (mode);
for (i = 0; i < n; i++)
@@ -14903,6 +15027,9 @@ quarter:
move from GPR to SSE register directly. */
if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
break;
+ /* FALLTHRU */
+
+ case E_V8HFmode:
n = GET_MODE_NUNITS (mode);
for (i = 0; i < n; i++)
@@ -15005,7 +15132,8 @@ ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
if (inner_mode == QImode
|| inner_mode == HImode
- || inner_mode == TImode)
+ || inner_mode == TImode
+ || inner_mode == HFmode)
{
unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
@@ -15150,6 +15278,16 @@ ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
case E_V16SFmode:
cmp_mode = V16SImode;
break;
+ /* TARGET_AVX512FP16 implies TARGET_AVX512BW. */
+ case E_V8HFmode:
+ cmp_mode = V8HImode;
+ break;
+ case E_V16HFmode:
+ cmp_mode = V16HImode;
+ break;
+ case E_V32HFmode:
+ cmp_mode = V32HImode;
+ break;
default:
gcc_unreachable ();
}
@@ -15185,24 +15323,27 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
machine_mode inner_mode = GET_MODE_INNER (mode);
machine_mode half_mode;
bool use_vec_merge = false;
+ bool blendm_const = false;
rtx tmp;
- static rtx (*gen_extract[6][2]) (rtx, rtx)
+ static rtx (*gen_extract[7][2]) (rtx, rtx)
= {
{ gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
{ gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
{ gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
{ gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
{ gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
- { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df }
+ { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
+ { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf }
};
- static rtx (*gen_insert[6][2]) (rtx, rtx, rtx)
+ static rtx (*gen_insert[7][2]) (rtx, rtx, rtx)
= {
{ gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
{ gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
{ gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
{ gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
{ gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
- { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df }
+ { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
+ { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
};
int i, j, n;
machine_mode mmode = VOIDmode;
@@ -15369,6 +15510,17 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
}
return;
+ case E_V8HFmode:
+ if (TARGET_AVX2)
+ {
+ mmode = SImode;
+ gen_blendm = gen_sse4_1_pblendph;
+ blendm_const = true;
+ }
+ else
+ use_vec_merge = true;
+ break;
+
case E_V8HImode:
case E_V2HImode:
use_vec_merge = TARGET_SSE2;
@@ -15392,6 +15544,22 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
n = 16;
goto half;
+ case E_V16HFmode:
+ if (TARGET_AVX2)
+ {
+ mmode = SImode;
+ gen_blendm = gen_avx2_pblendph;
+ blendm_const = true;
+ break;
+ }
+ else
+ {
+ half_mode = V8HFmode;
+ j = 6;
+ n = 8;
+ goto half;
+ }
+
case E_V16HImode:
half_mode = V8HImode;
j = 1;
@@ -15472,6 +15640,13 @@ half:
}
break;
+ case E_V32HFmode:
+ if (TARGET_AVX512BW)
+ {
+ mmode = SImode;
+ gen_blendm = gen_avx512bw_blendmv32hf;
+ }
+ break;
case E_V32HImode:
if (TARGET_AVX512BW)
{
@@ -15544,15 +15719,15 @@ quarter:
{
tmp = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
+ rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
/* The avx512*_blendm<mode> expanders have different operand order
from VEC_MERGE. In VEC_MERGE, the first input operand is used for
elements where the mask is set and second input operand otherwise,
in {sse,avx}*_*blend* the first input operand is used for elements
where the mask is clear and second input operand otherwise. */
- emit_insn (gen_blendm (target, target, tmp,
- force_reg (mmode,
- gen_int_mode (HOST_WIDE_INT_1U << elt,
- mmode))));
+ if (!blendm_const)
+ merge_mask = force_reg (mmode, merge_mask);
+ emit_insn (gen_blendm (target, target, tmp, merge_mask));
}
else if (use_vec_merge)
{
@@ -15843,6 +16018,28 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
ix86_expand_vector_extract (false, target, tmp, elt & 3);
return;
+ case E_V32HFmode:
+ tmp = gen_reg_rtx (V16HFmode);
+ if (elt < 16)
+ emit_insn (gen_vec_extract_lo_v32hf (tmp, vec));
+ else
+ emit_insn (gen_vec_extract_hi_v32hf (tmp, vec));
+ ix86_expand_vector_extract (false, target, tmp, elt & 15);
+ return;
+
+ case E_V16HFmode:
+ tmp = gen_reg_rtx (V8HFmode);
+ if (elt < 8)
+ emit_insn (gen_vec_extract_lo_v16hf (tmp, vec));
+ else
+ emit_insn (gen_vec_extract_hi_v16hf (tmp, vec));
+ ix86_expand_vector_extract (false, target, tmp, elt & 7);
+ return;
+
+ case E_V8HFmode:
+ use_vec_extr = true;
+ break;
+
case E_V8QImode:
use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
/* ??? Could extract the appropriate HImode element and shift. */
@@ -15860,11 +16057,15 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
/* Let the rtl optimizers know about the zero extension performed. */
if (inner_mode == QImode || inner_mode == HImode)
{
+ rtx reg = gen_reg_rtx (SImode);
tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
- target = gen_lowpart (SImode, target);
+ emit_move_insn (reg, tmp);
+ tmp = gen_lowpart (inner_mode, reg);
+ SUBREG_PROMOTED_VAR_P (tmp) = 1;
+ SUBREG_PROMOTED_SET (tmp, 1);
}
- emit_insn (gen_rtx_SET (target, tmp));
+ emit_move_insn (target, tmp);
}
else
{
@@ -15898,8 +16099,19 @@ emit_reduc_half (rtx dest, rtx src, int i)
case E_V2DFmode:
tem = gen_vec_interleave_highv2df (dest, src, src);
break;
+ case E_V4QImode:
+ d = gen_reg_rtx (V1SImode);
+ tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
+ GEN_INT (i / 2));
+ break;
+ case E_V4HImode:
+ d = gen_reg_rtx (V1DImode);
+ tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
+ GEN_INT (i / 2));
+ break;
case E_V16QImode:
case E_V8HImode:
+ case E_V8HFmode:
case E_V4SImode:
case E_V2DImode:
d = gen_reg_rtx (V1TImode);
@@ -15921,6 +16133,7 @@ emit_reduc_half (rtx dest, rtx src, int i)
break;
case E_V32QImode:
case E_V16HImode:
+ case E_V16HFmode:
case E_V8SImode:
case E_V4DImode:
if (i == 256)
@@ -15940,6 +16153,7 @@ emit_reduc_half (rtx dest, rtx src, int i)
break;
case E_V64QImode:
case E_V32HImode:
+ case E_V32HFmode:
if (i < 64)
{
d = gen_reg_rtx (V4TImode);
@@ -20935,6 +21149,20 @@ ix86_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0,
unsigned int i, nelt, which;
bool two_args;
+ /* For HF mode vector, convert it to HI using subreg. */
+ if (GET_MODE_INNER (vmode) == HFmode)
+ {
+ machine_mode orig_mode = vmode;
+ vmode = mode_for_vector (HImode,
+ GET_MODE_NUNITS (vmode)).require ();
+ if (target)
+ target = lowpart_subreg (vmode, target, orig_mode);
+ if (op0)
+ op0 = lowpart_subreg (vmode, op0, orig_mode);
+ if (op1)
+ op1 = lowpart_subreg (vmode, op1, orig_mode);
+ }
+
d.target = target;
d.op0 = op0;
d.op1 = op1;
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 5a99ea7..43bb676 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -2165,7 +2165,7 @@ make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
}
/* At entry of the nearest common dominator for basic blocks with
- conversions, generate a single
+ conversions/rcp/sqrt/rsqrt/round, generate a single
vxorps %xmmN, %xmmN, %xmmN
for all
vcvtss2sd op, %xmmN, %xmmX
@@ -2210,27 +2210,70 @@ remove_partial_avx_dependency (void)
!= AVX_PARTIAL_XMM_UPDATE_TRUE)
continue;
- if (!v4sf_const0)
- v4sf_const0 = gen_reg_rtx (V4SFmode);
-
/* Convert PARTIAL_XMM_UPDATE_TRUE insns, DF -> SF, SF -> DF,
- SI -> SF, SI -> DF, DI -> SF, DI -> DF, to vec_dup and
- vec_merge with subreg. */
+ SI -> SF, SI -> DF, DI -> SF, DI -> DF, sqrt, rsqrt, rcp,
+ round, to vec_dup and vec_merge with subreg. */
rtx src = SET_SRC (set);
rtx dest = SET_DEST (set);
machine_mode dest_mode = GET_MODE (dest);
+ bool convert_p = false;
+ switch (GET_CODE (src))
+ {
+ case FLOAT:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case UNSIGNED_FLOAT:
+ convert_p = true;
+ break;
+ default:
+ break;
+ }
+
+ /* Only hanlde conversion here. */
+ machine_mode src_mode
+ = convert_p ? GET_MODE (XEXP (src, 0)) : VOIDmode;
+ switch (src_mode)
+ {
+ case E_SFmode:
+ case E_DFmode:
+ if (TARGET_USE_VECTOR_FP_CONVERTS
+ || !TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY)
+ continue;
+ break;
+ case E_SImode:
+ case E_DImode:
+ if (TARGET_USE_VECTOR_CONVERTS
+ || !TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY)
+ continue;
+ break;
+ case E_VOIDmode:
+ gcc_assert (!convert_p);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!v4sf_const0)
+ v4sf_const0 = gen_reg_rtx (V4SFmode);
rtx zero;
machine_mode dest_vecmode;
- if (dest_mode == E_SFmode)
+ switch (dest_mode)
{
+ case E_HFmode:
+ dest_vecmode = V8HFmode;
+ zero = gen_rtx_SUBREG (V8HFmode, v4sf_const0, 0);
+ break;
+ case E_SFmode:
dest_vecmode = V4SFmode;
zero = v4sf_const0;
- }
- else
- {
+ break;
+ case E_DFmode:
dest_vecmode = V2DFmode;
zero = gen_rtx_SUBREG (V2DFmode, v4sf_const0, 0);
+ break;
+ default:
+ gcc_unreachable ();
}
/* Change source to vector mode. */
diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def
index a0d46cb..83d9302 100644
--- a/gcc/config/i386/i386-isa.def
+++ b/gcc/config/i386/i386-isa.def
@@ -108,3 +108,4 @@ DEF_PTA(HRESET)
DEF_PTA(KL)
DEF_PTA(WIDEKL)
DEF_PTA(AVXVNNI)
+DEF_PTA(AVX512FP16)
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index 4e7014b..2a2c8b8 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
+FLOAT_MODE (HF, 2, ieee_half_format);
/* In ILP32 mode, XFmode has size 12 and alignment 4.
In LP64 mode, XFmode has size and alignment 16. */
@@ -83,12 +84,14 @@ VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
VECTOR_MODES (INT, 32); /* V32QI V16HI V8SI V4DI */
VECTOR_MODES (INT, 64); /* V64QI V32HI V16SI V8DI */
VECTOR_MODES (INT, 128); /* V128QI V64HI V32SI V16DI */
-VECTOR_MODES (FLOAT, 8); /* V2SF */
-VECTOR_MODES (FLOAT, 16); /* V4SF V2DF */
-VECTOR_MODES (FLOAT, 32); /* V8SF V4DF V2TF */
-VECTOR_MODES (FLOAT, 64); /* V16SF V8DF V4TF */
-VECTOR_MODES (FLOAT, 128); /* V32SF V16DF V8TF */
-VECTOR_MODES (FLOAT, 256); /* V64SF V32DF V16TF */
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
+VECTOR_MODES (FLOAT, 32); /* V16HF V8SF V4DF V2TF */
+VECTOR_MODES (FLOAT, 64); /* V32HF V16SF V8DF V4TF */
+VECTOR_MODES (FLOAT, 128); /* V64HF V32SF V16DF V8TF */
+VECTOR_MODES (FLOAT, 256); /* V128HF V64SF V32DF V16TF */
+VECTOR_MODE (FLOAT, HF, 2); /* V2HF */
+VECTOR_MODE (FLOAT, HF, 6); /* V6HF */
VECTOR_MODE (INT, TI, 1); /* V1TI */
VECTOR_MODE (INT, DI, 1); /* V1DI */
VECTOR_MODE (INT, SI, 1); /* V1SI */
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index fee5a48..e7a3bd4 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -223,7 +223,8 @@ static struct ix86_target_opts isa2_opts[] =
{ "-mhreset", OPTION_MASK_ISA2_HRESET },
{ "-mkl", OPTION_MASK_ISA2_KL },
{ "-mwidekl", OPTION_MASK_ISA2_WIDEKL },
- { "-mavxvnni", OPTION_MASK_ISA2_AVXVNNI }
+ { "-mavxvnni", OPTION_MASK_ISA2_AVXVNNI },
+ { "-mavx512fp16", OPTION_MASK_ISA2_AVX512FP16 }
};
static struct ix86_target_opts isa_opts[] =
{
@@ -723,7 +724,7 @@ static const struct processor_costs *processor_cost_table[] =
&slm_cost,
&slm_cost,
&slm_cost,
- &slm_cost,
+ &tremont_cost,
&slm_cost,
&slm_cost,
&skylake_cost,
@@ -1049,6 +1050,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("amx-bf16", OPT_mamx_bf16),
IX86_ATTR_ISA ("hreset", OPT_mhreset),
IX86_ATTR_ISA ("avxvnni", OPT_mavxvnni),
+ IX86_ATTR_ISA ("avx512fp16", OPT_mavx512fp16),
/* enum options */
IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
@@ -2577,6 +2579,12 @@ ix86_option_override_internal (bool main_args_p,
SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
ix86_tune_cost->l2_cache_size);
+ /* 64B is the accepted value for these for all x86. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+
/* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */
if (opts->x_flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 2fd1307..708834a 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -135,10 +135,7 @@ extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode,
rtx[]);
extern void ix86_expand_copysign (rtx []);
-extern void ix86_split_copysign_const (rtx []);
-extern void ix86_split_copysign_var (rtx []);
extern void ix86_expand_xorsign (rtx []);
-extern void ix86_split_xorsign (rtx []);
extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[]);
extern bool ix86_match_ccmode (rtx, machine_mode);
extern void ix86_expand_branch (enum rtx_code, rtx, rtx, rtx);
@@ -323,12 +320,12 @@ struct ix86_address
addr_space_t seg;
};
-extern int ix86_decompose_address (rtx, struct ix86_address *);
+extern bool ix86_decompose_address (rtx, struct ix86_address *);
extern int memory_address_length (rtx, bool);
extern void x86_output_aligned_bss (FILE *, tree, const char *,
- unsigned HOST_WIDE_INT, int);
+ unsigned HOST_WIDE_INT, unsigned);
extern void x86_elf_aligned_decl_common (FILE *, tree, const char *,
- unsigned HOST_WIDE_INT, int);
+ unsigned HOST_WIDE_INT, unsigned);
#ifdef RTX_CODE
extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3bb2cab..3c3336d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -387,6 +387,7 @@ enum x86_64_reg_class
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS,
X86_64_SSE_CLASS,
+ X86_64_SSEHF_CLASS,
X86_64_SSESF_CLASS,
X86_64_SSEDF_CLASS,
X86_64_SSEUP_CLASS,
@@ -841,7 +842,7 @@ x86_64_elf_unique_section (tree decl, int reloc)
void
x86_elf_aligned_decl_common (FILE *file, tree decl,
const char *name, unsigned HOST_WIDE_INT size,
- int align)
+ unsigned align)
{
if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
&& size > (unsigned int)ix86_section_threshold)
@@ -862,7 +863,7 @@ x86_elf_aligned_decl_common (FILE *file, tree decl,
void
x86_output_aligned_bss (FILE *file, tree decl, const char *name,
- unsigned HOST_WIDE_INT size, int align)
+ unsigned HOST_WIDE_INT size, unsigned align)
{
if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
&& size > (unsigned int)ix86_section_threshold)
@@ -2027,8 +2028,10 @@ merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
return X86_64_MEMORY_CLASS;
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
- if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
- || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+ if ((class1 == X86_64_INTEGERSI_CLASS
+ && (class2 == X86_64_SSESF_CLASS || class2 == X86_64_SSEHF_CLASS))
+ || (class2 == X86_64_INTEGERSI_CLASS
+ && (class1 == X86_64_SSESF_CLASS || class1 == X86_64_SSEHF_CLASS)))
return X86_64_INTEGERSI_CLASS;
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
@@ -2182,6 +2185,8 @@ classify_argument (machine_mode mode, const_tree type,
/* The partial classes are now full classes. */
if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4)
subclasses[0] = X86_64_SSE_CLASS;
+ if (subclasses[0] == X86_64_SSEHF_CLASS && bytes != 2)
+ subclasses[0] = X86_64_SSE_CLASS;
if (subclasses[0] == X86_64_INTEGERSI_CLASS
&& !((bit_offset % 64) == 0 && bytes == 4))
subclasses[0] = X86_64_INTEGER_CLASS;
@@ -2354,6 +2359,12 @@ classify_argument (machine_mode mode, const_tree type,
gcc_unreachable ();
case E_CTImode:
return 0;
+ case E_HFmode:
+ if (!(bit_offset % 64))
+ classes[0] = X86_64_SSEHF_CLASS;
+ else
+ classes[0] = X86_64_SSE_CLASS;
+ return 1;
case E_SFmode:
if (!(bit_offset % 64))
classes[0] = X86_64_SSESF_CLASS;
@@ -2371,6 +2382,15 @@ classify_argument (machine_mode mode, const_tree type,
classes[0] = X86_64_SSE_CLASS;
classes[1] = X86_64_SSEUP_CLASS;
return 2;
+ case E_HCmode:
+ classes[0] = X86_64_SSE_CLASS;
+ if (!(bit_offset % 64))
+ return 1;
+ else
+ {
+ classes[1] = X86_64_SSEHF_CLASS;
+ return 2;
+ }
case E_SCmode:
classes[0] = X86_64_SSE_CLASS;
if (!(bit_offset % 64))
@@ -2402,6 +2422,7 @@ classify_argument (machine_mode mode, const_tree type,
case E_V8SFmode:
case E_V8SImode:
case E_V32QImode:
+ case E_V16HFmode:
case E_V16HImode:
case E_V4DFmode:
case E_V4DImode:
@@ -2412,6 +2433,7 @@ classify_argument (machine_mode mode, const_tree type,
return 4;
case E_V8DFmode:
case E_V16SFmode:
+ case E_V32HFmode:
case E_V8DImode:
case E_V16SImode:
case E_V32HImode:
@@ -2429,6 +2451,7 @@ classify_argument (machine_mode mode, const_tree type,
case E_V4SImode:
case E_V16QImode:
case E_V8HImode:
+ case E_V8HFmode:
case E_V2DFmode:
case E_V2DImode:
classes[0] = X86_64_SSE_CLASS;
@@ -2439,6 +2462,8 @@ classify_argument (machine_mode mode, const_tree type,
case E_V2SFmode:
case E_V2SImode:
case E_V4HImode:
+ case E_V4HFmode:
+ case E_V2HFmode:
case E_V8QImode:
classes[0] = X86_64_SSE_CLASS;
return 1;
@@ -2485,6 +2510,7 @@ examine_argument (machine_mode mode, const_tree type, int in_return,
(*int_nregs)++;
break;
case X86_64_SSE_CLASS:
+ case X86_64_SSEHF_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
(*sse_nregs)++;
@@ -2584,13 +2610,14 @@ construct_container (machine_mode mode, machine_mode orig_mode,
/* First construct simple cases. Avoid SCmode, since we want to use
single register to pass this type. */
- if (n == 1 && mode != SCmode)
+ if (n == 1 && mode != SCmode && mode != HCmode)
switch (regclass[0])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
return gen_rtx_REG (mode, intreg[0]);
case X86_64_SSE_CLASS:
+ case X86_64_SSEHF_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
if (mode != BLKmode)
@@ -2687,6 +2714,14 @@ construct_container (machine_mode mode, machine_mode orig_mode,
GEN_INT (i*8));
intreg++;
break;
+ case X86_64_SSEHF_CLASS:
+ exp [nexps++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (HFmode,
+ GET_SSE_REGNO (sse_regno)),
+ GEN_INT (i*8));
+ sse_regno++;
+ break;
case X86_64_SSESF_CLASS:
exp [nexps++]
= gen_rtx_EXPR_LIST (VOIDmode,
@@ -2832,12 +2867,14 @@ pass_in_reg:
break;
/* FALLTHRU */
+ case E_V16HFmode:
case E_V8SFmode:
case E_V8SImode:
case E_V64QImode:
case E_V32HImode:
case E_V16SImode:
case E_V8DImode:
+ case E_V32HFmode:
case E_V16SFmode:
case E_V8DFmode:
case E_V32QImode:
@@ -2849,6 +2886,7 @@ pass_in_reg:
case E_V8HImode:
case E_V4SImode:
case E_V2DImode:
+ case E_V8HFmode:
case E_V4SFmode:
case E_V2DFmode:
if (!type || !AGGREGATE_TYPE_P (type))
@@ -2866,6 +2904,7 @@ pass_in_reg:
case E_V8QImode:
case E_V4HImode:
+ case E_V4HFmode:
case E_V2SImode:
case E_V2SFmode:
case E_V1TImode:
@@ -2903,7 +2942,9 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, machine_mode mode,
/* Unnamed 512 and 256bit vector mode parameters are passed on stack. */
if (!named && (VALID_AVX512F_REG_MODE (mode)
- || VALID_AVX256_REG_MODE (mode)))
+ || VALID_AVX256_REG_MODE (mode)
+ || mode == V16HFmode
+ || mode == V32HFmode))
return 0;
if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs)
@@ -3071,6 +3112,7 @@ pass_in_reg:
case E_V8HImode:
case E_V4SImode:
case E_V2DImode:
+ case E_V8HFmode:
case E_V4SFmode:
case E_V2DFmode:
if (!type || !AGGREGATE_TYPE_P (type))
@@ -3090,8 +3132,10 @@ pass_in_reg:
case E_V32HImode:
case E_V16SImode:
case E_V8DImode:
+ case E_V32HFmode:
case E_V16SFmode:
case E_V8DFmode:
+ case E_V16HFmode:
case E_V8SFmode:
case E_V8SImode:
case E_V32QImode:
@@ -3108,6 +3152,7 @@ pass_in_reg:
case E_V8QImode:
case E_V4HImode:
+ case E_V4HFmode:
case E_V2SImode:
case E_V2SFmode:
case E_V1TImode:
@@ -3150,12 +3195,14 @@ function_arg_64 (const CUMULATIVE_ARGS *cum, machine_mode mode,
default:
break;
+ case E_V16HFmode:
case E_V8SFmode:
case E_V8SImode:
case E_V32QImode:
case E_V16HImode:
case E_V4DFmode:
case E_V4DImode:
+ case E_V32HFmode:
case E_V16SFmode:
case E_V16SImode:
case E_V64QImode:
@@ -3907,6 +3954,19 @@ function_value_32 (machine_mode orig_mode, machine_mode mode,
/* Most things go in %eax. */
regno = AX_REG;
+ /* Return _Float16/_Complex _Foat16 by sse register. */
+ if (mode == HFmode)
+ regno = FIRST_SSE_REG;
+ if (mode == HCmode)
+ {
+ rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc(1));
+ XVECEXP (ret, 0, 0)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode, FIRST_SSE_REG),
+ GEN_INT (0));
+ return ret;
+ }
+
/* Override FP return register with %xmm0 for local functions when
SSE math is enabled or for functions with sseregparm attribute. */
if ((fn || fntype) && (mode == SFmode || mode == DFmode))
@@ -3943,6 +4003,8 @@ function_value_64 (machine_mode orig_mode, machine_mode mode,
switch (mode)
{
+ case E_HFmode:
+ case E_HCmode:
case E_SFmode:
case E_SCmode:
case E_DFmode:
@@ -4635,12 +4697,14 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
nat_mode = type_natural_mode (type, NULL, false);
switch (nat_mode)
{
+ case E_V16HFmode:
case E_V8SFmode:
case E_V8SImode:
case E_V32QImode:
case E_V16HImode:
case E_V4DFmode:
case E_V4DImode:
+ case E_V32HFmode:
case E_V16SFmode:
case E_V16SImode:
case E_V64QImode:
@@ -4975,7 +5039,8 @@ standard_80387_constant_p (rtx x)
/* For XFmode constants, try to find a special 80387 instruction when
optimizing for size or on those CPUs that benefit from them. */
if (mode == XFmode
- && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS))
+ && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS)
+ && !flag_rounding_math)
{
int i;
@@ -5314,7 +5379,12 @@ ix86_get_ssemov (rtx *operands, unsigned size,
switch (type)
{
case opcode_int:
- opcode = misaligned_p ? "vmovdqu32" : "vmovdqa32";
+ if (scalar_mode == E_HFmode)
+ opcode = (misaligned_p
+ ? (TARGET_AVX512BW ? "vmovdqu16" : "vmovdqu64")
+ : "vmovdqa64");
+ else
+ opcode = misaligned_p ? "vmovdqu32" : "vmovdqa32";
break;
case opcode_float:
opcode = misaligned_p ? "vmovups" : "vmovaps";
@@ -5328,6 +5398,11 @@ ix86_get_ssemov (rtx *operands, unsigned size,
{
switch (scalar_mode)
{
+ case E_HFmode:
+ opcode = (misaligned_p
+ ? (TARGET_AVX512BW ? "vmovdqu16" : "vmovdqu64")
+ : "vmovdqa64");
+ break;
case E_SFmode:
opcode = misaligned_p ? "%vmovups" : "%vmovaps";
break;
@@ -5463,6 +5538,14 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands)
case MODE_SI:
return "%vmovd\t{%1, %0|%0, %1}";
+ case MODE_HI:
+ if (GENERAL_REG_P (operands[0]))
+ return "vmovw\t{%1, %k0|%k0, %1}";
+ else if (GENERAL_REG_P (operands[1]))
+ return "vmovw\t{%k1, %0|%0, %k1}";
+ else
+ return "vmovw\t{%1, %0|%0, %1}";
+
case MODE_DF:
if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1]))
return "vmovsd\t{%d1, %0|%0, %d1}";
@@ -5475,6 +5558,12 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands)
else
return "%vmovss\t{%1, %0|%0, %1}";
+ case MODE_HF:
+ if (REG_P (operands[0]) && REG_P (operands[1]))
+ return "vmovsh\t{%d1, %0|%0, %d1}";
+ else
+ return "vmovsh\t{%1, %0|%0, %1}";
+
case MODE_V1DF:
gcc_assert (!TARGET_AVX);
return "movlpd\t{%1, %0|%0, %1}";
@@ -10017,10 +10106,10 @@ ix86_live_on_entry (bitmap regs)
}
/* Extract the parts of an RTL expression that is a valid memory address
- for an instruction. Return 0 if the structure of the address is
+ for an instruction. Return false if the structure of the address is
grossly off. */
-int
+bool
ix86_decompose_address (rtx addr, struct ix86_address *out)
{
rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
@@ -10039,17 +10128,17 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
{
addr = XEXP (addr, 0);
if (CONST_INT_P (addr))
- return 0;
+ return false;
}
else if (GET_CODE (addr) == AND
&& const_32bit_mask (XEXP (addr, 1), DImode))
{
addr = lowpart_subreg (SImode, XEXP (addr, 0), DImode);
if (addr == NULL_RTX)
- return 0;
+ return false;
if (CONST_INT_P (addr))
- return 0;
+ return false;
}
else if (GET_CODE (addr) == AND)
{
@@ -10083,7 +10172,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
{
addr = SUBREG_REG (addr);
if (CONST_INT_P (addr))
- return 0;
+ return false;
}
}
@@ -10094,7 +10183,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
if (REG_P (SUBREG_REG (addr)))
base = addr;
else
- return 0;
+ return false;
}
else if (GET_CODE (addr) == PLUS)
{
@@ -10105,13 +10194,13 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
do
{
if (n >= 4)
- return 0;
+ return false;
addends[n++] = XEXP (op, 1);
op = XEXP (op, 0);
}
while (GET_CODE (op) == PLUS);
if (n >= 4)
- return 0;
+ return false;
addends[n] = op;
for (i = n; i >= 0; --i)
@@ -10121,28 +10210,28 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
{
case MULT:
if (index)
- return 0;
+ return false;
index = XEXP (op, 0);
scale_rtx = XEXP (op, 1);
break;
case ASHIFT:
if (index)
- return 0;
+ return false;
index = XEXP (op, 0);
tmp = XEXP (op, 1);
if (!CONST_INT_P (tmp))
- return 0;
+ return false;
scale = INTVAL (tmp);
if ((unsigned HOST_WIDE_INT) scale > 3)
- return 0;
+ return false;
scale = 1 << scale;
break;
case ZERO_EXTEND:
op = XEXP (op, 0);
if (GET_CODE (op) != UNSPEC)
- return 0;
+ return false;
/* FALLTHRU */
case UNSPEC:
@@ -10151,12 +10240,12 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
&& seg == ADDR_SPACE_GENERIC)
seg = DEFAULT_TLS_SEG_REG;
else
- return 0;
+ return false;
break;
case SUBREG:
if (!REG_P (SUBREG_REG (op)))
- return 0;
+ return false;
/* FALLTHRU */
case REG:
@@ -10165,7 +10254,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
else if (!index)
index = op;
else
- return 0;
+ return false;
break;
case CONST:
@@ -10173,12 +10262,12 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
case SYMBOL_REF:
case LABEL_REF:
if (disp)
- return 0;
+ return false;
disp = op;
break;
default:
- return 0;
+ return false;
}
}
}
@@ -10193,10 +10282,10 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
index = XEXP (addr, 0);
tmp = XEXP (addr, 1);
if (!CONST_INT_P (tmp))
- return 0;
+ return false;
scale = INTVAL (tmp);
if ((unsigned HOST_WIDE_INT) scale > 3)
- return 0;
+ return false;
scale = 1 << scale;
}
else
@@ -10210,14 +10299,14 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
&& REG_P (SUBREG_REG (index)))
;
else
- return 0;
+ return false;
}
/* Extract the integral value of scale. */
if (scale_rtx)
{
if (!CONST_INT_P (scale_rtx))
- return 0;
+ return false;
scale = INTVAL (scale_rtx);
}
@@ -10270,7 +10359,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
out->scale = scale;
out->seg = seg;
- return 1;
+ return true;
}
/* Return cost of the memory address x.
@@ -10619,24 +10708,19 @@ legitimate_pic_address_disp_p (rtx disp)
if (is_imported_p (op0))
return true;
- if (SYMBOL_REF_FAR_ADDR_P (op0)
- || !SYMBOL_REF_LOCAL_P (op0))
+ if (SYMBOL_REF_FAR_ADDR_P (op0) || !SYMBOL_REF_LOCAL_P (op0))
break;
- /* Function-symbols need to be resolved only for
- large-model.
- For the small-model we don't need to resolve anything
- here. */
+ /* Non-external-weak function symbols need to be resolved only
+ for the large model. Non-external symbols don't need to be
+ resolved for large and medium models. For the small model,
+ we don't need to resolve anything here. */
if ((ix86_cmodel != CM_LARGE_PIC
- && SYMBOL_REF_FUNCTION_P (op0))
+ && SYMBOL_REF_FUNCTION_P (op0)
+ && !(SYMBOL_REF_EXTERNAL_P (op0) && SYMBOL_REF_WEAK (op0)))
+ || !SYMBOL_REF_EXTERNAL_P (op0)
|| ix86_cmodel == CM_SMALL_PIC)
return true;
- /* Non-external symbols don't need to be resolved for
- large, and medium-model. */
- if ((ix86_cmodel == CM_LARGE_PIC
- || ix86_cmodel == CM_MEDIUM_PIC)
- && !SYMBOL_REF_EXTERNAL_P (op0))
- return true;
}
else if (!SYMBOL_REF_FAR_ADDR_P (op0)
&& (SYMBOL_REF_LOCAL_P (op0)
@@ -13455,6 +13539,15 @@ ix86_print_operand (FILE *file, rtx x, int code)
(file, addr, MEM_ADDR_SPACE (x), code == 'p' || code == 'P');
}
+ else if (CONST_DOUBLE_P (x) && GET_MODE (x) == HFmode)
+ {
+ long l = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (x),
+ REAL_MODE_FORMAT (HFmode));
+ if (ASSEMBLER_DIALECT == ASM_ATT)
+ putc ('$', file);
+ fprintf (file, "0x%04x", (unsigned int) l);
+ }
+
else if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
{
long l;
@@ -13517,12 +13610,17 @@ ix86_print_operand (FILE *file, rtx x, int code)
case E_V8SFmode:
case E_V8DFmode:
case E_V8DImode:
+ case E_V8HFmode:
fputs ("{1to8}", file);
break;
case E_V16SFmode:
case E_V16SImode:
+ case E_V16HFmode:
fputs ("{1to16}", file);
break;
+ case E_V32HFmode:
+ fputs ("{1to32}", file);
+ break;
default:
gcc_unreachable ();
}
@@ -13945,7 +14043,7 @@ output_387_binary_op (rtx_insn *insn, rtx *operands)
if (is_sse)
{
- p = (GET_MODE (operands[0]) == SFmode) ? "ss" : "sd";
+ p = GET_MODE (operands[0]) == SFmode ? "ss" : "sd";
strcat (buf, p);
if (TARGET_AVX)
@@ -15463,6 +15561,9 @@ ix86_build_const_vector (machine_mode mode, bool vect, rtx value)
case E_V2DImode:
gcc_assert (vect);
/* FALLTHRU */
+ case E_V8HFmode:
+ case E_V16HFmode:
+ case E_V32HFmode:
case E_V16SFmode:
case E_V8SFmode:
case E_V4SFmode:
@@ -15501,6 +15602,13 @@ ix86_build_signbit_mask (machine_mode mode, bool vect, bool invert)
switch (mode)
{
+ case E_V8HFmode:
+ case E_V16HFmode:
+ case E_V32HFmode:
+ vec_mode = mode;
+ imode = HImode;
+ break;
+
case E_V16SImode:
case E_V16SFmode:
case E_V8SImode:
@@ -16883,6 +16991,7 @@ ix86_sched_init_global (FILE *, int, int)
case PROCESSOR_NEHALEM:
case PROCESSOR_SANDYBRIDGE:
case PROCESSOR_HASWELL:
+ case PROCESSOR_TREMONT:
case PROCESSOR_GENERIC:
/* Do not perform multipass scheduling for pre-reload schedule
to save compile time. */
@@ -19107,6 +19216,16 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
return NO_REGS;
}
+ /* Require movement to gpr, and then store to memory. */
+ if (mode == HFmode
+ && !TARGET_SSE4_1
+ && SSE_CLASS_P (rclass)
+ && !in_p && MEM_P (x))
+ {
+ sri->extra_cost = 1;
+ return GENERAL_REGS;
+ }
+
/* This condition handles corner case where an expression involving
pointers gets vectorized. We're trying to use the address of a
stack slot as a vector initializer.
@@ -19184,7 +19303,9 @@ 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))
+ && !(VECTOR_MODE_P (GET_MODE (dst))
+ ? standard_sse_constant_p (src, GET_MODE (dst))
+ : x86_64_immediate_operand (src, GET_MODE (dst)))
&& ix86_class_likely_spilled_p (REGNO_REG_CLASS (REGNO (dst)))
&& !reload_completed)
return false;
@@ -19247,10 +19368,19 @@ inline_secondary_memory_needed (machine_mode mode, reg_class_t class1,
if (!TARGET_SSE2)
return true;
+ if (!(INTEGER_CLASS_P (class1) || INTEGER_CLASS_P (class2)))
+ return true;
+
+ int msize = GET_MODE_SIZE (mode);
+
/* Between SSE and general, we have moves no larger than word size. */
- if (!(INTEGER_CLASS_P (class1) || INTEGER_CLASS_P (class2))
- || GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)
- || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ if (msize > UNITS_PER_WORD)
+ return true;
+
+ /* In addition to SImode moves, AVX512FP16 also enables HImode moves. */
+ int minsize = GET_MODE_SIZE (TARGET_AVX512FP16 ? HImode : SImode);
+
+ if (msize < minsize)
return true;
/* If the target says that inter-unit moves are more expensive
@@ -19331,8 +19461,11 @@ ix86_can_change_mode_class (machine_mode from, machine_mode to,
/* Vector registers do not support QI or HImode loads. If we don't
disallow a change to these modes, reload will assume it's ok to
drop the subreg from (subreg:SI (reg:HI 100) 0). This affects
- the vec_dupv4hi pattern. */
- if (GET_MODE_SIZE (from) < 4)
+ the vec_dupv4hi pattern.
+ NB: AVX512FP16 supports vmovw which can load 16bit data to sse
+ register. */
+ int mov_size = MAYBE_SSE_CLASS_P (regclass) && TARGET_AVX512FP16 ? 2 : 4;
+ if (GET_MODE_SIZE (from) < mov_size)
return false;
}
@@ -19344,21 +19477,27 @@ ix86_can_change_mode_class (machine_mode from, machine_mode to,
static inline int
sse_store_index (machine_mode mode)
{
- switch (GET_MODE_SIZE (mode))
- {
- case 4:
- return 0;
- case 8:
- return 1;
- case 16:
- return 2;
- case 32:
- return 3;
- case 64:
- return 4;
- default:
- return -1;
- }
+ /* NB: Use SFmode cost for HFmode instead of adding HFmode load/store
+ costs to processor_costs, which requires changes to all entries in
+ processor cost table. */
+ if (mode == E_HFmode)
+ mode = E_SFmode;
+
+ switch (GET_MODE_SIZE (mode))
+ {
+ case 4:
+ return 0;
+ case 8:
+ return 1;
+ case 16:
+ return 2;
+ case 32:
+ return 3;
+ case 64:
+ return 4;
+ default:
+ return -1;
+ }
}
/* Return the cost of moving data of mode M between a
@@ -19380,6 +19519,7 @@ static inline int
inline_memory_move_cost (machine_mode mode, enum reg_class regclass, int in)
{
int cost;
+
if (FLOAT_CLASS_P (regclass))
{
int index;
@@ -19485,11 +19625,32 @@ inline_memory_move_cost (machine_mode mode, enum reg_class regclass, int in)
}
break;
case 2:
- if (in == 2)
- return MAX (ix86_cost->hard_register.int_load[1],
- ix86_cost->hard_register.int_store[1]);
- return in ? ix86_cost->hard_register.int_load[1]
- : ix86_cost->hard_register.int_store[1];
+ {
+ int cost;
+ if (in == 2)
+ cost = MAX (ix86_cost->hard_register.int_load[1],
+ ix86_cost->hard_register.int_store[1]);
+ else
+ cost = in ? ix86_cost->hard_register.int_load[1]
+ : ix86_cost->hard_register.int_store[1];
+
+ if (mode == E_HFmode)
+ {
+ /* Prefer SSE over GPR for HFmode. */
+ int sse_cost;
+ int index = sse_store_index (mode);
+ if (in == 2)
+ sse_cost = MAX (ix86_cost->hard_register.sse_load[index],
+ ix86_cost->hard_register.sse_store[index]);
+ else
+ sse_cost = (in
+ ? ix86_cost->hard_register.sse_load [index]
+ : ix86_cost->hard_register.sse_store [index]);
+ if (sse_cost >= cost)
+ cost = sse_cost + 1;
+ }
+ return cost;
+ }
default:
if (in == 2)
cost = MAX (ix86_cost->hard_register.int_load[2],
@@ -19663,8 +19824,11 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
- XI mode
- any of 512-bit wide vector mode
- any scalar mode. */
+ /* For AVX512FP16, vmovw supports movement of HImode
+ between gpr and sse registser. */
if (TARGET_AVX512F
&& (mode == XImode
+ || mode == V32HFmode
|| VALID_AVX512F_REG_MODE (mode)
|| VALID_AVX512F_SCALAR_MODE (mode)))
return true;
@@ -19679,9 +19843,7 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
/* TODO check for QI/HI scalars. */
/* AVX512VL allows sse regs16+ for 128/256 bit modes. */
if (TARGET_AVX512VL
- && (mode == OImode
- || mode == TImode
- || VALID_AVX256_REG_MODE (mode)
+ && (VALID_AVX256_REG_OR_OI_VHF_MODE (mode)
|| VALID_AVX512VL_128_REG_MODE (mode)))
return true;
@@ -19691,9 +19853,9 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
/* OImode and AVX modes are available only when AVX is enabled. */
return ((TARGET_AVX
- && VALID_AVX256_REG_OR_OI_MODE (mode))
+ && VALID_AVX256_REG_OR_OI_VHF_MODE (mode))
|| VALID_SSE_REG_MODE (mode)
- || VALID_SSE2_REG_MODE (mode)
+ || VALID_SSE2_REG_VHF_MODE (mode)
|| VALID_MMX_REG_MODE (mode)
|| VALID_MMX_REG_MODE_3DNOW (mode));
}
@@ -19904,7 +20066,8 @@ ix86_set_reg_reg_cost (machine_mode mode)
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
- if ((TARGET_AVX512F && VALID_AVX512F_REG_MODE (mode))
+ if ((TARGET_AVX512FP16 && VALID_AVX512FP16_REG_MODE (mode))
+ || (TARGET_AVX512F && VALID_AVX512F_REG_MODE (mode))
|| (TARGET_AVX && VALID_AVX256_REG_MODE (mode))
|| (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode))
|| (TARGET_SSE && VALID_SSE_REG_MODE (mode))
@@ -19984,7 +20147,7 @@ ix86_multiplication_cost (const struct processor_costs *cost,
if (VECTOR_MODE_P (mode))
inner_mode = GET_MODE_INNER (mode);
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
return inner_mode == DFmode ? cost->mulsd : cost->mulss;
else if (X87_FLOAT_MODE_P (mode))
return cost->fmul;
@@ -20036,7 +20199,7 @@ ix86_division_cost (const struct processor_costs *cost,
if (VECTOR_MODE_P (mode))
inner_mode = GET_MODE_INNER (mode);
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
return inner_mode == DFmode ? cost->divsd : cost->divss;
else if (X87_FLOAT_MODE_P (mode))
return cost->fdiv;
@@ -20454,7 +20617,7 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
return true;
}
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
{
*total = cost->addss;
return false;
@@ -20493,7 +20656,7 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
/* FALLTHRU */
case NEG:
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
{
*total = cost->sse_op;
return false;
@@ -20575,14 +20738,14 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
return false;
case FLOAT_EXTEND:
- if (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))
+ if (!SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
*total = 0;
else
*total = ix86_vec_cost (mode, cost->addss);
return false;
case FLOAT_TRUNCATE:
- if (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))
+ if (!SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
*total = cost->fadd;
else
*total = ix86_vec_cost (mode, cost->addss);
@@ -20592,7 +20755,7 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
/* SSE requires memory load for the constant operand. It may make
sense to account for this. Of course the constant operand may or
may not be reused. */
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
*total = cost->sse_op;
else if (X87_FLOAT_MODE_P (mode))
*total = cost->fabs;
@@ -20601,7 +20764,7 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
return false;
case SQRT:
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
*total = mode == SFmode ? cost->sqrtss : cost->sqrtsd;
else if (X87_FLOAT_MODE_P (mode))
*total = cost->fsqrt;
@@ -20638,6 +20801,13 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
*total = cost->sse_op;
return true;
+ case MEM:
+ /* An insn that accesses memory is slightly more expensive
+ than one that does not. */
+ if (speed)
+ *total += 1;
+ return false;
+
default:
return false;
}
@@ -21781,10 +21951,27 @@ ix86_scalar_mode_supported_p (scalar_mode mode)
return default_decimal_float_supported_p ();
else if (mode == TFmode)
return true;
+ else if (mode == HFmode && TARGET_SSE2)
+ return true;
else
return default_scalar_mode_supported_p (mode);
}
+/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
+ if MODE is HFmode, and punt to the generic implementation otherwise. */
+
+static bool
+ix86_libgcc_floating_mode_supported_p (scalar_float_mode mode)
+{
+ /* NB: Always return TRUE for HFmode so that the _Float16 type will
+ be defined by the C front-end for AVX512FP16 intrinsics. We will
+ issue an error in ix86_expand_move for HFmode if AVX512FP16 isn't
+ enabled. */
+ return ((mode == HFmode && TARGET_SSE2)
+ ? true
+ : default_libgcc_floating_mode_supported_p (mode));
+}
+
/* Implements target hook vector_mode_supported_p. */
static bool
ix86_vector_mode_supported_p (machine_mode mode)
@@ -21800,6 +21987,8 @@ ix86_vector_mode_supported_p (machine_mode mode)
if ((TARGET_MMX || TARGET_MMX_WITH_SSE)
&& VALID_MMX_REG_MODE (mode))
return true;
+ if (TARGET_AVX512FP16 && VALID_AVX512FP16_REG_MODE (mode))
+ return true;
if ((TARGET_3DNOW || TARGET_MMX_WITH_SSE)
&& VALID_MMX_REG_MODE_3DNOW (mode))
return true;
@@ -22073,6 +22262,10 @@ ix86_mangle_type (const_tree type)
switch (TYPE_MODE (type))
{
+ case E_HFmode:
+ /* _Float16 is "DF16_".
+ Align with clang's decision in https://reviews.llvm.org/D33719. */
+ return "DF16_";
case E_TFmode:
/* __float128 is "g". */
return "g";
@@ -22096,7 +22289,7 @@ ix86_stack_protect_guard (void)
tree type = build_qualified_type (type_node, qual);
tree t;
- if (global_options_set.x_ix86_stack_protector_guard_symbol_str)
+ if (OPTION_SET_P (ix86_stack_protector_guard_symbol_str))
{
t = ix86_tls_stack_chk_guard_decl;
@@ -22476,6 +22669,20 @@ ix86_preferred_simd_mode (scalar_mode mode)
else
return V2DImode;
+ case E_HFmode:
+ if (TARGET_AVX512FP16)
+ {
+ if (TARGET_AVX512VL)
+ {
+ if (TARGET_PREFER_AVX128)
+ return V8HFmode;
+ else if (TARGET_PREFER_AVX256)
+ return V16HFmode;
+ }
+ return V32HFmode;
+ }
+ return word_mode;
+
case E_SFmode:
if (TARGET_AVX512F && !TARGET_PREFER_AVX256)
return V16SFmode;
@@ -22596,12 +22803,12 @@ ix86_max_noce_ifcvt_seq_cost (edge e)
bool predictable_p = predictable_edge_p (e);
if (predictable_p)
{
- if (global_options_set.x_param_max_rtl_if_conversion_predictable_cost)
+ if (OPTION_SET_P (param_max_rtl_if_conversion_predictable_cost))
return param_max_rtl_if_conversion_predictable_cost;
}
else
{
- if (global_options_set.x_param_max_rtl_if_conversion_unpredictable_cost)
+ if (OPTION_SET_P (param_max_rtl_if_conversion_unpredictable_cost))
return param_max_rtl_if_conversion_unpredictable_cost;
}
@@ -22696,7 +22903,7 @@ ix86_add_stmt_cost (class vec_info *vinfo, void *data, int count,
case MINUS_EXPR:
if (kind == scalar_stmt)
{
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
stmt_cost = ix86_cost->addss;
else if (X87_FLOAT_MODE_P (mode))
stmt_cost = ix86_cost->fadd;
@@ -22722,7 +22929,7 @@ ix86_add_stmt_cost (class vec_info *vinfo, void *data, int count,
break;
case NEGATE_EXPR:
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
stmt_cost = ix86_cost->sse_op;
else if (X87_FLOAT_MODE_P (mode))
stmt_cost = ix86_cost->fchs;
@@ -22778,7 +22985,7 @@ ix86_add_stmt_cost (class vec_info *vinfo, void *data, int count,
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
case BIT_NOT_EXPR:
- if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
+ if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
stmt_cost = ix86_cost->sse_op;
else if (VECTOR_MODE_P (mode))
stmt_cost = ix86_vec_cost (mode, ix86_cost->sse_op);
@@ -23384,20 +23591,24 @@ ix86_optab_supported_p (int op, machine_mode mode1, machine_mode,
return opt_type == OPTIMIZE_FOR_SPEED;
case rint_optab:
- if (SSE_FLOAT_MODE_P (mode1)
- && TARGET_SSE_MATH
- && !flag_trapping_math
- && !TARGET_SSE4_1)
+ if (mode1 == HFmode)
+ return true;
+ else if (SSE_FLOAT_MODE_P (mode1)
+ && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && !TARGET_SSE4_1)
return opt_type == OPTIMIZE_FOR_SPEED;
return true;
case floor_optab:
case ceil_optab:
case btrunc_optab:
- if (SSE_FLOAT_MODE_P (mode1)
- && TARGET_SSE_MATH
- && !flag_trapping_math
- && TARGET_SSE4_1)
+ if (mode1 == HFmode)
+ return true;
+ else if (SSE_FLOAT_MODE_P (mode1)
+ && TARGET_SSE_MATH
+ && !flag_trapping_math
+ && TARGET_SSE4_1)
return true;
return opt_type == OPTIMIZE_FOR_SPEED;
@@ -23493,14 +23704,18 @@ ix86_get_excess_precision (enum excess_precision_type type)
/* The fastest type to promote to will always be the native type,
whether that occurs with implicit excess precision or
otherwise. */
- return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+ return TARGET_AVX512FP16
+ ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+ : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
case EXCESS_PRECISION_TYPE_STANDARD:
case EXCESS_PRECISION_TYPE_IMPLICIT:
/* Otherwise, the excess precision we want when we are
in a standards compliant mode, and the implicit precision we
provide would be identical were it not for the unpredictable
cases. */
- if (!TARGET_80387)
+ if (TARGET_AVX512FP16 && TARGET_SSE_MATH)
+ return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+ else if (!TARGET_80387)
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
else if (!TARGET_MIX_SSE_I387)
{
@@ -23518,6 +23733,11 @@ ix86_get_excess_precision (enum excess_precision_type type)
return (type == EXCESS_PRECISION_TYPE_STANDARD
? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
: FLT_EVAL_METHOD_UNPREDICTABLE);
+ case EXCESS_PRECISION_TYPE_FLOAT16:
+ if (TARGET_80387
+ && !(TARGET_SSE_MATH && TARGET_SSE))
+ error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
+ return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
default:
gcc_unreachable ();
}
@@ -24067,6 +24287,10 @@ ix86_run_selftests (void)
#undef TARGET_SCALAR_MODE_SUPPORTED_P
#define TARGET_SCALAR_MODE_SUPPORTED_P ix86_scalar_mode_supported_p
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+ix86_libgcc_floating_mode_supported_p
+
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P ix86_vector_mode_supported_p
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 6511422..cba6d83 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -334,6 +334,10 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
ix86_tune_features[X86_TUNE_PARTIAL_REG_DEPENDENCY]
#define TARGET_SSE_PARTIAL_REG_DEPENDENCY \
ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY]
+#define TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY \
+ ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY]
+#define TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY \
+ ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY]
#define TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \
ix86_tune_features[X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL]
#define TARGET_SSE_UNALIGNED_STORE_OPTIMAL \
@@ -403,6 +407,10 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
ix86_tune_features[X86_TUNE_AVOID_LEA_FOR_ADDR]
#define TARGET_SOFTWARE_PREFETCHING_BENEFICIAL \
ix86_tune_features[X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL]
+#define TARGET_AVX256_MOVE_BY_PIECES \
+ ix86_tune_features[X86_TUNE_AVX256_MOVE_BY_PIECES]
+#define TARGET_AVX256_STORE_BY_PIECES \
+ ix86_tune_features[X86_TUNE_AVX256_STORE_BY_PIECES]
#define TARGET_AVX256_SPLIT_REGS \
ix86_tune_features[X86_TUNE_AVX256_SPLIT_REGS]
#define TARGET_GENERAL_REGS_SSE_SPILL \
@@ -1002,12 +1010,13 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == V4DImode || (MODE) == V2TImode || (MODE) == V8SFmode \
|| (MODE) == V4DFmode)
-#define VALID_AVX256_REG_OR_OI_MODE(MODE) \
- (VALID_AVX256_REG_MODE (MODE) || (MODE) == OImode)
+#define VALID_AVX256_REG_OR_OI_VHF_MODE(MODE) \
+ (VALID_AVX256_REG_MODE (MODE) || (MODE) == OImode || (MODE) == V16HFmode)
#define VALID_AVX512F_SCALAR_MODE(MODE) \
((MODE) == DImode || (MODE) == DFmode || (MODE) == SImode \
- || (MODE) == SFmode)
+ || (MODE) == SFmode \
+ || (TARGET_AVX512FP16 && ((MODE) == HImode || (MODE) == HFmode)))
#define VALID_AVX512F_REG_MODE(MODE) \
((MODE) == V8DImode || (MODE) == V8DFmode || (MODE) == V64QImode \
@@ -1020,12 +1029,21 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_AVX512VL_128_REG_MODE(MODE) \
((MODE) == V2DImode || (MODE) == V2DFmode || (MODE) == V16QImode \
|| (MODE) == V4SImode || (MODE) == V4SFmode || (MODE) == V8HImode \
- || (MODE) == TFmode || (MODE) == V1TImode)
+ || (MODE) == TFmode || (MODE) == V1TImode || (MODE) == V8HFmode \
+ || (MODE) == TImode)
+
+#define VALID_AVX512FP16_REG_MODE(MODE) \
+ ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode \
+ || (MODE) == V2HFmode)
#define VALID_SSE2_REG_MODE(MODE) \
((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
|| (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \
- || (MODE) == V2DImode || (MODE) == DFmode)
+ || (MODE) == V2DImode || (MODE) == DFmode || (MODE) == HFmode)
+
+#define VALID_SSE2_REG_VHF_MODE(MODE) \
+ (VALID_SSE2_REG_MODE (MODE) || (MODE) == V8HFmode \
+ || (MODE) == V4HFmode || (MODE) == V2HFmode)
#define VALID_SSE_REG_MODE(MODE) \
((MODE) == V1TImode || (MODE) == TImode \
@@ -1035,10 +1053,12 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_MMX_REG_MODE_3DNOW(MODE) \
((MODE) == V2SFmode || (MODE) == SFmode)
+/* To match ia32 psABI, V4HFmode should be added here. */
#define VALID_MMX_REG_MODE(MODE) \
((MODE) == V1DImode || (MODE) == DImode \
|| (MODE) == V2SImode || (MODE) == SImode \
- || (MODE) == V4HImode || (MODE) == V8QImode)
+ || (MODE) == V4HImode || (MODE) == V8QImode \
+ || (MODE) == V4HFmode)
#define VALID_MASK_REG_MODE(MODE) ((MODE) == HImode || (MODE) == QImode)
@@ -1046,7 +1066,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_FP_MODE_P(MODE) \
((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode \
- || (MODE) == SCmode || (MODE) == DCmode || (MODE) == XCmode) \
+ || (MODE) == SCmode || (MODE) == DCmode || (MODE) == XCmode)
#define VALID_INT_MODE_P(MODE) \
((MODE) == QImode || (MODE) == HImode \
@@ -1054,6 +1074,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == CQImode || (MODE) == CHImode \
|| (MODE) == CSImode || (MODE) == CDImode \
|| (MODE) == SDmode || (MODE) == DDmode \
+ || (MODE) == HFmode || (MODE) == HCmode \
|| (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \
|| (TARGET_64BIT \
&& ((MODE) == TImode || (MODE) == CTImode \
@@ -1070,7 +1091,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == V4DImode || (MODE) == V8SFmode || (MODE) == V4DFmode \
|| (MODE) == V2TImode || (MODE) == V8DImode || (MODE) == V64QImode \
|| (MODE) == V16SImode || (MODE) == V32HImode || (MODE) == V8DFmode \
- || (MODE) == V16SFmode)
+ || (MODE) == V16SFmode || (MODE) == V32HFmode || (MODE) == V16HFmode \
+ || (MODE) == V8HFmode)
#define X87_FLOAT_MODE_P(MODE) \
(TARGET_80387 && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode))
@@ -1078,13 +1100,18 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define SSE_FLOAT_MODE_P(MODE) \
((TARGET_SSE && (MODE) == SFmode) || (TARGET_SSE2 && (MODE) == DFmode))
+#define SSE_FLOAT_MODE_SSEMATH_OR_HF_P(MODE) \
+ ((SSE_FLOAT_MODE_P (MODE) && TARGET_SSE_MATH) \
+ || (TARGET_AVX512FP16 && (MODE) == HFmode))
+
#define FMA4_VEC_FLOAT_MODE_P(MODE) \
(TARGET_FMA4 && ((MODE) == V4SFmode || (MODE) == V2DFmode \
|| (MODE) == V8SFmode || (MODE) == V4DFmode))
#define VALID_BCST_MODE_P(MODE) \
((MODE) == SFmode || (MODE) == DFmode \
- || (MODE) == SImode || (MODE) == DImode)
+ || (MODE) == SImode || (MODE) == DImode \
+ || (MODE) == HFmode)
/* It is possible to write patterns to move flags; but until someone
does it, */
@@ -1780,8 +1807,8 @@ typedef struct ix86_args {
? 64 \
: ((TARGET_AVX \
&& !TARGET_PREFER_AVX128 \
- && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD \
- && !TARGET_AVX256_SPLIT_UNALIGNED_STORE) \
+ && (TARGET_AVX256_MOVE_BY_PIECES \
+ || TARGET_AVX256_STORE_BY_PIECES)) \
? 32 \
: ((TARGET_SSE2 \
&& TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \
@@ -1798,7 +1825,7 @@ typedef struct ix86_args {
? 64 \
: ((TARGET_AVX \
&& !TARGET_PREFER_AVX128 \
- && !TARGET_AVX256_SPLIT_UNALIGNED_STORE) \
+ && TARGET_AVX256_STORE_BY_PIECES) \
? 32 \
: ((TARGET_SSE2 \
&& TARGET_SSE_UNALIGNED_STORE_OPTIMAL) \
@@ -2294,7 +2321,7 @@ constexpr wide_int_bitmask PTA_TIGERLAKE = PTA_ICELAKE_CLIENT | PTA_MOVDIRI
constexpr 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_AVXVNNI;
+ | PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR | PTA_AVXVNNI | PTA_AVX512FP16;
constexpr wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF
| PTA_AVX512ER | PTA_AVX512F | PTA_AVX512CD | PTA_PREFETCHWT1;
constexpr wide_int_bitmask PTA_BONNELL = PTA_CORE2 | PTA_MOVBE;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 528116d..e733a40 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -117,6 +117,7 @@
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
UNSPEC_MASKMOV
+ UNSPEC_MOVCC_MASK
UNSPEC_MOVMSK
UNSPEC_BLENDV
UNSPEC_PSHUFB
@@ -125,12 +126,11 @@
UNSPEC_RSQRT
UNSPEC_PSADBW
- ;; For AVX512F support
+ ;; For AVX/AVX512F support
UNSPEC_SCALEF
+ UNSPEC_PCMP
;; Generic math support
- UNSPEC_COPYSIGN
- UNSPEC_XORSIGN
UNSPEC_IEEE_MIN ; not commutative
UNSPEC_IEEE_MAX ; not commutative
@@ -499,8 +499,8 @@
;; Main data type used by the insn
(define_attr "mode"
- "unknown,none,QI,HI,SI,DI,TI,OI,XI,SF,DF,XF,TF,V16SF,V8SF,V4DF,V4SF,
- V2DF,V2SF,V1DF,V8DF"
+ "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF,
+ V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF"
(const_string "unknown"))
;; The CPU unit operations uses.
@@ -834,9 +834,8 @@
x64_avx,x64_avx512bw,x64_avx512dq,
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,
- avxvnni,avx512vnnivl"
+ avx512bw,noavx512bw,avx512dq,noavx512dq,fma_or_avx512vl,
+ avx512vl,noavx512vl,avxvnni,avx512vnnivl,avx512fp16"
(const_string "base"))
;; Define instruction set of MMX instructions
@@ -877,6 +876,8 @@
(eq_attr "isa" "bmi2") (symbol_ref "TARGET_BMI2")
(eq_attr "isa" "fma4") (symbol_ref "TARGET_FMA4")
(eq_attr "isa" "fma") (symbol_ref "TARGET_FMA")
+ (eq_attr "isa" "fma_or_avx512vl")
+ (symbol_ref "TARGET_FMA || TARGET_AVX512VL")
(eq_attr "isa" "avx512f") (symbol_ref "TARGET_AVX512F")
(eq_attr "isa" "noavx512f") (symbol_ref "!TARGET_AVX512F")
(eq_attr "isa" "avx512bw") (symbol_ref "TARGET_AVX512BW")
@@ -888,6 +889,8 @@
(eq_attr "isa" "avxvnni") (symbol_ref "TARGET_AVXVNNI")
(eq_attr "isa" "avx512vnnivl")
(symbol_ref "TARGET_AVX512VNNI && TARGET_AVX512VL")
+ (eq_attr "isa" "avx512fp16")
+ (symbol_ref "TARGET_AVX512FP16")
(eq_attr "mmx_isa" "native")
(symbol_ref "!TARGET_MMX_WITH_SSE")
@@ -909,6 +912,7 @@
(set_attr "type" "multi")])
(define_code_iterator plusminus [plus minus])
+(define_code_iterator plusminusmultdiv [plus minus mult div])
(define_code_iterator sat_plusminus [ss_plus us_plus ss_minus us_minus])
@@ -924,7 +928,8 @@
;; Mark commutative operators as such in constraints.
(define_code_attr comm [(plus "%") (ss_plus "%") (us_plus "%")
- (minus "") (ss_minus "") (us_minus "")])
+ (minus "") (ss_minus "") (us_minus "")
+ (mult "%") (div "")])
;; Mapping of max and min
(define_code_iterator maxmin [smax smin umax umin])
@@ -1024,7 +1029,8 @@
(minus "sub") (ss_minus "sssub") (us_minus "ussub")
(sign_extend "extend") (zero_extend "zero_extend")
(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")
- (rotate "rotl") (rotatert "rotr")])
+ (rotate "rotl") (rotatert "rotr")
+ (mult "mul") (div "div")])
;; All integer modes.
(define_mode_iterator SWI1248x [QI HI SI DI])
@@ -1092,15 +1098,18 @@
;; compile time constant, it is faster to use <MODE_SIZE> than
;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on
;; command line options just use GET_MODE_SIZE macro.
-(define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8") (TI "16")
- (SF "4") (DF "8") (XF "GET_MODE_SIZE (XFmode)")
+(define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8")
+ (TI "16") (HF "2") (SF "4") (DF "8")
+ (XF "GET_MODE_SIZE (XFmode)")
(V16QI "16") (V32QI "32") (V64QI "64")
(V8HI "16") (V16HI "32") (V32HI "64")
(V4SI "16") (V8SI "32") (V16SI "64")
(V2DI "16") (V4DI "32") (V8DI "64")
(V1TI "16") (V2TI "32") (V4TI "64")
(V2DF "16") (V4DF "32") (V8DF "64")
- (V4SF "16") (V8SF "32") (V16SF "64")])
+ (V4SF "16") (V8SF "32") (V16SF "64")
+ (V8HF "16") (V16HF "32") (V32HF "64")
+ (V4HF "8") (V2HF "4")])
;; Double word integer modes as mode attribute.
(define_mode_attr DWI [(QI "HI") (HI "SI") (SI "DI") (DI "TI") (TI "OI")])
@@ -1223,19 +1232,25 @@
;; SSE and x87 SFmode and DFmode floating point modes
(define_mode_iterator MODEF [SF DF])
+;; SSE floating point modes
+(define_mode_iterator MODEFH [(HF "TARGET_AVX512FP16") SF DF])
+
;; All x87 floating point modes
(define_mode_iterator X87MODEF [SF DF XF])
+;; All x87 floating point modes plus HFmode
+(define_mode_iterator X87MODEFH [HF SF DF XF])
+
;; All SSE floating point modes
-(define_mode_iterator SSEMODEF [SF DF TF])
-(define_mode_attr ssevecmodef [(SF "V4SF") (DF "V2DF") (TF "TF")])
+(define_mode_iterator SSEMODEF [HF SF DF TF])
+(define_mode_attr ssevecmodef [(HF "V8HF") (SF "V4SF") (DF "V2DF") (TF "TF")])
;; SSE instruction suffix for various modes
(define_mode_attr ssemodesuffix
- [(SF "ss") (DF "sd")
- (V16SF "ps") (V8DF "pd")
- (V8SF "ps") (V4DF "pd")
- (V4SF "ps") (V2DF "pd")
+ [(HF "sh") (SF "ss") (DF "sd")
+ (V32HF "ph") (V16SF "ps") (V8DF "pd")
+ (V16HF "ph") (V8SF "ps") (V4DF "pd")
+ (V8HF "ph") (V4SF "ps") (V2DF "pd")
(V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")
(V32QI "b") (V16HI "w") (V8SI "d") (V4DI "q")
(V64QI "b") (V32HI "w") (V16SI "d") (V8DI "q")])
@@ -1245,7 +1260,7 @@
;; SSE vector mode corresponding to a scalar mode
(define_mode_attr ssevecmode
- [(QI "V16QI") (HI "V8HI") (SI "V4SI") (DI "V2DI") (SF "V4SF") (DF "V2DF")])
+ [(QI "V16QI") (HI "V8HI") (SI "V4SI") (DI "V2DI") (HF "V8HF") (SF "V4SF") (DF "V2DF")])
(define_mode_attr ssevecmodelower
[(QI "v16qi") (HI "v8hi") (SI "v4si") (DI "v2di") (SF "v4sf") (DF "v2df")])
@@ -1497,6 +1512,23 @@
DONE;
})
+(define_expand "cbranchhf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:HF 1 "cmp_fp_expander_operand")
+ (match_operand:HF 2 "cmp_fp_expander_operand")))
+ (set (pc) (if_then_else
+ (match_operator 0 "ix86_fp_comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3))
+ (pc)))]
+ "TARGET_AVX512FP16"
+{
+ ix86_expand_branch (GET_CODE (operands[0]),
+ operands[1], operands[2], operands[3]);
+ DONE;
+})
+
(define_expand "cbranch<mode>4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand")
@@ -1514,6 +1546,21 @@
DONE;
})
+(define_expand "cstorehf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:HF 2 "cmp_fp_expander_operand")
+ (match_operand:HF 3 "cmp_fp_expander_operand")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator 1 "ix86_fp_comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ "TARGET_AVX512FP16"
+{
+ ix86_expand_setcc (operands[0], GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ DONE;
+})
+
(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand")
@@ -1706,6 +1753,17 @@
(eq_attr "alternative" "0")
(symbol_ref "true")
(symbol_ref "false"))))])
+
+(define_insn "*cmpi<unord>hf"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (match_operand:HF 0 "register_operand" "v")
+ (match_operand:HF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "v<unord>comish\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
;; Push/pop instructions.
@@ -2437,8 +2495,8 @@
(symbol_ref "true")))])
(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"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,m ,*k,*k ,*r,*m,*k,?r,?v,*v,*v,*m")
+ (match_operand:HI 1 "general_operand" "r ,rn,rm,rn,*r,*km,*k,*k,CBC,v, r, v, m, v"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
@@ -2464,6 +2522,9 @@
gcc_unreachable ();
}
+ case TYPE_SSEMOV:
+ return ix86_output_ssemov (insn, operands);
+
case TYPE_MSKLOG:
if (operands[1] == const0_rtx)
return "kxorw\t%0, %0, %0";
@@ -2478,8 +2539,15 @@
return "mov{w}\t{%1, %0|%0, %1}";
}
}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "4,5,6,7")
+ [(set (attr "isa")
+ (cond [(eq_attr "alternative" "9,10,11,12,13")
+ (const_string "avx512fp16")
+ ]
+ (const_string "*")))
+ (set (attr "type")
+ (cond [(eq_attr "alternative" "9,10,11,12,13")
+ (const_string "ssemov")
+ (eq_attr "alternative" "4,5,6,7")
(const_string "mskmov")
(eq_attr "alternative" "8")
(const_string "msklog")
@@ -2504,6 +2572,8 @@
(set (attr "mode")
(cond [(eq_attr "type" "imovx")
(const_string "SI")
+ (eq_attr "alternative" "11")
+ (const_string "HF")
(and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand"))
(const_string "SI")
@@ -3134,6 +3204,32 @@
operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);
})
+(define_insn "*pushhf_rex64"
+ [(set (match_operand:HF 0 "push_operand" "=X,X")
+ (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))]
+ "TARGET_64BIT"
+{
+ /* Anything else should be already split before reg-stack. */
+ gcc_assert (which_alternative == 0);
+ return "push{q}\t%q1";
+}
+ [(set_attr "isa" "*,sse4")
+ (set_attr "type" "push,multi")
+ (set_attr "mode" "DI,TI")])
+
+(define_insn "*pushhf"
+ [(set (match_operand:HF 0 "push_operand" "=X,X")
+ (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))]
+ "!TARGET_64BIT"
+{
+ /* Anything else should be already split before reg-stack. */
+ gcc_assert (which_alternative == 0);
+ return "push{l}\t%k1";
+}
+ [(set_attr "isa" "*,sse4")
+ (set_attr "type" "push,multi")
+ (set_attr "mode" "SI,TI")])
+
(define_insn "*pushsf_rex64"
[(set (match_operand:SF 0 "push_operand" "=X,X,X")
(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,v"))]
@@ -3162,10 +3258,11 @@
(set_attr "unit" "i387,*,*")
(set_attr "mode" "SF,SI,SF")])
+(define_mode_iterator MODESH [SF HF])
;; %%% Kill this when call knows how to work this out.
(define_split
- [(set (match_operand:SF 0 "push_operand")
- (match_operand:SF 1 "any_fp_register_operand"))]
+ [(set (match_operand:MODESH 0 "push_operand")
+ (match_operand:MODESH 1 "any_fp_register_operand"))]
"reload_completed"
[(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2)))
(set (match_dup 0) (match_dup 1))]
@@ -3213,8 +3310,8 @@
"ix86_expand_move (TFmode, operands); DONE;")
(define_expand "mov<mode>"
- [(set (match_operand:X87MODEF 0 "nonimmediate_operand")
- (match_operand:X87MODEF 1 "general_operand"))]
+ [(set (match_operand:X87MODEFH 0 "nonimmediate_operand")
+ (match_operand:X87MODEFH 1 "general_operand"))]
""
"ix86_expand_move (<MODE>mode, operands); DONE;")
@@ -3650,6 +3747,95 @@
]
(const_string "*")))])
+(define_insn "*movhf_internal"
+ [(set (match_operand:HF 0 "nonimmediate_operand"
+ "=?r,?m,v,v,?r,m,?v,v")
+ (match_operand:HF 1 "general_operand"
+ "rmF,rF,C,v, v,v, r,m"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && (lra_in_progress
+ || reload_completed
+ || !CONST_DOUBLE_P (operands[1])
+ || (TARGET_SSE && TARGET_SSE_MATH
+ && standard_sse_constant_p (operands[1], HFmode) == 1)
+ || memory_operand (operands[0], HFmode))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_IMOV:
+ return "mov{w}\t{%1, %0|%0, %1}";
+
+ case TYPE_SSELOG1:
+ return standard_sse_constant_opcode (insn, operands);
+
+ case TYPE_SSEMOV:
+ return ix86_output_ssemov (insn, operands);
+
+ case TYPE_SSELOG:
+ if (SSE_REG_P (operands[0]))
+ return MEM_P (operands[1])
+ ? "pinsrw\t{$0, %1, %0|%0, %1, 0}"
+ : "pinsrw\t{$0, %k1, %0|%0, %k1, 0}";
+ else
+ return MEM_P (operands[1])
+ ? "pextrw\t{$0, %1, %0|%0, %1, 0}"
+ : "pextrw\t{$0, %1, %k0|%k0, %k1, 0}";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set (attr "isa")
+ (cond [(eq_attr "alternative" "2,3,4,6,7")
+ (const_string "sse2")
+ (eq_attr "alternative" "5")
+ (const_string "sse4")
+ ]
+ (const_string "*")))
+ (set (attr "type")
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "imov")
+ (eq_attr "alternative" "2")
+ (const_string "sselog1")
+ (eq_attr "alternative" "4,5,6,7")
+ (if_then_else
+ (match_test ("TARGET_AVX512FP16"))
+ (const_string "ssemov")
+ (const_string "sselog"))
+ ]
+ (const_string "ssemov")))
+ (set (attr "memory")
+ (cond [(eq_attr "alternative" "4,6")
+ (const_string "none")
+ (eq_attr "alternative" "5")
+ (const_string "store")
+ (eq_attr "alternative" "7")
+ (const_string "load")
+ ]
+ (const_string "*")))
+ (set (attr "prefix")
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "orig")
+ ]
+ (const_string "maybe_vex")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "HI")
+ (eq_attr "alternative" "2")
+ (const_string "V4SF")
+ (eq_attr "alternative" "4,5,6,7")
+ (if_then_else
+ (match_test "TARGET_AVX512FP16")
+ (const_string "HI")
+ (const_string "TI"))
+ (eq_attr "alternative" "3")
+ (if_then_else
+ (match_test "TARGET_AVX512FP16")
+ (const_string "HF")
+ (const_string "SF"))
+ ]
+ (const_string "*")))])
+
(define_split
[(set (match_operand 0 "any_fp_register_operand")
(match_operand 1 "memory_operand"))]
@@ -4369,7 +4555,8 @@
(float_extend:DF
(match_operand:SF 1 "nonimmediate_operand")))]
"!TARGET_AVX
- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
+ && TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY
+ && epilogue_completed
&& optimize_function_for_speed_p (cfun)
&& (!REG_P (operands[1])
|| (!TARGET_AVX && REGNO (operands[0]) != REGNO (operands[1])))
@@ -4387,6 +4574,17 @@
emit_move_insn (operands[0], CONST0_RTX (V2DFmode));
})
+(define_insn "extendhf<mode>2"
+ [(set (match_operand:MODEF 0 "nonimm_ssenomem_operand" "=v")
+ (float_extend:MODEF
+ (match_operand:HF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "vcvtsh2<ssemodesuffix>\t{%1, %0, %0|%0, %0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+
(define_expand "extend<mode>xf2"
[(set (match_operand:XF 0 "nonimmediate_operand")
(float_extend:XF (match_operand:MODEF 1 "general_operand")))]
@@ -4531,7 +4729,8 @@
(float_truncate:SF
(match_operand:DF 1 "nonimmediate_operand")))]
"!TARGET_AVX
- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
+ && TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY
+ && epilogue_completed
&& optimize_function_for_speed_p (cfun)
&& (!REG_P (operands[1])
|| (!TARGET_AVX && REGNO (operands[0]) != REGNO (operands[1])))
@@ -4564,6 +4763,18 @@
(symbol_ref "flag_unsafe_math_optimizations")
]
(symbol_ref "true")))])
+
+;; Conversion from {SF,DF}mode to HFmode.
+
+(define_insn "trunc<mode>hf2"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (float_truncate:HF
+ (match_operand:MODEF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "vcvt<ssemodesuffix>2sh\t{%1, %d0|%d0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
;; Signed conversion to DImode.
@@ -4602,6 +4813,16 @@
}
})
+(define_insn "fix<fixunssuffix>_trunchf<mode>2"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (any_fix:SWI48
+ (match_operand:HF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "vcvttsh2<fixsuffix>si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
;; Signed conversion to SImode.
(define_expand "fix_truncxfsi2"
@@ -4709,6 +4930,17 @@
(set_attr "prefix" "evex")
(set_attr "mode" "SI")])
+(define_insn "*fixuns_trunchfsi2zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (unsigned_fix:SI
+ (match_operand:HF 1 "nonimmediate_operand" "vm"))))]
+ "TARGET_64BIT && TARGET_AVX512FP16"
+ "vcvttsh2usi\t{%1, %k0|%k0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
(define_insn "*fixuns_trunc<mode>si2_avx512f_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
@@ -4741,6 +4973,14 @@
;; Without these patterns, we'll try the unsigned SI conversion which
;; is complex for SSE, rather than the signed SI conversion, which isn't.
+(define_expand "fixuns_trunchfhi2"
+ [(set (match_dup 2)
+ (fix:SI (match_operand:HF 1 "nonimmediate_operand")))
+ (set (match_operand:HI 0 "nonimmediate_operand")
+ (subreg:HI (match_dup 2) 0))]
+ "TARGET_AVX512FP16"
+ "operands[2] = gen_reg_rtx (SImode);")
+
(define_expand "fixuns_trunc<mode>hi2"
[(set (match_dup 2)
(fix:SI (match_operand:MODEF 1 "nonimmediate_operand")))
@@ -4940,6 +5180,16 @@
(symbol_ref "TARGET_INTER_UNIT_CONVERSIONS")]
(symbol_ref "true")))])
+(define_insn "float<floatunssuffix><mode>hf2"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (any_float:HF
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))]
+ "TARGET_AVX512FP16"
+ "vcvt<floatsuffix>si2sh<rex64suffix>\t{%1, %d0|%d0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
(define_insn "*floatdi<MODEF:mode>2_i387"
[(set (match_operand:MODEF 0 "register_operand" "=f")
(float:MODEF (match_operand:DI 1 "nonimmediate_operand" "m")))]
@@ -5044,7 +5294,8 @@
[(set (match_operand:MODEF 0 "sse_reg_operand")
(float:MODEF (match_operand:SWI48 1 "nonimmediate_operand")))]
"!TARGET_AVX
- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
+ && TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY
+ && epilogue_completed
&& optimize_function_for_speed_p (cfun)
&& (!EXT_REX_SSE_REG_P (operands[0])
|| TARGET_AVX512VL)"
@@ -5479,16 +5730,17 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*add<mode>_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (plus:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
- (match_operand:SWI12 2 "general_operand" "<r>mn")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*add<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (plus:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0,!<r>")
+ (match_operand:SWI12 2 "general_operand" "<r>mn,<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && (rtx_equal_p (operands[0], operands[1])
- || rtx_equal_p (operands[0], operands[2]))"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
{
+ if (which_alternative)
+ return "#";
+
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
@@ -5507,6 +5759,13 @@
return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (plus:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set (attr "type")
(if_then_else (match_operand:QI 2 "incdec_operand")
(const_string "incdec")
@@ -6425,15 +6684,23 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
-(define_insn "*sub<mode>_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (minus:SWI12 (match_operand:SWI12 1 "register_operand" "0")
- (match_operand:SWI12 2 "general_operand" "<r>mn")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*sub<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (minus:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")
+ (match_operand:SWI12 2 "general_operand" "<r>mn,<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && rtx_equal_p (operands[0], operands[1])"
- "sub{<imodesuffix>}\t{%2, %0|%0, %2}"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "@
+ sub{<imodesuffix>}\t{%2, %0|%0, %2}
+ #"
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (minus:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
@@ -7543,6 +7810,13 @@
(match_operand:XF 2 "register_operand")))]
"TARGET_80387")
+(define_expand "<insn>hf3"
+ [(set (match_operand:HF 0 "register_operand")
+ (plusminus:HF
+ (match_operand:HF 1 "register_operand")
+ (match_operand:HF 2 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_expand "<insn><mode>3"
[(set (match_operand:MODEF 0 "register_operand")
(plusminus:MODEF
@@ -8120,6 +8394,12 @@
(match_operand:XF 2 "register_operand")))]
"TARGET_80387")
+(define_expand "mulhf3"
+ [(set (match_operand:HF 0 "register_operand")
+ (mult:HF (match_operand:HF 1 "register_operand")
+ (match_operand:HF 2 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_expand "mul<mode>3"
[(set (match_operand:MODEF 0 "register_operand")
(mult:MODEF (match_operand:MODEF 1 "register_operand")
@@ -8137,6 +8417,12 @@
(match_operand:XF 2 "register_operand")))]
"TARGET_80387")
+(define_expand "divhf3"
+ [(set (match_operand:HF 0 "register_operand")
+ (div:HF (match_operand:HF 1 "register_operand")
+ (match_operand:HF 2 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
(define_expand "div<mode>3"
[(set (match_operand:MODEF 0 "register_operand")
(div:MODEF (match_operand:MODEF 1 "register_operand")
@@ -9336,16 +9622,23 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*and<mode>_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (and:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
- (match_operand:SWI12 2 "general_operand" "<r>mn")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*and<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (and:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0,!<r>")
+ (match_operand:SWI12 2 "general_operand" "<r>mn,<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && (rtx_equal_p (operands[0], operands[1])
- || rtx_equal_p (operands[0], operands[2]))"
- "and{<imodesuffix>}\t{%2, %0|%0, %2}"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "@
+ and{<imodesuffix>}\t{%2, %0|%0, %2}
+ #"
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (and:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
@@ -9929,19 +10222,60 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*<code><mode>_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (any_or:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
- (match_operand:SWI12 2 "general_operand" "<r>mn")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*<code><mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (any_or:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0,!<r>")
+ (match_operand:SWI12 2 "general_operand" "<r>mn,<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && (rtx_equal_p (operands[0], operands[1])
- || rtx_equal_p (operands[0], operands[2]))"
- "<logic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "@
+ <logic>{<imodesuffix>}\t{%2, %0|%0, %2}
+ #"
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (any_or:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
+;; convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate)))
+;; to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))).
+;; This eliminates sign extension after logic operation.
+
+(define_split
+ [(set (match_operand:SWI248 0 "register_operand")
+ (sign_extend:SWI248
+ (any_logic:QI (match_operand:QI 1 "memory_operand")
+ (match_operand:QI 2 "const_int_operand"))))]
+ ""
+ [(set (match_dup 3) (sign_extend:SWI248 (match_dup 1)))
+ (set (match_dup 0) (any_logic:SWI248 (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (sign_extend:SWI48
+ (any_logic:HI (match_operand:HI 1 "memory_operand")
+ (match_operand:HI 2 "const_int_operand"))))]
+ ""
+ [(set (match_dup 3) (sign_extend:SWI48 (match_dup 1)))
+ (set (match_dup 0) (any_logic:SWI48 (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (<MODE>mode);")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (sign_extend:DI
+ (any_logic:SI (match_operand:SI 1 "memory_operand")
+ (match_operand:SI 2 "const_int_operand"))))]
+ "TARGET_64BIT"
+ [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
+ (set (match_dup 0) (any_logic:DI (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (DImode);")
+
(define_insn "*<code><mode>_2"
[(set (reg FLAGS_REG)
(compare (any_or:SWI
@@ -10201,6 +10535,25 @@
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*neg<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (neg:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "@
+ neg{<imodesuffix>}\t%0
+ #"
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (neg:SWI12 (match_dup 0)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ [(set_attr "type" "negnot")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "*neg<mode>_2"
[(set (reg FLAGS_REG)
(compare
@@ -10511,6 +10864,12 @@
}
[(set_attr "isa" "noavx,noavx,avx,avx")])
+(define_expand "<code>hf2"
+ [(set (match_operand:HF 0 "register_operand")
+ (absneg:HF (match_operand:HF 1 "register_operand")))]
+ "TARGET_AVX512FP16"
+ "ix86_expand_fp_absneg_operator (<CODE>, HFmode, operands); DONE;")
+
(define_expand "<code><mode>2"
[(set (match_operand:X87MODEF 0 "register_operand")
(absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand")))]
@@ -10541,6 +10900,22 @@
[(const_int 0)]
"ix86_split_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
+(define_insn_and_split "*<code>hf2_1"
+ [(set (match_operand:HF 0 "register_operand" "=Yv")
+ (absneg:HF
+ (match_operand:HF 1 "register_operand" "Yv")))
+ (use (match_operand:V8HF 2 "vector_operand" "Yvm"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_AVX512FP16"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (<absneg_op>:V8HF (match_dup 1) (match_dup 2)))]
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], HFmode);
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], HFmode);
+})
+
(define_insn "*<code><mode>2_1"
[(set (match_operand:MODEF 0 "register_operand" "=x,x,Yv,f,!r")
(absneg:MODEF
@@ -10641,72 +11016,23 @@
(match_operand:SSEMODEF 1 "nonmemory_operand")
(match_operand:SSEMODEF 2 "register_operand")]
"(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE && (<MODE>mode == TFmode))"
+ || (TARGET_SSE && (<MODE>mode == TFmode))
+ || (TARGET_AVX512FP16 && (<MODE>mode ==HFmode))"
"ix86_expand_copysign (operands); DONE;")
-(define_insn_and_split "@copysign<mode>3_const"
- [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv")
- (unspec:SSEMODEF
- [(match_operand:<ssevecmodef> 1 "nonimm_or_0_operand" "YvmC")
- (match_operand:SSEMODEF 2 "register_operand" "0")
- (match_operand:<ssevecmodef> 3 "nonimmediate_operand" "Yvm")]
- UNSPEC_COPYSIGN))]
- "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE && (<MODE>mode == TFmode))"
- "#"
- "&& reload_completed"
- [(const_int 0)]
- "ix86_split_copysign_const (operands); DONE;")
-
-(define_insn "@copysign<mode>3_var"
- [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv")
- (unspec:SSEMODEF
- [(match_operand:SSEMODEF 2 "register_operand" "Yv,0,0,Yv,Yv")
- (match_operand:SSEMODEF 3 "register_operand" "1,1,Yv,1,Yv")
- (match_operand:<ssevecmodef> 4
- "nonimmediate_operand" "X,Yvm,Yvm,0,0")
- (match_operand:<ssevecmodef> 5
- "nonimmediate_operand" "0,Yvm,1,Yvm,1")]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:<ssevecmodef> 1 "=Yv,Yv,Yv,Yv,Yv"))]
- "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE && (<MODE>mode == TFmode))"
- "#")
-
-(define_split
- [(set (match_operand:SSEMODEF 0 "register_operand")
- (unspec:SSEMODEF
- [(match_operand:SSEMODEF 2 "register_operand")
- (match_operand:SSEMODEF 3 "register_operand")
- (match_operand:<ssevecmodef> 4)
- (match_operand:<ssevecmodef> 5)]
- UNSPEC_COPYSIGN))
- (clobber (match_scratch:<ssevecmodef> 1))]
- "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || (TARGET_SSE && (<MODE>mode == TFmode)))
- && reload_completed"
- [(const_int 0)]
- "ix86_split_copysign_var (operands); DONE;")
-
(define_expand "xorsign<mode>3"
- [(match_operand:MODEF 0 "register_operand")
- (match_operand:MODEF 1 "register_operand")
- (match_operand:MODEF 2 "register_operand")]
- "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
- "ix86_expand_xorsign (operands); DONE;")
-
-(define_insn_and_split "@xorsign<mode>3_1"
- [(set (match_operand:MODEF 0 "register_operand" "=Yv")
- (unspec:MODEF
- [(match_operand:MODEF 1 "register_operand" "Yv")
- (match_operand:MODEF 2 "register_operand" "0")
- (match_operand:<ssevecmode> 3 "nonimmediate_operand" "Yvm")]
- UNSPEC_XORSIGN))]
- "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
- "#"
- "&& reload_completed"
- [(const_int 0)]
- "ix86_split_xorsign (operands); DONE;")
+ [(match_operand:MODEFH 0 "register_operand")
+ (match_operand:MODEFH 1 "register_operand")
+ (match_operand:MODEFH 2 "register_operand")]
+ "(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || <MODE>mode == HFmode"
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
+ else
+ ix86_expand_xorsign (operands);
+ DONE;
+})
;; One complement instructions
@@ -10783,6 +11109,22 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*one_cmpl<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (not:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")))]
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
+ "@
+ not{<imodesuffix>}\t%0
+ #"
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (set (strict_low_part (match_dup 0))
+ (not:SWI12 (match_dup 0)))]
+ ""
+ [(set_attr "type" "negnot")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "*one_cmpl<mode>2_2"
[(set (reg FLAGS_REG)
(compare (not:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))
@@ -11361,15 +11703,17 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*ashl<mode>3_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (ashift:SWI12 (match_operand:SWI12 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "cI")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*ashl<mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (ashift:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")
+ (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && rtx_equal_p (operands[0], operands[1])"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
{
+ if (which_alternative)
+ return "#";
+
switch (get_attr_type (insn))
{
case TYPE_ALU:
@@ -11384,6 +11728,13 @@
return "sal{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (ashift:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set (attr "type")
(cond [(and (match_test "TARGET_DOUBLE_WITH_ADD")
(match_operand 2 "const1_operand"))
@@ -12079,21 +12430,30 @@
(const_string "*")))
(set_attr "mode" "HI")])
-(define_insn "*<insn><mode>3_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (any_shiftrt:SWI12 (match_operand:SWI12 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "cI")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*<insn><mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (any_shiftrt:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")
+ (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && rtx_equal_p (operands[0], operands[1])"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
{
+ if (which_alternative)
+ return "#";
+
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
return "<shift>{<imodesuffix>}\t%0";
else
return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (any_shiftrt:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set_attr "type" "ishift")
(set (attr "length_immediate")
(if_then_else
@@ -12537,21 +12897,30 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "*<insn><mode>3_1_slp"
- [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
- (any_rotate:SWI12 (match_operand:SWI12 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "cI")))
+;; Alternative 1 is needed to work around LRA limitation, see PR82524.
+(define_insn_and_split "*<insn><mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>,<r>"))
+ (any_rotate:SWI12 (match_operand:SWI12 1 "register_operand" "0,!<r>")
+ (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
(clobber (reg:CC FLAGS_REG))]
- "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- /* FIXME: without this LRA can't reload this pattern, see PR82524. */
- && rtx_equal_p (operands[0], operands[1])"
+ "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
{
+ if (which_alternative)
+ return "#";
+
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
return "<rotate>{<imodesuffix>}\t%0";
else
return "<rotate>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
+ "&& reload_completed"
+ [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (parallel
+ [(set (strict_low_part (match_dup 0))
+ (any_rotate:SWI12 (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
[(set_attr "type" "rotate")
(set (attr "length_immediate")
(if_then_else
@@ -13333,6 +13702,20 @@
(set_attr "length_immediate" "1")
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<MODE>")])
+
+(define_insn "setcc_hf_mask"
+ [(set (match_operand:QI 0 "register_operand" "=k")
+ (unspec:QI
+ [(match_operand:HF 1 "register_operand" "v")
+ (match_operand:HF 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_31_operand" "n")]
+ UNSPEC_PCMP))]
+ "TARGET_AVX512FP16"
+ "vcmpsh\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
;; Basic conditional jump instructions.
@@ -16556,6 +16939,17 @@
(symbol_ref "true")
(symbol_ref "false"))))])
+(define_insn "*<insn>hf"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (plusminusmultdiv:HF
+ (match_operand:HF 1 "nonimmediate_operand" "<comm>v")
+ (match_operand:HF 2 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16
+ && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "v<insn>sh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
(define_insn "*rcpsf2_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x,x")
(unspec:SF [(match_operand:SF 1 "nonimmediate_operand" "0,x,m")]
@@ -16836,6 +17230,19 @@
DONE;
})
+(define_insn "sqrthf2"
+ [(set (match_operand:HF 0 "register_operand" "=v,v")
+ (sqrt:HF
+ (match_operand:HF 1 "nonimmediate_operand" "v,m")))]
+ "TARGET_AVX512FP16"
+ "@
+ vsqrtsh\t{%d1, %0|%0, %d1}
+ vsqrtsh\t{%1, %d0|%d0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "avx_partial_xmm_update" "false,true")
+ (set_attr "mode" "HF")])
+
(define_insn "*sqrt<mode>2_sse"
[(set (match_operand:MODEF 0 "register_operand" "=v,v,v")
(sqrt:MODEF
@@ -18015,9 +18422,9 @@
(define_insn "sse4_1_round<mode>2"
- [(set (match_operand:MODEF 0 "register_operand" "=x,x,x,v,v")
- (unspec:MODEF
- [(match_operand:MODEF 1 "nonimmediate_operand" "0,x,m,v,m")
+ [(set (match_operand:MODEFH 0 "register_operand" "=x,x,x,v,v")
+ (unspec:MODEFH
+ [(match_operand:MODEFH 1 "nonimmediate_operand" "0,x,m,v,m")
(match_operand:SI 2 "const_0_to_15_operand" "n,n,n,n,n")]
UNSPEC_ROUND))]
"TARGET_SSE4_1"
@@ -18052,6 +18459,17 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
+(define_expand "rinthf2"
+ [(match_operand:HF 0 "register_operand")
+ (match_operand:HF 1 "nonimmediate_operand")]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0],
+ operands[1],
+ GEN_INT (ROUND_MXCSR)));
+ DONE;
+})
+
(define_expand "rint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "nonimmediate_operand"))]
@@ -18085,6 +18503,17 @@
"TARGET_USE_FANCY_MATH_387
&& !flag_trapping_math")
+(define_expand "nearbyinthf2"
+ [(match_operand:HF 0 "register_operand")
+ (match_operand:HF 1 "nonimmediate_operand")]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0],
+ operands[1],
+ GEN_INT (ROUND_MXCSR | ROUND_NO_EXC)));
+ DONE;
+})
+
(define_expand "nearbyint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "nonimmediate_operand"))]
@@ -18274,6 +18703,18 @@
"TARGET_USE_FANCY_MATH_387
&& (flag_fp_int_builtin_inexact || !flag_trapping_math)")
+(define_expand "<rounding_insn>hf2"
+ [(parallel [(set (match_operand:HF 0 "register_operand")
+ (unspec:HF [(match_operand:HF 1 "register_operand")]
+ FRNDINT_ROUNDING))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_AVX512FP16"
+{
+ emit_insn (gen_sse4_1_roundhf2 (operands[0], operands[1],
+ GEN_INT (ROUND_<ROUNDING> | ROUND_NO_EXC)));
+ DONE;
+})
+
(define_expand "<rounding_insn><mode>2"
[(parallel [(set (match_operand:MODEF 0 "register_operand")
(unspec:MODEF [(match_operand:MODEF 1 "register_operand")]
@@ -19508,6 +19949,31 @@
operands[9] = replace_rtx (operands[6], operands[0], operands[1], true);
})
+(define_insn "movhf_mask"
+ [(set (match_operand:HF 0 "nonimmediate_operand" "=v,m,v")
+ (unspec:HF
+ [(match_operand:HF 1 "nonimmediate_operand" "m,v,v")
+ (match_operand:HF 2 "nonimm_or_0_operand" "0C,0C,0C")
+ (match_operand:QI 3 "register_operand" "Yk,Yk,Yk")]
+ UNSPEC_MOVCC_MASK))]
+ "TARGET_AVX512FP16"
+ "@
+ vmovsh\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}
+ vmovsh\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}
+ vmovsh\t{%d1, %0%{%3%}%N2|%0%{%3%}%N2, %d1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
+(define_expand "movhfcc"
+ [(set (match_operand:HF 0 "register_operand")
+ (if_then_else:HF
+ (match_operand 1 "comparison_operator")
+ (match_operand:HF 2 "register_operand")
+ (match_operand:HF 3 "register_operand")))]
+ "TARGET_AVX512FP16"
+ "if (ix86_expand_fp_movcc (operands)) DONE; else FAIL;")
+
(define_expand "mov<mode>cc"
[(set (match_operand:X87MODEF 0 "register_operand")
(if_then_else:X87MODEF
@@ -19668,12 +20134,35 @@
(set_attr "type" "sseadd")
(set_attr "mode" "<MODE>")])
+(define_insn "<code>hf3"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (smaxmin:HF
+ (match_operand:HF 1 "nonimmediate_operand" "%v")
+ (match_operand:HF 2 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "v<maxmin_float>sh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "type" "sseadd")
+ (set_attr "mode" "HF")])
+
;; These versions of the min/max patterns implement exactly the operations
;; min = (op1 < op2 ? op1 : op2)
;; max = (!(op1 < op2) ? op1 : op2)
;; Their operands are not commutative, and thus they may be used in the
;; presence of -0.0 and NaN.
+(define_insn "*ieee_s<ieee_maxmin>hf3"
+ [(set (match_operand:HF 0 "register_operand" "=v")
+ (unspec:HF
+ [(match_operand:HF 1 "register_operand" "v")
+ (match_operand:HF 2 "nonimmediate_operand" "vm")]
+ IEEE_MAXMIN))]
+ "TARGET_AVX512FP16"
+ "v<ieee_maxmin>sh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "type" "sseadd")
+ (set_attr "mode" "HF")])
+
(define_insn "*ieee_s<ieee_maxmin><mode>3"
[(set (match_operand:MODEF 0 "register_operand" "=x,v")
(unspec:MODEF
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 7b8547b..ad36697 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1166,3 +1166,7 @@ Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property.
mmwait
Target Mask(ISA2_MWAIT) Var(ix86_isa_flags2) Save
Support MWAIT and MONITOR built-in functions and code generation.
+
+mavx512fp16
+Target Mask(ISA2_AVX512FP16) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512FP16 built-in functions and code generation.
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index f129de4..1761c75 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -94,6 +94,12 @@
#include <avx512vp2intersectvlintrin.h>
+#ifdef __SSE2__
+#include <avx512fp16intrin.h>
+
+#include <avx512fp16vlintrin.h>
+#endif
+
#include <shaintrin.h>
#include <fmaintrin.h>
diff --git a/gcc/config/i386/lynx.h b/gcc/config/i386/lynx.h
index 70b2587..65fc6a7 100644
--- a/gcc/config/i386/lynx.h
+++ b/gcc/config/i386/lynx.h
@@ -60,10 +60,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_OUTPUT_ALIGN
-/* Undefine the definition from elfos.h to enable our default. */
-
-#undef PREFERRED_DEBUGGING_TYPE
-
/* The file i386.c defines TARGET_HAVE_TLS unconditionally if
HAVE_AS_TLS is defined. HAVE_AS_TLS is defined as gas support for
TLS is detected by configure. We undefine it here. */
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 2d3b63f..6c5cbcf 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -48,7 +48,7 @@
(define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI (V1DI "TARGET_SSE2")])
;; All 8-byte vector modes handled by MMX
-(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF])
+(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF V4HF])
(define_mode_iterator MMXMODE124 [V8QI V4HI V2SI V2SF])
;; Mix-n-match
@@ -57,8 +57,8 @@
(define_mode_iterator MMXMODE24 [V4HI V2SI])
(define_mode_iterator MMXMODE248 [V4HI V2SI V1DI])
-;; All 4-byte integer vector modes
-(define_mode_iterator V_32 [V4QI V2HI V1SI])
+;; All 4-byte integer/float16 vector modes
+(define_mode_iterator V_32 [V4QI V2HI V1SI V2HF])
;; 4-byte integer vector modes
(define_mode_iterator VI_32 [V4QI V2HI])
@@ -66,6 +66,9 @@
;; V2S* modes
(define_mode_iterator V2FI [V2SF V2SI])
+;; 4-byte and 8-byte float16 vector modes
+(define_mode_iterator VHF_32_64 [V4HF V2HF])
+
;; Mapping from integer vector mode to mnemonic suffix
(define_mode_attr mmxvecsize
[(V8QI "b") (V4QI "b") (V4HI "w") (V2HI "w") (V2SI "d") (V1DI "q")])
@@ -191,6 +194,8 @@
(eq_attr "alternative" "11,12")
(cond [(match_test "<MODE>mode == V2SFmode")
(const_string "V4SF")
+ (match_test "<MODE>mode == V4HFmode")
+ (const_string "V4SF")
(ior (not (match_test "TARGET_SSE2"))
(match_test "optimize_function_for_size_p (cfun)"))
(const_string "V4SF")
@@ -198,14 +203,16 @@
(const_string "TI"))
(and (eq_attr "alternative" "13")
- (ior (and (match_test "<MODE>mode == V2SFmode")
- (not (match_test "TARGET_MMX_WITH_SSE")))
- (not (match_test "TARGET_SSE2"))))
+ (ior (ior (and (match_test "<MODE>mode == V2SFmode")
+ (not (match_test "TARGET_MMX_WITH_SSE")))
+ (not (match_test "TARGET_SSE2")))
+ (match_test "<MODE>mode == V4HFmode")))
(const_string "V2SF")
(and (eq_attr "alternative" "14")
- (ior (match_test "<MODE>mode == V2SFmode")
- (not (match_test "TARGET_SSE2"))))
+ (ior (ior (match_test "<MODE>mode == V2SFmode")
+ (not (match_test "TARGET_SSE2")))
+ (match_test "<MODE>mode == V4HFmode")))
(const_string "V2SF")
]
(const_string "DI")))
@@ -289,12 +296,17 @@
(const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "2,3")
- (cond [(match_test "TARGET_AVX")
+ (cond [(match_test "<MODE>mode == V2HFmode")
+ (const_string "V4SF")
+ (match_test "TARGET_AVX")
(const_string "TI")
(match_test "optimize_function_for_size_p (cfun)")
(const_string "V4SF")
]
(const_string "TI"))
+ (and (eq_attr "alternative" "4,5")
+ (match_test "<MODE>mode == V2HFmode"))
+ (const_string "SF")
]
(const_string "SI")))
(set (attr "preferred_for_speed")
@@ -1019,12 +1031,13 @@
(match_operand:V2SF 1 "register_operand" "%0,v,x")
(match_operand:V2SF 2 "register_operand" "v,v,x")
(match_operand:V2SF 3 "register_operand" "v,0,x")))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfmadd132ps\t{%2, %3, %0|%0, %3, %2}
vfmadd231ps\t{%2, %1, %0|%0, %1, %2}
vfmaddps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1035,12 +1048,13 @@
(match_operand:V2SF 2 "register_operand" "v,v,x")
(neg:V2SF
(match_operand:V2SF 3 "register_operand" "v,0,x"))))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfmsub132ps\t{%2, %3, %0|%0, %3, %2}
vfmsub231ps\t{%2, %1, %0|%0, %1, %2}
vfmsubps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1051,12 +1065,13 @@
(match_operand:V2SF 1 "register_operand" "%0,v,x"))
(match_operand:V2SF 2 "register_operand" "v,v,x")
(match_operand:V2SF 3 "register_operand" "v,0,x")))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfnmadd132ps\t{%2, %3, %0|%0, %3, %2}
vfnmadd231ps\t{%2, %1, %0|%0, %1, %2}
vfnmaddps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1068,12 +1083,13 @@
(match_operand:V2SF 2 "register_operand" "v,v,x")
(neg:V2SF
(match_operand:V2SF 3 "register_operand" "v,0,x"))))]
- "(TARGET_FMA || TARGET_FMA4) && TARGET_MMX_WITH_SSE"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL)
+ && TARGET_MMX_WITH_SSE"
"@
vfnmsub132ps\t{%2, %3, %0|%0, %3, %2}
vfnmsub231ps\t{%2, %1, %0|%0, %1, %2}
vfnmsubps\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "isa" "fma,fma,fma4")
+ [(set_attr "isa" "fma_or_avx512vl,fma_or_avx512vl,fma4")
(set_attr "type" "ssemuladd")
(set_attr "mode" "V4SF")])
@@ -1389,6 +1405,28 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
+;; Parallel half-precision floating point arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "<insn><mode>3"
+ [(set (match_operand:VHF_32_64 0 "register_operand" "=v")
+ (plusminusmultdiv:VHF_32_64
+ (match_operand:VHF_32_64 1 "register_operand" "<comm>v")
+ (match_operand:VHF_32_64 2 "register_operand" "v")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "v<insn>ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set (attr "type")
+ (cond [(match_test "<CODE> == MULT")
+ (const_string "ssemul")
+ (match_test "<CODE> == DIV")
+ (const_string "ssediv")]
+ (const_string "sseadd")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8HF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
;; Parallel integral arithmetic
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3927,6 +3965,87 @@
DONE;
})
+(define_expand "reduc_plus_scal_v4hi"
+ [(plus:V4HI
+ (match_operand:HI 0 "register_operand")
+ (match_operand:V4HI 1 "register_operand"))]
+ "TARGET_MMX_WITH_SSE"
+{
+ rtx tmp = gen_reg_rtx (V4HImode);
+ ix86_expand_reduc (gen_addv4hi3, tmp, operands[1]);
+ emit_insn (gen_vec_extractv4hihi (operands[0], tmp, const0_rtx));
+ DONE;
+})
+
+(define_expand "reduc_<code>_scal_v4hi"
+ [(smaxmin:V4HI
+ (match_operand:HI 0 "register_operand")
+ (match_operand:V4HI 1 "register_operand"))]
+ "TARGET_MMX_WITH_SSE"
+{
+ rtx tmp = gen_reg_rtx (V4HImode);
+ ix86_expand_reduc (gen_<code>v4hi3, tmp, operands[1]);
+ emit_insn (gen_vec_extractv4hihi (operands[0], tmp, const0_rtx));
+ DONE;
+})
+
+(define_expand "reduc_<code>_scal_v4qi"
+ [(smaxmin:V4QI
+ (match_operand:QI 0 "register_operand")
+ (match_operand:V4QI 1 "register_operand"))]
+ "TARGET_SSE4_1"
+{
+ rtx tmp = gen_reg_rtx (V4QImode);
+ ix86_expand_reduc (gen_<code>v4qi3, tmp, operands[1]);
+ emit_insn (gen_vec_extractv4qiqi (operands[0], tmp, const0_rtx));
+ DONE;
+})
+
+(define_expand "reduc_<code>_scal_v4hi"
+ [(umaxmin:V4HI
+ (match_operand:HI 0 "register_operand")
+ (match_operand:V4HI 1 "register_operand"))]
+ "TARGET_MMX_WITH_SSE && TARGET_SSE4_1"
+{
+ rtx tmp = gen_reg_rtx (V4HImode);
+ ix86_expand_reduc (gen_<code>v4hi3, tmp, operands[1]);
+ emit_insn (gen_vec_extractv4hihi (operands[0], tmp, const0_rtx));
+ DONE;
+})
+
+(define_expand "reduc_<code>_scal_v4qi"
+ [(umaxmin:V4QI
+ (match_operand:QI 0 "register_operand")
+ (match_operand:V4QI 1 "register_operand"))]
+ "TARGET_SSE4_1"
+{
+ rtx tmp = gen_reg_rtx (V4QImode);
+ ix86_expand_reduc (gen_<code>v4qi3, tmp, operands[1]);
+ emit_insn (gen_vec_extractv4qiqi (operands[0], tmp, const0_rtx));
+ DONE;
+})
+
+(define_expand "reduc_plus_scal_v4qi"
+ [(plus:V4QI
+ (match_operand:QI 0 "register_operand")
+ (match_operand:V4QI 1 "register_operand"))]
+ "TARGET_SSE2"
+{
+ rtx op1 = gen_reg_rtx (V16QImode);
+ emit_insn (gen_vec_setv4si_0 (lowpart_subreg (V4SImode, op1, V16QImode),
+ CONST0_RTX (V4SImode),
+ lowpart_subreg (SImode,
+ operands[1],
+ V4QImode)));
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, CONST0_RTX (V16QImode));
+ rtx tmp2 = gen_reg_rtx (V2DImode);
+ emit_insn (gen_sse2_psadbw (tmp2, op1, tmp));
+ tmp2 = gen_lowpart (V16QImode, tmp2);
+ emit_insn (gen_vec_extractv16qiqi (operands[0], tmp2, const0_rtx));
+ DONE;
+})
+
(define_expand "usadv8qi"
[(match_operand:V2SI 0 "register_operand")
(match_operand:V8QI 1 "register_operand")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ac0c463..fbf056b 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -67,7 +67,6 @@
UNSPEC_PCLMUL
;; For AVX support
- UNSPEC_PCMP
UNSPEC_VPERMIL
UNSPEC_VPERMIL2
UNSPEC_VPERMIL2F128
@@ -100,8 +99,6 @@
UNSPEC_COMPRESS
UNSPEC_COMPRESS_STORE
UNSPEC_EXPAND
- UNSPEC_MASKED_EQ
- UNSPEC_MASKED_GT
;; Mask operations
UNSPEC_MASKOP
@@ -193,6 +190,14 @@
UNSPEC_VCVTNE2PS2BF16
UNSPEC_VCVTNEPS2BF16
UNSPEC_VDPBF16PS
+
+ ;; For AVX512FP16 suppport
+ UNSPEC_COMPLEX_FMA
+ UNSPEC_COMPLEX_FCMA
+ UNSPEC_COMPLEX_FMUL
+ UNSPEC_COMPLEX_FCMUL
+ UNSPEC_COMPLEX_MASK
+
])
(define_c_enum "unspecv" [
@@ -224,21 +229,45 @@
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
(V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX") V1TI
+ (V32HF "TARGET_AVX512F") (V16HF "TARGET_AVX") V8HF
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
-;; All AVX-512{F,VL} vector modes. Supposed TARGET_AVX512F baseline.
+;; All AVX-512{F,VL} vector modes without HF. Supposed TARGET_AVX512F baseline.
(define_mode_iterator V48_AVX512VL
[V16SI (V8SI "TARGET_AVX512VL") (V4SI "TARGET_AVX512VL")
V8DI (V4DI "TARGET_AVX512VL") (V2DI "TARGET_AVX512VL")
V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
+(define_mode_iterator V48_256_512_AVX512VL
+ [V16SI (V8SI "TARGET_AVX512VL")
+ V8DI (V4DI "TARGET_AVX512VL")
+ V16SF (V8SF "TARGET_AVX512VL")
+ V8DF (V4DF "TARGET_AVX512VL")])
+
+;; All AVX-512{F,VL} vector modes. Supposed TARGET_AVX512F baseline.
+(define_mode_iterator V48H_AVX512VL
+ [V16SI (V8SI "TARGET_AVX512VL") (V4SI "TARGET_AVX512VL")
+ V8DI (V4DI "TARGET_AVX512VL") (V2DI "TARGET_AVX512VL")
+ (V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
+ V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
+
;; 1,2 byte AVX-512{BW,VL} vector modes. Supposed TARGET_AVX512BW baseline.
(define_mode_iterator VI12_AVX512VL
[V64QI (V16QI "TARGET_AVX512VL") (V32QI "TARGET_AVX512VL")
V32HI (V16HI "TARGET_AVX512VL") (V8HI "TARGET_AVX512VL")])
+(define_mode_iterator VI12HF_AVX512VL
+ [V64QI (V16QI "TARGET_AVX512VL") (V32QI "TARGET_AVX512VL")
+ V32HI (V16HI "TARGET_AVX512VL") (V8HI "TARGET_AVX512VL")
+ (V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")])
+
;; Same iterator, but without supposed TARGET_AVX512BW
(define_mode_iterator VI12_AVX512VLBW
[(V64QI "TARGET_AVX512BW") (V16QI "TARGET_AVX512VL")
@@ -254,6 +283,8 @@
(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V32HF "TARGET_AVX512FP16") (V16HF "TARGET_AVX512FP16")
+ (V8HF "TARGET_AVX512FP16")
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
@@ -265,6 +296,10 @@
(define_mode_iterator V_256
[V32QI V16HI V8SI V4DI V8SF V4DF])
+;; All 256bit vector modes including HF vector mode
+(define_mode_iterator V_256H
+ [V32QI V16HI V8SI V4DI V8SF V4DF V16HF])
+
;; All 128bit and 256bit vector modes
(define_mode_iterator V_128_256
[V32QI V16QI V16HI V8HI V8SI V4SI V4DI V2DI V8SF V4SF V4DF V2DF])
@@ -276,18 +311,41 @@
(define_mode_iterator V_256_512
[V32QI V16HI V8SI V4DI V8SF V4DF
(V64QI "TARGET_AVX512F") (V32HI "TARGET_AVX512F") (V16SI "TARGET_AVX512F")
- (V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")])
+ (V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")
+ (V16HF "TARGET_AVX512FP16") (V32HF "TARGET_AVX512FP16")])
;; All vector float modes
(define_mode_iterator VF
[(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+(define_mode_iterator VFH
+ [(V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+
+;; 128-, 256- and 512-bit float vector modes for bitwise operations
+(define_mode_iterator VFB
+ [(V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16")
+ (V8HF "TARGET_AVX512FP16")
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+
;; 128- and 256-bit float vector modes
(define_mode_iterator VF_128_256
[(V8SF "TARGET_AVX") V4SF
(V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+;; 128- and 256-bit float vector modes for bitwise operations
+(define_mode_iterator VFB_128_256
+ [(V16HF "TARGET_AVX512FP16")
+ (V8HF "TARGET_AVX512FP16")
+ (V8SF "TARGET_AVX") V4SF
+ (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+
;; All SFmode vector float modes
(define_mode_iterator VF1
[(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF])
@@ -306,6 +364,13 @@
(define_mode_iterator VF2
[(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
+;; All DFmode & HFmode vector float modes
+(define_mode_iterator VF2H
+ [(V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
+
;; 128- and 256-bit DF vector modes
(define_mode_iterator VF2_128_256
[(V4DF "TARGET_AVX") V2DF])
@@ -316,10 +381,15 @@
(define_mode_iterator VF2_512_256VL
[V8DF (V4DF "TARGET_AVX512VL")])
-;; All 128bit vector float modes
+;; All 128bit vector SF/DF modes
(define_mode_iterator VF_128
[V4SF (V2DF "TARGET_SSE2")])
+;; All 128bit vector HF/SF/DF modes
+(define_mode_iterator VFH_128
+ [(V8HF "TARGET_AVX512FP16")
+ V4SF (V2DF "TARGET_SSE2")])
+
;; All 256bit vector float modes
(define_mode_iterator VF_256
[V8SF V4DF])
@@ -328,6 +398,10 @@
(define_mode_iterator VF_512
[V16SF V8DF])
+;; All 512bit vector float modes for bitwise operations
+(define_mode_iterator VFB_512
+ [(V32HF "TARGET_AVX512FP16") V16SF V8DF])
+
(define_mode_iterator VI48_AVX512VL
[V16SI (V8SI "TARGET_AVX512VL") (V4SI "TARGET_AVX512VL")
V8DI (V4DI "TARGET_AVX512VL") (V2DI "TARGET_AVX512VL")])
@@ -348,12 +422,25 @@
(define_mode_iterator VF1_AVX512ER_128_256
[(V16SF "TARGET_AVX512ER") (V8SF "TARGET_AVX") V4SF])
+(define_mode_iterator VFH_AVX512VL
+ [(V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
+ V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
+
(define_mode_iterator VF2_AVX512VL
[V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
(define_mode_iterator VF1_AVX512VL
[V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")])
+(define_mode_iterator VF_AVX512FP16
+ [V32HF V16HF V8HF])
+
+(define_mode_iterator VF_AVX512FP16VL
+ [V32HF (V16HF "TARGET_AVX512VL") (V8HF "TARGET_AVX512VL")])
+
;; All vector integer modes
(define_mode_iterator VI
[(V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")
@@ -362,6 +449,15 @@
(V8SI "TARGET_AVX") V4SI
(V4DI "TARGET_AVX") V2DI])
+;; All vector integer and HF modes
+(define_mode_iterator VIHF
+ [(V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")
+ (V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX") V16QI
+ (V32HI "TARGET_AVX512BW") (V16HI "TARGET_AVX") V8HI
+ (V8SI "TARGET_AVX") V4SI
+ (V4DI "TARGET_AVX") V2DI
+ (V32HF "TARGET_AVX512BW") (V16HF "TARGET_AVX") V8HF])
+
(define_mode_iterator VI_AVX2
[(V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX2") V16QI
(V32HI "TARGET_AVX512BW") (V16HI "TARGET_AVX2") V8HI
@@ -433,6 +529,11 @@
(define_mode_iterator VI2_AVX512VL
[(V8HI "TARGET_AVX512VL") (V16HI "TARGET_AVX512VL") V32HI])
+(define_mode_iterator VI2H_AVX512VL
+ [(V8HI "TARGET_AVX512VL") (V16HI "TARGET_AVX512VL") V32HI
+ (V8SI "TARGET_AVX512VL") V16SI
+ V8DI ])
+
(define_mode_iterator VI1_AVX512VL_F
[V32QI (V16QI "TARGET_AVX512VL") (V64QI "TARGET_AVX512F")])
@@ -562,6 +663,9 @@
(V4SI "TARGET_AVX2") (V2DI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")])
+(define_mode_iterator VF4_128_8_256
+ [V4DF V4SF])
+
(define_mode_iterator VI1_AVX512VLBW
[(V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX512VL")
(V16QI "TARGET_AVX512VL")])
@@ -571,6 +675,7 @@
(V8HI "avx512vl") (V16HI "avx512vl") (V32HI "avx512bw")
(V4SI "avx512vl") (V8SI "avx512vl") (V16SI "avx512f")
(V2DI "avx512vl") (V4DI "avx512vl") (V8DI "avx512f")
+ (V8HF "avx512fp16") (V16HF "avx512vl") (V32HF "avx512bw")
(V4SF "avx512vl") (V8SF "avx512vl") (V16SF "avx512f")
(V2DF "avx512vl") (V4DF "avx512vl") (V8DF "avx512f")])
@@ -631,12 +736,13 @@
(V8HI "avx512vl") (V16HI "avx512vl") (V32HI "avx512bw")])
(define_mode_attr shuffletype
- [(V16SF "f") (V16SI "i") (V8DF "f") (V8DI "i")
- (V8SF "f") (V8SI "i") (V4DF "f") (V4DI "i")
- (V4SF "f") (V4SI "i") (V2DF "f") (V2DI "i")
- (V32HI "i") (V16HI "i") (V8HI "i")
- (V64QI "i") (V32QI "i") (V16QI "i")
- (V4TI "i") (V2TI "i") (V1TI "i")])
+ [(V32HF "f") (V16HF "f") (V8HF "f")
+ (V16SF "f") (V16SI "i") (V8DF "f") (V8DI "i")
+ (V8SF "f") (V8SI "i") (V4DF "f") (V4DI "i")
+ (V4SF "f") (V4SI "i") (V2DF "f") (V2DI "i")
+ (V32HI "i") (V16HI "i") (V8HI "i")
+ (V64QI "i") (V32QI "i") (V16QI "i")
+ (V4TI "i") (V2TI "i") (V1TI "i")])
(define_mode_attr ssequartermode
[(V16SF "V4SF") (V8DF "V2DF") (V16SI "V4SI") (V8DI "V2DI")])
@@ -645,7 +751,8 @@
[(V16SF "V4SF") (V8DF "V2DF") (V16SI "TI") (V8DI "TI")])
(define_mode_attr vecmemsuffix
- [(V16SF "{z}") (V8SF "{y}") (V4SF "{x}")
+ [(V32HF "{z}") (V16HF "{y}") (V8HF "{x}")
+ (V16SF "{z}") (V8SF "{y}") (V4SF "{x}")
(V8DF "{z}") (V4DF "{y}") (V2DF "{x}")])
(define_mode_attr ssedoublemodelower
@@ -665,6 +772,11 @@
[(V8DI "V64QI") (V4DI "V32QI") (V2DI "V16QI")
(V16SI "V64QI") (V8SI "V32QI") (V4SI "V16QI")])
+(define_mode_attr sseintconvert
+ [(V32HI "w") (V16HI "w") (V8HI "w")
+ (V16SI "dq") (V8SI "dq") (V4SI "dq")
+ (V8DI "qq") (V4DI "qq") (V2DI "qq")])
+
;; All 128bit vector integer modes
(define_mode_iterator VI_128 [V16QI V8HI V4SI V2DI])
@@ -673,6 +785,8 @@
;; All 128 and 256bit vector integer modes
(define_mode_iterator VI_128_256 [V16QI V8HI V4SI V2DI V32QI V16HI V8SI V4DI])
+;; All 256bit vector integer and HF modes
+(define_mode_iterator VIHF_256 [V32QI V16HI V8SI V4DI V16HF])
;; Various 128bit vector integer mode combinations
(define_mode_iterator VI12_128 [V16QI V8HI])
@@ -699,8 +813,12 @@
(define_mode_iterator VI4_256_8_512 [V8SI V8DI])
(define_mode_iterator VI_AVX512BW
[V16SI V8DI (V32HI "TARGET_AVX512BW") (V64QI "TARGET_AVX512BW")])
+(define_mode_iterator VIHF_AVX512BW
+ [V16SI V8DI (V32HI "TARGET_AVX512BW") (V64QI "TARGET_AVX512BW")
+ (V32HF "TARGET_AVX512BW")])
;; Int-float size matches
+(define_mode_iterator VI2F [V8HI V16HI V32HI V8HF V16HF V32HF])
(define_mode_iterator VI4F_128 [V4SI V4SF])
(define_mode_iterator VI8F_128 [V2DI V2DF])
(define_mode_iterator VI4F_256 [V8SI V8SF])
@@ -715,6 +833,12 @@
(V4DI "TARGET_AVX512VL") (V4DF "TARGET_AVX512VL")])
(define_mode_iterator VF48_I1248
[V16SI V16SF V8DI V8DF V32HI V64QI])
+(define_mode_iterator VF48H_AVX512VL
+ [V8DF V16SF (V8SF "TARGET_AVX512VL")])
+
+(define_mode_iterator VF48_128
+ [V2DF V4SF])
+
(define_mode_iterator VI48F
[V16SI V16SF V8DI V8DF
(V8SI "TARGET_AVX512VL") (V8SF "TARGET_AVX512VL")
@@ -739,18 +863,16 @@
(V8SF "TARGET_AVX512VL") (V4DF "TARGET_AVX512VL")
V16SF V8DF])
-(define_mode_attr avx512bcst
- [(V4SI "%{1to4%}") (V2DI "%{1to2%}")
- (V8SI "%{1to8%}") (V4DI "%{1to4%}")
- (V16SI "%{1to16%}") (V8DI "%{1to8%}")
- (V4SF "%{1to4%}") (V2DF "%{1to2%}")
- (V8SF "%{1to8%}") (V4DF "%{1to4%}")
- (V16SF "%{1to16%}") (V8DF "%{1to8%}")])
+(define_mode_iterator V8_128 [V8HI V8HF])
+(define_mode_iterator V16_256 [V16HI V16HF])
+(define_mode_iterator V32_512 [V32HI V32HF])
;; Mapping from float mode to required SSE level
(define_mode_attr sse
- [(SF "sse") (DF "sse2")
+ [(SF "sse") (DF "sse2") (HF "avx512fp16")
(V4SF "sse") (V2DF "sse2")
+ (V32HF "avx512fp16") (V16HF "avx512fp16")
+ (V8HF "avx512fp16")
(V16SF "avx512f") (V8SF "avx")
(V8DF "avx512f") (V4DF "avx")])
@@ -786,6 +908,16 @@
(V16SF "V16SF") (V8DF "V8DF")
(V8SF "V8SF") (V4DF "V4DF")
(V4SF "V4SF") (V2DF "V2DF")
+ (V8HF "TI") (V16HF "OI") (V32HF "XI")
+ (TI "TI")])
+
+(define_mode_attr sseintvecinsnmode
+ [(V64QI "XI") (V32HI "XI") (V16SI "XI") (V8DI "XI") (V4TI "XI")
+ (V32QI "OI") (V16HI "OI") (V8SI "OI") (V4DI "OI") (V2TI "OI")
+ (V16QI "TI") (V8HI "TI") (V4SI "TI") (V2DI "TI") (V1TI "TI")
+ (V16SF "XI") (V8DF "XI")
+ (V8SF "OI") (V4DF "OI")
+ (V4SF "TI") (V2DF "TI")
(TI "TI")])
;; SSE constant -1 constraint
@@ -793,9 +925,16 @@
[(V64QI "BC") (V32HI "BC") (V16SI "BC") (V8DI "BC") (V4TI "BC")
(V32QI "BC") (V16HI "BC") (V8SI "BC") (V4DI "BC") (V2TI "BC")
(V16QI "BC") (V8HI "BC") (V4SI "BC") (V2DI "BC") (V1TI "BC")
- (V16SF "BF") (V8DF "BF")
- (V8SF "BF") (V4DF "BF")
- (V4SF "BF") (V2DF "BF")])
+ (V32HF "BF") (V16SF "BF") (V8DF "BF")
+ (V16HF "BF") (V8SF "BF") (V4DF "BF")
+ (V8HF "BF") (V4SF "BF") (V2DF "BF")])
+
+;; SSE integer instruction suffix for various modes
+(define_mode_attr sseintmodesuffix
+ [(V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")
+ (V32QI "b") (V16HI "w") (V8SI "d") (V4DI "q")
+ (V64QI "b") (V32HI "w") (V16SI "d") (V8DI "q")
+ (V8HF "w") (V16HF "w") (V32HF "w")])
;; Mapping of vector modes to corresponding mask size
(define_mode_attr avx512fmaskmode
@@ -803,15 +942,21 @@
(V32HI "SI") (V16HI "HI") (V8HI "QI") (V4HI "QI")
(V16SI "HI") (V8SI "QI") (V4SI "QI")
(V8DI "QI") (V4DI "QI") (V2DI "QI")
+ (V32HF "SI") (V16HF "HI") (V8HF "QI")
(V16SF "HI") (V8SF "QI") (V4SF "QI")
(V8DF "QI") (V4DF "QI") (V2DF "QI")])
+;; Mapping of vector modes to corresponding complex mask size
+(define_mode_attr avx512fmaskcmode
+ [(V32HF "HI") (V16HF "QI") (V8HF "QI")])
+
;; Mapping of vector modes to corresponding mask size
(define_mode_attr avx512fmaskmodelower
[(V64QI "di") (V32QI "si") (V16QI "hi")
(V32HI "si") (V16HI "hi") (V8HI "qi") (V4HI "qi")
(V16SI "hi") (V8SI "qi") (V4SI "qi")
(V8DI "qi") (V4DI "qi") (V2DI "qi")
+ (V32HF "si") (V16HF "hi") (V8HF "qi")
(V16SF "hi") (V8SF "qi") (V4SF "qi")
(V8DF "qi") (V4DF "qi") (V2DF "qi")])
@@ -821,14 +966,15 @@
(V32HI "HI") (V16HI "QI") (V8HI "QI") (V4HI "QI")
(V16SI "QI") (V8SI "QI") (V4SI "QI")
(V8DI "QI") (V4DI "QI") (V2DI "QI")
+ (V32HF "HI") (V16HF "QI") (V8HF "QI")
(V16SF "QI") (V8SF "QI") (V4SF "QI")
(V8DF "QI") (V4DF "QI") (V2DF "QI")])
;; Mapping of vector float modes to an integer mode of the same size
(define_mode_attr sseintvecmode
- [(V16SF "V16SI") (V8DF "V8DI")
- (V8SF "V8SI") (V4DF "V4DI")
- (V4SF "V4SI") (V2DF "V2DI")
+ [(V32HF "V32HI") (V16SF "V16SI") (V8DF "V8DI")
+ (V16HF "V16HI") (V8SF "V8SI") (V4DF "V4DI")
+ (V8HF "V8HI") (V4SF "V4SI") (V2DF "V2DI")
(V16SI "V16SI") (V8DI "V8DI")
(V8SI "V8SI") (V4DI "V4DI")
(V4SI "V4SI") (V2DI "V2DI")
@@ -838,12 +984,13 @@
(define_mode_attr sseintvecmode2
[(V8DF "XI") (V4DF "OI") (V2DF "TI")
- (V8SF "OI") (V4SF "TI")])
+ (V8SF "OI") (V4SF "TI")
+ (V16HF "OI") (V8HF "TI")])
(define_mode_attr sseintvecmodelower
- [(V16SF "v16si") (V8DF "v8di")
- (V8SF "v8si") (V4DF "v4di")
- (V4SF "v4si") (V2DF "v2di")
+ [(V32HF "v32hi") (V16SF "v16si") (V8DF "v8di")
+ (V16HF "v16hi") (V8SF "v8si") (V4DF "v4di")
+ (V8HF "v8hi") (V4SF "v4si") (V2DF "v2di")
(V8SI "v8si") (V4DI "v4di")
(V4SI "v4si") (V2DI "v2di")
(V16HI "v16hi") (V8HI "v8hi")
@@ -856,7 +1003,8 @@
(V16QI "V32QI") (V8HI "V16HI") (V4SI "V8SI") (V2DI "V4DI")
(V16SF "V32SF") (V8DF "V16DF")
(V8SF "V16SF") (V4DF "V8DF")
- (V4SF "V8SF") (V2DF "V4DF")])
+ (V4SF "V8SF") (V2DF "V4DF")
+ (V32HF "V64HF") (V16HF "V32HF") (V8HF "V16HF")])
;; Mapping of vector modes to a vector mode of half size
;; instead of V1DI/V1DF, DI/DF are used for V2DI/V2DF although they are scalar.
@@ -866,7 +1014,8 @@
(V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI") (V2DI "DI")
(V16SF "V8SF") (V8DF "V4DF")
(V8SF "V4SF") (V4DF "V2DF")
- (V4SF "V2SF") (V2DF "DF")])
+ (V4SF "V2SF") (V2DF "DF")
+ (V32HF "V16HF") (V16HF "V8HF") (V8HF "V4HF")])
(define_mode_attr ssehalfvecmodelower
[(V64QI "v32qi") (V32HI "v16hi") (V16SI "v8si") (V8DI "v4di") (V4TI "v2ti")
@@ -874,9 +1023,24 @@
(V16QI "v8qi") (V8HI "v4hi") (V4SI "v2si")
(V16SF "v8sf") (V8DF "v4df")
(V8SF "v4sf") (V4DF "v2df")
- (V4SF "v2sf")])
-
-;; Mapping of vector modes ti packed single mode of the same size
+ (V4SF "v2sf")
+ (V32HF "v16hf") (V16HF "v8hf") (V8HF "v4hf")])
+
+;; Mapping of vector modes to vector hf modes of conversion.
+(define_mode_attr ssePHmode
+ [(V32HI "V32HF") (V16HI "V16HF") (V8HI "V8HF")
+ (V16SI "V16HF") (V8SI "V8HF") (V4SI "V8HF")
+ (V8DI "V8HF") (V4DI "V8HF") (V2DI "V8HF")
+ (V8DF "V8HF") (V16SF "V16HF") (V8SF "V8HF")])
+
+;; Mapping of vector modes to vector hf modes of same element.
+(define_mode_attr ssePHmodelower
+ [(V32HI "v32hf") (V16HI "v16hf") (V8HI "v8hf")
+ (V16SI "v16hf") (V8SI "v8hf") (V4SI "v4hf")
+ (V8DI "v8hf") (V4DI "v4hf") (V2DI "v2hf")
+ (V8DF "v8hf") (V16SF "v16hf") (V8SF "v8hf")])
+
+;; Mapping of vector modes to packed single mode of the same size
(define_mode_attr ssePSmode
[(V16SI "V16SF") (V8DF "V16SF")
(V16SF "V16SF") (V8DI "V16SF")
@@ -886,7 +1050,8 @@
(V4DI "V8SF") (V2DI "V4SF")
(V4TI "V16SF") (V2TI "V8SF") (V1TI "V4SF")
(V8SF "V8SF") (V4SF "V4SF")
- (V4DF "V8SF") (V2DF "V4SF")])
+ (V4DF "V8SF") (V2DF "V4SF")
+ (V32HF "V16SF") (V16HF "V8SF") (V8HF "V4SF")])
(define_mode_attr ssePSmode2
[(V8DI "V8SF") (V4DI "V4SF")])
@@ -897,6 +1062,7 @@
(V32HI "HI") (V16HI "HI") (V8HI "HI")
(V16SI "SI") (V8SI "SI") (V4SI "SI")
(V8DI "DI") (V4DI "DI") (V2DI "DI")
+ (V32HF "HF") (V16HF "HF") (V8HF "HF")
(V16SF "SF") (V8SF "SF") (V4SF "SF")
(V8DF "DF") (V4DF "DF") (V2DF "DF")
(V4TI "TI") (V2TI "TI")])
@@ -907,6 +1073,7 @@
(V32HI "hi") (V16HI "hi") (V8HI "hi")
(V16SI "si") (V8SI "si") (V4SI "si")
(V8DI "di") (V4DI "di") (V2DI "di")
+ (V32HF "hf") (V16HF "hf") (V8HF "hf")
(V16SF "sf") (V8SF "sf") (V4SF "sf")
(V8DF "df") (V4DF "df") (V2DF "df")
(V4TI "ti") (V2TI "ti")])
@@ -917,6 +1084,7 @@
(V32HI "V8HI") (V16HI "V8HI") (V8HI "V8HI")
(V16SI "V4SI") (V8SI "V4SI") (V4SI "V4SI")
(V8DI "V2DI") (V4DI "V2DI") (V2DI "V2DI")
+ (V32HF "V8HF") (V16HF "V8HF") (V8HF "V8HF")
(V16SF "V4SF") (V8SF "V4SF") (V4SF "V4SF")
(V8DF "V2DF") (V4DF "V2DF") (V2DF "V2DF")])
@@ -925,10 +1093,10 @@
[(V64QI "b") (V32HI "w") (V16SI "k") (V8DI "q")
(V32QI "b") (V16HI "w") (V8SI "k") (V4DI "q")
(V16QI "b") (V8HI "w") (V4SI "k") (V2DI "q")
- (V16SF "k") (V8DF "q")
- (V8SF "k") (V4DF "q")
- (V4SF "k") (V2DF "q")
- (SF "k") (DF "q")])
+ (V32HF "w") (V16SF "k") (V8DF "q")
+ (V16HF "w") (V8SF "k") (V4DF "q")
+ (V8HF "w") (V4SF "k") (V2DF "q")
+ (HF "w") (SF "k") (DF "q")])
;; Mapping of vector modes to VPTERNLOG suffix
(define_mode_attr ternlogsuffix
@@ -937,6 +1105,7 @@
(V16SI "d") (V8SI "d") (V4SI "d")
(V16SF "d") (V8SF "d") (V4SF "d")
(V32HI "d") (V16HI "d") (V8HI "d")
+ (V32HF "d") (V16HF "d") (V8HF "d")
(V64QI "d") (V32QI "d") (V16QI "d")])
;; Number of scalar elements in each vector type
@@ -961,10 +1130,11 @@
(V64QI "8") (V32QI "8") (V16QI "8")
(V32HI "16") (V16HI "16") (V8HI "16")
(V16SI "32") (V8SI "32") (V4SI "32")
+ (V32HF "16") (V16HF "16") (V8HF "16")
(V16SF "32") (V8SF "32") (V4SF "32")
(V8DF "64") (V4DF "64") (V2DF "64")])
-;; SSE prefix for integer vector modes
+;; SSE prefix for integer and HF vector modes
(define_mode_attr sseintprefix
[(V2DI "p") (V2DF "")
(V4DI "p") (V4DF "")
@@ -972,16 +1142,28 @@
(V4SI "p") (V4SF "")
(V8SI "p") (V8SF "")
(V16SI "p") (V16SF "")
- (V16QI "p") (V8HI "p")
- (V32QI "p") (V16HI "p")
- (V64QI "p") (V32HI "p")])
+ (V16QI "p") (V8HI "p") (V8HF "p")
+ (V32QI "p") (V16HI "p") (V16HF "p")
+ (V64QI "p") (V32HI "p") (V32HF "p")])
+
+;; SSE prefix for integer and HF vector comparison.
+(define_mode_attr ssecmpintprefix
+ [(V2DI "p") (V2DF "")
+ (V4DI "p") (V4DF "")
+ (V8DI "p") (V8DF "")
+ (V4SI "p") (V4SF "")
+ (V8SI "p") (V8SF "")
+ (V16SI "p") (V16SF "")
+ (V16QI "p") (V8HI "p") (V8HF "")
+ (V32QI "p") (V16HI "p") (V16HF "")
+ (V64QI "p") (V32HI "p") (V32HF "")])
;; SSE scalar suffix for vector modes
(define_mode_attr ssescalarmodesuffix
- [(SF "ss") (DF "sd")
- (V16SF "ss") (V8DF "sd")
- (V8SF "ss") (V4DF "sd")
- (V4SF "ss") (V2DF "sd")
+ [(HF "sh") (SF "ss") (DF "sd")
+ (V32HF "sh") (V16SF "ss") (V8DF "sd")
+ (V16HF "sh") (V8SF "ss") (V4DF "sd")
+ (V8HF "sh") (V4SF "ss") (V2DF "sd")
(V16SI "d") (V8DI "q")
(V8SI "d") (V4DI "q")
(V4SI "d") (V2DI "q")])
@@ -1003,13 +1185,15 @@
;; Mapping of mode to cast intrinsic name
(define_mode_attr castmode
- [(V8SI "si") (V8SF "ps") (V4DF "pd")
+ [(V4SF "ps") (V2DF "pd")
+ (V8SI "si") (V8SF "ps") (V4DF "pd")
(V16SI "si") (V16SF "ps") (V8DF "pd")])
;; i128 for integer vectors and TARGET_AVX2, f128 otherwise.
;; i64x4 or f64x4 for 512bit modes.
(define_mode_attr i128
- [(V16SF "f64x4") (V8SF "f128") (V8DF "f64x4") (V4DF "f128")
+ [(V16HF "%~128") (V32HF "i64x4") (V16SF "f64x4") (V8SF "f128")
+ (V8DF "f64x4") (V4DF "f128")
(V64QI "i64x4") (V32QI "%~128") (V32HI "i64x4") (V16HI "%~128")
(V16SI "i64x4") (V8SI "%~128") (V8DI "i64x4") (V4DI "%~128")])
@@ -1033,14 +1217,18 @@
(V32HI "w") (V16HI "w") (V8HI "w")
(V16SI "d") (V8SI "d") (V4SI "d")
(V8DI "q") (V4DI "q") (V2DI "q")
+ (V32HF "w") (V16HF "w") (V8HF "w")
(V16SF "ss") (V8SF "ss") (V4SF "ss")
(V8DF "sd") (V4DF "sd") (V2DF "sd")])
;; Tie mode of assembler operand to mode iterator
(define_mode_attr xtg_mode
- [(V16QI "x") (V8HI "x") (V4SI "x") (V2DI "x") (V4SF "x") (V2DF "x")
- (V32QI "t") (V16HI "t") (V8SI "t") (V4DI "t") (V8SF "t") (V4DF "t")
- (V64QI "g") (V32HI "g") (V16SI "g") (V8DI "g") (V16SF "g") (V8DF "g")])
+ [(V16QI "x") (V8HI "x") (V4SI "x") (V2DI "x")
+ (V8HF "x") (V4SF "x") (V2DF "x")
+ (V32QI "t") (V16HI "t") (V8SI "t") (V4DI "t")
+ (V16HF "t") (V8SF "t") (V4DF "t")
+ (V64QI "g") (V32HI "g") (V16SI "g") (V8DI "g")
+ (V32HF "g") (V16SF "g") (V8DF "g")])
;; Half mask mode for unpacks
(define_mode_attr HALFMASKMODE
@@ -1081,7 +1269,8 @@
" C,<sseconstm1>,vm,v"))]
"TARGET_SSE
&& (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
+ || register_operand (operands[1], <MODE>mode))
+ && ix86_hardreg_mov_ok (operands[0], operands[1])"
{
switch (get_attr_type (insn))
{
@@ -1231,13 +1420,13 @@
[(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
- (vec_merge:VF_128
- (match_operand:VF_128 2 "register_operand" "v")
- (match_operand:VF_128 3 "nonimm_or_0_operand" "0C")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (match_operand:VFH_128 2 "register_operand" "v")
+ (match_operand:VFH_128 3 "nonimm_or_0_operand" "0C")
(match_operand:QI 4 "register_operand" "Yk"))
- (match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VFH_128 1 "register_operand" "v")
(const_int 1)))]
"TARGET_AVX512F"
"vmov<ssescalarmodesuffix>\t{%2, %1, %0%{%4%}%N3|%0%{%4%}%N3, %1, %2}"
@@ -1250,7 +1439,7 @@
(vec_merge:<ssevecmode>
(vec_merge:<ssevecmode>
(vec_duplicate:<ssevecmode>
- (match_operand:MODEF 1 "memory_operand"))
+ (match_operand:MODEFH 1 "memory_operand"))
(match_operand:<ssevecmode> 2 "nonimm_or_0_operand")
(match_operand:QI 3 "register_operand"))
(match_dup 4)
@@ -1263,7 +1452,7 @@
(vec_merge:<ssevecmode>
(vec_merge:<ssevecmode>
(vec_duplicate:<ssevecmode>
- (match_operand:MODEF 1 "memory_operand" "m"))
+ (match_operand:MODEFH 1 "memory_operand" "m"))
(match_operand:<ssevecmode> 2 "nonimm_or_0_operand" "0C")
(match_operand:QI 3 "register_operand" "Yk"))
(match_operand:<ssevecmode> 4 "const0_operand" "C")
@@ -1276,11 +1465,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_store<mode>_mask"
- [(set (match_operand:MODEF 0 "memory_operand" "=m")
- (if_then_else:MODEF
+ [(set (match_operand:MODEFH 0 "memory_operand" "=m")
+ (if_then_else:MODEFH
(and:QI (match_operand:QI 2 "register_operand" "Yk")
(const_int 1))
- (vec_select:MODEF
+ (vec_select:MODEFH
(match_operand:<ssevecmode> 1 "register_operand" "v")
(parallel [(const_int 0)]))
(match_dup 0)))]
@@ -1336,6 +1525,20 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn "<avx512>_blendm<mode>"
+ [(set (match_operand:VF_AVX512FP16 0 "register_operand" "=v,v")
+ (vec_merge:VF_AVX512FP16
+ (match_operand:VF_AVX512FP16 2 "nonimmediate_operand" "vm,vm")
+ (match_operand:VF_AVX512FP16 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}
+ vpblendmw\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")
(vec_merge:V48_AVX512VL
@@ -1365,9 +1568,9 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<avx512>_store<mode>_mask"
- [(set (match_operand:VI12_AVX512VL 0 "memory_operand" "=m")
- (vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 1 "register_operand" "v")
+ [(set (match_operand:VI12HF_AVX512VL 0 "memory_operand" "=m")
+ (vec_merge:VI12HF_AVX512VL
+ (match_operand:VI12HF_AVX512VL 1 "register_operand" "v")
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand" "Yk")))]
"TARGET_AVX512BW"
@@ -1866,22 +2069,22 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "<code><mode>2"
- [(set (match_operand:VF 0 "register_operand")
- (absneg:VF
- (match_operand:VF 1 "register_operand")))]
+ [(set (match_operand:VFB 0 "register_operand")
+ (absneg:VFB
+ (match_operand:VFB 1 "register_operand")))]
"TARGET_SSE"
"ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
(define_insn_and_split "*<code><mode>2"
- [(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
- (absneg:VF
- (match_operand:VF 1 "vector_operand" "0,xBm,v,m")))
- (use (match_operand:VF 2 "vector_operand" "xBm,0,vm,v"))]
+ [(set (match_operand:VFB 0 "register_operand" "=x,x,v,v")
+ (absneg:VFB
+ (match_operand:VFB 1 "vector_operand" "0,xBm,v,m")))
+ (use (match_operand:VFB 2 "vector_operand" "xBm,0,vm,v"))]
"TARGET_SSE"
"#"
"&& reload_completed"
[(set (match_dup 0)
- (<absneg_op>:VF (match_dup 1) (match_dup 2)))]
+ (<absneg_op>:VFB (match_dup 1) (match_dup 2)))]
{
if (TARGET_AVX)
{
@@ -1922,12 +2125,12 @@
[(set_attr "isa" "noavx,noavx,avx,avx")])
(define_expand "cond_<insn><mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (plusminus:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (plusminus:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -1940,18 +2143,18 @@
})
(define_expand "<insn><mode>3<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand")
- (plusminus:VF
- (match_operand:VF 1 "<round_nimm_predicate>")
- (match_operand:VF 2 "<round_nimm_predicate>")))]
+ [(set (match_operand:VFH 0 "register_operand")
+ (plusminus:VFH
+ (match_operand:VFH 1 "<round_nimm_predicate>")
+ (match_operand:VFH 2 "<round_nimm_predicate>")))]
"TARGET_SSE && <mask_mode512bit_condition> && <round_mode512bit_condition>"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*<insn><mode>3<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (plusminus:VF
- (match_operand:VF 1 "<bcst_round_nimm_predicate>" "<comm>0,v")
- (match_operand:VF 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (plusminus:VFH
+ (match_operand:VFH 1 "<bcst_round_nimm_predicate>" "<comm>0,v")
+ (match_operand:VFH 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
"TARGET_SSE && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
&& <mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
@@ -1965,12 +2168,12 @@
;; Standard scalar operation patterns which preserve the rest of the
;; vector for combiner.
(define_insn "*<sse>_vm<insn><mode>3"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(plusminus:<ssescalarmode>
(vec_select:<ssescalarmode>
- (match_operand:VF_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 1 "register_operand" "0,v")
(parallel [(const_int 0)]))
(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")))
(match_dup 1)
@@ -1981,15 +2184,24 @@
v<plusminus_mnemonic><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sseadd")
- (set_attr "prefix" "orig,vex")
+ (set (attr "prefix")
+ (cond [(eq_attr "alternative" "0")
+ (const_string "orig")
+ (eq_attr "alternative" "1")
+ (if_then_else
+ (match_test "<MODE>mode == V8HFmode")
+ (const_string "evex")
+ (const_string "vex"))
+ ]
+ (const_string "*")))
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<sse>_vm<insn><mode>3<mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (plusminus:VF_128
- (match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (plusminus:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 2 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
@@ -2002,12 +2214,12 @@
(set_attr "mode" "<ssescalarmode>")])
(define_expand "cond_mul<mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (mult:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (mult:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2020,18 +2232,18 @@
})
(define_expand "mul<mode>3<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand")
- (mult:VF
- (match_operand:VF 1 "<round_nimm_predicate>")
- (match_operand:VF 2 "<round_nimm_predicate>")))]
+ [(set (match_operand:VFH 0 "register_operand")
+ (mult:VFH
+ (match_operand:VFH 1 "<round_nimm_predicate>")
+ (match_operand:VFH 2 "<round_nimm_predicate>")))]
"TARGET_SSE && <mask_mode512bit_condition> && <round_mode512bit_condition>"
"ix86_fixup_binary_operands_no_copy (MULT, <MODE>mode, operands);")
(define_insn "*mul<mode>3<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (mult:VF
- (match_operand:VF 1 "<bcst_round_nimm_predicate>" "%0,v")
- (match_operand:VF 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (mult:VFH
+ (match_operand:VFH 1 "<bcst_round_nimm_predicate>" "%0,v")
+ (match_operand:VFH 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
"TARGET_SSE && ix86_binary_operator_ok (MULT, <MODE>mode, operands)
&& <mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
@@ -2046,12 +2258,12 @@
;; Standard scalar operation patterns which preserve the rest of the
;; vector for combiner.
(define_insn "*<sse>_vm<multdiv_mnemonic><mode>3"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(multdiv:<ssescalarmode>
(vec_select:<ssescalarmode>
- (match_operand:VF_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 1 "register_operand" "0,v")
(parallel [(const_int 0)]))
(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")))
(match_dup 1)
@@ -2062,16 +2274,25 @@
v<multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse<multdiv_mnemonic>")
- (set_attr "prefix" "orig,vex")
+ (set (attr "prefix")
+ (cond [(eq_attr "alternative" "0")
+ (const_string "orig")
+ (eq_attr "alternative" "1")
+ (if_then_else
+ (match_test "<MODE>mode == V8HFmode")
+ (const_string "evex")
+ (const_string "vex"))
+ ]
+ (const_string "*")))
(set_attr "btver2_decode" "direct,double")
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<sse>_vm<multdiv_mnemonic><mode>3<mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (multdiv:VF_128
- (match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (multdiv:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 2 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
@@ -2085,9 +2306,9 @@
(set_attr "mode" "<ssescalarmode>")])
(define_expand "div<mode>3"
- [(set (match_operand:VF2 0 "register_operand")
- (div:VF2 (match_operand:VF2 1 "register_operand")
- (match_operand:VF2 2 "vector_operand")))]
+ [(set (match_operand:VF2H 0 "register_operand")
+ (div:VF2H (match_operand:VF2H 1 "register_operand")
+ (match_operand:VF2H 2 "vector_operand")))]
"TARGET_SSE2")
(define_expand "div<mode>3"
@@ -2108,12 +2329,12 @@
})
(define_expand "cond_div<mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (div:VF
- (match_operand:VF 2 "register_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (div:VFH
+ (match_operand:VFH 2 "register_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2126,10 +2347,10 @@
})
(define_insn "<sse>_div<mode>3<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (div:VF
- (match_operand:VF 1 "register_operand" "0,v")
- (match_operand:VF 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (div:VFH
+ (match_operand:VFH 1 "register_operand" "0,v")
+ (match_operand:VFH 2 "<bcst_round_nimm_predicate>" "xBm,<bcst_round_constraint>")))]
"TARGET_SSE && <mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
div<ssemodesuffix>\t{%2, %0|%0, %2}
@@ -2188,6 +2409,30 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
+(define_insn "avx512fp16_rcp<mode>2<mask_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RCP))]
+ "TARGET_AVX512FP16"
+ "vrcpph\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512fp16_vmrcpv8hf2<mask_scalar_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (unspec:V8HF [(match_operand:V8HF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RCP)
+ (match_operand:V8HF 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vrcpsh\t{%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %w1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
(define_insn "<mask_codefor>rcp14<mode><mask_name>"
[(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
(unspec:VF_AVX512VL
@@ -2231,8 +2476,8 @@
(set_attr "mode" "<MODE>")])
(define_expand "sqrt<mode>2"
- [(set (match_operand:VF2 0 "register_operand")
- (sqrt:VF2 (match_operand:VF2 1 "vector_operand")))]
+ [(set (match_operand:VF2H 0 "register_operand")
+ (sqrt:VF2H (match_operand:VF2H 1 "vector_operand")))]
"TARGET_SSE2")
(define_expand "sqrt<mode>2"
@@ -2252,8 +2497,8 @@
})
(define_insn "<sse>_sqrt<mode>2<mask_name><round_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (sqrt:VF (match_operand:VF 1 "<round_nimm_predicate>" "xBm,<round_constraint>")))]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (sqrt:VFH (match_operand:VFH 1 "<round_nimm_predicate>" "xBm,<round_constraint>")))]
"TARGET_SSE && <mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
sqrt<ssemodesuffix>\t{%1, %0|%0, %1}
@@ -2266,11 +2511,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (sqrt:VF_128
- (match_operand:VF_128 1 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
- (match_operand:VF_128 2 "register_operand" "0,v")
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (sqrt:VFH_128
+ (match_operand:VFH_128 1 "nonimmediate_operand" "xm,<round_scalar_constraint>"))
+ (match_operand:VFH_128 2 "register_operand" "0,v")
(const_int 1)))]
"TARGET_SSE"
"@
@@ -2284,12 +2529,12 @@
(set_attr "mode" "<ssescalarmode>")])
(define_insn "*<sse>_vmsqrt<mode>2<mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(sqrt:<ssescalarmode>
(match_operand:<ssescalarmode> 1 "nonimmediate_operand" "xm,<round_scalar_constraint>")))
- (match_operand:VF_128 2 "register_operand" "0,v")
+ (match_operand:VFH_128 2 "register_operand" "0,v")
(const_int 1)))]
"TARGET_SSE"
"@
@@ -2323,6 +2568,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
+(define_insn "<sse>_rsqrt<mode>2<mask_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "vector_operand" "vBm")] UNSPEC_RSQRT))]
+ "TARGET_AVX512FP16"
+ "vrsqrtph\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "<mask_codefor>rsqrt14<mode><mask_name>"
[(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
(unspec:VF_AVX512VL
@@ -2398,13 +2653,26 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
+(define_insn "avx512fp16_vmrsqrtv8hf2<mask_scalar_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (unspec:V8HF [(match_operand:V8HF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RSQRT)
+ (match_operand:V8HF 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vrsqrtsh\t{%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %w1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
(define_expand "cond_<code><mode>"
- [(set (match_operand:VF 0 "register_operand")
- (vec_merge:VF
- (smaxmin:VF
- (match_operand:VF 2 "vector_operand")
- (match_operand:VF 3 "vector_operand"))
- (match_operand:VF 4 "nonimm_or_0_operand")
+ [(set (match_operand:VFH 0 "register_operand")
+ (vec_merge:VFH
+ (smaxmin:VFH
+ (match_operand:VFH 2 "vector_operand")
+ (match_operand:VFH 3 "vector_operand"))
+ (match_operand:VFH 4 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"<MODE_SIZE> == 64 || TARGET_AVX512VL"
{
@@ -2417,11 +2685,12 @@
})
(define_expand "<code><mode>3<mask_name><round_saeonly_name>"
- [(set (match_operand:VF 0 "register_operand")
- (smaxmin:VF
- (match_operand:VF 1 "<round_saeonly_nimm_predicate>")
- (match_operand:VF 2 "<round_saeonly_nimm_predicate>")))]
- "TARGET_SSE && <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
+ [(set (match_operand:VFH 0 "register_operand")
+ (smaxmin:VFH
+ (match_operand:VFH 1 "<round_saeonly_nimm_predicate>")
+ (match_operand:VFH 2 "<round_saeonly_nimm_predicate>")))]
+ "TARGET_SSE && <mask_mode512bit_condition>
+ && <round_saeonly_mode512bit_condition>"
{
if (!flag_finite_math_only || flag_signed_zeros)
{
@@ -2442,13 +2711,14 @@
;; are undefined in this condition, we're certain this is correct.
(define_insn "*<code><mode>3<mask_name><round_saeonly_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (smaxmin:VF
- (match_operand:VF 1 "<round_saeonly_nimm_predicate>" "%0,v")
- (match_operand:VF 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")))]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (smaxmin:VFH
+ (match_operand:VFH 1 "<round_saeonly_nimm_predicate>" "%0,v")
+ (match_operand:VFH 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")))]
"TARGET_SSE
&& !(MEM_P (operands[1]) && MEM_P (operands[2]))
- && <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
+ && <mask_mode512bit_condition>
+ && <round_saeonly_mode512bit_condition>"
"@
<maxmin_float><ssemodesuffix>\t{%2, %0|%0, %2}
v<maxmin_float><ssemodesuffix>\t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2<round_saeonly_mask_op3>}"
@@ -2465,13 +2735,14 @@
;; presence of -0.0 and NaN.
(define_insn "ieee_<ieee_maxmin><mode>3<mask_name><round_saeonly_name>"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "0,v")
- (match_operand:VF 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")]
+ [(set (match_operand:VFH 0 "register_operand" "=x,v")
+ (unspec:VFH
+ [(match_operand:VFH 1 "register_operand" "0,v")
+ (match_operand:VFH 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")]
IEEE_MAXMIN))]
"TARGET_SSE
- && <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
+ && <mask_mode512bit_condition>
+ && <round_saeonly_mode512bit_condition>"
"@
<ieee_maxmin><ssemodesuffix>\t{%2, %0|%0, %2}
v<ieee_maxmin><ssemodesuffix>\t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2<round_saeonly_mask_op3>}"
@@ -2484,12 +2755,12 @@
;; Standard scalar operation patterns which preserve the rest of the
;; vector for combiner.
(define_insn "*ieee_<ieee_maxmin><mode>3"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(unspec:<ssescalarmode>
[(vec_select:<ssescalarmode>
- (match_operand:VF_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 1 "register_operand" "0,v")
(parallel [(const_int 0)]))
(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")]
IEEE_MAXMIN))
@@ -2502,15 +2773,24 @@
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sseadd")
(set_attr "btver2_sse_attr" "maxmin")
- (set_attr "prefix" "orig,vex")
+ (set (attr "prefix")
+ (cond [(eq_attr "alternative" "0")
+ (const_string "orig")
+ (eq_attr "alternative" "1")
+ (if_then_else
+ (match_test "<MODE>mode == V8HFmode")
+ (const_string "evex")
+ (const_string "vex"))
+ ]
+ (const_string "*")))
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (smaxmin:VF_128
- (match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "nonimmediate_operand" "xm,<round_saeonly_scalar_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=x,v")
+ (vec_merge:VFH_128
+ (smaxmin:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,v")
+ (match_operand:VFH_128 2 "nonimmediate_operand" "xm,<round_saeonly_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
@@ -2877,7 +3157,8 @@
(set_attr "mode" "V4SF")])
(define_mode_iterator REDUC_SSE_PLUS_MODE
- [(V2DF "TARGET_SSE") (V4SF "TARGET_SSE")])
+ [(V2DF "TARGET_SSE") (V4SF "TARGET_SSE")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")])
(define_expand "reduc_plus_scal_<mode>"
[(plus:REDUC_SSE_PLUS_MODE
@@ -2914,7 +3195,9 @@
(define_mode_iterator REDUC_PLUS_MODE
[(V4DF "TARGET_AVX") (V8SF "TARGET_AVX")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V8DF "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
+ (V32HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V32QI "TARGET_AVX") (V64QI "TARGET_AVX512F")])
(define_expand "reduc_plus_scal_<mode>"
@@ -2934,7 +3217,8 @@
;; Modes handled by reduc_sm{in,ax}* patterns.
(define_mode_iterator REDUC_SSE_SMINMAX_MODE
- [(V4SF "TARGET_SSE") (V2DF "TARGET_SSE")
+ [(V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V4SF "TARGET_SSE") (V2DF "TARGET_SSE")
(V4SI "TARGET_SSE2") (V8HI "TARGET_SSE2") (V16QI "TARGET_SSE2")
(V2DI "TARGET_SSE4_2")])
@@ -2953,9 +3237,11 @@
(define_mode_iterator REDUC_SMINMAX_MODE
[(V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
(V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
(V64QI "TARGET_AVX512BW")
+ (V32HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
(V32HI "TARGET_AVX512BW") (V16SI "TARGET_AVX512F")
(V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
(V8DF "TARGET_AVX512F")])
@@ -3021,28 +3307,28 @@
})
(define_insn "<mask_codefor>reducep<mode><mask_name><round_saeonly_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")
(match_operand:SI 2 "const_0_to_255_operand")]
UNSPEC_REDUCE))]
- "TARGET_AVX512DQ"
+ "TARGET_AVX512DQ || (VALID_AVX512FP16_REG_MODE (<MODE>mode))"
"vreduce<ssemodesuffix>\t{%2, <round_saeonly_mask_op3>%1, %0<mask_operand3>|%0<mask_operand3>, %1<round_saeonly_mask_op3>, %2}"
[(set_attr "type" "sse")
(set_attr "prefix" "evex")
(set_attr "mode" "<MODE>")])
(define_insn "reduces<mode><mask_scalar_name><round_saeonly_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (unspec:VF_128
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (unspec:VFH_128
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
(match_operand:SI 3 "const_0_to_255_operand")]
UNSPEC_REDUCE)
(match_dup 1)
(const_int 1)))]
- "TARGET_AVX512DQ"
+ "TARGET_AVX512DQ || (VALID_AVX512FP16_REG_MODE (<MODE>mode))"
"vreduce<ssescalarmodesuffix>\t{%3, <round_saeonly_scalar_mask_op4>%2, %1, %0<mask_scalar_operand4>|%0<mask_scalar_operand4>, %1, %<iptr>2<round_saeonly_scalar_mask_op4>, %3}"
[(set_attr "type" "sse")
(set_attr "prefix" "evex")
@@ -3293,11 +3579,11 @@
(set_attr "mode" "<ssescalarmode>")])
(define_mode_attr cmp_imm_predicate
- [(V16SF "const_0_to_31_operand") (V8DF "const_0_to_31_operand")
+ [(V32HF "const_0_to_31_operand") (V16SF "const_0_to_31_operand") (V8DF "const_0_to_31_operand")
(V16SI "const_0_to_7_operand") (V8DI "const_0_to_7_operand")
- (V8SF "const_0_to_31_operand") (V4DF "const_0_to_31_operand")
+ (V16HF "const_0_to_31_operand") (V8SF "const_0_to_31_operand") (V4DF "const_0_to_31_operand")
(V8SI "const_0_to_7_operand") (V4DI "const_0_to_7_operand")
- (V4SF "const_0_to_31_operand") (V2DF "const_0_to_31_operand")
+ (V8HF "const_0_to_31_operand") (V4SF "const_0_to_31_operand") (V2DF "const_0_to_31_operand")
(V4SI "const_0_to_7_operand") (V2DI "const_0_to_7_operand")
(V32HI "const_0_to_7_operand") (V64QI "const_0_to_7_operand")
(V16HI "const_0_to_7_operand") (V32QI "const_0_to_7_operand")
@@ -3306,12 +3592,12 @@
(define_insn "<avx512>_cmp<mode>3<mask_scalar_merge_name><round_saeonly_name>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(unspec:<avx512fmaskmode>
- [(match_operand:V48_AVX512VL 1 "register_operand" "v")
- (match_operand:V48_AVX512VL 2 "nonimmediate_operand" "<round_saeonly_constraint>")
+ [(match_operand:V48H_AVX512VL 1 "register_operand" "v")
+ (match_operand:V48H_AVX512VL 2 "nonimmediate_operand" "<round_saeonly_constraint>")
(match_operand:SI 3 "<cmp_imm_predicate>" "n")]
UNSPEC_PCMP))]
"TARGET_AVX512F && <round_saeonly_mode512bit_condition>"
- "v<sseintprefix>cmp<ssemodesuffix>\t{%3, <round_saeonly_mask_scalar_merge_op4>%2, %1, %0<mask_scalar_merge_operand4>|%0<mask_scalar_merge_operand4>, %1, %2<round_saeonly_mask_scalar_merge_op4>, %3}"
+ "v<ssecmpintprefix>cmp<ssemodesuffix>\t{%3, <round_saeonly_mask_scalar_merge_op4>%2, %1, %0<mask_scalar_merge_operand4>|%0<mask_scalar_merge_operand4>, %1, %2<round_saeonly_mask_scalar_merge_op4>, %3}"
[(set_attr "type" "ssecmp")
(set_attr "length_immediate" "1")
(set_attr "prefix" "evex")
@@ -3426,7 +3712,7 @@
;; For signed comparison, handle EQ 0: NEQ 4,
;; for unsigned comparison extra handle LE:2, NLE:6, equivalent to EQ and NEQ.
-(define_split
+(define_insn_and_split "*<avx512>_ucmp<mode>3_1"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(unspec:<avx512fmaskmode>
[(us_minus:VI12_AVX512VL
@@ -3435,9 +3721,11 @@
(match_operand:VI12_AVX512VL 3 "const0_operand")
(match_operand:SI 4 "const_0_to_7_operand")]
UNSPEC_PCMP_ITER))]
- "TARGET_AVX512BW
+ "TARGET_AVX512BW && ix86_pre_reload_split ()
&& ix86_binary_operator_ok (US_MINUS, <MODE>mode, operands)
&& (INTVAL (operands[4]) & <pcmp_signed_mask>) == 0"
+ "#"
+ "&& 1"
[(const_int 0)]
{
/* LE: 2, NLT: 5, NLE: 6, LT: 1 */
@@ -3458,8 +3746,8 @@
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(and:<avx512fmaskmode>
(unspec:<avx512fmaskmode>
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
(match_operand:SI 3 "const_0_to_31_operand" "n")]
UNSPEC_PCMP)
(const_int 1)))]
@@ -3474,8 +3762,8 @@
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(and:<avx512fmaskmode>
(unspec:<avx512fmaskmode>
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
(match_operand:SI 3 "const_0_to_31_operand" "n")]
UNSPEC_PCMP)
(and:<avx512fmaskmode>
@@ -3491,10 +3779,10 @@
(define_insn "<sse>_<unord>comi<round_saeonly_name>"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP
- (vec_select:MODEF
+ (vec_select:MODEFH
(match_operand:<ssevecmode> 0 "register_operand" "v")
(parallel [(const_int 0)]))
- (vec_select:MODEF
+ (vec_select:MODEFH
(match_operand:<ssevecmode> 1 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
(parallel [(const_int 0)]))))]
"SSE_FLOAT_MODE_P (<MODE>mode)"
@@ -3511,8 +3799,8 @@
(define_expand "vec_cmp<mode><avx512fmaskmodelower>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(match_operator:<avx512fmaskmode> 1 ""
- [(match_operand:V48_AVX512VL 2 "register_operand")
- (match_operand:V48_AVX512VL 3 "nonimmediate_operand")]))]
+ [(match_operand:V48H_AVX512VL 2 "register_operand")
+ (match_operand:V48H_AVX512VL 3 "nonimmediate_operand")]))]
"TARGET_AVX512F"
{
bool ok = ix86_expand_mask_vec_cmp (operands[0], GET_CODE (operands[1]),
@@ -3719,6 +4007,51 @@
DONE;
})
+(define_expand "vcond<mode><mode>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:VF_AVX512FP16VL 4 "vector_operand")
+ (match_operand:VF_AVX512FP16VL 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_fp_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vcond<mode><sseintvecmodelower>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:<sseintvecmode> 4 "vector_operand")
+ (match_operand:<sseintvecmode> 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vcond<sseintvecmodelower><mode>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (if_then_else:<sseintvecmode>
+ (match_operator 3 ""
+ [(match_operand:VF_AVX512FP16VL 4 "vector_operand")
+ (match_operand:VF_AVX512FP16VL 5 "vector_operand")])
+ (match_operand:<sseintvecmode> 1 "general_operand")
+ (match_operand:<sseintvecmode> 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_fp_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcond_mask_<mode><avx512fmaskmodelower>"
[(set (match_operand:V48_AVX512VL 0 "register_operand")
(vec_merge:V48_AVX512VL
@@ -3728,10 +4061,10 @@
"TARGET_AVX512F")
(define_expand "vcond_mask_<mode><avx512fmaskmodelower>"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand")
- (vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 1 "nonimmediate_operand")
- (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand")
+ [(set (match_operand:VI12HF_AVX512VL 0 "register_operand")
+ (vec_merge:VI12HF_AVX512VL
+ (match_operand:VI12HF_AVX512VL 1 "nonimmediate_operand")
+ (match_operand:VI12HF_AVX512VL 2 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 3 "register_operand")))]
"TARGET_AVX512BW")
@@ -3813,11 +4146,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "<sse>_andnot<mode>3<mask_name>"
- [(set (match_operand:VF_128_256 0 "register_operand" "=x,x,v,v")
- (and:VF_128_256
- (not:VF_128_256
- (match_operand:VF_128_256 1 "register_operand" "0,x,v,v"))
- (match_operand:VF_128_256 2 "vector_operand" "xBm,xm,vm,vm")))]
+ [(set (match_operand:VFB_128_256 0 "register_operand" "=x,x,v,v")
+ (and:VFB_128_256
+ (not:VFB_128_256
+ (match_operand:VFB_128_256 1 "register_operand" "0,x,v,v"))
+ (match_operand:VFB_128_256 2 "vector_operand" "xBm,xm,vm,vm")))]
"TARGET_SSE && <mask_avx512vl_condition>"
{
char buf[128];
@@ -3840,6 +4173,8 @@
switch (get_attr_mode (insn))
{
+ case MODE_V16HF:
+ case MODE_V8HF:
case MODE_V8SF:
case MODE_V4SF:
suffix = "ps";
@@ -3878,11 +4213,11 @@
(const_string "<MODE>")))])
(define_insn "<sse>_andnot<mode>3<mask_name>"
- [(set (match_operand:VF_512 0 "register_operand" "=v")
- (and:VF_512
- (not:VF_512
- (match_operand:VF_512 1 "register_operand" "v"))
- (match_operand:VF_512 2 "nonimmediate_operand" "vm")))]
+ [(set (match_operand:VFB_512 0 "register_operand" "=v")
+ (and:VFB_512
+ (not:VFB_512
+ (match_operand:VFB_512 1 "register_operand" "v"))
+ (match_operand:VFB_512 2 "nonimmediate_operand" "vm")))]
"TARGET_AVX512F"
{
char buf[128];
@@ -3892,8 +4227,9 @@
suffix = "<ssemodesuffix>";
ops = "";
- /* There is no vandnp[sd] in avx512f. Use vpandn[qd]. */
- if (!TARGET_AVX512DQ)
+ /* Since there are no vandnp[sd] without AVX512DQ nor vandnph,
+ use vp<logic>[dq]. */
+ if (!TARGET_AVX512DQ || <MODE>mode == V32HFmode)
{
suffix = GET_MODE_INNER (<MODE>mode) == DFmode ? "q" : "d";
ops = "p";
@@ -3913,26 +4249,26 @@
(const_string "XI")))])
(define_expand "<code><mode>3<mask_name>"
- [(set (match_operand:VF_128_256 0 "register_operand")
- (any_logic:VF_128_256
- (match_operand:VF_128_256 1 "vector_operand")
- (match_operand:VF_128_256 2 "vector_operand")))]
+ [(set (match_operand:VFB_128_256 0 "register_operand")
+ (any_logic:VFB_128_256
+ (match_operand:VFB_128_256 1 "vector_operand")
+ (match_operand:VFB_128_256 2 "vector_operand")))]
"TARGET_SSE && <mask_avx512vl_condition>"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_expand "<code><mode>3<mask_name>"
- [(set (match_operand:VF_512 0 "register_operand")
- (any_logic:VF_512
- (match_operand:VF_512 1 "nonimmediate_operand")
- (match_operand:VF_512 2 "nonimmediate_operand")))]
+ [(set (match_operand:VFB_512 0 "register_operand")
+ (any_logic:VFB_512
+ (match_operand:VFB_512 1 "nonimmediate_operand")
+ (match_operand:VFB_512 2 "nonimmediate_operand")))]
"TARGET_AVX512F"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*<code><mode>3<mask_name>"
- [(set (match_operand:VF_128_256 0 "register_operand" "=x,x,v,v")
- (any_logic:VF_128_256
- (match_operand:VF_128_256 1 "vector_operand" "%0,x,v,v")
- (match_operand:VF_128_256 2 "vector_operand" "xBm,xm,vm,vm")))]
+ [(set (match_operand:VFB_128_256 0 "register_operand" "=x,x,v,v")
+ (any_logic:VFB_128_256
+ (match_operand:VFB_128_256 1 "vector_operand" "%0,x,v,v")
+ (match_operand:VFB_128_256 2 "vector_operand" "xBm,xm,vm,vm")))]
"TARGET_SSE && <mask_avx512vl_condition>
&& !(MEM_P (operands[1]) && MEM_P (operands[2]))"
{
@@ -3956,6 +4292,8 @@
switch (get_attr_mode (insn))
{
+ case MODE_V16HF:
+ case MODE_V8HF:
case MODE_V8SF:
case MODE_V4SF:
suffix = "ps";
@@ -3994,10 +4332,10 @@
(const_string "<MODE>")))])
(define_insn "*<code><mode>3<mask_name>"
- [(set (match_operand:VF_512 0 "register_operand" "=v")
- (any_logic:VF_512
- (match_operand:VF_512 1 "nonimmediate_operand" "%v")
- (match_operand:VF_512 2 "nonimmediate_operand" "vm")))]
+ [(set (match_operand:VFB_512 0 "register_operand" "=v")
+ (any_logic:VFB_512
+ (match_operand:VFB_512 1 "nonimmediate_operand" "%v")
+ (match_operand:VFB_512 2 "nonimmediate_operand" "vm")))]
"TARGET_AVX512F && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
{
char buf[128];
@@ -4007,8 +4345,9 @@
suffix = "<ssemodesuffix>";
ops = "";
- /* There is no v<logic>p[sd] in avx512f. Use vp<logic>[dq]. */
- if (!TARGET_AVX512DQ)
+ /* Since there are no v<logic>p[sd] without AVX512DQ nor v<logic>ph,
+ use vp<logic>[dq]. */
+ if (!TARGET_AVX512DQ || <MODE>mode == V32HFmode)
{
suffix = GET_MODE_INNER (<MODE>mode) == DFmode ? "q" : "d";
ops = "p";
@@ -4029,14 +4368,14 @@
(define_expand "copysign<mode>3"
[(set (match_dup 4)
- (and:VF
- (not:VF (match_dup 3))
- (match_operand:VF 1 "vector_operand")))
+ (and:VFB
+ (not:VFB (match_dup 3))
+ (match_operand:VFB 1 "vector_operand")))
(set (match_dup 5)
- (and:VF (match_dup 3)
- (match_operand:VF 2 "vector_operand")))
- (set (match_operand:VF 0 "register_operand")
- (ior:VF (match_dup 4) (match_dup 5)))]
+ (and:VFB (match_dup 3)
+ (match_operand:VFB 2 "vector_operand")))
+ (set (match_operand:VFB 0 "register_operand")
+ (ior:VFB (match_dup 4) (match_dup 5)))]
"TARGET_SSE"
{
operands[3] = ix86_build_signbit_mask (<MODE>mode, 1, 0);
@@ -4047,11 +4386,11 @@
(define_expand "xorsign<mode>3"
[(set (match_dup 4)
- (and:VF (match_dup 3)
- (match_operand:VF 2 "vector_operand")))
- (set (match_operand:VF 0 "register_operand")
- (xor:VF (match_dup 4)
- (match_operand:VF 1 "vector_operand")))]
+ (and:VFB (match_dup 3)
+ (match_operand:VFB 2 "vector_operand")))
+ (set (match_operand:VFB 0 "register_operand")
+ (xor:VFB (match_dup 4)
+ (match_operand:VFB 1 "vector_operand")))]
"TARGET_SSE"
{
operands[3] = ix86_build_signbit_mask (<MODE>mode, 1, 0);
@@ -4352,7 +4691,11 @@
(V8SF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL")
(V4DF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512VL")
(V16SF "TARGET_AVX512F")
- (V8DF "TARGET_AVX512F")])
+ (V8DF "TARGET_AVX512F")
+ (HF "TARGET_AVX512FP16")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V32HF "TARGET_AVX512FP16")])
(define_expand "fma<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -4429,10 +4772,10 @@
(match_operand:FMAMODE_AVX512 3 "nonimmediate_operand"))))])
(define_expand "<avx512>_fmadd_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_AVX512VL 0 "register_operand")
- (match_operand:VF_AVX512VL 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
(match_operand:<avx512fmaskmode> 4 "register_operand")]
"TARGET_AVX512F && <round_mode512bit_condition>"
{
@@ -4460,16 +4803,20 @@
(set_attr "mode" "<MODE>")])
;; Suppose AVX-512F as baseline
-(define_mode_iterator VF_SF_AVX512VL
- [SF V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
+(define_mode_iterator VFH_SF_AVX512VL
+ [(V32HF "TARGET_AVX512FP16")
+ (V16HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")
+ (HF "TARGET_AVX512FP16")
+ SF V16SF (V8SF "TARGET_AVX512VL") (V4SF "TARGET_AVX512VL")
DF V8DF (V4DF "TARGET_AVX512VL") (V2DF "TARGET_AVX512VL")])
(define_insn "<sd_mask_codefor>fma_fmadd_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (fma:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v")
- (match_operand:VF_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
- (match_operand:VF_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0")))]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (fma:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v")
+ (match_operand:VFH_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
+ (match_operand:VFH_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0")))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
vfmadd132<ssemodesuffix>\t{<round_sd_mask_op4>%2, %3, %0<sd_mask_op4>|%0<sd_mask_op4>, %3, %2<round_sd_mask_op4>}
@@ -4479,13 +4826,13 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fma<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand")
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (match_operand:VF_AVX512VL 4 "vector_operand"))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand")
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (match_operand:VFH_AVX512VL 4 "vector_operand"))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4502,12 +4849,12 @@
})
(define_insn "<avx512>_fmadd_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "register_operand" "0,0")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "register_operand" "0,0")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
"TARGET_AVX512F && <round_mode512bit_condition>"
@@ -4518,12 +4865,12 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmadd_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "<round_nimm_predicate>" "%v")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (match_operand:VF_AVX512VL 3 "register_operand" "0"))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "<round_nimm_predicate>" "%v")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0"))
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
"TARGET_AVX512F"
@@ -4550,10 +4897,10 @@
(set_attr "mode" "<MODE>")])
(define_expand "<avx512>_fmsub_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_AVX512VL 0 "register_operand")
- (match_operand:VF_AVX512VL 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
(match_operand:<avx512fmaskmode> 4 "register_operand")]
"TARGET_AVX512F && <round_mode512bit_condition>"
{
@@ -4564,12 +4911,12 @@
})
(define_insn "<sd_mask_codefor>fma_fmsub_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (fma:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v")
- (match_operand:VF_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
- (neg:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0"))))]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (fma:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v")
+ (match_operand:VFH_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
+ (neg:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0"))))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
vfmsub132<ssemodesuffix>\t{<round_sd_mask_op4>%2, %3, %0<sd_mask_op4>|%0<sd_mask_op4>, %3, %2<round_sd_mask_op4>}
@@ -4579,14 +4926,14 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fms<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand")
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 4 "vector_operand")))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand")
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 4 "vector_operand")))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4603,13 +4950,13 @@
})
(define_insn "<avx512>_fmsub_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "register_operand" "0,0")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "register_operand" "0,0")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")))
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
"TARGET_AVX512F"
@@ -4620,13 +4967,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmsub_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "<round_nimm_predicate>" "%v")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "register_operand" "0")))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "<round_nimm_predicate>" "%v")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0")))
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
"TARGET_AVX512F && <round_mode512bit_condition>"
@@ -4653,10 +5000,10 @@
(set_attr "mode" "<MODE>")])
(define_expand "<avx512>_fnmadd_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_AVX512VL 0 "register_operand")
- (match_operand:VF_AVX512VL 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
(match_operand:<avx512fmaskmode> 4 "register_operand")]
"TARGET_AVX512F && <round_mode512bit_condition>"
{
@@ -4667,12 +5014,12 @@
})
(define_insn "<sd_mask_codefor>fma_fnmadd_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (fma:VF_SF_AVX512VL
- (neg:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v"))
- (match_operand:VF_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
- (match_operand:VF_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0")))]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (fma:VFH_SF_AVX512VL
+ (neg:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v"))
+ (match_operand:VFH_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
+ (match_operand:VFH_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0")))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
vfnmadd132<ssemodesuffix>\t{<round_sd_mask_op4>%2, %3, %0<sd_mask_op4>|%0<sd_mask_op4>, %3, %2<round_sd_mask_op4>}
@@ -4682,14 +5029,14 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fnma<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand"))
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (match_operand:VF_AVX512VL 4 "vector_operand"))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand"))
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (match_operand:VFH_AVX512VL 4 "vector_operand"))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4706,13 +5053,13 @@
})
(define_insn "<avx512>_fnmadd_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "register_operand" "0,0"))
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "register_operand" "0,0"))
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
"TARGET_AVX512F && <round_mode512bit_condition>"
@@ -4723,13 +5070,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fnmadd_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "<round_nimm_predicate>" "%v"))
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (match_operand:VF_AVX512VL 3 "register_operand" "0"))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "<round_nimm_predicate>" "%v"))
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0"))
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
"TARGET_AVX512F && <round_mode512bit_condition>"
@@ -4757,10 +5104,10 @@
(set_attr "mode" "<MODE>")])
(define_expand "<avx512>_fnmsub_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_AVX512VL 0 "register_operand")
- (match_operand:VF_AVX512VL 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
(match_operand:<avx512fmaskmode> 4 "register_operand")]
"TARGET_AVX512F && <round_mode512bit_condition>"
{
@@ -4771,13 +5118,13 @@
})
(define_insn "<sd_mask_codefor>fma_fnmsub_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (fma:VF_SF_AVX512VL
- (neg:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v"))
- (match_operand:VF_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
- (neg:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0"))))]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (fma:VFH_SF_AVX512VL
+ (neg:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 1 "<bcst_round_nimm_predicate>" "%0,0,v"))
+ (match_operand:VFH_SF_AVX512VL 2 "<bcst_round_nimm_predicate>" "<bcst_round_constraint>,v,<bcst_round_constraint>")
+ (neg:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 3 "<bcst_round_nimm_predicate>" "v,<bcst_round_constraint>,0"))))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
vfnmsub132<ssemodesuffix>\t{<round_sd_mask_op4>%2, %3, %0<sd_mask_op4>|%0<sd_mask_op4>, %3, %2<round_sd_mask_op4>}
@@ -4787,15 +5134,15 @@
(set_attr "mode" "<MODE>")])
(define_expand "cond_fnms<mode>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 2 "vector_operand"))
- (match_operand:VF_AVX512VL 3 "vector_operand")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 4 "vector_operand")))
- (match_operand:VF_AVX512VL 5 "nonimm_or_0_operand")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 2 "vector_operand"))
+ (match_operand:VFH_AVX512VL 3 "vector_operand")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 4 "vector_operand")))
+ (match_operand:VFH_AVX512VL 5 "nonimm_or_0_operand")
(match_operand:<avx512fmaskmode> 1 "register_operand")))]
"TARGET_AVX512F"
{
@@ -4812,14 +5159,14 @@
})
(define_insn "<avx512>_fnmsub_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "register_operand" "0,0"))
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "register_operand" "0,0"))
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")))
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
"TARGET_AVX512F && <round_mode512bit_condition>"
@@ -4830,14 +5177,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fnmsub_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (fma:VF_AVX512VL
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 1 "<round_nimm_predicate>" "%v"))
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "register_operand" "0")))
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (fma:VFH_AVX512VL
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 1 "<round_nimm_predicate>" "%v"))
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0")))
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
"TARGET_AVX512F"
@@ -4885,10 +5232,10 @@
"TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F")
(define_expand "<avx512>_fmaddsub_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_AVX512VL 0 "register_operand")
- (match_operand:VF_AVX512VL 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_AVX512VL 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
(match_operand:<avx512fmaskmode> 4 "register_operand")]
"TARGET_AVX512F"
{
@@ -4898,6 +5245,20 @@
DONE;
})
+(define_expand "<avx512>_fmsubadd_<mode>_maskz<round_expand_name>"
+ [(match_operand:VFH_AVX512VL 0 "register_operand")
+ (match_operand:VFH_AVX512VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_AVX512VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskmode> 4 "register_operand")]
+ "TARGET_AVX512F"
+{
+ emit_insn (gen_fma_fmsubadd_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
(define_insn "*fma_fmaddsub_<mode>"
[(set (match_operand:VF_128_256 0 "register_operand" "=v,v,v,x,x")
(unspec:VF_128_256
@@ -4917,11 +5278,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sd_mask_codefor>fma_fmaddsub_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (unspec:VF_SF_AVX512VL
- [(match_operand:VF_SF_AVX512VL 1 "<round_nimm_predicate>" "%0,0,v")
- (match_operand:VF_SF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v,<round_constraint>")
- (match_operand:VF_SF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>,0")]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (unspec:VFH_SF_AVX512VL
+ [(match_operand:VFH_SF_AVX512VL 1 "<round_nimm_predicate>" "%0,0,v")
+ (match_operand:VFH_SF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v,<round_constraint>")
+ (match_operand:VFH_SF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>,0")]
UNSPEC_FMADDSUB))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
@@ -4932,12 +5293,12 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmaddsub_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "register_operand" "0,0")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "register_operand" "0,0")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>")]
UNSPEC_FMADDSUB)
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
@@ -4949,12 +5310,12 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmaddsub_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "register_operand" "v")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (match_operand:VF_AVX512VL 3 "register_operand" "0")]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "register_operand" "v")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0")]
UNSPEC_FMADDSUB)
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
@@ -4983,12 +5344,12 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sd_mask_codefor>fma_fmsubadd_<mode><sd_maskz_name><round_name>"
- [(set (match_operand:VF_SF_AVX512VL 0 "register_operand" "=v,v,v")
- (unspec:VF_SF_AVX512VL
- [(match_operand:VF_SF_AVX512VL 1 "<round_nimm_predicate>" "%0,0,v")
- (match_operand:VF_SF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v,<round_constraint>")
- (neg:VF_SF_AVX512VL
- (match_operand:VF_SF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>,0"))]
+ [(set (match_operand:VFH_SF_AVX512VL 0 "register_operand" "=v,v,v")
+ (unspec:VFH_SF_AVX512VL
+ [(match_operand:VFH_SF_AVX512VL 1 "<round_nimm_predicate>" "%0,0,v")
+ (match_operand:VFH_SF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v,<round_constraint>")
+ (neg:VFH_SF_AVX512VL
+ (match_operand:VFH_SF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>,0"))]
UNSPEC_FMADDSUB))]
"TARGET_AVX512F && <sd_mask_mode512bit_condition> && <round_mode512bit_condition>"
"@
@@ -4999,13 +5360,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmsubadd_<mode>_mask<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v,v")
- (vec_merge:VF_AVX512VL
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "register_operand" "0,0")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v,v")
+ (vec_merge:VFH_AVX512VL
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "register_operand" "0,0")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>,v")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "<round_nimm_predicate>" "v,<round_constraint>"))]
UNSPEC_FMADDSUB)
(match_dup 1)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk,Yk")))]
@@ -5017,13 +5378,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_fmsubadd_<mode>_mask3<round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (vec_merge:VF_AVX512VL
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "register_operand" "v")
- (match_operand:VF_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
- (neg:VF_AVX512VL
- (match_operand:VF_AVX512VL 3 "register_operand" "0"))]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VFH_AVX512VL
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "register_operand" "v")
+ (match_operand:VFH_AVX512VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (neg:VFH_AVX512VL
+ (match_operand:VFH_AVX512VL 3 "register_operand" "0"))]
UNSPEC_FMADDSUB)
(match_dup 3)
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk")))]
@@ -5036,60 +5397,60 @@
;; high-order elements from the destination register.
(define_expand "fmai_vmfmadd_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand")
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>"))
+ [(set (match_operand:VFH_128 0 "register_operand")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>"))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA")
(define_expand "fmai_vmfmsub_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand")
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>")))
+ [(set (match_operand:VFH_128 0 "register_operand")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>")))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA")
(define_expand "fmai_vmfnmadd_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand")
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>"))
- (match_operand:VF_128 1 "register_operand")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>"))
+ [(set (match_operand:VFH_128 0 "register_operand")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>"))
+ (match_operand:VFH_128 1 "register_operand")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>"))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA")
(define_expand "fmai_vmfnmsub_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand")
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>"))
- (match_operand:VF_128 1 "register_operand")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>")))
+ [(set (match_operand:VFH_128 0 "register_operand")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>"))
+ (match_operand:VFH_128 1 "register_operand")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>")))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA")
(define_insn "*fmai_fmadd_<mode>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>, v")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>, v")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA || TARGET_AVX512F"
@@ -5100,13 +5461,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "*fmai_fmsub_<mode>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA || TARGET_AVX512F"
@@ -5117,13 +5478,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "*fmai_fnmadd_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA || TARGET_AVX512F"
@@ -5134,14 +5495,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "*fmai_fnmsub_<mode><round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
(match_dup 1)
(const_int 1)))]
"TARGET_FMA || TARGET_AVX512F"
@@ -5152,13 +5513,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_vmfmadd_<mode>_mask<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
(match_dup 1)
(match_operand:QI 4 "register_operand" "Yk,Yk"))
(match_dup 1)
@@ -5171,13 +5532,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_vmfmadd_<mode>_mask3<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "<round_nimm_scalar_predicate>" "%v")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>")
- (match_operand:VF_128 3 "register_operand" "0"))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "<round_nimm_scalar_predicate>" "%v")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>")
+ (match_operand:VFH_128 3 "register_operand" "0"))
(match_dup 3)
(match_operand:QI 4 "register_operand" "Yk"))
(match_dup 3)
@@ -5188,10 +5549,10 @@
(set_attr "mode" "<MODE>")])
(define_expand "avx512f_vmfmadd_<mode>_maskz<round_expand_name>"
- [(match_operand:VF_128 0 "register_operand")
- (match_operand:VF_128 1 "<round_expand_nimm_predicate>")
- (match_operand:VF_128 2 "<round_expand_nimm_predicate>")
- (match_operand:VF_128 3 "<round_expand_nimm_predicate>")
+ [(match_operand:VFH_128 0 "register_operand")
+ (match_operand:VFH_128 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_128 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_128 3 "<round_expand_nimm_predicate>")
(match_operand:QI 4 "register_operand")]
"TARGET_AVX512F"
{
@@ -5202,14 +5563,14 @@
})
(define_insn "avx512f_vmfmadd_<mode>_maskz_1<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
- (match_operand:VF_128 4 "const0_operand" "C,C")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+ (match_operand:VFH_128 4 "const0_operand" "C,C")
(match_operand:QI 5 "register_operand" "Yk,Yk"))
(match_dup 1)
(const_int 1)))]
@@ -5221,14 +5582,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_vmfmsub_<mode>_mask<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
(match_dup 1)
(match_operand:QI 4 "register_operand" "Yk,Yk"))
(match_dup 1)
@@ -5241,14 +5602,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_vmfmsub_<mode>_mask3<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "<round_nimm_scalar_predicate>" "%v")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>")
- (neg:VF_128
- (match_operand:VF_128 3 "register_operand" "0")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "<round_nimm_scalar_predicate>" "%v")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "register_operand" "0")))
(match_dup 3)
(match_operand:QI 4 "register_operand" "Yk"))
(match_dup 3)
@@ -5259,15 +5620,15 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_vmfmsub_<mode>_maskz_1<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
- (match_operand:VF_128 4 "const0_operand" "C,C")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ (match_operand:VFH_128 4 "const0_operand" "C,C")
(match_operand:QI 5 "register_operand" "Yk,Yk"))
(match_dup 1)
(const_int 1)))]
@@ -5278,15 +5639,15 @@
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
-(define_insn "*avx512f_vmfnmadd_<mode>_mask<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+(define_insn "avx512f_vmfnmadd_<mode>_mask<round_name>"
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
(match_dup 1)
(match_operand:QI 4 "register_operand" "Yk,Yk"))
(match_dup 1)
@@ -5298,15 +5659,15 @@
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
-(define_insn "*avx512f_vmfnmadd_<mode>_mask3<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>"))
- (match_operand:VF_128 1 "<round_nimm_scalar_predicate>" "%v")
- (match_operand:VF_128 3 "register_operand" "0"))
+(define_insn "avx512f_vmfnmadd_<mode>_mask3<round_name>"
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>"))
+ (match_operand:VFH_128 1 "<round_nimm_scalar_predicate>" "%v")
+ (match_operand:VFH_128 3 "register_operand" "0"))
(match_dup 3)
(match_operand:QI 4 "register_operand" "Yk"))
(match_dup 3)
@@ -5316,16 +5677,30 @@
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
-(define_insn "*avx512f_vmfnmadd_<mode>_maskz_1<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
- (match_operand:VF_128 4 "const0_operand" "C,C")
+(define_expand "avx512f_vmfnmadd_<mode>_maskz<round_expand_name>"
+ [(match_operand:VFH_128 0 "register_operand")
+ (match_operand:VFH_128 1 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_128 2 "<round_expand_nimm_predicate>")
+ (match_operand:VFH_128 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512F"
+{
+ emit_insn (gen_avx512f_vmfnmadd_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_insn "avx512f_vmfnmadd_<mode>_maskz_1<round_name>"
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>"))
+ (match_operand:VFH_128 4 "const0_operand" "C,C")
(match_operand:QI 5 "register_operand" "Yk,Yk"))
(match_dup 1)
(const_int 1)))]
@@ -5337,15 +5712,15 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_vmfnmsub_<mode>_mask<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
(match_dup 1)
(match_operand:QI 4 "register_operand" "Yk,Yk"))
(match_dup 1)
@@ -5358,15 +5733,15 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_vmfnmsub_<mode>_mask3<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>"))
- (match_operand:VF_128 1 "<round_nimm_scalar_predicate>" "%v")
- (neg:VF_128
- (match_operand:VF_128 3 "register_operand" "0")))
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>"))
+ (match_operand:VFH_128 1 "<round_nimm_scalar_predicate>" "%v")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "register_operand" "0")))
(match_dup 3)
(match_operand:QI 4 "register_operand" "Yk"))
(match_dup 3)
@@ -5377,16 +5752,16 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_vmfnmsub_<mode>_maskz_1<round_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v,v")
- (vec_merge:VF_128
- (vec_merge:VF_128
- (fma:VF_128
- (neg:VF_128
- (match_operand:VF_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
- (match_operand:VF_128 1 "register_operand" "0,0")
- (neg:VF_128
- (match_operand:VF_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
- (match_operand:VF_128 4 "const0_operand" "C,C")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v,v")
+ (vec_merge:VFH_128
+ (vec_merge:VFH_128
+ (fma:VFH_128
+ (neg:VFH_128
+ (match_operand:VFH_128 2 "<round_nimm_scalar_predicate>" "<round_constraint>,v"))
+ (match_operand:VFH_128 1 "register_operand" "0,0")
+ (neg:VFH_128
+ (match_operand:VFH_128 3 "<round_nimm_scalar_predicate>" "v,<round_constraint>")))
+ (match_operand:VFH_128 4 "const0_operand" "C,C")
(match_operand:QI 5 "register_operand" "Yk,Yk"))
(match_dup 1)
(const_int 1)))]
@@ -5472,6 +5847,1024 @@
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Complex type operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_int_iterator UNSPEC_COMPLEX_F_C_MA
+ [UNSPEC_COMPLEX_FMA UNSPEC_COMPLEX_FCMA])
+
+(define_int_iterator UNSPEC_COMPLEX_F_C_MUL
+ [UNSPEC_COMPLEX_FMUL UNSPEC_COMPLEX_FCMUL])
+
+(define_int_attr complexopname
+ [(UNSPEC_COMPLEX_FMA "fmaddc")
+ (UNSPEC_COMPLEX_FCMA "fcmaddc")
+ (UNSPEC_COMPLEX_FMUL "fmulc")
+ (UNSPEC_COMPLEX_FCMUL "fcmulc")])
+
+(define_mode_attr complexmove
+ [(V32HF "avx512f_loadv16sf")
+ (V16HF "avx512vl_loadv8sf")
+ (V8HF "avx512vl_loadv4sf")])
+
+(define_expand "<avx512>_fmaddc_<mode>_mask1<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+ if (<round_embedded_complex>)
+ emit_insn (gen_<avx512>_fmaddc_<mode>_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ emit_insn (gen_<avx512>_fmaddc_<mode>_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+
+ op0 = lowpart_subreg (<ssePSmode>mode, operands[0], <MODE>mode);
+ op1 = lowpart_subreg (<ssePSmode>mode, operands[1], <MODE>mode);
+ emit_insn (gen_<complexmove>_mask (op0, op0, op1, operands[4]));
+ DONE;
+})
+
+(define_expand "<avx512>_fmaddc_<mode>_maskz<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_fma_fmaddc_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_expand "<avx512>_fcmaddc_<mode>_mask1<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+ if (<round_embedded_complex>)
+ emit_insn (gen_<avx512>_fcmaddc_<mode>_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ {
+ emit_insn (gen_<avx512>_fcmaddc_<mode>_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+ }
+
+ op0 = lowpart_subreg (<ssePSmode>mode, operands[0], <MODE>mode);
+ op1 = lowpart_subreg (<ssePSmode>mode, operands[1], <MODE>mode);
+ emit_insn (gen_<complexmove>_mask (op0, op0, op1, operands[4]));
+ DONE;
+})
+
+(define_expand "<avx512>_fcmaddc_<mode>_maskz<round_expand_name>"
+ [(match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (match_operand:VF_AVX512FP16VL 1 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 2 "<round_expand_nimm_predicate>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_expand_nimm_predicate>")
+ (match_operand:<avx512fmaskcmode> 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_fma_fcmaddc_<mode>_maskz_1<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (<MODE>mode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_insn "fma_<complexopname>_<mode><sdc_maskz_name><round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "<round_nimm_predicate>" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:VF_AVX512FP16VL 3 "<round_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA))]
+ "TARGET_AVX512FP16 && <sdc_mask_mode512bit_condition> && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_sdc_mask_op4>%2, %1, %0<sdc_mask_op4>|%0<sdc_mask_op4>, %1, %2<round_sdc_mask_op4>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<avx512>_<complexopname>_<mode>_mask<round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (vec_merge:VF_AVX512FP16VL
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "<round_constraint>")
+ (match_operand:VF_AVX512FP16VL 3 "register_operand" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 1)
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_op5>%2, %1, %0%{%4%}|%0%{%4%}, %1, %2<round_op5>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<avx512>_<complexopname>_<mode><maskc_name><round_name>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ (unspec:VF_AVX512FP16VL
+ [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "%v")
+ (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "<round_constraint>")]
+ UNSPEC_COMPLEX_F_C_MUL))]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+ "v<complexopname><ssemodesuffix>\t{<round_maskc_op3>%2, %1, %0<maskc_operand3>|%0<maskc_operand3>, %1, %2<round_maskc_op3>}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "avx512fp16_fmaddcsh_v8hf_maskz<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_avx512fp16_fma_fmaddcsh_v8hf_maskz<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (V8HFmode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_expand "avx512fp16_fmaddcsh_v8hf_mask1<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+
+ if (<round_embedded_complex>)
+ emit_insn (gen_avx512fp16_fmaddcsh_v8hf_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ emit_insn (gen_avx512fp16_fmaddcsh_v8hf_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+
+ if (TARGET_AVX512VL)
+ {
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[1], V8HFmode);
+ emit_insn (gen_avx512vl_loadv4sf_mask (op0, op0, op1, operands[4]));
+ }
+ else
+ {
+ rtx mask, tmp, vec_mask;
+ mask = lowpart_subreg (SImode, operands[4], QImode),
+ tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, mask, GEN_INT (31)));
+ vec_mask = gen_reg_rtx (V4SImode);
+ emit_insn (gen_rtx_SET (vec_mask, CONST0_RTX (V4SImode)));
+ emit_insn (gen_vec_setv4si_0 (vec_mask, vec_mask, tmp));
+ vec_mask = lowpart_subreg (V4SFmode, vec_mask, V4SImode);
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[1], V8HFmode);
+ emit_insn (gen_sse4_1_blendvps (op0, op1, op0, vec_mask));
+ }
+ DONE;
+})
+
+(define_expand "avx512fp16_fcmaddcsh_v8hf_maskz<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ emit_insn (gen_avx512fp16_fma_fcmaddcsh_v8hf_maskz<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ CONST0_RTX (V8HFmode), operands[4]<round_expand_operand>));
+ DONE;
+})
+
+(define_expand "avx512fp16_fcmaddcsh_v8hf_mask1<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+
+ if (<round_embedded_complex>)
+ emit_insn (gen_avx512fp16_fcmaddcsh_v8hf_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ emit_insn (gen_avx512fp16_fcmaddcsh_v8hf_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+
+ if (TARGET_AVX512VL)
+ {
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[1], V8HFmode);
+ emit_insn (gen_avx512vl_loadv4sf_mask (op0, op0, op1, operands[4]));
+ }
+ else
+ {
+ rtx mask, tmp, vec_mask;
+ mask = lowpart_subreg (SImode, operands[4], QImode),
+ tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, mask, GEN_INT (31)));
+ vec_mask = gen_reg_rtx (V4SImode);
+ emit_insn (gen_rtx_SET (vec_mask, CONST0_RTX (V4SImode)));
+ emit_insn (gen_vec_setv4si_0 (vec_mask, vec_mask, tmp));
+ vec_mask = lowpart_subreg (V4SFmode, vec_mask, V4SImode);
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[1], V8HFmode);
+ emit_insn (gen_sse4_1_blendvps (op0, op1, op0, vec_mask));
+ }
+ DONE;
+})
+
+(define_expand "avx512fp16_fcmaddcsh_v8hf_mask3<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+
+ if (<round_embedded_complex>)
+ emit_insn (gen_avx512fp16_fcmaddcsh_v8hf_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ emit_insn (gen_avx512fp16_fcmaddcsh_v8hf_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[3], V8HFmode);
+ emit_insn (gen_sse_movss (op0, op1, op0));
+ DONE;
+})
+
+(define_expand "avx512fp16_fmaddcsh_v8hf_mask3<round_expand_name>"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:V8HF 1 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 2 "<round_expand_nimm_predicate>")
+ (match_operand:V8HF 3 "<round_expand_nimm_predicate>")
+ (match_operand:QI 4 "register_operand")]
+ "TARGET_AVX512FP16 && <round_mode512bit_condition>"
+{
+ rtx op0, op1;
+
+ if (<round_embedded_complex>)
+ emit_insn (gen_avx512fp16_fmaddcsh_v8hf_mask<round_expand_name> (
+ operands[0], operands[1], operands[2], operands[3],
+ operands[4]<round_expand_operand>));
+ else
+ emit_insn (gen_avx512fp16_fmaddcsh_v8hf_mask (operands[0],
+ operands[1], operands[2], operands[3], operands[4]));
+
+ op0 = lowpart_subreg (V4SFmode, operands[0], V8HFmode);
+ op1 = lowpart_subreg (V4SFmode, operands[3], V8HFmode);
+ emit_insn (gen_sse_movss (op0, op1, op0));
+ DONE;
+})
+
+(define_insn "avx512fp16_fma_<complexopname>sh_v8hf<mask_scalarcz_name><round_scalarcz_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "<round_scalarcz_nimm_predicate>" "v")
+ (match_operand:V8HF 2 "<round_scalarcz_nimm_predicate>" "<round_scalarcz_constraint>")
+ (match_operand:V8HF 3 "<round_scalarcz_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 2)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_scalarcz_mask_op4>%2, %1, %0<mask_scalarcz_operand4>|%0<mask_scalarcz_operand4>, %1, %2<round_scalarcz_maskcz_mask_op4>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "V8HF")])
+
+(define_insn "avx512fp16_<complexopname>sh_v8hf_mask<round_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "<round_nimm_predicate>" "v")
+ (match_operand:V8HF 2 "<round_nimm_predicate>" "<round_constraint>")
+ (match_operand:V8HF 3 "<round_nimm_predicate>" "0")]
+ UNSPEC_COMPLEX_F_C_MA)
+ (match_dup 1)
+ (unspec:QI [(match_operand:QI 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_op5>%2, %1, %0%{%4%}|%0%{%4%}, %1, %2<round_op5>}"
+ [(set_attr "type" "ssemuladd")
+ (set_attr "mode" "V8HF")])
+
+(define_insn "avx512fp16_<complexopname>sh_v8hf<mask_scalarc_name><round_scalarcz_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=&v")
+ (vec_merge:V8HF
+ (unspec:V8HF
+ [(match_operand:V8HF 1 "nonimmediate_operand" "v")
+ (match_operand:V8HF 2 "<round_scalarcz_nimm_predicate>" "<round_scalarcz_constraint>")]
+ UNSPEC_COMPLEX_F_C_MUL)
+ (match_dup 1)
+ (const_int 3)))]
+ "TARGET_AVX512FP16"
+ "v<complexopname>sh\t{<round_scalarc_mask_op3>%2, %1, %0<mask_scalarc_operand3>|%0<mask_scalarc_operand3>, %1, %2<round_scalarc_mask_op3>}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V8HF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel half-precision floating point conversion operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_int_iterator UNSPEC_US_FIX_NOTRUNC
+ [UNSPEC_UNSIGNED_FIX_NOTRUNC UNSPEC_FIX_NOTRUNC])
+
+(define_int_attr sseintconvertsignprefix
+ [(UNSPEC_UNSIGNED_FIX_NOTRUNC "u")
+ (UNSPEC_FIX_NOTRUNC "")])
+
+(define_mode_attr qq2phsuff
+ [(V32HI "") (V16HI "") (V8HI "")
+ (V16SI "") (V8SI "{y}") (V4SI "{x}")
+ (V8DI "{z}") (V4DI "{y}") (V2DI "{x}")
+ (V16SF "") (V8SF "{y}") (V4SF "{x}")
+ (V8DF "{z}") (V4DF "{y}") (V2DF "{x}")])
+
+(define_insn "avx512fp16_vcvtph2<sseintconvertsignprefix><sseintconvert>_<mode><mask_name><round_name>"
+ [(set (match_operand:VI248_AVX512VL 0 "register_operand" "=v")
+ (unspec:VI248_AVX512VL
+ [(match_operand:<ssePHmode> 1 "<round_nimm_predicate>" "<round_constraint>")]
+ UNSPEC_US_FIX_NOTRUNC))]
+ "TARGET_AVX512FP16"
+ "vcvtph2<sseintconvertsignprefix><sseintconvert>\t{<round_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_mask_op2>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "float<floatunssuffix><mode><ssePHmodelower>2"
+ [(set (match_operand:<ssePHmode> 0 "register_operand")
+ (any_float:<ssePHmode>
+ (match_operand:VI2H_AVX512VL 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
+(define_insn "avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode><mask_name><round_name>"
+ [(set (match_operand:<ssePHmode> 0 "register_operand" "=v")
+ (any_float:<ssePHmode>
+ (match_operand:VI2H_AVX512VL 1 "<round_nimm_predicate>" "<round_constraint>")))]
+ "TARGET_AVX512FP16"
+ "vcvt<floatsuffix><sseintconvert>2ph<round_qq2phsuff>\t{<round_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_mask_op2>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "float<floatunssuffix><mode>v4hf2"
+ [(set (match_operand:V4HF 0 "register_operand")
+ (any_float:V4HF
+ (match_operand:VI4_128_8_256 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V4HFmode);
+ emit_insn (gen_avx512fp16_float<floatunssuffix><mode>v4hf2 (operands[0],
+ operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_float<floatunssuffix><mode>v4hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
+ (vec_concat:V8HF
+ (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand"))
+ (match_dup 2)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[2] = CONST0_RTX (V4HFmode);")
+
+(define_insn "*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand" "vm"))
+ (match_operand:V4HF 2 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix><sseintconvert>2ph<qq2phsuff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand" "vm"))
+ (vec_select:V4HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_dup 4)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[4] = CONST0_RTX (V4HFmode);")
+
+(define_insn "*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (any_float:V4HF (match_operand:VI4_128_8_256 1 "vector_operand" "vm"))
+ (vec_select:V4HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_operand:V4HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix><sseintconvert>2ph<qq2phsuff>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512fp16_vcvt<floatsuffix><sseintconvert>2ph_<mode>_mask_1"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (any_float:V4HF (match_operand:VI4_128_8_256 1
+ "vector_operand" "vm"))
+ (match_operand:V4HF 3 "const0_operand" "C")
+ (match_operand:QI 2 "register_operand" "Yk"))
+ (match_operand:V4HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix><sseintconvert>2ph<qq2phsuff>\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "float<floatunssuffix>v2div2hf2"
+ [(set (match_operand:V2HF 0 "register_operand")
+ (any_float:V2HF
+ (match_operand:V2DI 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V2HFmode);
+ emit_insn (gen_avx512fp16_float<floatunssuffix>v2div2hf2 (operands[0],
+ operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_float<floatunssuffix>v2div2hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
+ (vec_concat:V8HF
+ (any_float:V2HF (match_operand:V2DI 1 "vector_operand"))
+ (match_dup 2)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[2] = CONST0_RTX (V6HFmode);")
+
+(define_insn "*avx512fp16_vcvt<floatsuffix>qq2ph_v2di"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (any_float:V2HF (match_operand:V2DI 1 "vector_operand" "vm"))
+ (match_operand:V6HF 2 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix>qq2ph{x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_expand "avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (any_float:V2HF (match_operand:V2DI 1 "vector_operand" "vm"))
+ (vec_select:V2HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_dup 4)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[4] = CONST0_RTX (V6HFmode);")
+
+(define_insn "*avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (any_float:V2HF (match_operand:V2DI 1 "vector_operand" "vm"))
+ (vec_select:V2HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_operand:V6HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix>qq2ph{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "*avx512fp16_vcvt<floatsuffix>qq2ph_v2di_mask_1"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (any_float:V2HF (match_operand:V2DI 1
+ "vector_operand" "vm"))
+ (match_operand:V2HF 3 "const0_operand" "C")
+ (match_operand:QI 2 "register_operand" "Yk"))
+ (match_operand:V6HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<floatsuffix>qq2ph{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_vcvtsh2<sseintconvertsignprefix>si<rex64namesuffix><round_name>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec:SWI48
+ [(vec_select:HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0)]))]
+ UNSPEC_US_FIX_NOTRUNC))]
+ "TARGET_AVX512FP16"
+ "vcvtsh2<sseintconvertsignprefix>si\t{<round_op2>%1, %0|%0, %1<round_op2>}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512fp16_vcvtsh2<sseintconvertsignprefix>si<rex64namesuffix>_2"
+ [(set (match_operand:SWI48 0 "register_operand" "=r,r")
+ (unspec:SWI48
+ [(match_operand:HF 1 "nonimmediate_operand" "v,m")]
+ UNSPEC_US_FIX_NOTRUNC))]
+ "TARGET_AVX512FP16"
+ "vcvtsh2<sseintconvertsignprefix>si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_mode_attr sseicvtsuffix
+ [(SI "l") (DI "q")])
+(define_insn "avx512fp16_vcvt<floatsuffix>si2sh<rex64namesuffix><round_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (vec_duplicate:V8HF
+ (any_float:HF
+ (match_operand:SWI48 2 "<round_nimm_scalar_predicate>" "<round_constraint3>")))
+ (match_operand:V8HF 1 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vcvt<floatsuffix>si2sh{<sseicvtsuffix>}\t{%2, <round_op3>%1, %0|%0, %1<round_op3>, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
+(define_expand "fix<fixunssuffix>_trunc<ssePHmodelower><mode>2"
+ [(set (match_operand:VI2H_AVX512VL 0 "register_operand")
+ (any_fix:VI2H_AVX512VL
+ (match_operand:<ssePHmode> 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
+(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name><round_saeonly_name>"
+ [(set (match_operand:VI2H_AVX512VL 0 "register_operand" "=v")
+ (any_fix:VI2H_AVX512VL
+ (match_operand:<ssePHmode> 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")))]
+ "TARGET_AVX512FP16"
+ "vcvttph2<fixsuffix><sseintconvert>\t{<round_saeonly_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_saeonly_mask_op2>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "fix<fixunssuffix>_truncv4hf<mode>2"
+ [(set (match_operand:VI4_128_8_256 0 "register_operand")
+ (any_fix:VI4_128_8_256
+ (match_operand:V4HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V4HFmode);
+ emit_insn (gen_avx512fp16_fix<fixunssuffix>_trunc<mode>2 (operands[0],
+ operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2<mask_name>"
+ [(set (match_operand:VI4_128_8_256 0 "register_operand" "=v")
+ (any_fix:VI4_128_8_256
+ (vec_select:V4HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)]))))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvttph2<fixsuffix><sseintconvert>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512fp16_fix<fixunssuffix>_trunc<mode>2_load<mask_name>"
+ [(set (match_operand:VI4_128_8_256 0 "register_operand" "=v")
+ (any_fix:VI4_128_8_256
+ (match_operand:V4HF 1 "memory_operand" "m")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvttph2<fixsuffix><sseintconvert>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "fix<fixunssuffix>_truncv2hfv2di2"
+ [(set (match_operand:V2DI 0 "register_operand")
+ (any_fix:V2DI
+ (match_operand:V2HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V2HFmode);
+ emit_insn (gen_avx512fp16_fix<fixunssuffix>_truncv2di2 (operands[0],
+ operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "avx512fp16_fix<fixunssuffix>_truncv2di2<mask_name>"
+ [(set (match_operand:V2DI 0 "register_operand" "=v")
+ (any_fix:V2DI
+ (vec_select:V2HF
+ (match_operand:V8HF 1 "nonimmediate_operand" "v")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvttph2<fixsuffix>qq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "*avx512fp16_fix<fixunssuffix>_truncv2di2_load<mask_name>"
+ [(set (match_operand:V2DI 0 "register_operand" "=v")
+ (any_fix:V2DI
+ (match_operand:V2HF 1 "memory_operand" "m")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvttph2<fixsuffix>qq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %k1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2<round_saeonly_name>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (any_fix:SWI48
+ (vec_select:HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512FP16"
+ "%vcvttsh2<fixsuffix>si\t{<round_saeonly_op2>%1, %0|%0, %k1<round_saeonly_op2>}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512fp16_fix<fixunssuffix>_trunc<mode>2_mem"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (any_fix:SWI48
+ (match_operand:HF 1 "memory_operand" "vm")))]
+ "TARGET_AVX512FP16"
+ "%vcvttsh2<fixsuffix>si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_mode_attr ph2pssuffix
+ [(V16SF "x") (V8SF "x") (V4SF "x")
+ (V8DF "") (V4DF "") (V2DF "")])
+
+(define_expand "extend<ssePHmodelower><mode>2"
+ [(set (match_operand:VF48H_AVX512VL 0 "register_operand")
+ (float_extend:VF48H_AVX512VL
+ (match_operand:<ssePHmode> 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
+(define_insn "avx512fp16_float_extend_ph<mode>2<mask_name><round_saeonly_name>"
+ [(set (match_operand:VF48H_AVX512VL 0 "register_operand" "=v")
+ (float_extend:VF48H_AVX512VL
+ (match_operand:<ssePHmode> 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")))]
+ "TARGET_AVX512FP16"
+ "vcvtph2<castmode><ph2pssuffix>\t{<round_saeonly_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_saeonly_mask_op2>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "extendv4hf<mode>2"
+ [(set (match_operand:VF4_128_8_256 0 "register_operand")
+ (float_extend:VF4_128_8_256
+ (match_operand:V4HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V4HFmode);
+ emit_insn (gen_avx512fp16_float_extend_ph<mode>2
+ (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "avx512fp16_float_extend_ph<mode>2<mask_name>"
+ [(set (match_operand:VF4_128_8_256 0 "register_operand" "=v")
+ (float_extend:VF4_128_8_256
+ (vec_select:V4HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)]))))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtph2<castmode><ph2pssuffix>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512fp16_float_extend_ph<mode>2_load<mask_name>"
+ [(set (match_operand:VF4_128_8_256 0 "register_operand" "=v")
+ (float_extend:VF4_128_8_256
+ (match_operand:V4HF 1 "memory_operand" "m")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtph2<castmode><ph2pssuffix>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "extendv2hfv2df2"
+ [(set (match_operand:V2DF 0 "register_operand")
+ (float_extend:V2DF
+ (match_operand:V2HF 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ if (!MEM_P (operands[1]))
+ {
+ operands[1] = lowpart_subreg (V8HFmode, operands[1], V2HFmode);
+ emit_insn (gen_avx512fp16_float_extend_phv2df2
+ (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "avx512fp16_float_extend_phv2df2<mask_name>"
+ [(set (match_operand:V2DF 0 "register_operand" "=v")
+ (float_extend:V2DF
+ (vec_select:V2HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtph2pd\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "*avx512fp16_float_extend_phv2df2_load<mask_name>"
+ [(set (match_operand:V2DF 0 "register_operand" "=v")
+ (float_extend:V2DF
+ (match_operand:V2HF 1 "memory_operand" "m")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtph2pd\t{%1, %0<mask_operand2>|%0<mask_operand2>, %k1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_expand "trunc<mode><ssePHmodelower>2"
+ [(set (match_operand:<ssePHmode> 0 "register_operand")
+ (float_truncate:<ssePHmode>
+ (match_operand:VF48H_AVX512VL 1 "nonimmediate_operand")))]
+ "TARGET_AVX512FP16")
+
+(define_insn "avx512fp16_vcvt<castmode>2ph_<mode><mask_name><round_name>"
+ [(set (match_operand:<ssePHmode> 0 "register_operand" "=v")
+ (float_truncate:<ssePHmode>
+ (match_operand:VF48H_AVX512VL 1 "<round_nimm_predicate>" "<round_constraint>")))]
+ "TARGET_AVX512FP16"
+ "vcvt<castmode>2ph<ph2pssuffix><round_qq2phsuff>\t{<round_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_mask_op2>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "trunc<mode>v4hf2"
+ [(set (match_operand:V4HF 0 "register_operand")
+ (float_truncate:V4HF (match_operand:VF4_128_8_256 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V4HFmode);
+ emit_insn (gen_avx512fp16_trunc<mode>v4hf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_trunc<mode>v4hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
+ (vec_concat:V8HF
+ (float_truncate:V4HF
+ (match_operand:VF4_128_8_256 1 "vector_operand"))
+ (match_dup 2)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[2] = CONST0_RTX (V4HFmode);")
+
+(define_insn "*avx512fp16_vcvt<castmode>2ph_<mode>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (float_truncate:V4HF
+ (match_operand:VF4_128_8_256 1 "vector_operand" "vm"))
+ (match_operand:V4HF 2 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<castmode>2ph<ph2pssuffix><qq2phsuff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "avx512fp16_vcvt<castmode>2ph_<mode>_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (float_truncate:V4HF
+ (match_operand:VF4_128_8_256 1 "vector_operand" "vm"))
+ (vec_select:V4HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_dup 4)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[4] = CONST0_RTX (V4HFmode);")
+
+(define_insn "*avx512fp16_vcvt<castmode>2ph_<mode>_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (float_truncate:V4HF
+ (match_operand:VF4_128_8_256 1 "vector_operand" "vm"))
+ (vec_select:V4HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_operand:V4HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<castmode>2ph<ph2pssuffix><qq2phsuff>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512fp16_vcvt<castmode>2ph_<mode>_mask_1"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V4HF
+ (float_truncate:V4HF
+ (match_operand:VF4_128_8_256 1 "vector_operand" "vm"))
+ (match_operand:V4HF 3 "const0_operand" "C")
+ (match_operand:QI 2 "register_operand" "Yk"))
+ (match_operand:V4HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvt<castmode>2ph<ph2pssuffix><qq2phsuff>\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "truncv2dfv2hf2"
+ [(set (match_operand:V2HF 0 "register_operand")
+ (float_truncate:V2HF (match_operand:V2DF 1 "vector_operand")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+{
+ operands[0] = lowpart_subreg (V8HFmode, operands[0], V2HFmode);
+ emit_insn (gen_avx512fp16_truncv2dfv2hf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "avx512fp16_truncv2dfv2hf2"
+ [(set (match_operand:V8HF 0 "register_operand")
+ (vec_concat:V8HF
+ (float_truncate:V2HF (match_operand:V2DF 1 "vector_operand"))
+ (match_dup 2)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[2] = CONST0_RTX (V6HFmode);")
+
+(define_insn "*avx512fp16_vcvtpd2ph_v2df"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (float_truncate:V2HF
+ (match_operand:V2DF 1 "vector_operand" "vm"))
+ (match_operand:V6HF 2 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtpd2ph{x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_expand "avx512fp16_vcvtpd2ph_v2df_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (float_truncate:V2HF
+ (match_operand:V2DF 1 "vector_operand" "vm"))
+ (vec_select:V2HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_dup 4)))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "operands[4] = CONST0_RTX (V6HFmode);")
+
+(define_insn "*avx512fp16_vcvtpd2ph_v2df_mask"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (float_truncate:V2HF (match_operand:V2DF 1 "vector_operand" "vm"))
+ (vec_select:V2HF
+ (match_operand:V8HF 2 "nonimm_or_0_operand" "0C")
+ (parallel [(const_int 0) (const_int 1)]))
+ (match_operand:QI 3 "register_operand" "Yk"))
+ (match_operand:V6HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtpd2ph{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "*avx512fp16_vcvtpd2ph_v2df_mask_1"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_concat:V8HF
+ (vec_merge:V2HF
+ (float_truncate:V2HF
+ (match_operand:V2DF 1 "vector_operand" "vm"))
+ (match_operand:V2HF 3 "const0_operand" "C")
+ (match_operand:QI 2 "register_operand" "Yk"))
+ (match_operand:V6HF 4 "const0_operand" "C")))]
+ "TARGET_AVX512FP16 && TARGET_AVX512VL"
+ "vcvtpd2ph{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_vcvtsh2<ssescalarmodesuffix><mask_scalar_name><round_saeonly_scalar_name>"
+ [(set (match_operand:VF48_128 0 "register_operand" "=v")
+ (vec_merge:VF48_128
+ (vec_duplicate:VF48_128
+ (float_extend:<ssescalarmode>
+ (vec_select:HF
+ (match_operand:V8HF 1 "register_operand" "v")
+ (parallel [(const_int 0)]))))
+ (match_operand:VF48_128 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vcvtsh2<ssescalarmodesuffix>\t{<round_saeonly_scalar_mask_op3>%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %1<round_saeonly_scalar_mask_op3>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_vcvtsh2<ssescalarmodesuffix><mask_scalar_name>_mem"
+ [(set (match_operand:VF48_128 0 "register_operand" "=v")
+ (vec_merge:VF48_128
+ (vec_duplicate:VF48_128
+ (float_extend:<ssescalarmode>
+ (match_operand:HF 1 "memory_operand" "m")))
+ (match_operand:VF48_128 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vcvtsh2<ssescalarmodesuffix>\t{%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_vcvt<ssescalarmodesuffix>2sh<mask_scalar_name><round_scalar_name>"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (vec_duplicate:V8HF
+ (float_truncate:HF
+ (vec_select:<ssescalarmode>
+ (match_operand:VF48_128 1 "register_operand" "v")
+ (parallel [(const_int 0)]))))
+ (match_operand:V8HF 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vcvt<ssescalarmodesuffix>2sh\t{<round_scalar_mask_op3>%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %1<round_scalar_mask_op3>}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "avx512fp16_vcvt<ssescalarmodesuffix>2sh<mask_scalar_name>_mem"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (vec_duplicate:V8HF
+ (float_truncate:HF
+ (match_operand:MODEF 1 "memory_operand" "m")))
+ (match_operand:V8HF 2 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vcvt<ssescalarmodesuffix>2sh\t{%1, %2, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %2, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel single-precision floating point conversion operations
@@ -8576,6 +9969,47 @@
]
(symbol_ref "true")))])
+;; vmovw clears also the higer bits
+(define_insn "vec_set<mode>_0"
+ [(set (match_operand:VI2F 0 "register_operand" "=v,v")
+ (vec_merge:VI2F
+ (vec_duplicate:VI2F
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "r,m"))
+ (match_operand:VI2F 1 "const0_operand" "C,C")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "@
+ vmovw\t{%k2, %x0|%x0, %k2}
+ vmovw\t{%2, %x0|%x0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
+(define_insn "*avx512fp16_movsh"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (vec_duplicate:V8HF
+ (match_operand:HF 2 "register_operand" "v"))
+ (match_operand:V8HF 1 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vmovsh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
+(define_insn "avx512fp16_movsh"
+ [(set (match_operand:V8HF 0 "register_operand" "=v")
+ (vec_merge:V8HF
+ (match_operand:V8HF 2 "register_operand" "v")
+ (match_operand:V8HF 1 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512FP16"
+ "vmovsh\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "HF")])
+
;; A subset is vec_setv4sf.
(define_insn "*vec_setv4sf_sse4_1"
[(set (match_operand:V4SF 0 "register_operand" "=Yr,*x,v")
@@ -8711,6 +10145,20 @@
DONE;
})
+(define_expand "vec_setv8hf"
+ [(match_operand:V8HF 0 "register_operand")
+ (match_operand:HF 1 "register_operand")
+ (match_operand 2 "vec_setm_sse41_operand")]
+ "TARGET_SSE"
+{
+ 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;
+})
+
(define_expand "vec_set<mode>"
[(match_operand:V_256_512 0 "register_operand")
(match_operand:<ssescalarmode> 1 "register_operand")
@@ -8795,7 +10243,8 @@
[(V16SF "avx512f") (V16SI "avx512f") (V8DF "avx512dq") (V8DI "avx512dq")])
(define_mode_attr extract_suf
- [(V16SF "32x4") (V16SI "32x4") (V8DF "64x2") (V8DI "64x2")])
+ [(V16SF "32x4") (V16SI "32x4") (V8DF "64x2") (V8DI "64x2")
+ (V8SF "32x4") (V8SI "32x4") (V4DF "64x2") (V4DI "64x2")])
(define_mode_iterator AVX512_VEC
[(V8DF "TARGET_AVX512DQ") (V8DI "TARGET_AVX512DQ") V16SF V16SI])
@@ -9173,7 +10622,7 @@
(define_expand "avx_vextractf128<mode>"
[(match_operand:<ssehalfvecmode> 0 "nonimmediate_operand")
- (match_operand:V_256 1 "register_operand")
+ (match_operand:V_256H 1 "register_operand")
(match_operand:SI 2 "const_0_to_1_operand")]
"TARGET_AVX"
{
@@ -9426,10 +10875,10 @@
(set_attr "length_immediate" "1")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn_and_split "vec_extract_lo_v32hi"
- [(set (match_operand:V16HI 0 "nonimmediate_operand" "=v,v,m")
- (vec_select:V16HI
- (match_operand:V32HI 1 "nonimmediate_operand" "v,m,v")
+(define_insn_and_split "vec_extract_lo_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,v,m")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V32_512 1 "nonimmediate_operand" "v,m,v")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)
(const_int 4) (const_int 5)
@@ -9456,9 +10905,10 @@
if (!TARGET_AVX512VL
&& REG_P (operands[0])
&& EXT_REX_SSE_REG_P (operands[1]))
- operands[0] = lowpart_subreg (V32HImode, operands[0], V16HImode);
+ operands[0] = lowpart_subreg (<MODE>mode, operands[0],
+ <ssehalfvecmode>mode);
else
- operands[1] = gen_lowpart (V16HImode, operands[1]);
+ operands[1] = gen_lowpart (<ssehalfvecmode>mode, operands[1]);
}
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
@@ -9467,10 +10917,10 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_insn "vec_extract_hi_v32hi"
- [(set (match_operand:V16HI 0 "nonimmediate_operand" "=vm")
- (vec_select:V16HI
- (match_operand:V32HI 1 "register_operand" "v")
+(define_insn "vec_extract_hi_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V32_512 1 "register_operand" "v")
(parallel [(const_int 16) (const_int 17)
(const_int 18) (const_int 19)
(const_int 20) (const_int 21)
@@ -9487,10 +10937,10 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_insn_and_split "vec_extract_lo_v16hi"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=v,m")
- (vec_select:V8HI
- (match_operand:V16HI 1 "nonimmediate_operand" "vm,v")
+(define_insn_and_split "vec_extract_lo_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,m")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16_256 1 "nonimmediate_operand" "vm,v")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)
(const_int 4) (const_int 5)
@@ -9499,12 +10949,12 @@
"#"
"&& reload_completed"
[(set (match_dup 0) (match_dup 1))]
- "operands[1] = gen_lowpart (V8HImode, operands[1]);")
+ "operands[1] = gen_lowpart (<ssehalfvecmode>mode, operands[1]);")
-(define_insn "vec_extract_hi_v16hi"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=xm,vm,vm")
- (vec_select:V8HI
- (match_operand:V16HI 1 "register_operand" "x,v,v")
+(define_insn "vec_extract_hi_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xm,vm,vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16_256 1 "register_operand" "x,v,v")
(parallel [(const_int 8) (const_int 9)
(const_int 10) (const_int 11)
(const_int 12) (const_int 13)
@@ -9640,12 +11090,57 @@
(set_attr "prefix" "vex,evex,evex")
(set_attr "mode" "OI")])
+;; NB: *vec_extract<mode>_0 must be placed before *vec_extracthf.
+;; Otherwise, it will be ignored.
+(define_insn_and_split "*vec_extract<mode>_0"
+ [(set (match_operand:HF 0 "nonimmediate_operand" "=v,m,r")
+ (vec_select:HF
+ (match_operand:VF_AVX512FP16 1 "nonimmediate_operand" "vm,v,m")
+ (parallel [(const_int 0)])))]
+ "TARGET_AVX512FP16 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+ "operands[1] = gen_lowpart (HFmode, operands[1]);")
+
+(define_insn "*vec_extracthf"
+ [(set (match_operand:HF 0 "register_sse4nonimm_operand" "=*r,m,x,v")
+ (vec_select:HF
+ (match_operand:V8HF 1 "register_operand" "v,v,0,v")
+ (parallel
+ [(match_operand:SI 2 "const_0_to_7_operand")])))]
+ "TARGET_SSE2"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "vpextrw\t{%2, %1, %k0|%k0, %1, %2}";
+ case 1:
+ return "vpextrw\t{%2, %1, %0|%0, %1, %2}";
+
+ case 2:
+ operands[2] = GEN_INT (INTVAL (operands[2]) * 2);
+ return "psrldq\t{%2, %0|%0, %2}";
+ case 3:
+ operands[2] = GEN_INT (INTVAL (operands[2]) * 2);
+ return "vpsrldq\t{%2, %1, %0|%0, %1, %2}";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "isa" "*,*,noavx,avx")
+ (set_attr "type" "sselog1,sselog1,sseishft1,sseishft1")
+ (set_attr "prefix" "maybe_evex")
+ (set_attr "mode" "TI")])
+
;; Modes handled by vec_extract patterns.
(define_mode_iterator VEC_EXTRACT_MODE
[(V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX") V16QI
(V32HI "TARGET_AVX512BW") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V32HF "TARGET_AVX512BW") (V16HF "TARGET_AVX") V8HF
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF
(V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
@@ -9990,11 +11485,11 @@
})
(define_insn "avx512f_vmscalef<mode><mask_scalar_name><round_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (unspec:VF_128
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_scalar_nimm_predicate>" "<round_scalar_constraint>")]
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (unspec:VFH_128
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_scalar_nimm_predicate>" "<round_scalar_constraint>")]
UNSPEC_SCALEF)
(match_dup 1)
(const_int 1)))]
@@ -10004,10 +11499,10 @@
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<avx512>_scalef<mode><mask_name><round_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "register_operand" "v")
- (match_operand:VF_AVX512VL 2 "nonimmediate_operand" "<round_constraint>")]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "register_operand" "v")
+ (match_operand:VFH_AVX512VL 2 "nonimmediate_operand" "<round_constraint>")]
UNSPEC_SCALEF))]
"TARGET_AVX512F"
"vscalef<ssemodesuffix>\t{<round_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2<round_mask_op3>}"
@@ -10293,8 +11788,8 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<avx512>_getexp<mode><mask_name><round_saeonly_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (unspec:VF_AVX512VL [(match_operand:VF_AVX512VL 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")]
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (unspec:VFH_AVX512VL [(match_operand:VFH_AVX512VL 1 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")]
UNSPEC_GETEXP))]
"TARGET_AVX512F"
"vgetexp<ssemodesuffix>\t{<round_saeonly_mask_op2>%1, %0<mask_operand2>|%0<mask_operand2>, %1<round_saeonly_mask_op2>}";
@@ -10302,11 +11797,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_sgetexp<mode><mask_scalar_name><round_saeonly_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (unspec:VF_128
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")]
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (unspec:VFH_128
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")]
UNSPEC_GETEXP)
(match_dup 1)
(const_int 1)))]
@@ -10326,6 +11821,35 @@
[(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_mode_attr vec_extract_imm_predicate
+ [(V16SF "const_0_to_15_operand") (V8SF "const_0_to_7_operand")
+ (V16SI "const_0_to_15_operand") (V8SI "const_0_to_7_operand")
+ (V8DF "const_0_to_7_operand") (V4DF "const_0_to_3_operand")
+ (V8DI "const_0_to_7_operand") (V4DI "const_0_to_3_operand")])
+
+(define_insn "*vec_extract<mode><ssescalarmodelower>_valign"
+ [(set (match_operand:<ssescalarmode> 0 "register_operand" "=v")
+ (vec_select:<ssescalarmode>
+ (match_operand:V48_256_512_AVX512VL 1 "register_operand" "v")
+ (parallel [(match_operand 2 "<vec_extract_imm_predicate>")])))]
+ "TARGET_AVX512F
+ && INTVAL(operands[2]) * GET_MODE_SIZE (<ssescalarmode>mode) >= 16"
+{
+ int byte_offset = INTVAL (operands[2]) * GET_MODE_SIZE (<ssescalarmode>mode);
+ if (byte_offset % 16 == 0)
+ {
+ operands[2] = GEN_INT (byte_offset / 16);
+ if (byte_offset / 16 == 1)
+ return "vextract<shuffletype><extract_suf>\t{%2, %t1, %x0|%x0, %t1, %2}";
+ else
+ return "vextract<shuffletype><extract_suf>\t{%2, %1, %x0|%x0, %1, %2}";
+ }
+ else
+ return "valign<ternlogsuffix>\t{%2, %1, %1, %<xtg_mode>0|%<xtg_mode>0, %1, %1, %2}";
+}
+ [(set_attr "prefix" "maybe_evex")
+ (set_attr "mode" "<sseintvecinsnmode>")])
+
(define_expand "avx512f_shufps512_mask"
[(match_operand:V16SF 0 "register_operand")
(match_operand:V16SF 1 "register_operand")
@@ -10455,9 +11979,9 @@
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<avx512>_rndscale<mode><mask_name><round_saeonly_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "nonimmediate_operand" "<round_saeonly_constraint>")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "nonimmediate_operand" "<round_saeonly_constraint>")
(match_operand:SI 2 "const_0_to_255_operand")]
UNSPEC_ROUND))]
"TARGET_AVX512F"
@@ -10467,13 +11991,13 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_rndscale<mode><mask_scalar_name><round_saeonly_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (unspec:VF_128
- [(match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (unspec:VFH_128
+ [(match_operand:VFH_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
(match_operand:SI 3 "const_0_to_255_operand")]
UNSPEC_ROUND)
- (match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VFH_128 1 "register_operand" "v")
(const_int 1)))]
"TARGET_AVX512F"
"vrndscale<ssescalarmodesuffix>\t{%3, <round_saeonly_scalar_mask_op4>%2, %1, %0<mask_scalar_operand4>|%0<mask_scalar_operand4>, %1, %<iptr>2<round_saeonly_scalar_mask_op4>, %3}"
@@ -10482,14 +12006,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "*avx512f_rndscale<mode><round_saeonly_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(unspec:<ssescalarmode>
[(match_operand:<ssescalarmode> 2 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")
(match_operand:SI 3 "const_0_to_255_operand")]
UNSPEC_ROUND))
- (match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VFH_128 1 "register_operand" "v")
(const_int 1)))]
"TARGET_AVX512F"
"vrndscale<ssescalarmodesuffix>\t{%3, <round_saeonly_op4>%2, %1, %0|%0, %1, %2<round_saeonly_op4>, %3}"
@@ -11233,6 +12757,33 @@
(truncate:V16HI (match_dup 1)))]
"operands[1] = lowpart_subreg (V16SImode, operands[1], V32HImode);")
+(define_insn_and_split "*avx512bw_permvar_truncv16siv16hi_1_hf"
+ [(set (match_operand:V16HF 0 "nonimmediate_operand")
+ (vec_select:V16HF
+ (subreg:V32HF
+ (unspec:V32HI
+ [(match_operand:V32HI 1 "register_operand")
+ (match_operand:V32HI 2 "permvar_truncate_operand")]
+ UNSPEC_VPERMVAR) 0)
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)])))]
+ "TARGET_AVX512BW && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (truncate:V16HI (match_dup 1)))]
+{
+ operands[0] = lowpart_subreg (V16HImode, operands[0], V16HFmode);
+ operands[1] = lowpart_subreg (V16SImode, operands[1], V32HImode);
+})
+
+
(define_insn_and_split "*avx512f_permvar_truncv8siv8hi_1"
[(set (match_operand:V8HI 0 "nonimmediate_operand")
(vec_select:V8HI
@@ -11251,6 +12802,28 @@
(truncate:V8HI (match_dup 1)))]
"operands[1] = lowpart_subreg (V8SImode, operands[1], V16HImode);")
+(define_insn_and_split "*avx512f_permvar_truncv8siv8hi_1_hf"
+ [(set (match_operand:V8HF 0 "nonimmediate_operand")
+ (vec_select:V8HF
+ (subreg:V16HF
+ (unspec:V16HI
+ [(match_operand:V16HI 1 "register_operand")
+ (match_operand:V16HI 2 "permvar_truncate_operand")]
+ UNSPEC_VPERMVAR) 0)
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "TARGET_AVX512VL && TARGET_AVX512BW && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (truncate:V8HI (match_dup 1)))]
+{
+ operands[0] = lowpart_subreg (V8HImode, operands[0], V8HFmode);
+ operands[1] = lowpart_subreg (V8SImode, operands[1], V16HImode);
+})
+
(define_insn_and_split "*avx512f_vpermvar_truncv8div8si_1"
[(set (match_operand:V8SI 0 "nonimmediate_operand")
(vec_select:V8SI
@@ -13801,24 +15374,6 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn_and_split "*avx2_eq<mode>3"
- [(set (match_operand:VI_128_256 0 "register_operand")
- (vec_merge:VI_128_256
- (match_operand:VI_128_256 1 "vector_all_ones_operand")
- (match_operand:VI_128_256 2 "const0_operand")
- (unspec:<avx512fmaskmode>
- [(match_operand:VI_128_256 3 "nonimmediate_operand")
- (match_operand:VI_128_256 4 "nonimmediate_operand")]
- UNSPEC_MASKED_EQ)))]
- "TARGET_AVX512VL && ix86_pre_reload_split ()
- && !(MEM_P (operands[3]) && MEM_P (operands[4]))"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (eq:VI_128_256
- (match_dup 3)
- (match_dup 4)))])
-
(define_insn_and_split "*avx2_pcmp<mode>3_1"
[(set (match_operand:VI_128_256 0 "register_operand")
(vec_merge:VI_128_256
@@ -13978,8 +15533,9 @@
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(unspec:<avx512fmaskmode>
[(match_operand:VI12_AVX512VL 1 "nonimmediate_operand")
- (match_operand:VI12_AVX512VL 2 "nonimmediate_operand")]
- UNSPEC_MASKED_EQ))]
+ (match_operand:VI12_AVX512VL 2 "nonimmediate_operand")
+ (const_int 0)]
+ UNSPEC_PCMP))]
"TARGET_AVX512BW"
"ix86_fixup_binary_operands_no_copy (EQ, <MODE>mode, operands);")
@@ -13987,17 +15543,19 @@
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(unspec:<avx512fmaskmode>
[(match_operand:VI48_AVX512VL 1 "nonimmediate_operand")
- (match_operand:VI48_AVX512VL 2 "nonimmediate_operand")]
- UNSPEC_MASKED_EQ))]
+ (match_operand:VI48_AVX512VL 2 "nonimmediate_operand")
+ (const_int 0)]
+ UNSPEC_PCMP))]
"TARGET_AVX512F"
"ix86_fixup_binary_operands_no_copy (EQ, <MODE>mode, operands);")
-(define_insn "<avx512>_eq<mode>3<mask_scalar_merge_name>_1"
+(define_insn "*<avx512>_eq<mode>3<mask_scalar_merge_name>_1"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k,k")
(unspec:<avx512fmaskmode>
[(match_operand:VI12_AVX512VL 1 "nonimm_or_0_operand" "%v,v")
- (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand" "vm,C")]
- UNSPEC_MASKED_EQ))]
+ (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand" "vm,C")
+ (const_int 0)]
+ UNSPEC_PCMP))]
"TARGET_AVX512BW && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
"@
vpcmpeq<ssemodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}
@@ -14007,12 +15565,13 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "<avx512>_eq<mode>3<mask_scalar_merge_name>_1"
+(define_insn "*<avx512>_eq<mode>3<mask_scalar_merge_name>_1"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k,k")
(unspec:<avx512fmaskmode>
[(match_operand:VI48_AVX512VL 1 "nonimm_or_0_operand" "%v,v")
- (match_operand:VI48_AVX512VL 2 "nonimm_or_0_operand" "vm,C")]
- UNSPEC_MASKED_EQ))]
+ (match_operand:VI48_AVX512VL 2 "nonimm_or_0_operand" "vm,C")
+ (const_int 0)]
+ UNSPEC_PCMP))]
"TARGET_AVX512F && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
"@
vpcmpeq<ssemodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}
@@ -14082,47 +15641,21 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn_and_split "*avx2_gt<mode>3"
- [(set (match_operand:VI_128_256 0 "register_operand")
- (vec_merge:VI_128_256
- (match_operand:VI_128_256 1 "vector_all_ones_operand")
- (match_operand:VI_128_256 2 "const0_operand")
- (unspec:<avx512fmaskmode>
- [(match_operand:VI_128_256 3 "register_operand")
- (match_operand:VI_128_256 4 "nonimmediate_operand")]
- UNSPEC_MASKED_GT)))]
- "TARGET_AVX512VL
- && ix86_pre_reload_split ()"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (gt:VI_128_256
- (match_dup 3)
- (match_dup 4)))])
-
-(define_insn "<avx512>_gt<mode>3<mask_scalar_merge_name>"
- [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+(define_expand "<avx512>_gt<mode>3<mask_scalar_merge_name>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(unspec:<avx512fmaskmode>
- [(match_operand:VI48_AVX512VL 1 "register_operand" "v")
- (match_operand:VI48_AVX512VL 2 "nonimmediate_operand" "vm")] UNSPEC_MASKED_GT))]
- "TARGET_AVX512F"
- "vpcmpgt<ssemodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "prefix_extra" "1")
- (set_attr "prefix" "evex")
- (set_attr "mode" "<sseinsnmode>")])
+ [(match_operand:VI48_AVX512VL 1 "register_operand")
+ (match_operand:VI48_AVX512VL 2 "nonimmediate_operand")
+ (const_int 6)] UNSPEC_PCMP))]
+ "TARGET_AVX512F")
-(define_insn "<avx512>_gt<mode>3<mask_scalar_merge_name>"
- [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+(define_expand "<avx512>_gt<mode>3<mask_scalar_merge_name>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(unspec:<avx512fmaskmode>
- [(match_operand:VI12_AVX512VL 1 "register_operand" "v")
- (match_operand:VI12_AVX512VL 2 "nonimmediate_operand" "vm")] UNSPEC_MASKED_GT))]
- "TARGET_AVX512BW"
- "vpcmpgt<ssemodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "prefix_extra" "1")
- (set_attr "prefix" "evex")
- (set_attr "mode" "<sseinsnmode>")])
+ [(match_operand:VI12_AVX512VL 1 "register_operand")
+ (match_operand:VI12_AVX512VL 2 "nonimmediate_operand")
+ (const_int 6)] UNSPEC_PCMP))]
+ "TARGET_AVX512BW")
(define_insn "*sse2_gt<mode>3"
[(set (match_operand:VI124_128 0 "register_operand" "=x,x")
@@ -14271,6 +15804,21 @@
DONE;
})
+(define_expand "vcondu<mode><sseintvecmodelower>"
+ [(set (match_operand:VF_AVX512FP16VL 0 "register_operand")
+ (if_then_else:VF_AVX512FP16VL
+ (match_operator 3 ""
+ [(match_operand:<sseintvecmode> 4 "vector_operand")
+ (match_operand:<sseintvecmode> 5 "vector_operand")])
+ (match_operand:VF_AVX512FP16VL 1 "general_operand")
+ (match_operand:VF_AVX512FP16VL 2 "general_operand")))]
+ "TARGET_AVX512FP16"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcondeq<VI8F_128:mode>v2di"
[(set (match_operand:VI8F_128 0 "register_operand")
(if_then_else:VI8F_128
@@ -14288,12 +15836,15 @@
(define_mode_iterator VEC_PERM_AVX2
[V16QI V8HI V4SI V2DI V4SF V2DF
+ (V8HF "TARGET_AVX512FP16")
(V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
(V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")
+ (V16HF "TARGET_AVX512FP16")
(V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")
(V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")
- (V32HI "TARGET_AVX512BW") (V64QI "TARGET_AVX512VBMI")])
+ (V32HI "TARGET_AVX512BW") (V64QI "TARGET_AVX512VBMI")
+ (V32HF "TARGET_AVX512FP16")])
(define_expand "vec_perm<mode>"
[(match_operand:VEC_PERM_AVX2 0 "register_operand")
@@ -15117,12 +16668,12 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
-(define_insn "avx512bw_interleave_highv32hi<mask_name>"
- [(set (match_operand:V32HI 0 "register_operand" "=v")
- (vec_select:V32HI
- (vec_concat:V64HI
- (match_operand:V32HI 1 "register_operand" "v")
- (match_operand:V32HI 2 "nonimmediate_operand" "vm"))
+(define_insn "avx512bw_interleave_high<mode><mask_name>"
+ [(set (match_operand:V32_512 0 "register_operand" "=v")
+ (vec_select:V32_512
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V32_512 1 "register_operand" "v")
+ (match_operand:V32_512 2 "nonimmediate_operand" "vm"))
(parallel [(const_int 4) (const_int 36)
(const_int 5) (const_int 37)
(const_int 6) (const_int 38)
@@ -15145,12 +16696,12 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_insn "avx2_interleave_highv16hi<mask_name>"
- [(set (match_operand:V16HI 0 "register_operand" "=Yw")
- (vec_select:V16HI
- (vec_concat:V32HI
- (match_operand:V16HI 1 "register_operand" "Yw")
- (match_operand:V16HI 2 "nonimmediate_operand" "Ywm"))
+(define_insn "avx2_interleave_high<mode><mask_name>"
+ [(set (match_operand:V16_256 0 "register_operand" "=Yw")
+ (vec_select:V16_256
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V16_256 1 "register_operand" "Yw")
+ (match_operand:V16_256 2 "nonimmediate_operand" "Ywm"))
(parallel [(const_int 4) (const_int 20)
(const_int 5) (const_int 21)
(const_int 6) (const_int 22)
@@ -15165,12 +16716,12 @@
(set_attr "prefix" "maybe_evex")
(set_attr "mode" "OI")])
-(define_insn "vec_interleave_highv8hi<mask_name>"
- [(set (match_operand:V8HI 0 "register_operand" "=x,Yw")
- (vec_select:V8HI
- (vec_concat:V16HI
- (match_operand:V8HI 1 "register_operand" "0,Yw")
- (match_operand:V8HI 2 "vector_operand" "xBm,Ywm"))
+(define_insn "vec_interleave_high<mode><mask_name>"
+ [(set (match_operand:V8_128 0 "register_operand" "=x,Yw")
+ (vec_select:V8_128
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V8_128 1 "register_operand" "0,Yw")
+ (match_operand:V8_128 2 "vector_operand" "xBm,Ywm"))
(parallel [(const_int 4) (const_int 12)
(const_int 5) (const_int 13)
(const_int 6) (const_int 14)
@@ -15185,12 +16736,12 @@
(set_attr "prefix" "orig,maybe_vex")
(set_attr "mode" "TI")])
-(define_insn "<mask_codefor>avx512bw_interleave_lowv32hi<mask_name>"
- [(set (match_operand:V32HI 0 "register_operand" "=v")
- (vec_select:V32HI
- (vec_concat:V64HI
- (match_operand:V32HI 1 "register_operand" "v")
- (match_operand:V32HI 2 "nonimmediate_operand" "vm"))
+(define_insn "<mask_codefor>avx512bw_interleave_low<mode><mask_name>"
+ [(set (match_operand:V32_512 0 "register_operand" "=v")
+ (vec_select:V32_512
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V32_512 1 "register_operand" "v")
+ (match_operand:V32_512 2 "nonimmediate_operand" "vm"))
(parallel [(const_int 0) (const_int 32)
(const_int 1) (const_int 33)
(const_int 2) (const_int 34)
@@ -15213,12 +16764,12 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_insn "avx2_interleave_lowv16hi<mask_name>"
- [(set (match_operand:V16HI 0 "register_operand" "=Yw")
- (vec_select:V16HI
- (vec_concat:V32HI
- (match_operand:V16HI 1 "register_operand" "Yw")
- (match_operand:V16HI 2 "nonimmediate_operand" "Ywm"))
+(define_insn "avx2_interleave_low<mode><mask_name>"
+ [(set (match_operand:V16_256 0 "register_operand" "=Yw")
+ (vec_select:V16_256
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V16_256 1 "register_operand" "Yw")
+ (match_operand:V16_256 2 "nonimmediate_operand" "Ywm"))
(parallel [(const_int 0) (const_int 16)
(const_int 1) (const_int 17)
(const_int 2) (const_int 18)
@@ -15233,12 +16784,12 @@
(set_attr "prefix" "maybe_evex")
(set_attr "mode" "OI")])
-(define_insn "vec_interleave_lowv8hi<mask_name>"
- [(set (match_operand:V8HI 0 "register_operand" "=x,Yw")
- (vec_select:V8HI
- (vec_concat:V16HI
- (match_operand:V8HI 1 "register_operand" "0,Yw")
- (match_operand:V8HI 2 "vector_operand" "xBm,Ywm"))
+(define_insn "vec_interleave_low<mode><mask_name>"
+ [(set (match_operand:V8_128 0 "register_operand" "=x,Yw")
+ (vec_select:V8_128
+ (vec_concat:<ssedoublevecmode>
+ (match_operand:V8_128 1 "register_operand" "0,Yw")
+ (match_operand:V8_128 2 "vector_operand" "xBm,Ywm"))
(parallel [(const_int 0) (const_int 8)
(const_int 1) (const_int 9)
(const_int 2) (const_int 10)
@@ -15400,19 +16951,20 @@
;; Modes handled by pinsr patterns.
(define_mode_iterator PINSR_MODE
- [(V16QI "TARGET_SSE4_1") V8HI
+ [(V16QI "TARGET_SSE4_1") V8HI V8HF
(V4SI "TARGET_SSE4_1")
(V2DI "TARGET_SSE4_1 && TARGET_64BIT")])
(define_mode_attr sse2p4_1
- [(V16QI "sse4_1") (V8HI "sse2")
+ [(V16QI "sse4_1") (V8HI "sse2") (V8HF "sse4_1")
(V4SI "sse4_1") (V2DI "sse4_1")])
(define_mode_attr pinsr_evex_isa
- [(V16QI "avx512bw") (V8HI "avx512bw")
+ [(V16QI "avx512bw") (V8HI "avx512bw") (V8HF "avx512bw")
(V4SI "avx512dq") (V2DI "avx512dq")])
;; sse4_1_pinsrd must come before sse2_loadld since it is preferred.
+;; For V8HFmode and TARGET_AVX2, broadcastw + pblendw should be better.
(define_insn "<sse2p4_1>_pinsr<ssemodesuffix>"
[(set (match_operand:PINSR_MODE 0 "register_operand" "=x,x,x,x,v,v")
(vec_merge:PINSR_MODE
@@ -15422,7 +16974,8 @@
(match_operand:SI 3 "const_int_operand")))]
"TARGET_SSE2
&& ((unsigned) exact_log2 (INTVAL (operands[3]))
- < GET_MODE_NUNITS (<MODE>mode))"
+ < GET_MODE_NUNITS (<MODE>mode))
+ && !(<MODE>mode == V8HFmode && TARGET_AVX2)"
{
operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
@@ -15430,18 +16983,18 @@
{
case 0:
if (GET_MODE_SIZE (<ssescalarmode>mode) < GET_MODE_SIZE (SImode))
- return "pinsr<ssemodesuffix>\t{%3, %k2, %0|%0, %k2, %3}";
+ return "pinsr<sseintmodesuffix>\t{%3, %k2, %0|%0, %k2, %3}";
/* FALLTHRU */
case 1:
- return "pinsr<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}";
+ return "pinsr<sseintmodesuffix>\t{%3, %2, %0|%0, %2, %3}";
case 2:
case 4:
if (GET_MODE_SIZE (<ssescalarmode>mode) < GET_MODE_SIZE (SImode))
- return "vpinsr<ssemodesuffix>\t{%3, %k2, %1, %0|%0, %1, %k2, %3}";
+ return "vpinsr<sseintmodesuffix>\t{%3, %k2, %1, %0|%0, %1, %k2, %3}";
/* FALLTHRU */
case 3:
case 5:
- return "vpinsr<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ return "vpinsr<sseintmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}";
default:
gcc_unreachable ();
}
@@ -18929,11 +20482,14 @@
(lt:VI1_AVX2 (match_dup 3) (match_dup 4))] UNSPEC_BLENDV))]
"operands[3] = gen_lowpart (<MODE>mode, operands[3]);")
-(define_insn "sse4_1_pblendw"
- [(set (match_operand:V8HI 0 "register_operand" "=Yr,*x,x")
- (vec_merge:V8HI
- (match_operand:V8HI 2 "vector_operand" "YrBm,*xBm,xm")
- (match_operand:V8HI 1 "register_operand" "0,0,x")
+(define_mode_attr blendsuf
+ [(V8HI "w") (V8HF "ph")])
+
+(define_insn "sse4_1_pblend<blendsuf>"
+ [(set (match_operand:V8_128 0 "register_operand" "=Yr,*x,x")
+ (vec_merge:V8_128
+ (match_operand:V8_128 2 "vector_operand" "YrBm,*xBm,xm")
+ (match_operand:V8_128 1 "register_operand" "0,0,x")
(match_operand:SI 3 "const_0_to_255_operand" "n,n,n")))]
"TARGET_SSE4_1"
"@
@@ -18960,6 +20516,47 @@
operands[3] = GEN_INT (val << 8 | val);
})
+(define_expand "avx2_pblendph"
+ [(set (match_operand:V16HF 0 "register_operand")
+ (vec_merge:V16HF
+ (match_operand:V16HF 2 "register_operand")
+ (match_operand:V16HF 1 "register_operand")
+ (match_operand:SI 3 "const_int_operand")))]
+ "TARGET_AVX2
+ && !((INTVAL (operands[3]) & 0xff) && (INTVAL (operands[3]) & 0xff00))"
+{
+ int mask = INTVAL (operands[3]);
+ if (mask == 0)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ {
+ rtx tmp = gen_reg_rtx (V16HImode);
+ rtx blendw_idx, blendd_idx;
+
+ if (mask & 0xff)
+ {
+ blendw_idx = GEN_INT (mask & 0xff);
+ blendd_idx = GEN_INT (15);
+ }
+ else
+ {
+ blendw_idx = GEN_INT (mask >> 8 & 0xff);
+ blendd_idx = GEN_INT (240);
+ }
+ operands[1] = lowpart_subreg (V16HImode, operands[1], V16HFmode);
+ operands[2] = lowpart_subreg (V16HImode, operands[2], V16HFmode);
+ emit_insn (gen_avx2_pblendw (tmp, operands[1], operands[2], blendw_idx));
+
+ operands[0] = lowpart_subreg (V8SImode, operands[0], V16HFmode);
+ tmp = lowpart_subreg (V8SImode, tmp, V16HImode);
+ operands[1] = lowpart_subreg (V8SImode, operands[1], V16HImode);
+ emit_insn (gen_avx2_pblenddv8si (operands[0], operands[1],
+ tmp, blendd_idx));
+ }
+
+ DONE;
+})
+
(define_insn "*avx2_pblendw"
[(set (match_operand:V16HI 0 "register_operand" "=x")
(vec_merge:V16HI
@@ -20294,14 +21891,14 @@
(set_attr "mode" "<MODE>")])
(define_insn "*sse4_1_round<ssescalarmodesuffix>"
- [(set (match_operand:VF_128 0 "register_operand" "=Yr,*x,x,v")
- (vec_merge:VF_128
- (vec_duplicate:VF_128
+ [(set (match_operand:VFH_128 0 "register_operand" "=Yr,*x,x,v")
+ (vec_merge:VFH_128
+ (vec_duplicate:VFH_128
(unspec:<ssescalarmode>
[(match_operand:<ssescalarmode> 2 "nonimmediate_operand" "Yrm,*xm,xm,vm")
(match_operand:SI 3 "const_0_to_15_operand" "n,n,n,n")]
UNSPEC_ROUND))
- (match_operand:VF_128 1 "register_operand" "0,0,x,v")
+ (match_operand:VFH_128 1 "register_operand" "0,0,x,v")
(const_int 1)))]
"TARGET_SSE4_1"
"@
@@ -22191,16 +23788,17 @@
[(V64QI "avx512bw") (V32QI "avx512bw") (V16QI "avx512bw")
(V32HI "avx512bw") (V16HI "avx512bw") (V8HI "avx512bw")
(V16SI "avx512f") (V8SI "avx512f") (V4SI "avx512f")
- (V8DI "avx512f") (V4DI "avx512f") (V2DI "avx512f")])
+ (V8DI "avx512f") (V4DI "avx512f") (V2DI "avx512f")
+ (V32HF "avx512bw") (V16HF "avx512bw") (V8HF "avx512bw")])
(define_insn "avx2_pbroadcast<mode>"
- [(set (match_operand:VI 0 "register_operand" "=x,v")
- (vec_duplicate:VI
+ [(set (match_operand:VIHF 0 "register_operand" "=x,v")
+ (vec_duplicate:VIHF
(vec_select:<ssescalarmode>
(match_operand:<ssexmmmode> 1 "nonimmediate_operand" "xm,vm")
(parallel [(const_int 0)]))))]
"TARGET_AVX2"
- "vpbroadcast<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}"
+ "vpbroadcast<sseintmodesuffix>\t{%1, %0|%0, %<iptr>1}"
[(set_attr "isa" "*,<pbroadcast_evex_isa>")
(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
@@ -22208,17 +23806,17 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "avx2_pbroadcast<mode>_1"
- [(set (match_operand:VI_256 0 "register_operand" "=x,x,v,v")
- (vec_duplicate:VI_256
+ [(set (match_operand:VIHF_256 0 "register_operand" "=x,x,v,v")
+ (vec_duplicate:VIHF_256
(vec_select:<ssescalarmode>
- (match_operand:VI_256 1 "nonimmediate_operand" "m,x,m,v")
+ (match_operand:VIHF_256 1 "nonimmediate_operand" "m,x,m,v")
(parallel [(const_int 0)]))))]
"TARGET_AVX2"
"@
- vpbroadcast<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}
- vpbroadcast<ssemodesuffix>\t{%x1, %0|%0, %x1}
- vpbroadcast<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}
- vpbroadcast<ssemodesuffix>\t{%x1, %0|%0, %x1}"
+ vpbroadcast<sseintmodesuffix>\t{%1, %0|%0, %<iptr>1}
+ vpbroadcast<sseintmodesuffix>\t{%x1, %0|%0, %x1}
+ vpbroadcast<sseintmodesuffix>\t{%1, %0|%0, %<iptr>1}
+ vpbroadcast<sseintmodesuffix>\t{%x1, %0|%0, %x1}"
[(set_attr "isa" "*,*,<pbroadcast_evex_isa>,<pbroadcast_evex_isa>")
(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
@@ -22572,15 +24170,15 @@
(set_attr "mode" "V4DF")])
(define_insn "<avx512>_vec_dup<mode>_1"
- [(set (match_operand:VI_AVX512BW 0 "register_operand" "=v,v")
- (vec_duplicate:VI_AVX512BW
+ [(set (match_operand:VIHF_AVX512BW 0 "register_operand" "=v,v")
+ (vec_duplicate:VIHF_AVX512BW
(vec_select:<ssescalarmode>
- (match_operand:VI_AVX512BW 1 "nonimmediate_operand" "v,m")
+ (match_operand:VIHF_AVX512BW 1 "nonimmediate_operand" "v,m")
(parallel [(const_int 0)]))))]
"TARGET_AVX512F"
"@
- vpbroadcast<ssemodesuffix>\t{%x1, %0|%0, %x1}
- vpbroadcast<ssemodesuffix>\t{%x1, %0|%0, %<iptr>1}"
+ vpbroadcast<sseintmodesuffix>\t{%x1, %0|%0, %x1}
+ vpbroadcast<sseintmodesuffix>\t{%x1, %0|%0, %<iptr>1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
@@ -22605,8 +24203,8 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<avx512>_vec_dup<mode><mask_name>"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
- (vec_duplicate:VI12_AVX512VL
+ [(set (match_operand:VI12HF_AVX512VL 0 "register_operand" "=v")
+ (vec_duplicate:VI12HF_AVX512VL
(vec_select:<ssescalarmode>
(match_operand:<ssexmmmode> 1 "nonimmediate_operand" "vm")
(parallel [(const_int 0)]))))]
@@ -22641,8 +24239,8 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<mask_codefor><avx512>_vec_dup_gpr<mode><mask_name>"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v,v")
- (vec_duplicate:VI12_AVX512VL
+ [(set (match_operand:VI12HF_AVX512VL 0 "register_operand" "=v,v")
+ (vec_duplicate:VI12HF_AVX512VL
(match_operand:<ssescalarmode> 1 "nonimmediate_operand" "vm,r")))]
"TARGET_AVX512BW"
"@
@@ -22737,7 +24335,7 @@
[(V8SF "ss") (V4DF "sd") (V8SI "ss") (V4DI "sd")])
;; Modes handled by AVX2 vec_dup patterns.
(define_mode_iterator AVX2_VEC_DUP_MODE
- [V32QI V16QI V16HI V8HI V8SI V4SI])
+ [V32QI V16QI V16HI V8HI V8SI V4SI V16HF V8HF])
(define_insn "*vec_dup<mode>"
[(set (match_operand:AVX2_VEC_DUP_MODE 0 "register_operand" "=x,x,v")
@@ -23293,12 +24891,12 @@
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "vec_set_lo_v16hi"
- [(set (match_operand:V16HI 0 "register_operand" "=x,v")
- (vec_concat:V16HI
- (match_operand:V8HI 2 "nonimmediate_operand" "xm,vm")
- (vec_select:V8HI
- (match_operand:V16HI 1 "register_operand" "x,v")
+(define_insn "vec_set_lo_<mode>"
+ [(set (match_operand:V16_256 0 "register_operand" "=x,v")
+ (vec_concat:V16_256
+ (match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "xm,vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16_256 1 "register_operand" "x,v")
(parallel [(const_int 8) (const_int 9)
(const_int 10) (const_int 11)
(const_int 12) (const_int 13)
@@ -23313,16 +24911,16 @@
(set_attr "prefix" "vex,evex")
(set_attr "mode" "OI")])
-(define_insn "vec_set_hi_v16hi"
- [(set (match_operand:V16HI 0 "register_operand" "=x,v")
- (vec_concat:V16HI
- (vec_select:V8HI
- (match_operand:V16HI 1 "register_operand" "x,v")
+(define_insn "vec_set_hi_<mode>"
+ [(set (match_operand:V16_256 0 "register_operand" "=x,v")
+ (vec_concat:V16_256
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16_256 1 "register_operand" "x,v")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)
(const_int 4) (const_int 5)
(const_int 6) (const_int 7)]))
- (match_operand:V8HI 2 "nonimmediate_operand" "xm,vm")))]
+ (match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "xm,vm")))]
"TARGET_AVX"
"@
vinsert%~128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}
@@ -23419,9 +25017,9 @@
"TARGET_AVX")
(define_expand "maskload<mode><avx512fmaskmodelower>"
- [(set (match_operand:V48_AVX512VL 0 "register_operand")
- (vec_merge:V48_AVX512VL
- (match_operand:V48_AVX512VL 1 "memory_operand")
+ [(set (match_operand:V48H_AVX512VL 0 "register_operand")
+ (vec_merge:V48H_AVX512VL
+ (match_operand:V48H_AVX512VL 1 "memory_operand")
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand")))]
"TARGET_AVX512F")
@@ -23444,9 +25042,9 @@
"TARGET_AVX")
(define_expand "maskstore<mode><avx512fmaskmodelower>"
- [(set (match_operand:V48_AVX512VL 0 "memory_operand")
- (vec_merge:V48_AVX512VL
- (match_operand:V48_AVX512VL 1 "register_operand")
+ [(set (match_operand:V48H_AVX512VL 0 "memory_operand")
+ (vec_merge:V48H_AVX512VL
+ (match_operand:V48H_AVX512VL 1 "register_operand")
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand")))]
"TARGET_AVX512F")
@@ -23499,6 +25097,7 @@
(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V32HF "TARGET_AVX512F") (V16HF "TARGET_AVX") V8HF
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")
(V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
@@ -23510,6 +25109,7 @@
(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX")
+ (V32HF "TARGET_AVX512F") (V16HF "TARGET_AVX") V8HF
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX")
(V4TI "TARGET_AVX512F")])
@@ -24461,10 +26061,10 @@
(define_insn "avx512dq_fpclass<mode><mask_scalar_merge_name>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(unspec:<avx512fmaskmode>
- [(match_operand:VF_AVX512VL 1 "vector_operand" "vm")
+ [(match_operand:VFH_AVX512VL 1 "vector_operand" "vm")
(match_operand 2 "const_0_to_255_operand" "n")]
UNSPEC_FPCLASS))]
- "TARGET_AVX512DQ"
+ "TARGET_AVX512DQ || VALID_AVX512FP16_REG_MODE(<MODE>mode)"
"vfpclass<ssemodesuffix><vecmemsuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}";
[(set_attr "type" "sse")
(set_attr "length_immediate" "1")
@@ -24475,11 +26075,11 @@
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(and:<avx512fmaskmode>
(unspec:<avx512fmaskmode>
- [(match_operand:VF_128 1 "nonimmediate_operand" "vm")
+ [(match_operand:VFH_128 1 "nonimmediate_operand" "vm")
(match_operand 2 "const_0_to_255_operand" "n")]
UNSPEC_FPCLASS)
(const_int 1)))]
- "TARGET_AVX512DQ"
+ "TARGET_AVX512DQ || VALID_AVX512FP16_REG_MODE(<MODE>mode)"
"vfpclass<ssescalarmodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}";
[(set_attr "type" "sse")
(set_attr "length_immediate" "1")
@@ -24487,9 +26087,9 @@
(set_attr "mode" "<MODE>")])
(define_insn "<avx512>_getmant<mode><mask_name><round_saeonly_name>"
- [(set (match_operand:VF_AVX512VL 0 "register_operand" "=v")
- (unspec:VF_AVX512VL
- [(match_operand:VF_AVX512VL 1 "nonimmediate_operand" "<round_saeonly_constraint>")
+ [(set (match_operand:VFH_AVX512VL 0 "register_operand" "=v")
+ (unspec:VFH_AVX512VL
+ [(match_operand:VFH_AVX512VL 1 "nonimmediate_operand" "<round_saeonly_constraint>")
(match_operand:SI 2 "const_0_to_15_operand")]
UNSPEC_GETMANT))]
"TARGET_AVX512F"
@@ -24498,11 +26098,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "avx512f_vgetmant<mode><mask_scalar_name><round_saeonly_scalar_name>"
- [(set (match_operand:VF_128 0 "register_operand" "=v")
- (vec_merge:VF_128
- (unspec:VF_128
- [(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
+ [(set (match_operand:VFH_128 0 "register_operand" "=v")
+ (vec_merge:VFH_128
+ (unspec:VFH_128
+ [(match_operand:VFH_128 1 "register_operand" "v")
+ (match_operand:VFH_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
(match_operand:SI 3 "const_0_to_15_operand")]
UNSPEC_GETMANT)
(match_dup 1)
diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md
index 6614e04..510e82c 100644
--- a/gcc/config/i386/subst.md
+++ b/gcc/config/i386/subst.md
@@ -24,9 +24,13 @@
V32HI V16HI V8HI
V16SI V8SI V4SI
V8DI V4DI V2DI
+ V32HF V16HF V8HF
V16SF V8SF V4SF
V8DF V4DF V2DF])
+(define_mode_iterator SUBST_CV
+ [V32HF V16HF V8HF])
+
(define_mode_iterator SUBST_S
[QI HI SI DI])
@@ -35,14 +39,17 @@
V32HI V16HI V8HI
V16SI V8SI V4SI
V8DI V4DI V2DI
+ V32HF V16HF V8HF
V16SF V8SF V4SF
V8DF V4DF V2DF
QI HI SI DI SF DF])
(define_subst_attr "mask_name" "mask" "" "_mask")
+(define_subst_attr "maskc_name" "maskc" "" "_mask")
(define_subst_attr "mask_applied" "mask" "false" "true")
(define_subst_attr "mask_operand2" "mask" "" "%{%3%}%N2")
(define_subst_attr "mask_operand3" "mask" "" "%{%4%}%N3")
+(define_subst_attr "maskc_operand3" "maskc" "" "%{%4%}%N3")
(define_subst_attr "mask_operand3_1" "mask" "" "%%{%%4%%}%%N3") ;; for sprintf
(define_subst_attr "mask_operand4" "mask" "" "%{%5%}%N4")
(define_subst_attr "mask_operand6" "mask" "" "%{%7%}%N6")
@@ -87,6 +94,18 @@
(match_dup 0)
(match_operand:<avx512fmaskmode> 2 "register_operand" "Yk")))])
+(define_subst "maskc"
+ [(set (match_operand:SUBST_CV 0)
+ (match_operand:SUBST_CV 1))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 2 "nonimm_or_0_operand" "0C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 3 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))])
+
(define_subst_attr "mask_scalar_merge_name" "mask_scalar_merge" "" "_mask")
(define_subst_attr "mask_scalar_merge_operand3" "mask_scalar_merge" "" "%{%3%}")
(define_subst_attr "mask_scalar_merge_operand4" "mask_scalar_merge" "" "%{%4%}")
@@ -135,12 +154,31 @@
(match_operand:<avx512fmaskmode> 4 "register_operand" "Yk"))
(match_dup 2)
(const_int 1)))])
+(define_subst_attr "sdc_maskz_name" "sdc" "" "_maskz_1")
+(define_subst_attr "sdc_mask_op4" "sdc" "" "%{%5%}%N4")
+(define_subst_attr "sdc_mask_op5" "sdc" "" "%{%6%}%N5")
+(define_subst_attr "sdc_mask_mode512bit_condition" "sdc" "1" "(<MODE_SIZE> == 64 || TARGET_AVX512VL)")
+
+(define_subst "sdc"
+ [(set (match_operand:SUBST_CV 0)
+ (match_operand:SUBST_CV 1))]
+ ""
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 2 "const0_operand" "C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 3 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK)))
+])
(define_subst_attr "round_name" "round" "" "_round")
(define_subst_attr "round_mask_operand2" "mask" "%R2" "%R4")
(define_subst_attr "round_mask_operand3" "mask" "%R3" "%R5")
+(define_subst_attr "round_maskc_operand3" "maskc" "%R3" "%R5")
(define_subst_attr "round_mask_operand4" "mask" "%R4" "%R6")
(define_subst_attr "round_sd_mask_operand4" "sd" "%R4" "%R6")
+(define_subst_attr "round_sdc_mask_operand4" "sdc" "%R4" "%R6")
(define_subst_attr "round_op2" "round" "" "%R2")
(define_subst_attr "round_op3" "round" "" "%R3")
(define_subst_attr "round_op4" "round" "" "%R4")
@@ -148,9 +186,12 @@
(define_subst_attr "round_op6" "round" "" "%R6")
(define_subst_attr "round_mask_op2" "round" "" "<round_mask_operand2>")
(define_subst_attr "round_mask_op3" "round" "" "<round_mask_operand3>")
+(define_subst_attr "round_maskc_op3" "round" "" "<round_maskc_operand3>")
(define_subst_attr "round_mask_op4" "round" "" "<round_mask_operand4>")
(define_subst_attr "round_sd_mask_op4" "round" "" "<round_sd_mask_operand4>")
+(define_subst_attr "round_sdc_mask_op4" "round" "" "<round_sdc_mask_operand4>")
(define_subst_attr "round_constraint" "round" "vm" "v")
+(define_subst_attr "round_qq2phsuff" "round" "<qq2phsuff>" "")
(define_subst_attr "bcst_round_constraint" "round" "vmBr" "v")
(define_subst_attr "round_constraint2" "round" "m" "v")
(define_subst_attr "round_constraint3" "round" "rm" "r")
@@ -161,7 +202,9 @@
(define_subst_attr "round_mode512bit_condition" "round" "1" "(<MODE>mode == V16SFmode
|| <MODE>mode == V8DFmode
|| <MODE>mode == V8DImode
- || <MODE>mode == V16SImode)")
+ || <MODE>mode == V16SImode
+ || <MODE>mode == V32HFmode)")
+
(define_subst_attr "round_modev8sf_condition" "round" "1" "(<MODE>mode == V8SFmode)")
(define_subst_attr "round_modev4sf_condition" "round" "1" "(<MODE>mode == V4SFmode)")
(define_subst_attr "round_codefor" "round" "*" "")
@@ -184,6 +227,7 @@
(define_subst_attr "round_saeonly_mask_scalar_merge_operand4" "mask_scalar_merge" "%r4" "%r5")
(define_subst_attr "round_saeonly_maskz_scalar_operand5" "maskz_scalar" "%r5" "%r7")
(define_subst_attr "round_saeonly_sd_mask_operand5" "sd" "%r5" "%r7")
+(define_subst_attr "round_saeonly_sdc_mask_operand5" "sdc" "%r5" "%r7")
(define_subst_attr "round_saeonly_op2" "round_saeonly" "" "%r2")
(define_subst_attr "round_saeonly_op3" "round_saeonly" "" "%r3")
(define_subst_attr "round_saeonly_op4" "round_saeonly" "" "%r4")
@@ -204,7 +248,9 @@
(define_subst_attr "round_saeonly_mode512bit_condition" "round_saeonly" "1" "(<MODE>mode == V16SFmode
|| <MODE>mode == V8DFmode
|| <MODE>mode == V8DImode
- || <MODE>mode == V16SImode)")
+ || <MODE>mode == V16SImode
+ || <MODE>mode == V32HFmode)")
+
(define_subst_attr "round_saeonly_modev8sf_condition" "round_saeonly" "1" "(<MODE>mode == V8SFmode)")
(define_subst "round_saeonly"
@@ -230,6 +276,9 @@
(define_subst_attr "round_expand_name" "round_expand" "" "_round")
(define_subst_attr "round_expand_nimm_predicate" "round_expand" "nonimmediate_operand" "register_operand")
(define_subst_attr "round_expand_operand" "round_expand" "" ", operands[5]")
+(define_subst_attr "round_embedded_complex" "round_expand" "0" "!(CONST_INT_P (operands[5])
+ && (INTVAL (operands[5])
+ == NO_ROUND))")
(define_subst "round_expand"
[(match_operand:SUBST_V 0)
@@ -282,8 +331,12 @@
(match_operand:<avx512fmaskmode> 5 "register_operand")])
(define_subst_attr "mask_scalar_name" "mask_scalar" "" "_mask")
+(define_subst_attr "mask_scalarcz_name" "mask_scalarcz" "" "_maskz")
+(define_subst_attr "mask_scalarc_name" "mask_scalarc" "" "_mask")
+(define_subst_attr "mask_scalarc_operand3" "mask_scalarc" "" "%{%4%}%N3")
(define_subst_attr "mask_scalar_operand3" "mask_scalar" "" "%{%4%}%N3")
(define_subst_attr "mask_scalar_operand4" "mask_scalar" "" "%{%5%}%N4")
+(define_subst_attr "mask_scalarcz_operand4" "mask_scalarcz" "" "%{%5%}%N4")
(define_subst "mask_scalar"
[(set (match_operand:SUBST_V 0)
@@ -301,12 +354,55 @@
(match_dup 2)
(const_int 1)))])
+(define_subst "mask_scalarcz"
+ [(set (match_operand:SUBST_CV 0)
+ (vec_merge:SUBST_CV
+ (match_operand:SUBST_CV 1)
+ (match_operand:SUBST_CV 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 3 "const0_operand" "C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))])
+
+(define_subst "mask_scalarc"
+ [(set (match_operand:SUBST_CV 0)
+ (vec_merge:SUBST_CV
+ (match_operand:SUBST_CV 1)
+ (match_operand:SUBST_CV 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_CV
+ (vec_merge:SUBST_CV
+ (match_dup 1)
+ (match_operand:SUBST_CV 3 "nonimm_or_0_operand" "0C")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:<avx512fmaskcmode> 4 "register_operand" "Yk")]
+ UNSPEC_COMPLEX_MASK))
+ (match_dup 2)
+ (const_int 3)))])
+
(define_subst_attr "round_scalar_name" "round_scalar" "" "_round")
+(define_subst_attr "round_scalarcz_name" "round_scalarcz" "" "_round")
(define_subst_attr "round_scalar_mask_operand3" "mask_scalar" "%R3" "%R5")
+(define_subst_attr "round_scalarc_mask_operand3" "mask_scalarc" "%R3" "%R5")
+(define_subst_attr "round_scalarcz_mask_operand4" "mask_scalarcz" "%R4" "%R6")
(define_subst_attr "round_scalar_mask_op3" "round_scalar" "" "<round_scalar_mask_operand3>")
+(define_subst_attr "round_scalarc_mask_op3" "round_scalarcz" "" "<round_scalarc_mask_operand3>")
+(define_subst_attr "round_scalarcz_mask_op4" "round_scalarcz" "" "<round_scalarcz_mask_operand4>")
(define_subst_attr "round_scalar_constraint" "round_scalar" "vm" "v")
+(define_subst_attr "round_scalarcz_constraint" "round_scalarcz" "vm" "v")
(define_subst_attr "round_scalar_prefix" "round_scalar" "vex" "evex")
(define_subst_attr "round_scalar_nimm_predicate" "round_scalar" "nonimmediate_operand" "register_operand")
+(define_subst_attr "round_scalarcz_nimm_predicate" "round_scalarcz" "vector_operand" "register_operand")
(define_subst "round_scalar"
[(set (match_operand:SUBST_V 0)
@@ -324,6 +420,22 @@
(match_operand:SI 3 "const_4_or_8_to_11_operand")]
UNSPEC_EMBEDDED_ROUNDING))])
+(define_subst "round_scalarcz"
+ [(set (match_operand:SUBST_V 0)
+ (vec_merge:SUBST_V
+ (match_operand:SUBST_V 1)
+ (match_operand:SUBST_V 2)
+ (const_int 3)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (unspec:SUBST_V [
+ (vec_merge:SUBST_V
+ (match_dup 1)
+ (match_dup 2)
+ (const_int 3))
+ (match_operand:SI 3 "const_4_or_8_to_11_operand")]
+ UNSPEC_EMBEDDED_ROUNDING))])
+
(define_subst_attr "round_saeonly_scalar_name" "round_saeonly_scalar" "" "_round")
(define_subst_attr "round_saeonly_scalar_mask_operand3" "mask_scalar" "%r3" "%r5")
(define_subst_attr "round_saeonly_scalar_mask_operand4" "mask_scalar" "%r4" "%r6")
diff --git a/gcc/config/i386/vxworks.h b/gcc/config/i386/vxworks.h
index ebda7d9..0676cb4 100644
--- a/gcc/config/i386/vxworks.h
+++ b/gcc/config/i386/vxworks.h
@@ -73,37 +73,37 @@ along with GCC; see the file COPYING3. If not see
VXWORKS_OS_CPP_BUILTINS (); \
if (TARGET_64BIT) \
VX_CPUDEF (X86_64); \
- else if (TARGET_PENTIUM4) \
+ else if (TARGET_CPU_P (PENTIUM4)) \
{ \
VX_CPUDEF (PENTIUM4); \
VX_CPUVDEF (PENTIUM4); \
} \
- else if (TARGET_CORE2) \
+ else if (TARGET_CPU_P (CORE2)) \
VX_CPUDEF (CORE2); \
- else if (TARGET_NEHALEM) \
+ else if (TARGET_CPU_P (NEHALEM)) \
VX_CPUDEF (NEHALEM); \
- else if (TARGET_SANDYBRIDGE) \
+ else if (TARGET_CPU_P (SANDYBRIDGE)) \
VX_CPUDEF (SANDYBRIDGE); \
- else if (TARGET_HASWELL) \
+ else if (TARGET_CPU_P (HASWELL)) \
VX_CPUDEF (HASWELL); \
- else if (TARGET_SILVERMONT) \
+ else if (TARGET_CPU_P (SILVERMONT)) \
VX_CPUDEF (SILVERMONT); \
- else if (TARGET_SKYLAKE || TARGET_SKYLAKE_AVX512) \
+ else if (TARGET_CPU_P (SKYLAKE) || TARGET_CPU_P (SKYLAKE_AVX512)) \
VX_CPUDEF (SKYLAKE); \
- else if (TARGET_GOLDMONT) \
+ else if (TARGET_CPU_P (GOLDMONT)) \
VX_CPUDEF (GOLDMONT); \
else if (TARGET_VXWORKS7) \
VX_CPUDEF (PENTIUM4); \
- else if (TARGET_386) \
+ else if (TARGET_CPU_P (I386)) \
VX_CPUDEF (I80386); \
- else if (TARGET_486) \
+ else if (TARGET_CPU_P (I486)) \
VX_CPUDEF (I80486); \
- else if (TARGET_PENTIUM) \
+ else if (TARGET_CPU_P (PENTIUM)) \
{ \
VX_CPUDEF (PENTIUM); \
VX_CPUVDEF (PENTIUM); \
} \
- else if (TARGET_PENTIUMPRO) \
+ else if (TARGET_CPU_P (PENTIUMPRO)) \
{ \
VX_CPUDEF (PENTIUM2); \
VX_CPUVDEF (PENTIUMPRO); \
diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h
index ffe810f..93644be 100644
--- a/gcc/config/i386/x86-tune-costs.h
+++ b/gcc/config/i386/x86-tune-costs.h
@@ -2734,6 +2734,130 @@ struct processor_costs slm_cost = {
"16", /* Func alignment. */
};
+static stringop_algs tremont_memcpy[2] = {
+ {libcall,
+ {{256, rep_prefix_1_byte, true},
+ {256, loop, false},
+ {-1, libcall, false}}},
+ {libcall,
+ {{256, rep_prefix_1_byte, true},
+ {256, loop, false},
+ {-1, libcall, false}}}};
+static stringop_algs tremont_memset[2] = {
+ {libcall,
+ {{256, rep_prefix_1_byte, true},
+ {256, loop, false},
+ {-1, libcall, false}}},
+ {libcall,
+ {{256, rep_prefix_1_byte, true},
+ {256, loop, false},
+ {-1, libcall, false}}}};
+static const
+struct processor_costs tremont_cost = {
+ {
+ /* Start of register allocator costs. integer->integer move cost is 2. */
+ 6, /* cost for loading QImode using movzbl */
+ {6, 6, 6}, /* cost of loading integer registers
+ in QImode, HImode and SImode.
+ Relative to reg-reg move (2). */
+ {6, 6, 6}, /* cost of storing integer registers */
+ 4, /* cost of reg,reg fld/fst */
+ {6, 6, 12}, /* cost of loading fp registers
+ in SFmode, DFmode and XFmode */
+ {6, 6, 12}, /* cost of storing fp registers
+ in SFmode, DFmode and XFmode */
+ 2, /* cost of moving MMX register */
+ {6, 6}, /* cost of loading MMX registers
+ in SImode and DImode */
+ {6, 6}, /* cost of storing MMX registers
+ in SImode and DImode */
+ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */
+ {6, 6, 6, 10, 15}, /* cost of loading SSE registers
+ in 32,64,128,256 and 512-bit */
+ {6, 6, 6, 10, 15}, /* cost of storing SSE registers
+ in 32,64,128,256 and 512-bit */
+ 6, 6, /* SSE->integer and integer->SSE moves */
+ 6, 6, /* mask->integer and integer->mask moves */
+ {6, 6, 6}, /* cost of loading mask register
+ in QImode, HImode, SImode. */
+ {6, 6, 6}, /* cost if storing mask register
+ in QImode, HImode, SImode. */
+ 2, /* cost of moving mask register. */
+ /* End of register allocator costs. */
+ },
+
+ COSTS_N_INSNS (1), /* cost of an add instruction */
+ /* Setting cost to 2 makes our current implementation of synth_mult result in
+ use of unnecessary temporary registers causing regression on several
+ SPECfp benchmarks. */
+ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */
+ COSTS_N_INSNS (1), /* variable shift costs */
+ COSTS_N_INSNS (1), /* constant shift costs */
+ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */
+ COSTS_N_INSNS (4), /* HI */
+ COSTS_N_INSNS (3), /* SI */
+ COSTS_N_INSNS (4), /* DI */
+ COSTS_N_INSNS (4)}, /* other */
+ 0, /* cost of multiply per each bit set */
+ {COSTS_N_INSNS (16), /* cost of a divide/mod for QI */
+ COSTS_N_INSNS (22), /* HI */
+ COSTS_N_INSNS (30), /* SI */
+ COSTS_N_INSNS (74), /* DI */
+ COSTS_N_INSNS (74)}, /* other */
+ COSTS_N_INSNS (1), /* cost of movsx */
+ COSTS_N_INSNS (1), /* cost of movzx */
+ 8, /* "large" insn */
+ 17, /* MOVE_RATIO */
+ 17, /* CLEAR_RATIO */
+ {6, 6, 6}, /* cost of loading integer registers
+ in QImode, HImode and SImode.
+ Relative to reg-reg move (2). */
+ {6, 6, 6}, /* cost of storing integer registers */
+ {6, 6, 6, 10, 15}, /* cost of loading SSE register
+ in 32bit, 64bit, 128bit, 256bit and 512bit */
+ {6, 6, 6, 10, 15}, /* cost of storing SSE register
+ in 32bit, 64bit, 128bit, 256bit and 512bit */
+ {6, 6, 6, 10, 15}, /* cost of unaligned loads. */
+ {6, 6, 6, 10, 15}, /* cost of unaligned storess. */
+ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */
+ 6, /* cost of moving SSE register to integer. */
+ 18, 6, /* Gather load static, per_elt. */
+ 18, 6, /* Gather store static, per_elt. */
+ 32, /* size of l1 cache. */
+ 512, /* size of l2 cache. */
+ 64, /* size of prefetch block */
+ 6, /* number of parallel prefetches */
+ /* Benchmarks shows large regressions on K8 sixtrack benchmark when this
+ value is increased to perhaps more appropriate value of 5. */
+ 3, /* Branch cost */
+ COSTS_N_INSNS (3), /* cost of FADD and FSUB insns. */
+ COSTS_N_INSNS (5), /* cost of FMUL instruction. */
+ COSTS_N_INSNS (17), /* cost of FDIV instruction. */
+ COSTS_N_INSNS (1), /* cost of FABS instruction. */
+ COSTS_N_INSNS (1), /* cost of FCHS instruction. */
+ COSTS_N_INSNS (14), /* cost of FSQRT instruction. */
+
+ COSTS_N_INSNS (1), /* cost of cheap SSE instruction. */
+ COSTS_N_INSNS (3), /* cost of ADDSS/SD SUBSS/SD insns. */
+ COSTS_N_INSNS (4), /* cost of MULSS instruction. */
+ COSTS_N_INSNS (5), /* cost of MULSD instruction. */
+ COSTS_N_INSNS (5), /* cost of FMA SS instruction. */
+ COSTS_N_INSNS (5), /* cost of FMA SD instruction. */
+ COSTS_N_INSNS (13), /* cost of DIVSS instruction. */
+ COSTS_N_INSNS (17), /* cost of DIVSD instruction. */
+ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */
+ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */
+ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */
+ tremont_memcpy,
+ tremont_memset,
+ COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
+ COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:11:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
+};
+
static stringop_algs intel_memcpy[2] = {
{libcall, {{11, loop, false}, {-1, rep_prefix_4_byte, false}}},
{libcall, {{32, loop, false}, {64, rep_prefix_4_byte, false},
diff --git a/gcc/config/i386/x86-tune-sched.c b/gcc/config/i386/x86-tune-sched.c
index 2e5ee4e..56ada99 100644
--- a/gcc/config/i386/x86-tune-sched.c
+++ b/gcc/config/i386/x86-tune-sched.c
@@ -71,6 +71,7 @@ ix86_issue_rate (void)
case PROCESSOR_NEHALEM:
case PROCESSOR_SANDYBRIDGE:
case PROCESSOR_HASWELL:
+ case PROCESSOR_TREMONT:
case PROCESSOR_GENERIC:
return 4;
@@ -429,6 +430,7 @@ ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
case PROCESSOR_NEHALEM:
case PROCESSOR_SANDYBRIDGE:
case PROCESSOR_HASWELL:
+ case PROCESSOR_TREMONT:
case PROCESSOR_GENERIC:
/* Stack engine allows to execute push&pop instructions in parall. */
if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index 8f55da8..58e8ead 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -62,6 +62,21 @@ DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency",
that can be partly masked by careful scheduling of moves. */
DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency",
m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10
+ | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC)
+
+/* X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY: This knob avoids
+ partial write to the destination in scalar SSE conversion from FP
+ to FP. */
+DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY,
+ "sse_partial_reg_fp_converts_dependency",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10
+ | m_BDVER | m_ZNVER | m_GENERIC)
+
+/* X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY: This knob avoids partial
+ write to the destination in scalar SSE conversion from integer to FP. */
+DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY,
+ "sse_partial_reg_converts_dependency",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10
| m_BDVER | m_ZNVER | m_GENERIC)
/* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies
@@ -136,7 +151,7 @@ DEF_TUNE (X86_TUNE_FUSE_ALU_AND_BRANCH, "fuse_alu_and_branch",
DEF_TUNE (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, "accumulate_outgoing_args",
m_PPRO | m_P4_NOCONA | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_INTEL
- | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ATHLON_K8)
+ | m_GOLDMONT | m_GOLDMONT_PLUS | m_ATHLON_K8)
/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in prologues that are
considered on critical path. */
@@ -150,14 +165,15 @@ DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move",
/* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */
DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave",
- m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC)
+ m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_TREMONT
+ | m_GENERIC)
/* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions.
Some chips, like 486 and Pentium works faster with separate load
and push instructions. */
DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory",
m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE
- | m_GENERIC)
+ | m_TREMONT | m_GENERIC)
/* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred
over esp subtraction. */
@@ -198,8 +214,7 @@ DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns",
than 4 branch instructions in the 16 byte window. */
DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit",
m_PPRO | m_P4_NOCONA | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM
- | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL | m_ATHLON_K8
- | m_AMDFAM10)
+ | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL | m_ATHLON_K8 | m_AMDFAM10)
/*****************************************************************************/
/* Integer instruction selection tuning */
@@ -240,11 +255,11 @@ DEF_TUNE (X86_TUNE_INTEGER_DFMODE_MOVES, "integer_dfmode_moves",
/* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
will impact LEA instruction selection. */
DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_BONNELL | m_SILVERMONT | m_KNL
- | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL)
+ | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL)
/* X86_TUNE_AVOID_LEA_FOR_ADDR: Avoid lea for address computation. */
DEF_TUNE (X86_TUNE_AVOID_LEA_FOR_ADDR, "avoid_lea_for_addr",
- m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT
+ m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS
| m_KNL | m_KNM)
/* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is
@@ -263,7 +278,7 @@ DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8",
a conditional move. */
DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove",
m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_KNL
- | m_KNM | m_TREMONT | m_INTEL)
+ | m_KNM | m_INTEL)
/* X86_TUNE_SINGLE_STRINGOP: Enable use of single string operations, such
as MOVS and STOS (without a REP prefix) to move/set sequences of bytes. */
@@ -273,7 +288,7 @@ DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA)
move/set sequences of bytes with known size. */
DEF_TUNE (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB,
"prefer_known_rep_movsb_stosb",
- m_SKYLAKE | m_ALDERLAKE | m_CORE_AVX512)
+ m_SKYLAKE | m_ALDERLAKE | m_TREMONT | m_CORE_AVX512)
/* X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES: Enable generation of
compact prologues and epilogues by issuing a misaligned moves. This
@@ -282,7 +297,8 @@ DEF_TUNE (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB,
FIXME: This may actualy be a win on more targets than listed here. */
DEF_TUNE (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES,
"misaligned_move_string_pro_epilogues",
- m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC)
+ m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_TREMONT
+ | m_GENERIC)
/* X86_TUNE_USE_SAHF: Controls use of SAHF. */
DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf",
@@ -294,7 +310,7 @@ DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf",
/* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */
DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd",
~(m_PENT | m_LAKEMONT | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_INTEL
- | m_K6 | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT))
+ | m_K6 | m_GOLDMONT | m_GOLDMONT_PLUS))
/* X86_TUNE_USE_BT: Enable use of BT (bit test) instructions. */
DEF_TUNE (X86_TUNE_USE_BT, "use_bt",
@@ -305,7 +321,7 @@ DEF_TUNE (X86_TUNE_USE_BT, "use_bt",
/* X86_TUNE_AVOID_FALSE_DEP_FOR_BMI: Avoid false dependency
for bit-manipulation instructions. */
DEF_TUNE (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI, "avoid_false_dep_for_bmi",
- m_SANDYBRIDGE | m_CORE_AVX2 | m_GENERIC)
+ m_SANDYBRIDGE | m_CORE_AVX2 | m_TREMONT | m_GENERIC)
/* X86_TUNE_ADJUST_UNROLL: This enables adjusting the unroll factor based
on hardware capabilities. Bdver3 hardware has a loop buffer which makes
@@ -321,14 +337,14 @@ DEF_TUNE (X86_TUNE_ONE_IF_CONV_INSN, "one_if_conv_insn",
/* X86_TUNE_AVOID_MFENCE: Use lock prefixed instructions instead of mfence. */
DEF_TUNE (X86_TUNE_AVOID_MFENCE, "avoid_mfence",
- m_CORE_ALL | m_BDVER | m_ZNVER | m_GENERIC)
+ m_CORE_ALL | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC)
/* X86_TUNE_EXPAND_ABS: This enables a new abs pattern by
generating instructions for abs (x) = (((signed) x >> (W-1) ^ x) -
(signed) x >> (W-1)) instead of cmove or SSE max/abs instructions. */
DEF_TUNE (X86_TUNE_EXPAND_ABS, "expand_abs",
m_CORE_ALL | m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT
- | m_GOLDMONT_PLUS | m_TREMONT )
+ | m_GOLDMONT_PLUS)
/*****************************************************************************/
/* 387 instruction selection tuning */
@@ -386,13 +402,13 @@ DEF_TUNE (X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL, "sse_packed_single_insn_optim
/* X86_TUNE_SSE_TYPELESS_STORES: Always movaps/movups for 128bit stores. */
DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores",
- m_AMD_MULTIPLE | m_CORE_ALL | m_GENERIC)
+ m_AMD_MULTIPLE | m_CORE_ALL | m_TREMONT | m_GENERIC)
/* X86_TUNE_SSE_LOAD0_BY_PXOR: Always use pxor to load0 as opposed to
xorps/xorpd and other variants. */
DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor",
m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BDVER | m_BTVER | m_ZNVER
- | m_GENERIC)
+ | m_TREMONT | m_GENERIC)
/* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from integer
to SSE registers. If disabled, the moves will be done by storing
@@ -419,7 +435,7 @@ DEF_TUNE (X86_TUNE_INTER_UNIT_CONVERSIONS, "inter_unit_conversions",
fp converts to destination register. */
DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts",
m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS
- | m_TREMONT | m_INTEL)
+ | m_INTEL)
/* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion
from FP to FP. This form of instructions avoids partial write to the
@@ -434,7 +450,7 @@ DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10)
/* X86_TUNE_SLOW_SHUFB: Indicates tunings with slow pshufb instruction. */
DEF_TUNE (X86_TUNE_SLOW_PSHUFB, "slow_pshufb",
m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT
- | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL)
+ | m_GOLDMONT_PLUS | m_INTEL)
/* X86_TUNE_AVOID_4BYTE_PREFIXES: Avoid instructions requiring 4+ bytes of prefixes. */
DEF_TUNE (X86_TUNE_AVOID_4BYTE_PREFIXES, "avoid_4byte_prefixes",
@@ -484,6 +500,17 @@ DEF_TUNE (X86_TUNE_AVX128_OPTIMAL, "avx128_optimal", m_BDVER | m_BTVER2
instructions in the auto-vectorizer. */
DEF_TUNE (X86_TUNE_AVX256_OPTIMAL, "avx256_optimal", m_CORE_AVX512)
+/* X86_TUNE_AVX256_MOVE_BY_PIECES: Optimize move_by_pieces with 256-bit
+ AVX instructions. */
+DEF_TUNE (X86_TUNE_AVX256_MOVE_BY_PIECES, "avx256_move_by_pieces",
+ m_ALDERLAKE | m_CORE_AVX512)
+
+/* X86_TUNE_AVX256_STORE_BY_PIECES: Optimize store_by_pieces with 256-bit
+ AVX instructions. */
+DEF_TUNE (X86_TUNE_AVX256_STORE_BY_PIECES, "avx256_store_by_pieces",
+ m_ALDERLAKE | m_CORE_AVX512)
+
+/*****************************************************************************/
/*****************************************************************************/
/* Historical relics: tuning flags that helps a specific old CPU designs */
/*****************************************************************************/
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 632b9df..39a0e07 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -6098,7 +6098,7 @@ ia64_option_override (void)
flag_ira_loop_pressure = 1;
- ia64_section_threshold = (global_options_set.x_g_switch_value
+ ia64_section_threshold = (OPTION_SET_P (g_switch_value)
? g_switch_value
: IA64_DEFAULT_GVALUE);
@@ -6120,8 +6120,8 @@ static void
ia64_override_options_after_change (void)
{
if (optimize >= 3
- && !global_options_set.x_flag_selective_scheduling
- && !global_options_set.x_flag_selective_scheduling2)
+ && !OPTION_SET_P (flag_selective_scheduling)
+ && !OPTION_SET_P (flag_selective_scheduling2))
{
flag_selective_scheduling2 = 1;
flag_sel_sched_pipelining = 1;
diff --git a/gcc/config/lm32/uclinux-elf.h b/gcc/config/lm32/uclinux-elf.h
index 370df4c5..5b638fa 100644
--- a/gcc/config/lm32/uclinux-elf.h
+++ b/gcc/config/lm32/uclinux-elf.h
@@ -67,6 +67,7 @@
#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS()
+#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static|static-pie:--start-group} %G %{!nolibc:%L} \
%{static|static-pie:--end-group}%{!static:%{!static-pie:%G}}"
diff --git a/gcc/config/lynx.h b/gcc/config/lynx.h
index 020cc97..1438704 100644
--- a/gcc/config/lynx.h
+++ b/gcc/config/lynx.h
@@ -158,13 +158,6 @@ along with GCC; see the file COPYING3. If not see
while (0)
#endif
-/* Keep the *_DEBUGGING_INFO defines from elfos.h except that stabs is
- the default on LynxOS. */
-
-#ifndef PREFERRED_DEBUGGING_TYPE
-# define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#endif
-
#ifndef TARGET_POSIX_IO
# define TARGET_POSIX_IO
#endif
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index d22bdd7..f99e2b0 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -48,6 +48,7 @@
#include "expr.h"
#include "tm-constrs.h"
#include "builtins.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -412,7 +413,7 @@ static void
m32c_option_override (void)
{
/* We limit memregs to 0..16, and provide a default. */
- if (global_options_set.x_target_memregs)
+ if (OPTION_SET_P (target_memregs))
{
if (target_memregs < 0 || target_memregs > 16)
error ("invalid target memregs value %<%d%>", target_memregs);
diff --git a/gcc/config/m32r/linux.h b/gcc/config/m32r/linux.h
deleted file mode 100644
index 4fdebbc..0000000
--- a/gcc/config/m32r/linux.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Definitions for Renesas M32R running Linux-based GNU systems using ELF.
- Copyright (C) 2003-2021 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/>. */
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
-
-/* Provide a LINK_SPEC appropriate for Linux. Here we provide support
- for the special GCC options -static and -shared, which allow us to
- link things in one of these three modes by applying the appropriate
- combinations of options at link-time.
-
- When the -shared link option is used a final link is not being
- done. */
-
-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
-
-#undef LINK_SPEC
-#if TARGET_LITTLE_ENDIAN
-#define LINK_SPEC "%(link_cpu) -m m32rlelf_linux %{shared:-shared} \
- %{!shared: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
- %{static:-static}}"
-#else
-#define LINK_SPEC "%(link_cpu) -m m32relf_linux %{shared:-shared} \
- %{!shared: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
- %{static:-static}}"
-#endif
-
-#undef LIB_SPEC
-#define LIB_SPEC \
- "%{pthread:-lpthread} \
- %{shared: -lc} \
- %{!shared: \
- %{mieee-fp:-lieee} \
- %{profile:-lc_p} %{!profile: -lc}}"
-
-#undef STARTFILE_SPEC
-#if defined HAVE_LD_PIE
-#define STARTFILE_SPEC \
- "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
- crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
-#else
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
- crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-#endif
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
-
-#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "\
- %{posix:-D_POSIX_SOURCE} \
- %{pthread:-D_REENTRANT -D_PTHREADS} \
-"
-
-#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS()
-
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 1aaba94..d644f6b 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -45,6 +45,7 @@
#include "expr.h"
#include "tm-constrs.h"
#include "builtins.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -244,7 +245,7 @@ m32r_init (void)
m32r_punct_chars['@'] = 1; /* ??? no longer used */
/* Provide default value if not specified. */
- if (!global_options_set.x_g_switch_value)
+ if (!OPTION_SET_P (g_switch_value))
g_switch_value = SDATA_DEFAULT_SIZE;
}
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 83a4b0b..047805f 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -769,29 +769,6 @@ L2: .word STATIC
/* Globalizing directive for a label. */
#define GLOBAL_ASM_OP "\t.global\t"
-/* We do not use DBX_LINES_FUNCTION_RELATIVE or
- dbxout_stab_value_internal_label_diff here because
- we need to use .debugsym for the line label. */
-
-#define DBX_OUTPUT_SOURCE_LINE(file, line, counter) \
- do \
- { \
- const char * begin_label = \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); \
- char label[64]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "LM", counter); \
- \
- dbxout_begin_stabn_sline (line); \
- assemble_name (file, label); \
- putc ('-', file); \
- assemble_name (file, begin_label); \
- fputs ("\n\t.debugsym ", file); \
- assemble_name (file, label); \
- putc ('\n', file); \
- counter += 1; \
- } \
- while (0)
-
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
#ifndef SUBTARGET_REGISTER_NAMES
@@ -930,16 +907,13 @@ L2: .word STATIC
/* Debugging information. */
-/* Generate DBX and DWARF debugging information. */
-#define DBX_DEBUGGING_INFO 1
+/* Generate DWARF debugging information. */
#define DWARF2_DEBUGGING_INFO 1
/* Use DWARF2 debugging info by default. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* Turn off splitting of long stabs. */
-#define DBX_CONTIN_LENGTH 0
/* Miscellaneous. */
diff --git a/gcc/config/m32r/t-linux b/gcc/config/m32r/t-linux
deleted file mode 100644
index 3384b8a..0000000
--- a/gcc/config/m32r/t-linux
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 2003-2021 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/>.
-
-# Don't install "assert.h" in gcc. We use the one in glibc.
-INSTALL_ASSERT_H =
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 3f63c60..d1105e7 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -500,13 +500,13 @@ m68k_option_override (void)
const struct m68k_target_selection *entry;
unsigned long target_mask;
- if (global_options_set.x_m68k_arch_option)
+ if (OPTION_SET_P (m68k_arch_option))
m68k_arch_entry = &all_isas[m68k_arch_option];
- if (global_options_set.x_m68k_cpu_option)
+ if (OPTION_SET_P (m68k_cpu_option))
m68k_cpu_entry = &all_devices[(int) m68k_cpu_option];
- if (global_options_set.x_m68k_tune_option)
+ if (OPTION_SET_P (m68k_tune_option))
m68k_tune_entry = &all_microarchs[(int) m68k_tune_option];
/* User can choose:
@@ -7115,6 +7115,9 @@ m68k_excess_precision (enum excess_precision_type type)
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+ case EXCESS_PRECISION_TYPE_FLOAT16:
+ error ("%<-fexcess-precision=16%> is not supported on this target");
+ break;
default:
gcc_unreachable ();
}
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 6e8f367..4813f7a 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -51,6 +51,7 @@
#include "cfgloop.h"
#include "insn-addr.h"
#include "cfgrtl.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -1741,7 +1742,7 @@ microblaze_option_override (void)
machine_mode mode;
int ver;
- microblaze_section_threshold = (global_options_set.x_g_switch_value
+ microblaze_section_threshold = (OPTION_SET_P (g_switch_value)
? g_switch_value
: MICROBLAZE_DEFAULT_GVALUE);
diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def
index b02294b..45fb6bc 100644
--- a/gcc/config/mips/mips-cpus.def
+++ b/gcc/config/mips/mips-cpus.def
@@ -33,146 +33,146 @@ along with GCC; see the file COPYING3. If not see
where the arguments are the fields of struct mips_cpu_info. */
/* Entries for generic ISAs. */
-MIPS_CPU ("mips1", PROCESSOR_R3000, 1, 0)
-MIPS_CPU ("mips2", PROCESSOR_R6000, 2, PTF_AVOID_BRANCHLIKELY_SIZE)
-MIPS_CPU ("mips3", PROCESSOR_R4000, 3, PTF_AVOID_BRANCHLIKELY_SIZE)
-MIPS_CPU ("mips4", PROCESSOR_R10000, 4, PTF_AVOID_BRANCHLIKELY_SIZE)
+MIPS_CPU ("mips1", PROCESSOR_R3000, MIPS_ISA_MIPS1, 0)
+MIPS_CPU ("mips2", PROCESSOR_R6000, MIPS_ISA_MIPS2, PTF_AVOID_BRANCHLIKELY_SIZE)
+MIPS_CPU ("mips3", PROCESSOR_R4000, MIPS_ISA_MIPS3, PTF_AVOID_BRANCHLIKELY_SIZE)
+MIPS_CPU ("mips4", PROCESSOR_R10000, MIPS_ISA_MIPS4, PTF_AVOID_BRANCHLIKELY_SIZE)
/* Prefer not to use branch-likely instructions for generic MIPS32rX
and MIPS64rX code. The instructions were officially deprecated
in revisions 2 and earlier, but revision 3 is likely to downgrade
that to a recommendation to avoid the instructions in code that
isn't tuned to a specific processor. */
-MIPS_CPU ("mips32", PROCESSOR_4KC, 32, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, 33, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips32", PROCESSOR_4KC, MIPS_ISA_MIPS32, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, MIPS_ISA_MIPS32R2, PTF_AVOID_BRANCHLIKELY_ALWAYS)
/* mips32r3 is micromips hense why it uses the M4K processor. */
-MIPS_CPU ("mips32r3", PROCESSOR_M4K, 34, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips32r5", PROCESSOR_P5600, 36, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips32r6", PROCESSOR_I6400, 37, 0)
-MIPS_CPU ("mips64", PROCESSOR_5KC, 64, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips32r3", PROCESSOR_M4K, MIPS_ISA_MIPS32R3, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips32r5", PROCESSOR_P5600, MIPS_ISA_MIPS32R5, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips32r6", PROCESSOR_I6400, MIPS_ISA_MIPS32R6, 0)
+MIPS_CPU ("mips64", PROCESSOR_5KC, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_ALWAYS)
/* ??? For now just tune the generic MIPS64r2 and above for 5KC as well. */
-MIPS_CPU ("mips64r2", PROCESSOR_5KC, 65, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips64r3", PROCESSOR_5KC, 66, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips64r5", PROCESSOR_5KC, 68, PTF_AVOID_BRANCHLIKELY_ALWAYS)
-MIPS_CPU ("mips64r6", PROCESSOR_I6400, 69, 0)
+MIPS_CPU ("mips64r2", PROCESSOR_5KC, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips64r3", PROCESSOR_5KC, MIPS_ISA_MIPS64R3, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips64r5", PROCESSOR_5KC, MIPS_ISA_MIPS64R5, PTF_AVOID_BRANCHLIKELY_ALWAYS)
+MIPS_CPU ("mips64r6", PROCESSOR_I6400, MIPS_ISA_MIPS64R6, 0)
/* MIPS I processors. */
-MIPS_CPU ("r3000", PROCESSOR_R3000, 1, 0)
-MIPS_CPU ("r2000", PROCESSOR_R3000, 1, 0)
-MIPS_CPU ("r3900", PROCESSOR_R3900, 1, 0)
+MIPS_CPU ("r3000", PROCESSOR_R3000, MIPS_ISA_MIPS1, 0)
+MIPS_CPU ("r2000", PROCESSOR_R3000, MIPS_ISA_MIPS1, 0)
+MIPS_CPU ("r3900", PROCESSOR_R3900, MIPS_ISA_MIPS1, 0)
/* MIPS II processors. */
-MIPS_CPU ("r6000", PROCESSOR_R6000, 2, 0)
+MIPS_CPU ("r6000", PROCESSOR_R6000, MIPS_ISA_MIPS2, 0)
/* MIPS III processors. */
-MIPS_CPU ("r4000", PROCESSOR_R4000, 3, 0)
-MIPS_CPU ("vr4100", PROCESSOR_R4100, 3, 0)
-MIPS_CPU ("vr4111", PROCESSOR_R4111, 3, 0)
-MIPS_CPU ("vr4120", PROCESSOR_R4120, 3, 0)
-MIPS_CPU ("vr4130", PROCESSOR_R4130, 3, 0)
-MIPS_CPU ("vr4300", PROCESSOR_R4300, 3, 0)
-MIPS_CPU ("r4400", PROCESSOR_R4000, 3, 0)
-MIPS_CPU ("r4600", PROCESSOR_R4600, 3, 0)
-MIPS_CPU ("orion", PROCESSOR_R4600, 3, 0)
-MIPS_CPU ("r4650", PROCESSOR_R4650, 3, 0)
-MIPS_CPU ("r4700", PROCESSOR_R4700, 3, 0)
-MIPS_CPU ("r5900", PROCESSOR_R5900, 3, 0)
+MIPS_CPU ("r4000", PROCESSOR_R4000, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("vr4100", PROCESSOR_R4100, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("vr4111", PROCESSOR_R4111, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("vr4120", PROCESSOR_R4120, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("vr4130", PROCESSOR_R4130, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("vr4300", PROCESSOR_R4300, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("r4400", PROCESSOR_R4000, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("r4600", PROCESSOR_R4600, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("orion", PROCESSOR_R4600, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("r4650", PROCESSOR_R4650, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("r4700", PROCESSOR_R4700, MIPS_ISA_MIPS3, 0)
+MIPS_CPU ("r5900", PROCESSOR_R5900, MIPS_ISA_MIPS3, 0)
/* ST Loongson 2E/2F processors. */
-MIPS_CPU ("loongson2e", PROCESSOR_LOONGSON_2E, 3, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("loongson2f", PROCESSOR_LOONGSON_2F, 3, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("loongson2e", PROCESSOR_LOONGSON_2E, MIPS_ISA_MIPS3, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("loongson2f", PROCESSOR_LOONGSON_2F, MIPS_ISA_MIPS3, PTF_AVOID_BRANCHLIKELY_SPEED)
/* MIPS IV processors. */
-MIPS_CPU ("r8000", PROCESSOR_R8000, 4, 0)
-MIPS_CPU ("r10000", PROCESSOR_R10000, 4, 0)
-MIPS_CPU ("r12000", PROCESSOR_R10000, 4, 0)
-MIPS_CPU ("r14000", PROCESSOR_R10000, 4, 0)
-MIPS_CPU ("r16000", PROCESSOR_R10000, 4, 0)
-MIPS_CPU ("vr5000", PROCESSOR_R5000, 4, 0)
-MIPS_CPU ("vr5400", PROCESSOR_R5400, 4, 0)
-MIPS_CPU ("vr5500", PROCESSOR_R5500, 4, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("rm7000", PROCESSOR_R7000, 4, 0)
-MIPS_CPU ("rm9000", PROCESSOR_R9000, 4, 0)
+MIPS_CPU ("r8000", PROCESSOR_R8000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("r10000", PROCESSOR_R10000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("r12000", PROCESSOR_R10000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("r14000", PROCESSOR_R10000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("r16000", PROCESSOR_R10000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("vr5000", PROCESSOR_R5000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("vr5400", PROCESSOR_R5400, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("vr5500", PROCESSOR_R5500, MIPS_ISA_MIPS4, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("rm7000", PROCESSOR_R7000, MIPS_ISA_MIPS4, 0)
+MIPS_CPU ("rm9000", PROCESSOR_R9000, MIPS_ISA_MIPS4, 0)
/* MIPS32 processors. */
-MIPS_CPU ("4kc", PROCESSOR_4KC, 32, 0)
-MIPS_CPU ("4km", PROCESSOR_4KC, 32, 0)
-MIPS_CPU ("4kp", PROCESSOR_4KP, 32, 0)
-MIPS_CPU ("4ksc", PROCESSOR_4KC, 32, 0)
+MIPS_CPU ("4kc", PROCESSOR_4KC, MIPS_ISA_MIPS32, 0)
+MIPS_CPU ("4km", PROCESSOR_4KC, MIPS_ISA_MIPS32, 0)
+MIPS_CPU ("4kp", PROCESSOR_4KP, MIPS_ISA_MIPS32, 0)
+MIPS_CPU ("4ksc", PROCESSOR_4KC, MIPS_ISA_MIPS32, 0)
/* MIPS32 Release 2 processors. */
-MIPS_CPU ("m4k", PROCESSOR_M4K, 33, 0)
-MIPS_CPU ("m14kc", PROCESSOR_M4K, 33, 0)
-MIPS_CPU ("m14k", PROCESSOR_M4K, 33, 0)
-MIPS_CPU ("m14ke", PROCESSOR_M4K, 33, 0)
-MIPS_CPU ("m14kec", PROCESSOR_M4K, 33, 0)
-MIPS_CPU ("4kec", PROCESSOR_4KC, 33, 0)
-MIPS_CPU ("4kem", PROCESSOR_4KC, 33, 0)
-MIPS_CPU ("4kep", PROCESSOR_4KP, 33, 0)
-MIPS_CPU ("4ksd", PROCESSOR_4KC, 33, 0)
-
-MIPS_CPU ("24kc", PROCESSOR_24KC, 33, 0)
-MIPS_CPU ("24kf2_1", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("24kf", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("24kf1_1", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("24kfx", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("24kx", PROCESSOR_24KF1_1, 33, 0)
-
-MIPS_CPU ("24kec", PROCESSOR_24KC, 33, 0) /* 24K with DSP. */
-MIPS_CPU ("24kef2_1", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("24kef", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("24kef1_1", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("24kefx", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("24kex", PROCESSOR_24KF1_1, 33, 0)
-
-MIPS_CPU ("34kc", PROCESSOR_24KC, 33, 0) /* 34K with MT/DSP. */
-MIPS_CPU ("34kf2_1", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("34kf", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("34kf1_1", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("34kfx", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("34kx", PROCESSOR_24KF1_1, 33, 0)
-MIPS_CPU ("34kn", PROCESSOR_24KC, 33, 0) /* 34K with MT but no DSP. */
-
-MIPS_CPU ("74kc", PROCESSOR_74KC, 33, PTF_AVOID_IMADD) /* 74K with DSPr2. */
-MIPS_CPU ("74kf2_1", PROCESSOR_74KF2_1, 33, PTF_AVOID_IMADD)
-MIPS_CPU ("74kf", PROCESSOR_74KF2_1, 33, PTF_AVOID_IMADD)
-MIPS_CPU ("74kf1_1", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
-MIPS_CPU ("74kfx", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
-MIPS_CPU ("74kx", PROCESSOR_74KF1_1, 33, PTF_AVOID_IMADD)
-MIPS_CPU ("74kf3_2", PROCESSOR_74KF3_2, 33, PTF_AVOID_IMADD)
-
-MIPS_CPU ("1004kc", PROCESSOR_24KC, 33, 0) /* 1004K with MT/DSP. */
-MIPS_CPU ("1004kf2_1", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("1004kf", PROCESSOR_24KF2_1, 33, 0)
-MIPS_CPU ("1004kf1_1", PROCESSOR_24KF1_1, 33, 0)
-
-MIPS_CPU ("interaptiv", PROCESSOR_24KF2_1, 33, 0)
+MIPS_CPU ("m4k", PROCESSOR_M4K, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("m14kc", PROCESSOR_M4K, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("m14k", PROCESSOR_M4K, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("m14ke", PROCESSOR_M4K, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("m14kec", PROCESSOR_M4K, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("4kec", PROCESSOR_4KC, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("4kem", PROCESSOR_4KC, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("4kep", PROCESSOR_4KP, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("4ksd", PROCESSOR_4KC, MIPS_ISA_MIPS32R2, 0)
+
+MIPS_CPU ("24kc", PROCESSOR_24KC, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kf2_1", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kf", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kf1_1", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kfx", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kx", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+
+MIPS_CPU ("24kec", PROCESSOR_24KC, MIPS_ISA_MIPS32R2, 0) /* 24K with DSP. */
+MIPS_CPU ("24kef2_1", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kef", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kef1_1", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kefx", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("24kex", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+
+MIPS_CPU ("34kc", PROCESSOR_24KC, MIPS_ISA_MIPS32R2, 0) /* 34K with MT/DSP. */
+MIPS_CPU ("34kf2_1", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("34kf", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("34kf1_1", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("34kfx", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("34kx", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("34kn", PROCESSOR_24KC, MIPS_ISA_MIPS32R2, 0) /* 34K with MT but no DSP. */
+
+MIPS_CPU ("74kc", PROCESSOR_74KC, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD) /* 74K with DSPr2. */
+MIPS_CPU ("74kf2_1", PROCESSOR_74KF2_1, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf", PROCESSOR_74KF2_1, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf1_1", PROCESSOR_74KF1_1, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+MIPS_CPU ("74kfx", PROCESSOR_74KF1_1, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+MIPS_CPU ("74kx", PROCESSOR_74KF1_1, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+MIPS_CPU ("74kf3_2", PROCESSOR_74KF3_2, MIPS_ISA_MIPS32R2, PTF_AVOID_IMADD)
+
+MIPS_CPU ("1004kc", PROCESSOR_24KC, MIPS_ISA_MIPS32R2, 0) /* 1004K with MT/DSP. */
+MIPS_CPU ("1004kf2_1", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("1004kf", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
+MIPS_CPU ("1004kf1_1", PROCESSOR_24KF1_1, MIPS_ISA_MIPS32R2, 0)
+
+MIPS_CPU ("interaptiv", PROCESSOR_24KF2_1, MIPS_ISA_MIPS32R2, 0)
/* MIPS32 Release 5 processors. */
-MIPS_CPU ("p5600", PROCESSOR_P5600, 36, (PTF_AVOID_BRANCHLIKELY_SPEED
+MIPS_CPU ("p5600", PROCESSOR_P5600, MIPS_ISA_MIPS32R5, (PTF_AVOID_BRANCHLIKELY_SPEED
| PTF_AVOID_IMADD))
-MIPS_CPU ("m5100", PROCESSOR_M5100, 36, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("m5101", PROCESSOR_M5100, 36, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("m5100", PROCESSOR_M5100, MIPS_ISA_MIPS32R5, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("m5101", PROCESSOR_M5100, MIPS_ISA_MIPS32R5, PTF_AVOID_BRANCHLIKELY_SPEED)
/* MIPS64 processors. */
-MIPS_CPU ("5kc", PROCESSOR_5KC, 64, 0)
-MIPS_CPU ("5kf", PROCESSOR_5KF, 64, 0)
-MIPS_CPU ("20kc", PROCESSOR_20KC, 64, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("sb1", PROCESSOR_SB1, 64, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("sb1a", PROCESSOR_SB1A, 64, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("sr71000", PROCESSOR_SR71000, 64, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("xlr", PROCESSOR_XLR, 64, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("5kc", PROCESSOR_5KC, MIPS_ISA_MIPS64, 0)
+MIPS_CPU ("5kf", PROCESSOR_5KF, MIPS_ISA_MIPS64, 0)
+MIPS_CPU ("20kc", PROCESSOR_20KC, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("sb1", PROCESSOR_SB1, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("sb1a", PROCESSOR_SB1A, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("sr71000", PROCESSOR_SR71000, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("xlr", PROCESSOR_XLR, MIPS_ISA_MIPS64, PTF_AVOID_BRANCHLIKELY_SPEED)
/* MIPS64 Release 2 processors. */
-MIPS_CPU ("loongson3a", PROCESSOR_GS464, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("gs464", PROCESSOR_GS464, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("gs464e", PROCESSOR_GS464E, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("gs264e", PROCESSOR_GS264E, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("octeon", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("octeon+", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("octeon2", PROCESSOR_OCTEON2, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("octeon3", PROCESSOR_OCTEON3, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
-MIPS_CPU ("xlp", PROCESSOR_XLP, 65, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("loongson3a", PROCESSOR_GS464, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("gs464", PROCESSOR_GS464, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("gs464e", PROCESSOR_GS464E, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("gs264e", PROCESSOR_GS264E, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("octeon", PROCESSOR_OCTEON, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("octeon+", PROCESSOR_OCTEON, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("octeon2", PROCESSOR_OCTEON2, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("octeon3", PROCESSOR_OCTEON3, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
+MIPS_CPU ("xlp", PROCESSOR_XLP, MIPS_ISA_MIPS64R2, PTF_AVOID_BRANCHLIKELY_SPEED)
/* MIPS64 Release 6 processors. */
-MIPS_CPU ("i6400", PROCESSOR_I6400, 69, 0)
-MIPS_CPU ("i6500", PROCESSOR_I6400, 69, 0)
-MIPS_CPU ("p6600", PROCESSOR_P6600, 69, 0)
+MIPS_CPU ("i6400", PROCESSOR_I6400, MIPS_ISA_MIPS64R6, 0)
+MIPS_CPU ("i6500", PROCESSOR_I6400, MIPS_ISA_MIPS64R6, 0)
+MIPS_CPU ("p6600", PROCESSOR_P6600, MIPS_ISA_MIPS64R6, 0)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 2f7ffe8..807bf1a 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "rtl-iter.h"
#include "flags.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -9896,6 +9897,43 @@ mips_file_start (void)
else
fputs ("\t.module\tnooddspreg\n", asm_out_file);
+ fprintf (asm_out_file, "\t.module\tarch=%s\n", mips_arch_info->name);
+ /* FIXME: DSPR3 is not supported by GCC? gas does support it */
+ if (TARGET_DSPR2)
+ fputs ("\t.module\tdspr2\n", asm_out_file);
+ else if (TARGET_DSP)
+ fputs ("\t.module\tdsp\n", asm_out_file);
+ if (TARGET_EVA)
+ fputs ("\t.module\teva\n", asm_out_file);
+ if (TARGET_MCU)
+ fputs ("\t.module\tmcu\n", asm_out_file);
+ if (TARGET_MDMX)
+ fputs ("\t.module\tmdmx\n", asm_out_file);
+ if (TARGET_MIPS3D)
+ fputs ("\t.module\tmips3d\n", asm_out_file);
+ if (TARGET_MT)
+ fputs ("\t.module\tmt\n", asm_out_file);
+ if (TARGET_SMARTMIPS)
+ fputs ("\t.module\tsmartmips\n", asm_out_file);
+ if (TARGET_VIRT)
+ fputs ("\t.module\tvirt\n", asm_out_file);
+ if (TARGET_MSA)
+ fputs ("\t.module\tmsa\n", asm_out_file);
+ if (TARGET_XPA)
+ fputs ("\t.module\txpa\n", asm_out_file);
+ /* FIXME: MIPS16E2 is not supported by GCC? gas does support it */
+ if (TARGET_CRC)
+ fputs ("\t.module\tcrc\n", asm_out_file);
+ if (TARGET_GINV)
+ fputs ("\t.module\tginv\n", asm_out_file);
+ if (TARGET_LOONGSON_MMI)
+ fputs ("\t.module\tloongson-mmi\n", asm_out_file);
+ /* FIXME: LOONGSON-CAM is not supported by GCC? gas does support it */
+ if (TARGET_LOONGSON_EXT2)
+ fputs ("\t.module\tloongson-ext2\n", asm_out_file);
+ else if (TARGET_LOONGSON_EXT)
+ fputs ("\t.module\tloongson-ext\n", asm_out_file);
+
#else
#ifdef HAVE_AS_GNU_ATTRIBUTE
{
@@ -19817,9 +19855,12 @@ mips_set_architecture (const struct mips_cpu_info *info)
mips_arch_info = info;
mips_arch = info->cpu;
mips_isa = info->isa;
- if (mips_isa < 32)
+ if (mips_isa < MIPS_ISA_MIPS32)
mips_isa_rev = 0;
else
+ /* we can do this is due to the
+ * enum of MIPS32rN is from 32 to 37
+ * enum of MIPS64rN is from 64 to 69 */
mips_isa_rev = (mips_isa & 31) + 1;
}
}
@@ -19843,7 +19884,7 @@ mips_option_override (void)
{
int i, start, regno, mode;
- if (global_options_set.x_mips_isa_option)
+ if (OPTION_SET_P (mips_isa_option))
mips_isa_option_info = &mips_cpu_info_table[mips_isa_option];
#ifdef SUBTARGET_OVERRIDE_OPTIONS
@@ -19875,7 +19916,7 @@ mips_option_override (void)
TARGET_INTERLINK_COMPRESSED = 1;
/* Set the small data limit. */
- mips_small_data_threshold = (global_options_set.x_g_switch_value
+ mips_small_data_threshold = (OPTION_SET_P (g_switch_value)
? g_switch_value
: MIPS_DEFAULT_GVALUE);
@@ -19883,7 +19924,7 @@ mips_option_override (void)
Similar code was added to GAS 2.14 (see tc-mips.c:md_after_parse_args()).
The GAS and GCC code should be kept in sync as much as possible. */
- if (global_options_set.x_mips_arch_option)
+ if (OPTION_SET_P (mips_arch_option))
mips_set_architecture (mips_cpu_info_from_opt (mips_arch_option));
if (mips_isa_option_info != 0)
@@ -19905,7 +19946,7 @@ mips_option_override (void)
mips_arch_info->name);
/* Optimize for mips_arch, unless -mtune selects a different processor. */
- if (global_options_set.x_mips_tune_option)
+ if (OPTION_SET_P (mips_tune_option))
mips_set_tune (mips_cpu_info_from_opt (mips_tune_option));
if (mips_tune_info == 0)
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 47aac9d..973372e 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -42,6 +42,23 @@ extern int target_flags_explicit;
#define ABI_EABI 3
#define ABI_O64 4
+enum mips_isa {
+ MIPS_ISA_MIPS1 = 1,
+ MIPS_ISA_MIPS2 = 2,
+ MIPS_ISA_MIPS3 = 3,
+ MIPS_ISA_MIPS4 = 4,
+ MIPS_ISA_MIPS32 = 32,
+ MIPS_ISA_MIPS32R2 = 33,
+ MIPS_ISA_MIPS32R3 = 34,
+ MIPS_ISA_MIPS32R5 = 36,
+ MIPS_ISA_MIPS32R6 = 37,
+ MIPS_ISA_MIPS64 = 64,
+ MIPS_ISA_MIPS64R2 = 65,
+ MIPS_ISA_MIPS64R3 = 66,
+ MIPS_ISA_MIPS64R5 = 68,
+ MIPS_ISA_MIPS64R6 = 69
+};
+
/* Masks that affect tuning.
PTF_AVOID_BRANCHLIKELY_SPEED
@@ -81,7 +98,7 @@ struct mips_cpu_info {
enum processor cpu;
/* The ISA level that the processor implements. */
- int isa;
+ enum mips_isa isa;
/* A mask of PTF_* values. */
unsigned int tune_flags;
@@ -232,7 +249,7 @@ struct mips_cpu_info {
/* Generate mips16 code */
#define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0)
/* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */
-#define GENERATE_MIPS16E (TARGET_MIPS16 && mips_isa >= 32)
+#define GENERATE_MIPS16E (TARGET_MIPS16 && mips_isa >= MIPS_ISA_MIPS32)
/* Generate mips16e register save/restore sequences. */
#define GENERATE_MIPS16E_SAVE_RESTORE (GENERATE_MIPS16E && mips_abi == ABI_32)
@@ -247,20 +264,20 @@ struct mips_cpu_info {
(TARGET_MIPS16 && mips_code_readable >= CODE_READABLE_PCREL)
/* Generic ISA defines. */
-#define ISA_MIPS1 (mips_isa == 1)
-#define ISA_MIPS2 (mips_isa == 2)
-#define ISA_MIPS3 (mips_isa == 3)
-#define ISA_MIPS4 (mips_isa == 4)
-#define ISA_MIPS32 (mips_isa == 32)
-#define ISA_MIPS32R2 (mips_isa == 33)
-#define ISA_MIPS32R3 (mips_isa == 34)
-#define ISA_MIPS32R5 (mips_isa == 36)
-#define ISA_MIPS32R6 (mips_isa == 37)
-#define ISA_MIPS64 (mips_isa == 64)
-#define ISA_MIPS64R2 (mips_isa == 65)
-#define ISA_MIPS64R3 (mips_isa == 66)
-#define ISA_MIPS64R5 (mips_isa == 68)
-#define ISA_MIPS64R6 (mips_isa == 69)
+#define ISA_MIPS1 (mips_isa == MIPS_ISA_MIPS1)
+#define ISA_MIPS2 (mips_isa == MIPS_ISA_MIPS2)
+#define ISA_MIPS3 (mips_isa == MIPS_ISA_MIPS3)
+#define ISA_MIPS4 (mips_isa == MIPS_ISA_MIPS4)
+#define ISA_MIPS32 (mips_isa == MIPS_ISA_MIPS32)
+#define ISA_MIPS32R2 (mips_isa == MIPS_ISA_MIPS32R2)
+#define ISA_MIPS32R3 (mips_isa == MIPS_ISA_MIPS32R3)
+#define ISA_MIPS32R5 (mips_isa == MIPS_ISA_MIPS32R5)
+#define ISA_MIPS32R6 (mips_isa == MIPS_ISA_MIPS32R6)
+#define ISA_MIPS64 (mips_isa == MIPS_ISA_MIPS64)
+#define ISA_MIPS64R2 (mips_isa == MIPS_ISA_MIPS64R2)
+#define ISA_MIPS64R3 (mips_isa == MIPS_ISA_MIPS64R3)
+#define ISA_MIPS64R5 (mips_isa == MIPS_ISA_MIPS64R5)
+#define ISA_MIPS64R6 (mips_isa == MIPS_ISA_MIPS64R6)
/* Architecture target defines. */
#define TARGET_LOONGSON_2E (mips_arch == PROCESSOR_LOONGSON_2E)
@@ -511,12 +528,13 @@ struct mips_cpu_info {
builtin_define ("__mips=4"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS4"); \
} \
- else if (mips_isa >= 32 && mips_isa < 64) \
+ else if (mips_isa >= MIPS_ISA_MIPS32 \
+ && mips_isa < MIPS_ISA_MIPS64) \
{ \
builtin_define ("__mips=32"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32"); \
} \
- else if (mips_isa >= 64) \
+ else if (mips_isa >= MIPS_ISA_MIPS64) \
{ \
builtin_define ("__mips=64"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \
@@ -708,25 +726,25 @@ struct mips_cpu_info {
#endif
#ifndef MULTILIB_ISA_DEFAULT
-#if MIPS_ISA_DEFAULT == 1
+#if MIPS_ISA_DEFAULT == MIPS_ISA_MIPS1
#define MULTILIB_ISA_DEFAULT "mips1"
-#elif MIPS_ISA_DEFAULT == 2
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS2
#define MULTILIB_ISA_DEFAULT "mips2"
-#elif MIPS_ISA_DEFAULT == 3
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS3
#define MULTILIB_ISA_DEFAULT "mips3"
-#elif MIPS_ISA_DEFAULT == 4
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS4
#define MULTILIB_ISA_DEFAULT "mips4"
-#elif MIPS_ISA_DEFAULT == 32
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS32
#define MULTILIB_ISA_DEFAULT "mips32"
-#elif MIPS_ISA_DEFAULT == 33
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS32R2
#define MULTILIB_ISA_DEFAULT "mips32r2"
-#elif MIPS_ISA_DEFAULT == 37
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS32R6
#define MULTILIB_ISA_DEFAULT "mips32r6"
-#elif MIPS_ISA_DEFAULT == 64
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS64
#define MULTILIB_ISA_DEFAULT "mips64"
-#elif MIPS_ISA_DEFAULT == 65
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS64R2
#define MULTILIB_ISA_DEFAULT "mips64r2"
-#elif MIPS_ISA_DEFAULT == 69
+#elif MIPS_ISA_DEFAULT == MIPS_ISA_MIPS64R6
#define MULTILIB_ISA_DEFAULT "mips64r6"
#else
#define MULTILIB_ISA_DEFAULT "mips1"
@@ -1275,12 +1293,12 @@ struct mips_cpu_info {
&& !TARGET_MICROMIPS)
/* Likewise mtc1 and mfc1. */
-#define ISA_HAS_XFER_DELAY (mips_isa <= 3 \
+#define ISA_HAS_XFER_DELAY (mips_isa <= MIPS_ISA_MIPS3 \
&& !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
/* Likewise floating-point comparisons. */
-#define ISA_HAS_FCMP_DELAY (mips_isa <= 3 \
+#define ISA_HAS_FCMP_DELAY (mips_isa <= MIPS_ISA_MIPS3 \
&& !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
@@ -1305,7 +1323,7 @@ struct mips_cpu_info {
#define ISA_HAS_SYNCI (mips_isa_rev >= 2 && !TARGET_MIPS16)
/* ISA includes sync. */
-#define ISA_HAS_SYNC ((mips_isa >= 2 || TARGET_MIPS3900) && !TARGET_MIPS16)
+#define ISA_HAS_SYNC ((mips_isa >= MIPS_ISA_MIPS2 || TARGET_MIPS3900) && !TARGET_MIPS16)
#define GENERATE_SYNC \
(target_flags_explicit & MASK_LLSC \
? TARGET_LLSC && !TARGET_MIPS16 \
@@ -1314,7 +1332,7 @@ struct mips_cpu_info {
/* ISA includes ll and sc. Note that this implies ISA_HAS_SYNC
because the expanders use both ISA_HAS_SYNC and ISA_HAS_LL_SC
instructions. */
-#define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS5900 && !TARGET_MIPS16)
+#define ISA_HAS_LL_SC (mips_isa >= MIPS_ISA_MIPS2 && !TARGET_MIPS5900 && !TARGET_MIPS16)
#define GENERATE_LL_SC \
(target_flags_explicit & MASK_LLSC \
? TARGET_LLSC && !TARGET_MIPS16 \
@@ -1342,7 +1360,7 @@ struct mips_cpu_info {
#define ISA_HAS_POP (TARGET_OCTEON && !TARGET_MIPS16)
/* The CACHE instruction is available in non-MIPS16 code. */
-#define TARGET_CACHE_BUILTIN (mips_isa >= 3)
+#define TARGET_CACHE_BUILTIN (mips_isa >= MIPS_ISA_MIPS3)
/* The CACHE instruction is available. */
#define ISA_HAS_CACHE (TARGET_CACHE_BUILTIN && !TARGET_MIPS16)
diff --git a/gcc/config/mips/netbsd.h b/gcc/config/mips/netbsd.h
index 5844f00..1c6a59d 100644
--- a/gcc/config/mips/netbsd.h
+++ b/gcc/config/mips/netbsd.h
@@ -84,9 +84,10 @@ along with GCC; see the file COPYING3. If not see
builtin_define ("__mips=3"); \
else if (ISA_MIPS4) \
builtin_define ("__mips=4"); \
- else if (mips_isa >= 32 && mips_isa < 64) \
+ else if (mips_isa >= MIPS_ISA_MIPS32 \
+ && mips_isa < MIPS_ISA_MIPS64) \
builtin_define ("__mips=32"); \
- else if (mips_isa >= 64) \
+ else if (mips_isa >= MIPS_ISA_MIPS64) \
builtin_define ("__mips=64"); \
if (mips_isa_rev > 0) \
builtin_define_with_int_value ("__mips_isa_rev", \
diff --git a/gcc/config/mn10300/linux.h b/gcc/config/mn10300/linux.h
index 657bfe4..44825eb 100644
--- a/gcc/config/mn10300/linux.h
+++ b/gcc/config/mn10300/linux.h
@@ -44,8 +44,6 @@
#undef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_AM33_2
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
extern int mn10300_protect_label;
#undef PRINT_OPERAND
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index d94d8e6..cb0d072 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -649,9 +649,6 @@ do { \
if ((LOG) != 0) \
fprintf (FILE, "\t.align %d\n", (LOG))
-/* We don't have to worry about dbx compatibility for the mn10300. */
-#define DEFAULT_GDB_EXTENSIONS 1
-
/* Use dwarf2 debugging info by default. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 26d4333..7a613e4 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -52,6 +52,7 @@
#include "builtins.h"
#include "tree-pass.h"
#include "xregex.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -1363,7 +1364,7 @@ nios2_option_override (void)
init_machine_status = &nios2_init_machine_status;
nios2_section_threshold
- = (global_options_set.x_g_switch_value
+ = (OPTION_SET_P (g_switch_value)
? g_switch_value : NIOS2_DEFAULT_GVALUE);
if (nios2_gpopt_option == gpopt_unspecified)
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 4e4909e..951252e 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -215,7 +215,7 @@ nvptx_option_override (void)
/* Set toplevel_reorder, unless explicitly disabled. We need
reordering so that we emit necessary assembler decls of
undeclared variables. */
- if (!global_options_set.x_flag_toplevel_reorder)
+ if (!OPTION_SET_P (flag_toplevel_reorder))
flag_toplevel_reorder = 1;
debug_nonbind_markers_p = 0;
@@ -223,7 +223,7 @@ nvptx_option_override (void)
/* Set flag_no_common, unless explicitly disabled. We fake common
using .weak, and that's not entirely accurate, so avoid it
unless forced. */
- if (!global_options_set.x_flag_no_common)
+ if (!OPTION_SET_P (flag_no_common))
flag_no_common = 1;
/* The patch area requires nops, which we don't have. */
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 0614302..d13021a 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -541,6 +541,16 @@ pa_option_override (void)
write_symbols = NO_DEBUG;
}
+ if (TARGET_64BIT && TARGET_HPUX)
+ {
+ /* DWARF5 is not supported by gdb. Don't emit DWARF5 unless
+ specifically selected. */
+ if (!OPTION_SET_P (dwarf_strict))
+ dwarf_strict = 1;
+ if (!OPTION_SET_P (dwarf_version))
+ dwarf_version = 4;
+ }
+
/* We only support the "big PIC" model now. And we always generate PIC
code when in 64bit mode. */
if (flag_pic == 1 || TARGET_64BIT)
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index b314f96..5cda3b7 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -1383,7 +1383,7 @@
(match_operand:SF 2 "reg_or_0_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- ""
+ "! TARGET_SOFT_FLOAT"
"
{
pa_emit_bcond_fp (operands);
@@ -1398,7 +1398,7 @@
(match_operand:DF 2 "reg_or_0_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- ""
+ "! TARGET_SOFT_FLOAT"
"
{
pa_emit_bcond_fp (operands);
@@ -2186,14 +2186,14 @@
[(set (match_operand:SI 0 "move_dest_operand"
"=r,r,r,r,r,r,Q,!*q,!r,!*f,*f,T,?r,?*f")
(match_operand:SI 1 "move_src_operand"
- "A,r,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f,*f,r"))]
+ "A,rG,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f,*f,r"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& !TARGET_SOFT_FLOAT
&& !TARGET_64BIT"
"@
ldw RT'%A1,%0
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
{zdepi|depwi,z} %Z1,%0
@@ -2214,14 +2214,14 @@
[(set (match_operand:SI 0 "move_dest_operand"
"=r,r,r,r,r,r,Q,!*q,!r,!*f,*f,T")
(match_operand:SI 1 "move_src_operand"
- "A,r,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f"))]
+ "A,rG,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& !TARGET_SOFT_FLOAT
&& TARGET_64BIT"
"@
ldw RT'%A1,%0
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
{zdepi|depwi,z} %Z1,%0
@@ -2237,6 +2237,29 @@
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4")])
(define_insn ""
+ [(set (match_operand:SI 0 "move_dest_operand"
+ "=r,r,r,r,r,r,Q,!*q,!r")
+ (match_operand:SI 1 "move_src_operand"
+ "A,rG,J,N,K,RQ,rM,!rM,!*q"))]
+ "(register_operand (operands[0], SImode)
+ || reg_or_0_operand (operands[1], SImode))
+ && TARGET_SOFT_FLOAT
+ && TARGET_64BIT"
+ "@
+ ldw RT'%A1,%0
+ copy %r1,%0
+ ldi %1,%0
+ ldil L'%1,%0
+ {zdepi|depwi,z} %Z1,%0
+ ldw%M1 %1,%0
+ stw%M0 %r1,%0
+ mtsar %r1
+ {mfctl|mfctl,w} %%sar,%0"
+ [(set_attr "type" "load,move,move,move,shift,load,store,move,move")
+ (set_attr "pa_combine_type" "addmove")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4")])
+
+(define_insn ""
[(set (match_operand:SI 0 "indexed_memory_operand" "=R")
(match_operand:SI 1 "register_operand" "f"))]
"!TARGET_SOFT_FLOAT
@@ -2358,13 +2381,13 @@
[(set (match_operand:SI 0 "move_dest_operand"
"=r,r,r,r,r,r,Q,!*q,!r")
(match_operand:SI 1 "move_src_operand"
- "A,r,J,N,K,RQ,rM,!rM,!*q"))]
+ "A,rG,J,N,K,RQ,rM,!rM,!*q"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& TARGET_SOFT_FLOAT"
"@
ldw RT'%A1,%0
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
{zdepi|depwi,z} %Z1,%0
@@ -2886,11 +2909,11 @@
[(set (match_operand:HI 0 "move_dest_operand"
"=r,r,r,r,r,Q,!*q,!r")
(match_operand:HI 1 "move_src_operand"
- "r,J,N,K,RQ,rM,!rM,!*q"))]
+ "rG,J,N,K,RQ,rM,!rM,!*q"))]
"(register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
"@
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
{zdepi|depwi,z} %Z1,%0
@@ -3046,11 +3069,11 @@
[(set (match_operand:QI 0 "move_dest_operand"
"=r,r,r,r,r,Q,!*q,!r")
(match_operand:QI 1 "move_src_operand"
- "r,J,N,K,RQ,rM,!rM,!*q"))]
+ "rG,J,N,K,RQ,rM,!rM,!*q"))]
"(register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
"@
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
{zdepi|depwi,z} %Z1,%0
@@ -4024,12 +4047,12 @@
[(set (match_operand:DF 0 "move_dest_operand"
"=!*r,*r,*r,*r,*r,Q,f,f,T")
(match_operand:DF 1 "move_src_operand"
- "!*r,J,N,K,RQ,*rG,fG,RT,f"))]
+ "!*rG,J,N,K,RQ,*rG,fG,RT,f"))]
"(register_operand (operands[0], DFmode)
|| reg_or_0_operand (operands[1], DFmode))
&& !TARGET_SOFT_FLOAT && TARGET_64BIT"
"@
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
depdi,z %z1,%0
@@ -4042,6 +4065,25 @@
(set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4,4,4,4")])
+(define_insn ""
+ [(set (match_operand:DF 0 "move_dest_operand"
+ "=!*r,*r,*r,*r,*r,Q")
+ (match_operand:DF 1 "move_src_operand"
+ "!*rG,J,N,K,RQ,*rG"))]
+ "(register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))
+ && TARGET_SOFT_FLOAT && TARGET_64BIT"
+ "@
+ copy %r1,%0
+ ldi %1,%0
+ ldil L'%1,%0
+ depdi,z %z1,%0
+ ldd%M1 %1,%0
+ std%M0 %r1,%0"
+ [(set_attr "type" "move,move,move,shift,load,store")
+ (set_attr "pa_combine_type" "addmove")
+ (set_attr "length" "4,4,4,4,4,4")])
+
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
@@ -4179,13 +4221,13 @@
[(set (match_operand:DI 0 "move_dest_operand"
"=r,r,r,r,r,r,Q,!*q,!r,!*f,*f,T")
(match_operand:DI 1 "move_src_operand"
- "A,r,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f"))]
+ "A,rG,J,N,K,RQ,rM,!rM,!*q,!*fM,RT,*f"))]
"(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))
&& !TARGET_SOFT_FLOAT && TARGET_64BIT"
"@
ldd RT'%A1,%0
- copy %1,%0
+ copy %r1,%0
ldi %1,%0
ldil L'%1,%0
depdi,z %z1,%0
@@ -4201,6 +4243,28 @@
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4")])
(define_insn ""
+ [(set (match_operand:DI 0 "move_dest_operand"
+ "=r,r,r,r,r,r,Q,!*q,!r")
+ (match_operand:DI 1 "move_src_operand"
+ "A,rG,J,N,K,RQ,rM,!rM,!*q"))]
+ "(register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))
+ && TARGET_SOFT_FLOAT && TARGET_64BIT"
+ "@
+ ldd RT'%A1,%0
+ copy %r1,%0
+ ldi %1,%0
+ ldil L'%1,%0
+ depdi,z %z1,%0
+ ldd%M1 %1,%0
+ std%M0 %r1,%0
+ mtsar %r1
+ {mfctl|mfctl,w} %%sar,%0"
+ [(set_attr "type" "load,move,move,move,shift,load,store,move,move")
+ (set_attr "pa_combine_type" "addmove")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4")])
+
+(define_insn ""
[(set (match_operand:DI 0 "indexed_memory_operand" "=R")
(match_operand:DI 1 "register_operand" "f"))]
"!TARGET_SOFT_FLOAT
@@ -4406,6 +4470,23 @@
(set_attr "length" "4,4,4,4,4,4")])
(define_insn ""
+ [(set (match_operand:SF 0 "move_dest_operand"
+ "=!*r,*r,Q")
+ (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
+ "!*rG,RQ,*rG"))]
+ "(register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))
+ && TARGET_SOFT_FLOAT
+ && TARGET_64BIT"
+ "@
+ copy %r1,%0
+ ldw%M1 %1,%0
+ stw%M0 %r1,%0"
+ [(set_attr "type" "move,load,store")
+ (set_attr "pa_combine_type" "addmove")
+ (set_attr "length" "4,4,4")])
+
+(define_insn ""
[(set (match_operand:SF 0 "indexed_memory_operand" "=R")
(match_operand:SF 1 "register_operand" "f"))]
"!TARGET_SOFT_FLOAT
@@ -5374,32 +5455,38 @@
[(set (match_operand:DI 0 "register_operand" "")
(mult:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))]
- "TARGET_64BIT && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT"
+ "! optimize_size
+ && TARGET_PA_11
+ && ! TARGET_DISABLE_FPREGS
+ && ! TARGET_SOFT_FLOAT"
"
{
rtx low_product = gen_reg_rtx (DImode);
rtx cross_product1 = gen_reg_rtx (DImode);
rtx cross_product2 = gen_reg_rtx (DImode);
- rtx cross_scratch = gen_reg_rtx (DImode);
- rtx cross_product = gen_reg_rtx (DImode);
rtx op1l, op1r, op2l, op2r;
- rtx op1shifted, op2shifted;
-
- op1shifted = gen_reg_rtx (DImode);
- op2shifted = gen_reg_rtx (DImode);
- op1l = gen_reg_rtx (SImode);
- op1r = gen_reg_rtx (SImode);
- op2l = gen_reg_rtx (SImode);
- op2r = gen_reg_rtx (SImode);
-
- emit_move_insn (op1shifted, gen_rtx_LSHIFTRT (DImode, operands[1],
- GEN_INT (32)));
- emit_move_insn (op2shifted, gen_rtx_LSHIFTRT (DImode, operands[2],
- GEN_INT (32)));
- op1r = force_reg (SImode, gen_rtx_SUBREG (SImode, operands[1], 4));
- op2r = force_reg (SImode, gen_rtx_SUBREG (SImode, operands[2], 4));
- op1l = force_reg (SImode, gen_rtx_SUBREG (SImode, op1shifted, 4));
- op2l = force_reg (SImode, gen_rtx_SUBREG (SImode, op2shifted, 4));
+
+ if (TARGET_64BIT)
+ {
+ rtx op1shifted = gen_reg_rtx (DImode);
+ rtx op2shifted = gen_reg_rtx (DImode);
+
+ emit_move_insn (op1shifted, gen_rtx_LSHIFTRT (DImode, operands[1],
+ GEN_INT (32)));
+ emit_move_insn (op2shifted, gen_rtx_LSHIFTRT (DImode, operands[2],
+ GEN_INT (32)));
+ op1r = force_reg (SImode, gen_rtx_SUBREG (SImode, operands[1], 4));
+ op2r = force_reg (SImode, gen_rtx_SUBREG (SImode, operands[2], 4));
+ op1l = force_reg (SImode, gen_rtx_SUBREG (SImode, op1shifted, 4));
+ op2l = force_reg (SImode, gen_rtx_SUBREG (SImode, op2shifted, 4));
+ }
+ else
+ {
+ op1r = force_reg (SImode, gen_lowpart (SImode, operands[1]));
+ op2r = force_reg (SImode, gen_lowpart (SImode, operands[2]));
+ op1l = force_reg (SImode, gen_highpart (SImode, operands[1]));
+ op2l = force_reg (SImode, gen_highpart (SImode, operands[2]));
+ }
/* Emit multiplies for the cross products. */
emit_insn (gen_umulsidi3 (cross_product1, op2r, op1l));
@@ -5408,13 +5495,35 @@
/* Emit a multiply for the low sub-word. */
emit_insn (gen_umulsidi3 (low_product, copy_rtx (op2r), copy_rtx (op1r)));
- /* Sum the cross products and shift them into proper position. */
- emit_insn (gen_adddi3 (cross_scratch, cross_product1, cross_product2));
- emit_insn (gen_ashldi3 (cross_product, cross_scratch, GEN_INT (32)));
+ if (TARGET_64BIT)
+ {
+ rtx cross_scratch = gen_reg_rtx (DImode);
+ rtx cross_product = gen_reg_rtx (DImode);
- /* Add the cross product to the low product and store the result
- into the output operand . */
- emit_insn (gen_adddi3 (operands[0], cross_product, low_product));
+ /* Sum the cross products and shift them into proper position. */
+ emit_insn (gen_adddi3 (cross_scratch, cross_product1, cross_product2));
+ emit_insn (gen_ashldi3 (cross_product, cross_scratch, GEN_INT (32)));
+
+ /* Add the cross product to the low product and store the result
+ into the output operand . */
+ emit_insn (gen_adddi3 (operands[0], cross_product, low_product));
+ }
+ else
+ {
+ rtx cross_scratch = gen_reg_rtx (SImode);
+
+ /* Sum cross products. */
+ emit_move_insn (cross_scratch,
+ gen_rtx_PLUS (SImode,
+ gen_lowpart (SImode, cross_product1),
+ gen_lowpart (SImode, cross_product2)));
+ emit_move_insn (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, low_product));
+ emit_move_insn (gen_highpart (SImode, operands[0]),
+ gen_rtx_PLUS (SImode,
+ gen_highpart (SImode, low_product),
+ cross_scratch));
+ }
DONE;
}")
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index 05cc315..36a1122 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -21,6 +21,10 @@ along with GCC; see the file COPYING3. If not see
#undef TARGET_SOM
#define TARGET_SOM 1
+/* With SOM we can only do STABS. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
/* We do not use BINCL stabs in SOM.
??? If it does not hurt, we probably should to avoid useless divergence
from other embedded stabs implementations. */
diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
index 9bc5e08..91a8ce7 100644
--- a/gcc/config/pdp11/pdp11.h
+++ b/gcc/config/pdp11/pdp11.h
@@ -54,6 +54,9 @@ along with GCC; see the file COPYING3. If not see
#define DBX_DEBUGGING_INFO
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
#define TARGET_40_PLUS (TARGET_40 || TARGET_45)
#define TARGET_10 (! TARGET_40_PLUS)
diff --git a/gcc/config/pru/constraints.md b/gcc/config/pru/constraints.md
index a31ae93..1e0e703 100644
--- a/gcc/config/pru/constraints.md
+++ b/gcc/config/pru/constraints.md
@@ -34,6 +34,7 @@
;; The following constraints are intended for internal use only:
;; Rmd0, Rms0, Rms1: Registers for MUL instruction operands.
;; Rsib: Jump address register suitable for sibling calls.
+;; Rrio: The R30 and R31 I/O registers.
;; M: -255 to 0 (for converting ADD to SUB with suitable UBYTE OP2).
;; N: -32768 to 32767 (16-bit signed integer).
;; O: -128 to 127 (8-bit signed integer).
@@ -57,6 +58,10 @@
"@internal
The multiply source 1 register.")
+(define_register_constraint "Rrio" "REGIO_REGS"
+ "@internal
+ The R30 and R31 I/O registers.")
+
;; Integer constraints.
(define_constraint "I"
diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md
index 469002f..1a4b98e 100644
--- a/gcc/config/pru/predicates.md
+++ b/gcc/config/pru/predicates.md
@@ -121,6 +121,25 @@
return 0;
})
+(define_predicate "regio_operand"
+ (match_code "subreg,reg")
+{
+ if (register_operand (op, mode))
+ {
+ int regno;
+
+ if (REG_P (op))
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 0;
+
+ return REGNO_REG_CLASS (regno) == REGIO_REGS;
+ }
+ return 0;
+})
+
(define_predicate "reg_or_const_int_operand"
(ior (match_operand 0 "const_int_operand")
(match_operand 0 "register_operand")))
diff --git a/gcc/config/pru/pru-pragma.c b/gcc/config/pru/pru-pragma.c
index 01d0761..3beec23 100644
--- a/gcc/config/pru/pru-pragma.c
+++ b/gcc/config/pru/pru-pragma.c
@@ -83,4 +83,6 @@ pru_register_pragmas (void)
{
c_register_pragma (NULL, "ctable_entry", pru_pragma_ctable_entry);
c_register_pragma (NULL, "CTABLE_ENTRY", pru_pragma_ctable_entry);
+
+ c_register_addr_space ("__regio_symbol", ADDR_SPACE_REGIO);
}
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index 74129e9..031ea9e 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -62,7 +62,10 @@ extern int pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr);
extern int pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr);
extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
+extern int pru_symref2ioregno (rtx op);
+
extern void pru_register_abicheck_pass (void);
+
#endif /* RTX_CODE */
#ifdef TREE_CODE
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
index 30d0da1..9f264b4 100644
--- a/gcc/config/pru/pru.c
+++ b/gcc/config/pru/pru.c
@@ -1403,11 +1403,42 @@ pru_valid_addr_expr_p (machine_mode mode, rtx base, rtx offset, bool strict_p)
return false;
}
-/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
+/* Return register number (either for r30 or r31) which maps to the
+ corresponding symbol OP's name in the __regio_symbol address namespace.
+
+ If no mapping can be established (i.e. symbol name is invalid), then
+ return -1. */
+int pru_symref2ioregno (rtx op)
+{
+ if (!SYMBOL_REF_P (op))
+ return -1;
+
+ const char *name = XSTR (op, 0);
+ if (!strcmp (name, "__R30"))
+ return R30_REGNUM;
+ else if (!strcmp (name, "__R31"))
+ return R31_REGNUM;
+ else
+ return -1;
+}
+
+/* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P. */
static bool
-pru_legitimate_address_p (machine_mode mode,
- rtx operand, bool strict_p)
+pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
+ bool strict_p, addr_space_t as)
{
+ if (as == ADDR_SPACE_REGIO)
+ {
+ /* Address space constraints for __regio_symbol have been checked in
+ TARGET_INSERT_ATTRIBUTES, and some more checks will be done
+ during RTL expansion of "mov<mode>". */
+ return true;
+ }
+ else if (as != ADDR_SPACE_GENERIC)
+ {
+ gcc_unreachable ();
+ }
+
switch (GET_CODE (operand))
{
/* Direct. */
@@ -2002,6 +2033,117 @@ pru_file_start (void)
need to confuse users with this warning. */
fprintf (asm_out_file, "\t.set no_warn_regname_label\n");
}
+
+/* Scan type TYP for pointer references to address space other than
+ ADDR_SPACE_GENERIC. Return true if such reference is found.
+ Much of this code was taken from the avr port. */
+
+static bool
+pru_nongeneric_pointer_addrspace (tree typ)
+{
+ while (ARRAY_TYPE == TREE_CODE (typ))
+ typ = TREE_TYPE (typ);
+
+ if (POINTER_TYPE_P (typ))
+ {
+ addr_space_t as;
+ tree target = TREE_TYPE (typ);
+
+ /* Pointer to function: Test the function's return type. */
+ if (FUNCTION_TYPE == TREE_CODE (target))
+ return pru_nongeneric_pointer_addrspace (TREE_TYPE (target));
+
+ /* "Ordinary" pointers... */
+
+ while (TREE_CODE (target) == ARRAY_TYPE)
+ target = TREE_TYPE (target);
+
+ as = TYPE_ADDR_SPACE (target);
+
+ if (!ADDR_SPACE_GENERIC_P (as))
+ return true;
+
+ /* Scan pointer's target type. */
+ return pru_nongeneric_pointer_addrspace (target);
+ }
+
+ return false;
+}
+
+/* Implement `TARGET_INSERT_ATTRIBUTES'. For PRU it's used as a hook to
+ provide better diagnostics for some invalid usages of the __regio_symbol
+ address space.
+
+ Any escapes of the following checks are supposed to be caught
+ during the "mov<mode>" pattern expansion. */
+
+static void
+pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
+{
+
+ /* Validate __regio_symbol variable declarations. */
+ if (VAR_P (node))
+ {
+ const char *name = DECL_NAME (node)
+ ? IDENTIFIER_POINTER (DECL_NAME (node))
+ : "<unknown>";
+ tree typ = TREE_TYPE (node);
+ addr_space_t as = TYPE_ADDR_SPACE (typ);
+
+ if (as == ADDR_SPACE_GENERIC)
+ return;
+
+ if (AGGREGATE_TYPE_P (typ))
+ {
+ error ("aggregate types are prohibited in "
+ "%<__regio_symbol%> address space");
+ /* Don't bother anymore. Below checks would pile
+ meaningless errors, which would confuse user. */
+ return;
+ }
+ if (DECL_INITIAL (node) != NULL_TREE)
+ error ("variables in %<__regio_symbol%> address space "
+ "cannot have initial value");
+ if (DECL_REGISTER (node))
+ error ("variables in %<__regio_symbol%> address space "
+ "cannot be declared %<register%>");
+ if (!TYPE_VOLATILE (typ))
+ error ("variables in %<__regio_symbol%> address space "
+ "must be declared %<volatile%>");
+ if (!DECL_EXTERNAL (node))
+ error ("variables in %<__regio_symbol%> address space "
+ "must be declared %<extern%>");
+ if (TYPE_MODE (typ) != SImode)
+ error ("only 32-bit access is supported "
+ "for %<__regio_symbol%> address space");
+ if (strcmp (name, "__R30") != 0 && strcmp (name, "__R31") != 0)
+ error ("register name %<%s%> not recognized "
+ "in %<__regio_symbol%> address space", name);
+ }
+
+ tree typ = NULL_TREE;
+
+ switch (TREE_CODE (node))
+ {
+ case FUNCTION_DECL:
+ typ = TREE_TYPE (TREE_TYPE (node));
+ break;
+ case TYPE_DECL:
+ case RESULT_DECL:
+ case VAR_DECL:
+ case FIELD_DECL:
+ case PARM_DECL:
+ typ = TREE_TYPE (node);
+ break;
+ case POINTER_TYPE:
+ typ = node;
+ break;
+ default:
+ break;
+ }
+ if (typ != NULL_TREE && pru_nongeneric_pointer_addrspace (typ))
+ error ("pointers to %<__regio_symbol%> address space are prohibited");
+}
/* Function argument related. */
@@ -2933,6 +3075,9 @@ pru_unwind_word_mode (void)
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START pru_file_start
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES pru_insert_attributes
+
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS pru_init_builtins
#undef TARGET_EXPAND_BUILTIN
@@ -2979,8 +3124,9 @@ pru_unwind_word_mode (void)
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P pru_legitimate_address_p
+#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
+ pru_addr_space_legitimate_address_p
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS pru_init_libfuncs
diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h
index 9b6be32..03f08b1 100644
--- a/gcc/config/pru/pru.h
+++ b/gcc/config/pru/pru.h
@@ -215,6 +215,7 @@ enum reg_class
MULDST_REGS,
MULSRC0_REGS,
MULSRC1_REGS,
+ REGIO_REGS,
GP_REGS,
ALL_REGS,
LIM_REG_CLASSES
@@ -229,6 +230,7 @@ enum reg_class
"MULDST_REGS", \
"MULSRC0_REGS", \
"MULSRC1_REGS", \
+ "REGIO_REGS", \
"GP_REGS", \
"ALL_REGS" }
@@ -242,6 +244,7 @@ enum reg_class
/* MULDST_REGS */ { 0, 0, 0, 0x00000f00, 0}, \
/* MULSRC0_REGS */ { 0, 0, 0, 0x000f0000, 0}, \
/* MULSRC1_REGS */ { 0, 0, 0, 0x00f00000, 0}, \
+ /* REGIO_REGS */ { 0, 0, 0, 0xff000000, 0}, \
/* GP_REGS */ { ~0, ~0, ~0, ~0, 0}, \
/* ALL_REGS */ { ~0,~0, ~0, ~0, ~0} \
}
@@ -252,6 +255,8 @@ enum reg_class
((REGNO) == MULDST_REGNUM ? MULDST_REGS \
: (REGNO) == MULSRC0_REGNUM ? MULSRC0_REGS \
: (REGNO) == MULSRC1_REGNUM ? MULSRC1_REGS \
+ : (REGNO) == R30_REGNUM ? REGIO_REGS \
+ : (REGNO) == R31_REGNUM ? REGIO_REGS \
: (REGNO) >= FIRST_ARG_REGNUM \
&& (REGNO) <= LAST_ARG_REGNUM ? SIB_REGS \
: (REGNO) == STATIC_CHAIN_REGNUM ? SIB_REGS \
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index e6cfa8e..c0ded8e 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -36,6 +36,8 @@
(MULSRC0_REGNUM 112) ; Multiply source register.
(MULSRC1_REGNUM 116) ; Multiply source register.
(LAST_NONIO_GP_REGNUM 119) ; Last non-I/O general purpose register.
+ (R30_REGNUM 120) ; R30 I/O register.
+ (R31_REGNUM 124) ; R31 I/O register.
(LOOPCNTR_REGNUM 128) ; internal LOOP counter register
(LAST_GP_REGNUM 132) ; Last general purpose register.
@@ -49,6 +51,13 @@
]
)
+;; Enumerate address spaces.
+(define_constants
+ [
+ (ADDR_SPACE_REGIO 1) ; Access to R30 and R31 I/O registers.
+ ]
+)
+
;; Enumeration of UNSPECs.
(define_c_enum "unspec" [
@@ -68,6 +77,9 @@
UNSPECV_HALT
UNSPECV_BLOCKAGE
+
+ UNSPECV_REGIO_READ
+ UNSPECV_REGIO_WRITE
])
; Length of an instruction (in bytes).
@@ -129,11 +141,62 @@
(match_operand:MOV8_16_32 1 "general_operand"))]
""
{
- /* It helps to split constant loading and memory access
- early, so that the LDI/LDI32 instructions can be hoisted
- outside a loop body. */
- if (MEM_P (operands[0]))
- operands[1] = force_reg (<MODE>mode, operands[1]);
+ if (MEM_P (operands[0])
+ && MEM_ADDR_SPACE (operands[0]) == ADDR_SPACE_REGIO)
+
+ {
+ /* Intercept writes to the SImode register I/O "address space". */
+ gcc_assert (<MODE>mode == SImode);
+
+ if (!SYMBOL_REF_P (XEXP (operands[0], 0)))
+ {
+ error ("invalid access to %<__regio_symbol%> address space");
+ FAIL;
+ }
+
+ if (!REG_P (operands[1]))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+
+ int regiono = pru_symref2ioregno (XEXP (operands[0], 0));
+ gcc_assert (regiono >= 0);
+ rtx regio = gen_rtx_REG (<MODE>mode, regiono);
+ rtx unspecv = gen_rtx_UNSPEC_VOLATILE (<MODE>mode,
+ gen_rtvec (1, operands[1]),
+ UNSPECV_REGIO_WRITE);
+ emit_insn (gen_rtx_SET (regio, unspecv));
+ DONE;
+ }
+ else if (MEM_P (operands[1])
+ && MEM_ADDR_SPACE (operands[1]) == ADDR_SPACE_REGIO)
+ {
+ /* Intercept reads from the SImode register I/O "address space". */
+ gcc_assert (<MODE>mode == SImode);
+
+ if (!SYMBOL_REF_P (XEXP (operands[1], 0)))
+ {
+ error ("invalid access to %<__regio_symbol%> address space");
+ FAIL;
+ }
+
+ if (MEM_P (operands[0]))
+ operands[0] = force_reg (<MODE>mode, operands[0]);
+
+ int regiono = pru_symref2ioregno (XEXP (operands[1], 0));
+ gcc_assert (regiono >= 0);
+ rtx regio = gen_rtx_REG (<MODE>mode, regiono);
+ rtx unspecv = gen_rtx_UNSPEC_VOLATILE (<MODE>mode,
+ gen_rtvec (1, regio),
+ UNSPECV_REGIO_READ);
+ emit_insn (gen_rtx_SET (operands[0], unspecv));
+ DONE;
+ }
+ else if (MEM_P (operands[0]))
+ {
+ /* It helps to split constant loading and memory access
+ early, so that the LDI/LDI32 instructions can be hoisted
+ outside a loop body. */
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ }
})
;; Keep a single pattern for 32 bit MOV operations. LRA requires that the
@@ -546,6 +609,35 @@
(include "alu-zext.md")
+;; Patterns for accessing the R30/R31 I/O registers.
+
+(define_insn "*regio_readsi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "regio_operand" "Rrio")]
+ UNSPECV_REGIO_READ))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+(define_insn "*regio_nozext_writesi"
+ [(set (match_operand:SI 0 "regio_operand" "=Rrio")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "r")]
+ UNSPECV_REGIO_WRITE))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+(define_insn "*regio_zext_write_r30<EQS0:mode>"
+ [(set (match_operand:SI 0 "regio_operand" "=Rrio")
+ (unspec_volatile:SI
+ [(zero_extend:SI (match_operand:EQS0 1 "register_operand" "r"))]
+ UNSPECV_REGIO_WRITE))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
;; DI logical ops could be automatically split into WORD-mode ops in
;; expand_binop(). But then we'll miss an opportunity to use SI mode
;; operations, since WORD mode for PRU is QI.
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 576960b..126572c 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "predict.h"
#include "tree-pass.h"
+#include "opts.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
@@ -4839,7 +4840,7 @@ riscv_option_override (void)
#endif
if (riscv_stack_protector_guard == SSP_GLOBAL
- && global_options_set.x_riscv_stack_protector_guard_offset_str)
+ && OPTION_SET_P (riscv_stack_protector_guard_offset_str))
{
error ("incompatible options %<-mstack-protector-guard=global%> and "
"%<-mstack-protector-guard-offset=%s%>",
@@ -4847,15 +4848,15 @@ riscv_option_override (void)
}
if (riscv_stack_protector_guard == SSP_TLS
- && !(global_options_set.x_riscv_stack_protector_guard_offset_str
- && global_options_set.x_riscv_stack_protector_guard_reg_str))
+ && !(OPTION_SET_P (riscv_stack_protector_guard_offset_str)
+ && OPTION_SET_P (riscv_stack_protector_guard_reg_str)))
{
error ("both %<-mstack-protector-guard-offset%> and "
"%<-mstack-protector-guard-reg%> must be used "
"with %<-mstack-protector-guard=sysreg%>");
}
- if (global_options_set.x_riscv_stack_protector_guard_reg_str)
+ if (OPTION_SET_P (riscv_stack_protector_guard_reg_str))
{
const char *str = riscv_stack_protector_guard_reg_str;
int reg = decode_reg_name (str);
@@ -4867,7 +4868,7 @@ riscv_option_override (void)
riscv_stack_protector_guard_reg = reg;
}
- if (global_options_set.x_riscv_stack_protector_guard_offset_str)
+ if (OPTION_SET_P (riscv_stack_protector_guard_offset_str))
{
char *end;
const char *str = riscv_stack_protector_guard_offset_str;
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index f88877f..98364f0 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -802,7 +802,7 @@
rtx hp = gen_reg_rtx (<MODE>mode);
rtx lp = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_mul<mode>3_highpart (hp, operands[1], operands[2]));
+ emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
emit_insn (gen_ashr<mode>3 (lp, operands[0],
GEN_INT (BITS_PER_WORD - 1)));
@@ -899,14 +899,14 @@
emit_insn (gen_muldi3 (low, operands[1], operands[2]));
rtx high = gen_reg_rtx (DImode);
- emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
+ emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
emit_move_insn (gen_lowpart (DImode, operands[0]), low);
emit_move_insn (gen_highpart (DImode, operands[0]), high);
DONE;
})
-(define_insn "<u>muldi3_highpart"
+(define_insn "<su>muldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TI
@@ -961,13 +961,13 @@
{
rtx temp = gen_reg_rtx (SImode);
emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
- emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
+ emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
operands[1], operands[2]));
emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
DONE;
})
-(define_insn "<u>mulsi3_highpart"
+(define_insn "<su>mulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI
diff --git a/gcc/config/rs6000/aix71.h b/gcc/config/rs6000/aix71.h
index 1bc1560..ddd204d 100644
--- a/gcc/config/rs6000/aix71.h
+++ b/gcc/config/rs6000/aix71.h
@@ -33,7 +33,7 @@ do { \
if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
{ \
rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
+ if (OPTION_SET_P (rs6000_long_double_type_size)) \
warning (0, "soft-float and long-double-128 are incompatible"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
@@ -43,7 +43,7 @@ do { \
if ((rs6000_isa_flags_explicit \
& OPTION_MASK_MINIMAL_TOC) != 0) \
{ \
- if (global_options_set.x_rs6000_current_cmodel \
+ if (OPTION_SET_P (rs6000_current_cmodel) \
&& rs6000_current_cmodel != CMODEL_SMALL) \
error ("%<-mcmodel%> incompatible with other toc options"); \
SET_CMODEL (CMODEL_SMALL); \
@@ -63,7 +63,7 @@ do { \
/* aix/ppc doesn't support -mvsx and -maltivec with Go */ \
rs6000_isa_flags &= ~(OPTION_MASK_VSX | OPTION_MASK_ALTIVEC); \
} \
- if (!global_options_set.x_dwarf_version) \
+ if (!OPTION_SET_P (dwarf_version)) \
/* AIX only supports DWARF 4. */ \
dwarf_version = 4; \
} while (0)
diff --git a/gcc/config/rs6000/aix72.h b/gcc/config/rs6000/aix72.h
index cca64f1..f0e375c 100644
--- a/gcc/config/rs6000/aix72.h
+++ b/gcc/config/rs6000/aix72.h
@@ -33,7 +33,7 @@ do { \
if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
{ \
rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
+ if (OPTION_SET_P (rs6000_long_double_type_size)) \
warning (0, "soft-float and long-double-128 are incompatible"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
@@ -43,7 +43,7 @@ do { \
if ((rs6000_isa_flags_explicit \
& OPTION_MASK_MINIMAL_TOC) != 0) \
{ \
- if (global_options_set.x_rs6000_current_cmodel \
+ if (OPTION_SET_P (rs6000_current_cmodel) \
&& rs6000_current_cmodel != CMODEL_SMALL) \
error ("%<-mcmodel%> incompatible with other toc options"); \
SET_CMODEL (CMODEL_SMALL); \
@@ -63,7 +63,7 @@ do { \
/* aix/ppc doesn't support -mvsx and -maltivec with Go */ \
rs6000_isa_flags &= ~(OPTION_MASK_VSX | OPTION_MASK_ALTIVEC); \
} \
- if (!global_options_set.x_dwarf_version) \
+ if (!OPTION_SET_P (dwarf_version)) \
/* AIX only supports DWARF 4. */ \
dwarf_version = 4; \
} while (0)
diff --git a/gcc/config/rs6000/aix73.h b/gcc/config/rs6000/aix73.h
index f0ca1a5..2c92cc3 100644
--- a/gcc/config/rs6000/aix73.h
+++ b/gcc/config/rs6000/aix73.h
@@ -33,7 +33,7 @@ do { \
if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
{ \
rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
+ if (OPTION_SET_P (rs6000_long_double_type_size)) \
warning (0, "soft-float and long-double-128 are incompatible"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
@@ -43,7 +43,7 @@ do { \
if ((rs6000_isa_flags_explicit \
& OPTION_MASK_MINIMAL_TOC) != 0) \
{ \
- if (global_options_set.x_rs6000_current_cmodel \
+ if (OPTION_SET_P (rs6000_current_cmodel) \
&& rs6000_current_cmodel != CMODEL_SMALL) \
error ("%<-mcmodel%> incompatible with other toc options"); \
SET_CMODEL (CMODEL_SMALL); \
@@ -63,7 +63,7 @@ do { \
/* aix/ppc doesn't support -mvsx and -maltivec with Go */ \
rs6000_isa_flags &= ~(OPTION_MASK_VSX | OPTION_MASK_ALTIVEC); \
} \
- if (!global_options_set.x_dwarf_version) \
+ if (!OPTION_SET_P (dwarf_version)) \
/* AIX only supports DWARF 4. */ \
dwarf_version = 4; \
} while (0)
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 5b631c7..ea72c9c 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -129,7 +129,7 @@
#define vec_vcfux __builtin_vec_vcfux
#define vec_cts __builtin_vec_cts
#define vec_ctu __builtin_vec_ctu
-#define vec_cpsgn __builtin_vec_copysign
+#define vec_cpsgn(x,y) __builtin_vec_copysign(y,x)
#define vec_double __builtin_vec_double
#define vec_doublee __builtin_vec_doublee
#define vec_doubleo __builtin_vec_doubleo
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index 42f39e6..120b01f 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -203,7 +203,7 @@
/* Make both r2 and r13 available for allocation. */
#define FIXED_R2 0
-#define FIXED_R13 0
+#define FIXED_R13 TARGET_64BIT
/* Base register for access to local variables of the function. */
@@ -213,6 +213,9 @@
#undef RS6000_PIC_OFFSET_TABLE_REGNUM
#define RS6000_PIC_OFFSET_TABLE_REGNUM 31
+#undef FIRST_SAVED_GP_REGNO
+#define FIRST_SAVED_GP_REGNO 13
+
/* Darwin's stack must remain 16-byte aligned for both 32 and 64 bit
ABIs. */
@@ -504,8 +507,12 @@
#define SUBTARGET_INIT_BUILTINS \
do { \
darwin_patch_builtins (); \
- rs6000_builtin_decls[(unsigned) (RS6000_BUILTIN_CFSTRING)] \
- = darwin_init_cfstring_builtins ((unsigned) (RS6000_BUILTIN_CFSTRING)); \
+ if (new_builtins_are_live) \
+ rs6000_builtin_decls_x[(unsigned) (RS6000_BIF_CFSTRING)] \
+ = darwin_init_cfstring_builtins ((unsigned) (RS6000_BIF_CFSTRING)); \
+ else \
+ rs6000_builtin_decls[(unsigned) (RS6000_BUILTIN_CFSTRING)] \
+ = darwin_init_cfstring_builtins ((unsigned) (RS6000_BUILTIN_CFSTRING)); \
} while(0)
/* So far, there is no rs6000_fold_builtin, if one is introduced, then
diff --git a/gcc/config/rs6000/lynx.h b/gcc/config/rs6000/lynx.h
index 3434c8b..0ddb54f 100644
--- a/gcc/config/rs6000/lynx.h
+++ b/gcc/config/rs6000/lynx.h
@@ -80,7 +80,6 @@
#undef SIZE_TYPE
#undef ASM_OUTPUT_ALIGN
-#undef PREFERRED_DEBUGGING_TYPE
/* The file rs6000.c defines TARGET_HAVE_TLS unconditionally to the
value of HAVE_AS_TLS. HAVE_AS_TLS is true as gas support for TLS
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 1f6fc03..1990a21 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -91,7 +91,10 @@
UNSPEC_MMA_XVI8GER4SPP
UNSPEC_MMA_XXMFACC
UNSPEC_MMA_XXMTACC
- UNSPEC_MMA_XXSETACCZ
+ ])
+
+(define_c_enum "unspecv"
+ [UNSPECV_MMA_XXSETACCZ
])
;; MMA instructions with 1 accumulator argument
@@ -467,30 +470,16 @@
"<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:XO 0 "fpr_reg_operand")
- (const_int 0))]
- "TARGET_MMA"
-{
- rtx xo0 = gen_rtx_UNSPEC (XOmode, gen_rtvec (1, const0_rtx),
- UNSPEC_MMA_XXSETACCZ);
- emit_insn (gen_rtx_SET (operands[0], xo0));
- DONE;
-})
+;; We can't have integer constants in XOmode so we wrap this in an
+;; UNSPEC_VOLATILE.
-(define_insn_and_split "*mma_xxsetaccz"
+(define_insn "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))]
+ (unspec_volatile:XO [(const_int 0)]
+ UNSPECV_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")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<vv>"
[(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
diff --git a/gcc/config/rs6000/nmmintrin.h b/gcc/config/rs6000/nmmintrin.h
new file mode 100644
index 0000000..20a70be
--- /dev/null
+++ b/gcc/config/rs6000/nmmintrin.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2021 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 NO_WARN_X86_INTRINSICS
+/* This header is distributed to simplify porting x86_64 code that
+ makes explicit use of Intel intrinsics to powerpc64le.
+ It is the user's responsibility to determine if the results are
+ acceptable and make additional changes as necessary.
+ Note that much code that uses Intel intrinsics can be rewritten in
+ standard C or GNU C extensions, which are more portable and better
+ optimized across multiple targets. */
+#endif
+
+#ifndef _NMMINTRIN_H_INCLUDED
+#define _NMMINTRIN_H_INCLUDED
+
+/* We just include SSE4.1 header file. */
+#include <smmintrin.h>
+
+#endif /* _NMMINTRIN_H_INCLUDED */
diff --git a/gcc/config/rs6000/rs6000-builtin-new.def b/gcc/config/rs6000/rs6000-builtin-new.def
index 3e732ce..1966516 100644
--- a/gcc/config/rs6000/rs6000-builtin-new.def
+++ b/gcc/config/rs6000/rs6000-builtin-new.def
@@ -129,6 +129,7 @@
; mma Needs special handling for MMA
; quad MMA instruction using a register quad as an input operand
; pair MMA instruction using a register pair as an input operand
+; mmaint MMA instruction expanding to internal call at GIMPLE time
; no32bit Not valid for TARGET_32BIT
; 32bit Requires different handling for TARGET_32BIT
; cpu This is a "cpu_is" or "cpu_supports" builtin
@@ -187,6 +188,12 @@
; Builtins that have been around since time immemorial or are just
; considered available everywhere.
[always]
+; __builtin_cfstring is for Darwin, which will replace the decl we
+; create here with another one during subtarget processing. We just
+; need to ensure it has a slot in the builtin enumeration.
+ void __builtin_cfstring ();
+ CFSTRING nothing {}
+
void __builtin_cpu_init ();
CPU_INIT nothing {cpu}
@@ -202,6 +209,12 @@
double __builtin_mffs ();
MFFS rs6000_mffs {}
+; Although the mffsl instruction is only available on POWER9 and later
+; processors, this builtin automatically falls back to mffs on older
+; platforms. Thus it appears here in the [always] stanza.
+ double __builtin_mffsl ();
+ MFFSL rs6000_mffsl {}
+
; This thing really assumes long double == __ibm128, and I'm told it has
; been used as such within libgcc. Given that __builtin_pack_ibm128
; exists for the same purpose, this should really not be used at all.
@@ -2778,9 +2791,6 @@
signed long long __builtin_darn_raw ();
DARN_RAW darn_raw {}
- double __builtin_mffsl ();
- MFFSL rs6000_mffsl {}
-
const signed int __builtin_dtstsfi_eq_dd (const int<6>, _Decimal64);
TSTSFI_EQ_DD dfptstsfi_eq_dd {}
@@ -3575,415 +3585,421 @@
[mma]
void __builtin_mma_assemble_acc (v512 *, vuc, vuc, vuc, vuc);
- ASSEMBLE_ACC nothing {mma}
+ ASSEMBLE_ACC nothing {mma,mmaint}
v512 __builtin_mma_assemble_acc_internal (vuc, vuc, vuc, vuc);
ASSEMBLE_ACC_INTERNAL mma_assemble_acc {mma}
void __builtin_mma_assemble_pair (v256 *, vuc, vuc);
- ASSEMBLE_PAIR nothing {mma}
+ ASSEMBLE_PAIR nothing {mma,mmaint}
v256 __builtin_mma_assemble_pair_internal (vuc, vuc);
ASSEMBLE_PAIR_INTERNAL vsx_assemble_pair {mma}
void __builtin_mma_build_acc (v512 *, vuc, vuc, vuc, vuc);
- BUILD_ACC nothing {mma}
+ BUILD_ACC nothing {mma,mmaint}
v512 __builtin_mma_build_acc_internal (vuc, vuc, vuc, vuc);
BUILD_ACC_INTERNAL mma_assemble_acc {mma}
void __builtin_mma_disassemble_acc (void *, v512 *);
- DISASSEMBLE_ACC nothing {mma,quad}
+ DISASSEMBLE_ACC nothing {mma,quad,mmaint}
vuc __builtin_mma_disassemble_acc_internal (v512, const int<2>);
DISASSEMBLE_ACC_INTERNAL mma_disassemble_acc {mma}
void __builtin_mma_disassemble_pair (void *, v256 *);
- DISASSEMBLE_PAIR nothing {mma,pair}
+ DISASSEMBLE_PAIR nothing {mma,pair,mmaint}
vuc __builtin_mma_disassemble_pair_internal (v256, const int<2>);
DISASSEMBLE_PAIR_INTERNAL vsx_disassemble_pair {mma}
void __builtin_mma_pmxvbf16ger2 (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVBF16GER2 nothing {mma}
+ PMXVBF16GER2 nothing {mma,mmaint}
v512 __builtin_mma_pmxvbf16ger2_internal (vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVBF16GER2_INTERNAL mma_pmxvbf16ger2 {mma}
void __builtin_mma_pmxvbf16ger2nn (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVBF16GER2NN nothing {mma,quad}
+ PMXVBF16GER2NN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvbf16ger2nn_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVBF16GER2NN_INTERNAL mma_pmxvbf16ger2nn {mma,quad}
void __builtin_mma_pmxvbf16ger2np (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVBF16GER2NP nothing {mma,quad}
+ PMXVBF16GER2NP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvbf16ger2np_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVBF16GER2NP_INTERNAL mma_pmxvbf16ger2np {mma,quad}
void __builtin_mma_pmxvbf16ger2pn (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVBF16GER2PN nothing {mma,quad}
+ PMXVBF16GER2PN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvbf16ger2pn_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVBF16GER2PN_INTERNAL mma_pmxvbf16ger2pn {mma,quad}
void __builtin_mma_pmxvbf16ger2pp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVBF16GER2PP nothing {mma,quad}
+ PMXVBF16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvbf16ger2pp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVBF16GER2PP_INTERNAL mma_pmxvbf16ger2pp {mma,quad}
void __builtin_mma_pmxvf16ger2 (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVF16GER2 nothing {mma}
+ PMXVF16GER2 nothing {mma,mmaint}
v512 __builtin_mma_pmxvf16ger2_internal (vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVF16GER2_INTERNAL mma_pmxvf16ger2 {mma}
void __builtin_mma_pmxvf16ger2nn (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVF16GER2NN nothing {mma,quad}
+ PMXVF16GER2NN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf16ger2nn_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVF16GER2NN_INTERNAL mma_pmxvf16ger2nn {mma,quad}
void __builtin_mma_pmxvf16ger2np (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVF16GER2NP nothing {mma,quad}
+ PMXVF16GER2NP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf16ger2np_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVF16GER2NP_INTERNAL mma_pmxvf16ger2np {mma,quad}
void __builtin_mma_pmxvf16ger2pn (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVF16GER2PN nothing {mma,quad}
+ PMXVF16GER2PN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf16ger2pn_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVF16GER2PN_INTERNAL mma_pmxvf16ger2pn {mma,quad}
void __builtin_mma_pmxvf16ger2pp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVF16GER2PP nothing {mma,quad}
+ PMXVF16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf16ger2pp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVF16GER2PP_INTERNAL mma_pmxvf16ger2pp {mma,quad}
void __builtin_mma_pmxvf32ger (v512 *, vuc, vuc, const int<4>, const int<4>);
- PMXVF32GER nothing {mma}
+ PMXVF32GER nothing {mma,mmaint}
v512 __builtin_mma_pmxvf32ger_internal (vuc, vuc, const int<4>, const int<4>);
PMXVF32GER_INTERNAL mma_pmxvf32ger {mma}
void __builtin_mma_pmxvf32gernn (v512 *, vuc, vuc, const int<4>, const int<4>);
- PMXVF32GERNN nothing {mma,quad}
+ PMXVF32GERNN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf32gernn_internal (v512, vuc, vuc, const int<4>, const int<4>);
PMXVF32GERNN_INTERNAL mma_pmxvf32gernn {mma,quad}
void __builtin_mma_pmxvf32gernp (v512 *, vuc, vuc, const int<4>, const int<4>);
- PMXVF32GERNP nothing {mma,quad}
+ PMXVF32GERNP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf32gernp_internal (v512, vuc, vuc, const int<4>, const int<4>);
PMXVF32GERNP_INTERNAL mma_pmxvf32gernp {mma,quad}
void __builtin_mma_pmxvf32gerpn (v512 *, vuc, vuc, const int<4>, const int<4>);
- PMXVF32GERPN nothing {mma,quad}
+ PMXVF32GERPN nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf32gerpn_internal (v512, vuc, vuc, const int<4>, const int<4>);
PMXVF32GERPN_INTERNAL mma_pmxvf32gerpn {mma,quad}
void __builtin_mma_pmxvf32gerpp (v512 *, vuc, vuc, const int<4>, const int<4>);
- PMXVF32GERPP nothing {mma,quad}
+ PMXVF32GERPP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvf32gerpp_internal (v512, vuc, vuc, const int<4>, const int<4>);
PMXVF32GERPP_INTERNAL mma_pmxvf32gerpp {mma,quad}
void __builtin_mma_pmxvf64ger (v512 *, v256, vuc, const int<4>, const int<2>);
- PMXVF64GER nothing {mma,pair}
+ PMXVF64GER nothing {mma,pair,mmaint}
v512 __builtin_mma_pmxvf64ger_internal (v256, vuc, const int<4>, const int<2>);
PMXVF64GER_INTERNAL mma_pmxvf64ger {mma,pair}
void __builtin_mma_pmxvf64gernn (v512 *, v256, vuc, const int<4>, const int<2>);
- PMXVF64GERNN nothing {mma,pair,quad}
+ PMXVF64GERNN nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_pmxvf64gernn_internal (v512, v256, vuc, const int<4>, const int<2>);
PMXVF64GERNN_INTERNAL mma_pmxvf64gernn {mma,pair,quad}
void __builtin_mma_pmxvf64gernp (v512 *, v256, vuc, const int<4>, const int<2>);
- PMXVF64GERNP nothing {mma,pair,quad}
+ PMXVF64GERNP nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_pmxvf64gernp_internal (v512, v256, vuc, const int<4>, const int<2>);
PMXVF64GERNP_INTERNAL mma_pmxvf64gernp {mma,pair,quad}
void __builtin_mma_pmxvf64gerpn (v512 *, v256, vuc, const int<4>, const int<2>);
- PMXVF64GERPN nothing {mma,pair,quad}
+ PMXVF64GERPN nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_pmxvf64gerpn_internal (v512, v256, vuc, const int<4>, const int<2>);
PMXVF64GERPN_INTERNAL mma_pmxvf64gerpn {mma,pair,quad}
void __builtin_mma_pmxvf64gerpp (v512 *, v256, vuc, const int<4>, const int<2>);
- PMXVF64GERPP nothing {mma,pair,quad}
+ PMXVF64GERPP nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_pmxvf64gerpp_internal (v512, v256, vuc, const int<4>, const int<2>);
PMXVF64GERPP_INTERNAL mma_pmxvf64gerpp {mma,pair,quad}
void __builtin_mma_pmxvi16ger2 (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVI16GER2 nothing {mma}
+ PMXVI16GER2 nothing {mma,mmaint}
v512 __builtin_mma_pmxvi16ger2_internal (vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVI16GER2_INTERNAL mma_pmxvi16ger2 {mma}
void __builtin_mma_pmxvi16ger2pp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVI16GER2PP nothing {mma,quad}
+ PMXVI16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvi16ger2pp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVI16GER2PP_INTERNAL mma_pmxvi16ger2pp {mma,quad}
void __builtin_mma_pmxvi16ger2s (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVI16GER2S nothing {mma}
+ PMXVI16GER2S nothing {mma,mmaint}
v512 __builtin_mma_pmxvi16ger2s_internal (vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVI16GER2S_INTERNAL mma_pmxvi16ger2s {mma}
void __builtin_mma_pmxvi16ger2spp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<2>);
- PMXVI16GER2SPP nothing {mma,quad}
+ PMXVI16GER2SPP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvi16ger2spp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<2>);
PMXVI16GER2SPP_INTERNAL mma_pmxvi16ger2spp {mma,quad}
void __builtin_mma_pmxvi4ger8 (v512 *, vuc, vuc, const int<4>, const int<4>, const int<8>);
- PMXVI4GER8 nothing {mma}
+ PMXVI4GER8 nothing {mma,mmaint}
v512 __builtin_mma_pmxvi4ger8_internal (vuc, vuc, const int<4>, const int<4>, const int<8>);
PMXVI4GER8_INTERNAL mma_pmxvi4ger8 {mma}
void __builtin_mma_pmxvi4ger8pp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<4>);
- PMXVI4GER8PP nothing {mma,quad}
+ PMXVI4GER8PP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvi4ger8pp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<4>);
PMXVI4GER8PP_INTERNAL mma_pmxvi4ger8pp {mma,quad}
void __builtin_mma_pmxvi8ger4 (v512 *, vuc, vuc, const int<4>, const int<4>, const int<4>);
- PMXVI8GER4 nothing {mma}
+ PMXVI8GER4 nothing {mma,mmaint}
v512 __builtin_mma_pmxvi8ger4_internal (vuc, vuc, const int<4>, const int<4>, const int<4>);
PMXVI8GER4_INTERNAL mma_pmxvi8ger4 {mma}
void __builtin_mma_pmxvi8ger4pp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<4>);
- PMXVI8GER4PP nothing {mma,quad}
+ PMXVI8GER4PP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvi8ger4pp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<4>);
PMXVI8GER4PP_INTERNAL mma_pmxvi8ger4pp {mma,quad}
void __builtin_mma_pmxvi8ger4spp (v512 *, vuc, vuc, const int<4>, const int<4>, const int<4>);
- PMXVI8GER4SPP nothing {mma,quad}
+ PMXVI8GER4SPP nothing {mma,quad,mmaint}
v512 __builtin_mma_pmxvi8ger4spp_internal (v512, vuc, vuc, const int<4>, const int<4>, const int<4>);
PMXVI8GER4SPP_INTERNAL mma_pmxvi8ger4spp {mma,quad}
void __builtin_mma_xvbf16ger2 (v512 *, vuc, vuc);
- XVBF16GER2 nothing {mma}
+ XVBF16GER2 nothing {mma,mmaint}
v512 __builtin_mma_xvbf16ger2_internal (vuc, vuc);
XVBF16GER2_INTERNAL mma_xvbf16ger2 {mma}
void __builtin_mma_xvbf16ger2nn (v512 *, vuc, vuc);
- XVBF16GER2NN nothing {mma,quad}
+ XVBF16GER2NN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvbf16ger2nn_internal (v512, vuc, vuc);
XVBF16GER2NN_INTERNAL mma_xvbf16ger2nn {mma,quad}
void __builtin_mma_xvbf16ger2np (v512 *, vuc, vuc);
- XVBF16GER2NP nothing {mma,quad}
+ XVBF16GER2NP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvbf16ger2np_internal (v512, vuc, vuc);
XVBF16GER2NP_INTERNAL mma_xvbf16ger2np {mma,quad}
void __builtin_mma_xvbf16ger2pn (v512 *, vuc, vuc);
- XVBF16GER2PN nothing {mma,quad}
+ XVBF16GER2PN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvbf16ger2pn_internal (v512, vuc, vuc);
XVBF16GER2PN_INTERNAL mma_xvbf16ger2pn {mma,quad}
void __builtin_mma_xvbf16ger2pp (v512 *, vuc, vuc);
- XVBF16GER2PP nothing {mma,quad}
+ XVBF16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvbf16ger2pp_internal (v512, vuc, vuc);
XVBF16GER2PP_INTERNAL mma_xvbf16ger2pp {mma,quad}
void __builtin_mma_xvf16ger2 (v512 *, vuc, vuc);
- XVF16GER2 nothing {mma}
+ XVF16GER2 nothing {mma,mmaint}
v512 __builtin_mma_xvf16ger2_internal (vuc, vuc);
XVF16GER2_INTERNAL mma_xvf16ger2 {mma}
void __builtin_mma_xvf16ger2nn (v512 *, vuc, vuc);
- XVF16GER2NN nothing {mma,quad}
+ XVF16GER2NN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf16ger2nn_internal (v512, vuc, vuc);
XVF16GER2NN_INTERNAL mma_xvf16ger2nn {mma,quad}
void __builtin_mma_xvf16ger2np (v512 *, vuc, vuc);
- XVF16GER2NP nothing {mma,quad}
+ XVF16GER2NP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf16ger2np_internal (v512, vuc, vuc);
XVF16GER2NP_INTERNAL mma_xvf16ger2np {mma,quad}
void __builtin_mma_xvf16ger2pn (v512 *, vuc, vuc);
- XVF16GER2PN nothing {mma,quad}
+ XVF16GER2PN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf16ger2pn_internal (v512, vuc, vuc);
XVF16GER2PN_INTERNAL mma_xvf16ger2pn {mma,quad}
void __builtin_mma_xvf16ger2pp (v512 *, vuc, vuc);
- XVF16GER2PP nothing {mma,quad}
+ XVF16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf16ger2pp_internal (v512, vuc, vuc);
XVF16GER2PP_INTERNAL mma_xvf16ger2pp {mma,quad}
void __builtin_mma_xvf32ger (v512 *, vuc, vuc);
- XVF32GER nothing {mma}
+ XVF32GER nothing {mma,mmaint}
v512 __builtin_mma_xvf32ger_internal (vuc, vuc);
XVF32GER_INTERNAL mma_xvf32ger {mma}
void __builtin_mma_xvf32gernn (v512 *, vuc, vuc);
- XVF32GERNN nothing {mma,quad}
+ XVF32GERNN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf32gernn_internal (v512, vuc, vuc);
XVF32GERNN_INTERNAL mma_xvf32gernn {mma,quad}
void __builtin_mma_xvf32gernp (v512 *, vuc, vuc);
- XVF32GERNP nothing {mma,quad}
+ XVF32GERNP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf32gernp_internal (v512, vuc, vuc);
XVF32GERNP_INTERNAL mma_xvf32gernp {mma,quad}
void __builtin_mma_xvf32gerpn (v512 *, vuc, vuc);
- XVF32GERPN nothing {mma,quad}
+ XVF32GERPN nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf32gerpn_internal (v512, vuc, vuc);
XVF32GERPN_INTERNAL mma_xvf32gerpn {mma,quad}
void __builtin_mma_xvf32gerpp (v512 *, vuc, vuc);
- XVF32GERPP nothing {mma,quad}
+ XVF32GERPP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvf32gerpp_internal (v512, vuc, vuc);
XVF32GERPP_INTERNAL mma_xvf32gerpp {mma,quad}
void __builtin_mma_xvf64ger (v512 *, v256, vuc);
- XVF64GER nothing {mma,pair}
+ XVF64GER nothing {mma,pair,mmaint}
v512 __builtin_mma_xvf64ger_internal (v256, vuc);
XVF64GER_INTERNAL mma_xvf64ger {mma,pair}
void __builtin_mma_xvf64gernn (v512 *, v256, vuc);
- XVF64GERNN nothing {mma,pair,quad}
+ XVF64GERNN nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_xvf64gernn_internal (v512, v256, vuc);
XVF64GERNN_INTERNAL mma_xvf64gernn {mma,pair,quad}
void __builtin_mma_xvf64gernp (v512 *, v256, vuc);
- XVF64GERNP nothing {mma,pair,quad}
+ XVF64GERNP nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_xvf64gernp_internal (v512, v256, vuc);
XVF64GERNP_INTERNAL mma_xvf64gernp {mma,pair,quad}
void __builtin_mma_xvf64gerpn (v512 *, v256, vuc);
- XVF64GERPN nothing {mma,pair,quad}
+ XVF64GERPN nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_xvf64gerpn_internal (v512, v256, vuc);
XVF64GERPN_INTERNAL mma_xvf64gerpn {mma,pair,quad}
void __builtin_mma_xvf64gerpp (v512 *, v256, vuc);
- XVF64GERPP nothing {mma,pair,quad}
+ XVF64GERPP nothing {mma,pair,quad,mmaint}
v512 __builtin_mma_xvf64gerpp_internal (v512, v256, vuc);
XVF64GERPP_INTERNAL mma_xvf64gerpp {mma,pair,quad}
void __builtin_mma_xvi16ger2 (v512 *, vuc, vuc);
- XVI16GER2 nothing {mma}
+ XVI16GER2 nothing {mma,mmaint}
v512 __builtin_mma_xvi16ger2_internal (vuc, vuc);
XVI16GER2_INTERNAL mma_xvi16ger2 {mma}
void __builtin_mma_xvi16ger2pp (v512 *, vuc, vuc);
- XVI16GER2PP nothing {mma,quad}
+ XVI16GER2PP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvi16ger2pp_internal (v512, vuc, vuc);
XVI16GER2PP_INTERNAL mma_xvi16ger2pp {mma,quad}
void __builtin_mma_xvi16ger2s (v512 *, vuc, vuc);
- XVI16GER2S nothing {mma}
+ XVI16GER2S nothing {mma,mmaint}
v512 __builtin_mma_xvi16ger2s_internal (vuc, vuc);
XVI16GER2S_INTERNAL mma_xvi16ger2s {mma}
void __builtin_mma_xvi16ger2spp (v512 *, vuc, vuc);
- XVI16GER2SPP nothing {mma,quad}
+ XVI16GER2SPP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvi16ger2spp_internal (v512, vuc, vuc);
XVI16GER2SPP_INTERNAL mma_xvi16ger2spp {mma,quad}
void __builtin_mma_xvi4ger8 (v512 *, vuc, vuc);
- XVI4GER8 nothing {mma}
+ XVI4GER8 nothing {mma,mmaint}
v512 __builtin_mma_xvi4ger8_internal (vuc, vuc);
XVI4GER8_INTERNAL mma_xvi4ger8 {mma}
void __builtin_mma_xvi4ger8pp (v512 *, vuc, vuc);
- XVI4GER8PP nothing {mma,quad}
+ XVI4GER8PP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvi4ger8pp_internal (v512, vuc, vuc);
XVI4GER8PP_INTERNAL mma_xvi4ger8pp {mma,quad}
void __builtin_mma_xvi8ger4 (v512 *, vuc, vuc);
- XVI8GER4 nothing {mma}
+ XVI8GER4 nothing {mma,mmaint}
v512 __builtin_mma_xvi8ger4_internal (vuc, vuc);
XVI8GER4_INTERNAL mma_xvi8ger4 {mma}
void __builtin_mma_xvi8ger4pp (v512 *, vuc, vuc);
- XVI8GER4PP nothing {mma,quad}
+ XVI8GER4PP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvi8ger4pp_internal (v512, vuc, vuc);
XVI8GER4PP_INTERNAL mma_xvi8ger4pp {mma,quad}
void __builtin_mma_xvi8ger4spp (v512 *, vuc, vuc);
- XVI8GER4SPP nothing {mma,quad}
+ XVI8GER4SPP nothing {mma,quad,mmaint}
v512 __builtin_mma_xvi8ger4spp_internal (v512, vuc, vuc);
XVI8GER4SPP_INTERNAL mma_xvi8ger4spp {mma,quad}
void __builtin_mma_xxmfacc (v512 *);
- XXMFACC nothing {mma,quad}
+ XXMFACC nothing {mma,quad,mmaint}
v512 __builtin_mma_xxmfacc_internal (v512);
XXMFACC_INTERNAL mma_xxmfacc {mma,quad}
void __builtin_mma_xxmtacc (v512 *);
- XXMTACC nothing {mma,quad}
+ XXMTACC nothing {mma,quad,mmaint}
v512 __builtin_mma_xxmtacc_internal (v512);
XXMTACC_INTERNAL mma_xxmtacc {mma,quad}
void __builtin_mma_xxsetaccz (v512 *);
- XXSETACCZ nothing {mma}
+ XXSETACCZ nothing {mma,mmaint}
v512 __builtin_mma_xxsetaccz_internal ();
XXSETACCZ_INTERNAL mma_xxsetaccz {mma}
void __builtin_vsx_assemble_pair (v256 *, vuc, vuc);
- ASSEMBLE_PAIR_V nothing {mma}
+ ASSEMBLE_PAIR_V nothing {mma,mmaint}
v256 __builtin_vsx_assemble_pair_internal (vuc, vuc);
ASSEMBLE_PAIR_V_INTERNAL vsx_assemble_pair {mma}
void __builtin_vsx_build_pair (v256 *, vuc, vuc);
- BUILD_PAIR nothing {mma}
+ BUILD_PAIR nothing {mma,mmaint}
v256 __builtin_vsx_build_pair_internal (vuc, vuc);
BUILD_PAIR_INTERNAL vsx_assemble_pair {mma}
void __builtin_vsx_disassemble_pair (void *, v256 *);
- DISASSEMBLE_PAIR_V nothing {mma,pair}
+ DISASSEMBLE_PAIR_V nothing {mma,pair,mmaint}
vuc __builtin_vsx_disassemble_pair_internal (v256, const int<2>);
DISASSEMBLE_PAIR_V_INTERNAL vsx_disassemble_pair {mma}
+
+ v256 __builtin_vsx_lxvp (unsigned long, const v256 *);
+ LXVP nothing {mma}
+
+ void __builtin_vsx_stxvp (v256, unsigned long, const v256 *);
+ STXVP nothing {mma,pair}
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index afcb5bb..d08bdfe 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -35,6 +35,9 @@
#include "langhooks.h"
#include "c/c-tree.h"
+#include "rs6000-builtins.h"
+
+static tree altivec_resolve_new_overloaded_builtin (location_t, tree, void *);
/* Handle the machine specific pragma longcall. Its syntax is
@@ -811,6 +814,32 @@ is_float128_p (tree t)
&& t == long_double_type_node));
}
+
+/* Return true iff ARGTYPE can be compatibly passed as PARMTYPE. */
+static bool
+rs6000_new_builtin_type_compatible (tree parmtype, tree argtype)
+{
+ if (parmtype == error_mark_node)
+ return false;
+
+ if (INTEGRAL_TYPE_P (parmtype) && INTEGRAL_TYPE_P (argtype))
+ return true;
+
+ if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
+ && is_float128_p (parmtype) && is_float128_p (argtype))
+ return true;
+
+ if (POINTER_TYPE_P (parmtype) && POINTER_TYPE_P (argtype))
+ {
+ parmtype = TREE_TYPE (parmtype);
+ argtype = TREE_TYPE (argtype);
+ if (TYPE_READONLY (argtype))
+ parmtype = build_qualified_type (parmtype, TYPE_QUAL_CONST);
+ }
+
+ return lang_hooks.types_compatible_p (parmtype, argtype);
+}
+
static inline bool
rs6000_builtin_type_compatible (tree t, int id)
{
@@ -927,6 +956,10 @@ tree
altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
void *passed_arglist)
{
+ if (new_builtins_are_live)
+ return altivec_resolve_new_overloaded_builtin (loc, fndecl,
+ passed_arglist);
+
vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
unsigned int nargs = vec_safe_length (arglist);
enum rs6000_builtins fcode
@@ -1930,3 +1963,1048 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return error_mark_node;
}
}
+
+/* Build a tree for a function call to an Altivec non-overloaded builtin.
+ The overloaded builtin that matched the types and args is described
+ by DESC. The N arguments are given in ARGS, respectively.
+
+ Actually the only thing it does is calling fold_convert on ARGS, with
+ a small exception for vec_{all,any}_{ge,le} predicates. */
+
+static tree
+altivec_build_new_resolved_builtin (tree *args, int n, tree fntype,
+ tree ret_type,
+ rs6000_gen_builtins bif_id,
+ rs6000_gen_builtins ovld_id)
+{
+ tree argtypes = TYPE_ARG_TYPES (fntype);
+ tree arg_type[MAX_OVLD_ARGS];
+ tree fndecl = rs6000_builtin_decls_x[bif_id];
+
+ for (int i = 0; i < n; i++)
+ {
+ arg_type[i] = TREE_VALUE (argtypes);
+ argtypes = TREE_CHAIN (argtypes);
+ }
+
+ /* The AltiVec overloading implementation is overall gross, but this
+ is particularly disgusting. The vec_{all,any}_{ge,le} builtins
+ are completely different for floating-point vs. integer vector
+ types, because the former has vcmpgefp, but the latter should use
+ vcmpgtXX.
+
+ In practice, the second and third arguments are swapped, and the
+ condition (LT vs. EQ, which is recognizable by bit 1 of the first
+ argument) is reversed. Patch the arguments here before building
+ the resolved CALL_EXPR. */
+ if (n == 3
+ && ovld_id == RS6000_OVLD_VEC_CMPGE_P
+ && bif_id != RS6000_BIF_VCMPGEFP_P
+ && bif_id != RS6000_BIF_XVCMPGEDP_P)
+ {
+ std::swap (args[1], args[2]);
+ std::swap (arg_type[1], arg_type[2]);
+
+ args[0] = fold_build2 (BIT_XOR_EXPR, TREE_TYPE (args[0]), args[0],
+ build_int_cst (NULL_TREE, 2));
+ }
+
+ for (int j = 0; j < n; j++)
+ args[j] = fully_fold_convert (arg_type[j], args[j]);
+
+ /* If the number of arguments to an overloaded function increases,
+ we must expand this switch. */
+ gcc_assert (MAX_OVLD_ARGS <= 4);
+
+ tree call;
+ switch (n)
+ {
+ case 0:
+ call = build_call_expr (fndecl, 0);
+ break;
+ case 1:
+ call = build_call_expr (fndecl, 1, args[0]);
+ break;
+ case 2:
+ call = build_call_expr (fndecl, 2, args[0], args[1]);
+ break;
+ case 3:
+ call = build_call_expr (fndecl, 3, args[0], args[1], args[2]);
+ break;
+ case 4:
+ call = build_call_expr (fndecl, 4, args[0], args[1], args[2], args[3]);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return fold_convert (ret_type, call);
+}
+
+/* Implementation of the resolve_overloaded_builtin target hook, to
+ support Altivec's overloaded builtins. FIXME: This code needs
+ to be brutally factored. */
+
+static tree
+altivec_resolve_new_overloaded_builtin (location_t loc, tree fndecl,
+ void *passed_arglist)
+{
+ vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
+ unsigned int nargs = vec_safe_length (arglist);
+ enum rs6000_gen_builtins fcode
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ tree types[MAX_OVLD_ARGS];
+ tree args[MAX_OVLD_ARGS];
+
+ /* Return immediately if this isn't an overload. */
+ if (fcode <= RS6000_OVLD_NONE)
+ return NULL_TREE;
+
+ unsigned int adj_fcode = fcode - RS6000_OVLD_NONE;
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "altivec_resolve_overloaded_builtin, code = %4d, %s\n",
+ (int) fcode, IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+
+ /* vec_lvsl and vec_lvsr are deprecated for use with LE element order. */
+ if (fcode == RS6000_OVLD_VEC_LVSL && !BYTES_BIG_ENDIAN)
+ warning (OPT_Wdeprecated,
+ "%<vec_lvsl%> is deprecated for little endian; use "
+ "assignment for unaligned loads and stores");
+ else if (fcode == RS6000_OVLD_VEC_LVSR && !BYTES_BIG_ENDIAN)
+ warning (OPT_Wdeprecated,
+ "%<vec_lvsr%> is deprecated for little endian; use "
+ "assignment for unaligned loads and stores");
+
+ if (fcode == RS6000_OVLD_VEC_MUL)
+ {
+ /* vec_mul needs to be special cased because there are no instructions
+ for it for the {un}signed char, {un}signed short, and {un}signed int
+ types. */
+ if (nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments", "vec_mul");
+ return error_mark_node;
+ }
+
+ tree arg0 = (*arglist)[0];
+ tree arg0_type = TREE_TYPE (arg0);
+ tree arg1 = (*arglist)[1];
+ tree arg1_type = TREE_TYPE (arg1);
+
+ /* Both arguments must be vectors and the types must be compatible. */
+ if (TREE_CODE (arg0_type) != VECTOR_TYPE)
+ goto bad;
+ if (!lang_hooks.types_compatible_p (arg0_type, arg1_type))
+ goto bad;
+
+ switch (TYPE_MODE (TREE_TYPE (arg0_type)))
+ {
+ case E_QImode:
+ case E_HImode:
+ case E_SImode:
+ case E_DImode:
+ case E_TImode:
+ {
+ /* For scalar types just use a multiply expression. */
+ return fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg0), arg0,
+ fold_convert (TREE_TYPE (arg0), arg1));
+ }
+ case E_SFmode:
+ {
+ /* For floats use the xvmulsp instruction directly. */
+ tree call = rs6000_builtin_decls_x[RS6000_BIF_XVMULSP];
+ return build_call_expr (call, 2, arg0, arg1);
+ }
+ case E_DFmode:
+ {
+ /* For doubles use the xvmuldp instruction directly. */
+ tree call = rs6000_builtin_decls_x[RS6000_BIF_XVMULDP];
+ return build_call_expr (call, 2, arg0, arg1);
+ }
+ /* Other types are errors. */
+ default:
+ goto bad;
+ }
+ }
+
+ if (fcode == RS6000_OVLD_VEC_CMPNE)
+ {
+ /* vec_cmpne needs to be special cased because there are no instructions
+ for it (prior to power 9). */
+ if (nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments", "vec_cmpne");
+ return error_mark_node;
+ }
+
+ tree arg0 = (*arglist)[0];
+ tree arg0_type = TREE_TYPE (arg0);
+ tree arg1 = (*arglist)[1];
+ tree arg1_type = TREE_TYPE (arg1);
+
+ /* Both arguments must be vectors and the types must be compatible. */
+ if (TREE_CODE (arg0_type) != VECTOR_TYPE)
+ goto bad;
+ if (!lang_hooks.types_compatible_p (arg0_type, arg1_type))
+ goto bad;
+
+ /* Power9 instructions provide the most efficient implementation of
+ ALTIVEC_BUILTIN_VEC_CMPNE if the mode is not DImode or TImode
+ or SFmode or DFmode. */
+ if (!TARGET_P9_VECTOR
+ || (TYPE_MODE (TREE_TYPE (arg0_type)) == DImode)
+ || (TYPE_MODE (TREE_TYPE (arg0_type)) == TImode)
+ || (TYPE_MODE (TREE_TYPE (arg0_type)) == SFmode)
+ || (TYPE_MODE (TREE_TYPE (arg0_type)) == DFmode))
+ {
+ switch (TYPE_MODE (TREE_TYPE (arg0_type)))
+ {
+ /* vec_cmpneq (va, vb) == vec_nor (vec_cmpeq (va, vb),
+ vec_cmpeq (va, vb)). */
+ /* Note: vec_nand also works but opt changes vec_nand's
+ to vec_nor's anyway. */
+ case E_QImode:
+ case E_HImode:
+ case E_SImode:
+ case E_DImode:
+ case E_TImode:
+ case E_SFmode:
+ case E_DFmode:
+ {
+ /* call = vec_cmpeq (va, vb)
+ result = vec_nor (call, call). */
+ vec<tree, va_gc> *params = make_tree_vector ();
+ vec_safe_push (params, arg0);
+ vec_safe_push (params, arg1);
+ tree call = altivec_resolve_new_overloaded_builtin
+ (loc, rs6000_builtin_decls_x[RS6000_OVLD_VEC_CMPEQ],
+ params);
+ /* Use save_expr to ensure that operands used more than once
+ that may have side effects (like calls) are only evaluated
+ once. */
+ call = save_expr (call);
+ params = make_tree_vector ();
+ vec_safe_push (params, call);
+ vec_safe_push (params, call);
+ return altivec_resolve_new_overloaded_builtin
+ (loc, rs6000_builtin_decls_x[RS6000_OVLD_VEC_NOR], params);
+ }
+ /* Other types are errors. */
+ default:
+ goto bad;
+ }
+ }
+ /* else, fall through and process the Power9 alternative below */
+ }
+
+ if (fcode == RS6000_OVLD_VEC_ADDE || fcode == RS6000_OVLD_VEC_SUBE)
+ {
+ /* vec_adde needs to be special cased because there is no instruction
+ for the {un}signed int version. */
+ if (nargs != 3)
+ {
+ const char *name;
+ name = fcode == RS6000_OVLD_VEC_ADDE ? "vec_adde" : "vec_sube";
+ error ("builtin %qs only accepts 3 arguments", name);
+ return error_mark_node;
+ }
+
+ tree arg0 = (*arglist)[0];
+ tree arg0_type = TREE_TYPE (arg0);
+ tree arg1 = (*arglist)[1];
+ tree arg1_type = TREE_TYPE (arg1);
+ tree arg2 = (*arglist)[2];
+ tree arg2_type = TREE_TYPE (arg2);
+
+ /* All 3 arguments must be vectors of (signed or unsigned) (int or
+ __int128) and the types must be compatible. */
+ if (TREE_CODE (arg0_type) != VECTOR_TYPE)
+ goto bad;
+ if (!lang_hooks.types_compatible_p (arg0_type, arg1_type)
+ || !lang_hooks.types_compatible_p (arg1_type, arg2_type))
+ goto bad;
+
+ switch (TYPE_MODE (TREE_TYPE (arg0_type)))
+ {
+ /* For {un}signed ints,
+ vec_adde (va, vb, carryv) == vec_add (vec_add (va, vb),
+ vec_and (carryv, 1)).
+ vec_sube (va, vb, carryv) == vec_sub (vec_sub (va, vb),
+ vec_and (carryv, 1)). */
+ case E_SImode:
+ {
+ tree add_sub_builtin;
+
+ vec<tree, va_gc> *params = make_tree_vector ();
+ vec_safe_push (params, arg0);
+ vec_safe_push (params, arg1);
+
+ if (fcode == RS6000_OVLD_VEC_ADDE)
+ add_sub_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADD];
+ else
+ add_sub_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUB];
+
+ tree call
+ = altivec_resolve_new_overloaded_builtin (loc,
+ add_sub_builtin,
+ params);
+ tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
+ tree ones_vector = build_vector_from_val (arg0_type, const1);
+ tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, arg0_type,
+ arg2, ones_vector);
+ params = make_tree_vector ();
+ vec_safe_push (params, call);
+ vec_safe_push (params, and_expr);
+ return altivec_resolve_new_overloaded_builtin (loc,
+ add_sub_builtin,
+ params);
+ }
+ /* For {un}signed __int128s use the vaddeuqm/vsubeuqm instruction
+ directly. */
+ case E_TImode:
+ break;
+
+ /* Types other than {un}signed int and {un}signed __int128
+ are errors. */
+ default:
+ goto bad;
+ }
+ }
+
+ if (fcode == RS6000_OVLD_VEC_ADDEC || fcode == RS6000_OVLD_VEC_SUBEC)
+ {
+ /* vec_addec and vec_subec needs to be special cased because there is
+ no instruction for the {un}signed int version. */
+ if (nargs != 3)
+ {
+ const char *name;
+ name = fcode == RS6000_OVLD_VEC_ADDEC ? "vec_addec" : "vec_subec";
+ error ("builtin %qs only accepts 3 arguments", name);
+ return error_mark_node;
+ }
+
+ tree arg0 = (*arglist)[0];
+ tree arg0_type = TREE_TYPE (arg0);
+ tree arg1 = (*arglist)[1];
+ tree arg1_type = TREE_TYPE (arg1);
+ tree arg2 = (*arglist)[2];
+ tree arg2_type = TREE_TYPE (arg2);
+
+ /* All 3 arguments must be vectors of (signed or unsigned) (int or
+ __int128) and the types must be compatible. */
+ if (TREE_CODE (arg0_type) != VECTOR_TYPE)
+ goto bad;
+ if (!lang_hooks.types_compatible_p (arg0_type, arg1_type)
+ || !lang_hooks.types_compatible_p (arg1_type, arg2_type))
+ goto bad;
+
+ switch (TYPE_MODE (TREE_TYPE (arg0_type)))
+ {
+ /* For {un}signed ints,
+ vec_addec (va, vb, carryv) ==
+ vec_or (vec_addc (va, vb),
+ vec_addc (vec_add (va, vb),
+ vec_and (carryv, 0x1))). */
+ case E_SImode:
+ {
+ /* Use save_expr to ensure that operands used more than once
+ that may have side effects (like calls) are only evaluated
+ once. */
+ tree as_builtin;
+ tree as_c_builtin;
+
+ arg0 = save_expr (arg0);
+ arg1 = save_expr (arg1);
+ vec<tree, va_gc> *params = make_tree_vector ();
+ vec_safe_push (params, arg0);
+ vec_safe_push (params, arg1);
+
+ if (fcode == RS6000_OVLD_VEC_ADDEC)
+ as_c_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADDC];
+ else
+ as_c_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUBC];
+
+ tree call1 = altivec_resolve_new_overloaded_builtin (loc,
+ as_c_builtin,
+ params);
+ params = make_tree_vector ();
+ vec_safe_push (params, arg0);
+ vec_safe_push (params, arg1);
+
+ if (fcode == RS6000_OVLD_VEC_ADDEC)
+ as_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_ADD];
+ else
+ as_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_SUB];
+
+ tree call2 = altivec_resolve_new_overloaded_builtin (loc,
+ as_builtin,
+ params);
+ tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
+ tree ones_vector = build_vector_from_val (arg0_type, const1);
+ tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, arg0_type,
+ arg2, ones_vector);
+ params = make_tree_vector ();
+ vec_safe_push (params, call2);
+ vec_safe_push (params, and_expr);
+ call2 = altivec_resolve_new_overloaded_builtin (loc, as_c_builtin,
+ params);
+ params = make_tree_vector ();
+ vec_safe_push (params, call1);
+ vec_safe_push (params, call2);
+ tree or_builtin = rs6000_builtin_decls_x[RS6000_OVLD_VEC_OR];
+ return altivec_resolve_new_overloaded_builtin (loc, or_builtin,
+ params);
+ }
+ /* For {un}signed __int128s use the vaddecuq/vsubbecuq
+ instructions. This occurs through normal processing. */
+ case E_TImode:
+ break;
+
+ /* Types other than {un}signed int and {un}signed __int128
+ are errors. */
+ default:
+ goto bad;
+ }
+ }
+
+ /* For now treat vec_splats and vec_promote as the same. */
+ if (fcode == RS6000_OVLD_VEC_SPLATS || fcode == RS6000_OVLD_VEC_PROMOTE)
+ {
+ tree type, arg;
+ int size;
+ int i;
+ bool unsigned_p;
+ vec<constructor_elt, va_gc> *vec;
+ const char *name;
+ name = fcode == RS6000_OVLD_VEC_SPLATS ? "vec_splats" : "vec_promote";
+
+ if (fcode == RS6000_OVLD_VEC_SPLATS && nargs != 1)
+ {
+ error ("builtin %qs only accepts 1 argument", name);
+ return error_mark_node;
+ }
+ if (fcode == RS6000_OVLD_VEC_PROMOTE && nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments", name);
+ return error_mark_node;
+ }
+ /* Ignore promote's element argument. */
+ if (fcode == RS6000_OVLD_VEC_PROMOTE
+ && !INTEGRAL_TYPE_P (TREE_TYPE ((*arglist)[1])))
+ goto bad;
+
+ arg = (*arglist)[0];
+ type = TREE_TYPE (arg);
+ if (!SCALAR_FLOAT_TYPE_P (type)
+ && !INTEGRAL_TYPE_P (type))
+ goto bad;
+ unsigned_p = TYPE_UNSIGNED (type);
+ switch (TYPE_MODE (type))
+ {
+ case E_TImode:
+ type = unsigned_p ? unsigned_V1TI_type_node : V1TI_type_node;
+ size = 1;
+ break;
+ case E_DImode:
+ type = unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node;
+ size = 2;
+ break;
+ case E_SImode:
+ type = unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node;
+ size = 4;
+ break;
+ case E_HImode:
+ type = unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node;
+ size = 8;
+ break;
+ case E_QImode:
+ type = unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node;
+ size = 16;
+ break;
+ case E_SFmode:
+ type = V4SF_type_node;
+ size = 4;
+ break;
+ case E_DFmode:
+ type = V2DF_type_node;
+ size = 2;
+ break;
+ default:
+ goto bad;
+ }
+ arg = save_expr (fold_convert (TREE_TYPE (type), arg));
+ vec_alloc (vec, size);
+ for (i = 0; i < size; i++)
+ {
+ constructor_elt elt = {NULL_TREE, arg};
+ vec->quick_push (elt);
+ }
+ return build_constructor (type, vec);
+ }
+
+ /* For now use pointer tricks to do the extraction, unless we are on VSX
+ extracting a double from a constant offset. */
+ if (fcode == RS6000_OVLD_VEC_EXTRACT)
+ {
+ tree arg1;
+ tree arg1_type;
+ tree arg2;
+ tree arg1_inner_type;
+ tree decl, stmt;
+ tree innerptrtype;
+ machine_mode mode;
+
+ /* No second argument. */
+ if (nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments", "vec_extract");
+ return error_mark_node;
+ }
+
+ arg2 = (*arglist)[1];
+ arg1 = (*arglist)[0];
+ arg1_type = TREE_TYPE (arg1);
+
+ if (TREE_CODE (arg1_type) != VECTOR_TYPE)
+ goto bad;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
+ goto bad;
+
+ /* See if we can optimize vec_extracts with the current VSX instruction
+ set. */
+ mode = TYPE_MODE (arg1_type);
+ if (VECTOR_MEM_VSX_P (mode))
+
+ {
+ tree call = NULL_TREE;
+ int nunits = GET_MODE_NUNITS (mode);
+
+ arg2 = fold_for_warn (arg2);
+
+ /* If the second argument is an integer constant, generate
+ the built-in code if we can. We need 64-bit and direct
+ move to extract the small integer vectors. */
+ if (TREE_CODE (arg2) == INTEGER_CST)
+ {
+ wide_int selector = wi::to_wide (arg2);
+ selector = wi::umod_trunc (selector, nunits);
+ arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
+ switch (mode)
+ {
+ default:
+ break;
+
+ case E_V1TImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V1TI];
+ break;
+
+ case E_V2DFmode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DF];
+ break;
+
+ case E_V2DImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DI];
+ break;
+
+ case E_V4SFmode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SF];
+ break;
+
+ case E_V4SImode:
+ if (TARGET_DIRECT_MOVE_64BIT)
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SI];
+ break;
+
+ case E_V8HImode:
+ if (TARGET_DIRECT_MOVE_64BIT)
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V8HI];
+ break;
+
+ case E_V16QImode:
+ if (TARGET_DIRECT_MOVE_64BIT)
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V16QI];
+ break;
+ }
+ }
+
+ /* If the second argument is variable, we can optimize it if we are
+ generating 64-bit code on a machine with direct move. */
+ else if (TREE_CODE (arg2) != INTEGER_CST && TARGET_DIRECT_MOVE_64BIT)
+ {
+ switch (mode)
+ {
+ default:
+ break;
+
+ case E_V2DFmode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DF];
+ break;
+
+ case E_V2DImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V2DI];
+ break;
+
+ case E_V4SFmode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SF];
+ break;
+
+ case E_V4SImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V4SI];
+ break;
+
+ case E_V8HImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V8HI];
+ break;
+
+ case E_V16QImode:
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_EXT_V16QI];
+ break;
+ }
+ }
+
+ if (call)
+ {
+ tree result = build_call_expr (call, 2, arg1, arg2);
+ /* Coerce the result to vector element type. May be no-op. */
+ arg1_inner_type = TREE_TYPE (arg1_type);
+ result = fold_convert (arg1_inner_type, result);
+ return result;
+ }
+ }
+
+ /* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2). */
+ arg1_inner_type = TREE_TYPE (arg1_type);
+ tree subp = build_int_cst (TREE_TYPE (arg2),
+ TYPE_VECTOR_SUBPARTS (arg1_type) - 1);
+ arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2, subp, 0);
+ decl = build_decl (loc, VAR_DECL, NULL_TREE, arg1_type);
+ DECL_EXTERNAL (decl) = 0;
+ TREE_PUBLIC (decl) = 0;
+ DECL_CONTEXT (decl) = current_function_decl;
+ TREE_USED (decl) = 1;
+ TREE_TYPE (decl) = arg1_type;
+ TREE_READONLY (decl) = TYPE_READONLY (arg1_type);
+ if (c_dialect_cxx ())
+ {
+ stmt = build4 (TARGET_EXPR, arg1_type, decl, arg1,
+ NULL_TREE, NULL_TREE);
+ SET_EXPR_LOCATION (stmt, loc);
+ }
+ else
+ {
+ DECL_INITIAL (decl) = arg1;
+ stmt = build1 (DECL_EXPR, arg1_type, decl);
+ TREE_ADDRESSABLE (decl) = 1;
+ SET_EXPR_LOCATION (stmt, loc);
+ stmt = build1 (COMPOUND_LITERAL_EXPR, arg1_type, stmt);
+ }
+
+ innerptrtype = build_pointer_type (arg1_inner_type);
+
+ stmt = build_unary_op (loc, ADDR_EXPR, stmt, 0);
+ stmt = convert (innerptrtype, stmt);
+ stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1);
+ stmt = build_indirect_ref (loc, stmt, RO_NULL);
+
+ /* PR83660: We mark this as having side effects so that
+ downstream in fold_build_cleanup_point_expr () it will get a
+ CLEANUP_POINT_EXPR. If it does not we can run into an ICE
+ later in gimplify_cleanup_point_expr (). Potentially this
+ causes missed optimization because there actually is no side
+ effect. */
+ if (c_dialect_cxx ())
+ TREE_SIDE_EFFECTS (stmt) = 1;
+
+ return stmt;
+ }
+
+ /* For now use pointer tricks to do the insertion, unless we are on VSX
+ inserting a double to a constant offset. */
+ if (fcode == RS6000_OVLD_VEC_INSERT)
+ {
+ tree arg0;
+ tree arg1;
+ tree arg2;
+ tree arg1_type;
+ tree decl, stmt;
+ machine_mode mode;
+
+ /* No second or third arguments. */
+ if (nargs != 3)
+ {
+ error ("builtin %qs only accepts 3 arguments", "vec_insert");
+ return error_mark_node;
+ }
+
+ arg0 = (*arglist)[0];
+ arg1 = (*arglist)[1];
+ arg1_type = TREE_TYPE (arg1);
+ arg2 = fold_for_warn ((*arglist)[2]);
+
+ if (TREE_CODE (arg1_type) != VECTOR_TYPE)
+ goto bad;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
+ goto bad;
+
+ /* If we can use the VSX xxpermdi instruction, use that for insert. */
+ mode = TYPE_MODE (arg1_type);
+ if ((mode == V2DFmode || mode == V2DImode) && VECTOR_UNIT_VSX_P (mode)
+ && TREE_CODE (arg2) == INTEGER_CST)
+ {
+ wide_int selector = wi::to_wide (arg2);
+ selector = wi::umod_trunc (selector, 2);
+ tree call = NULL_TREE;
+
+ arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
+ if (mode == V2DFmode)
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V2DF];
+ else if (mode == V2DImode)
+ call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V2DI];
+
+ /* Note, __builtin_vec_insert_<xxx> has vector and scalar types
+ reversed. */
+ if (call)
+ return build_call_expr (call, 3, arg1, arg0, arg2);
+ }
+ else if (mode == V1TImode && VECTOR_UNIT_VSX_P (mode)
+ && TREE_CODE (arg2) == INTEGER_CST)
+ {
+ tree call = rs6000_builtin_decls_x[RS6000_BIF_VEC_SET_V1TI];
+ wide_int selector = wi::zero(32);
+
+ arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector);
+ /* Note, __builtin_vec_insert_<xxx> has vector and scalar types
+ reversed. */
+ return build_call_expr (call, 3, arg1, arg0, arg2);
+ }
+
+ /* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2) = arg0 with
+ VIEW_CONVERT_EXPR. i.e.:
+ D.3192 = v1;
+ _1 = n & 3;
+ VIEW_CONVERT_EXPR<int[4]>(D.3192)[_1] = i;
+ v1 = D.3192;
+ D.3194 = v1; */
+ if (TYPE_VECTOR_SUBPARTS (arg1_type) == 1)
+ arg2 = build_int_cst (TREE_TYPE (arg2), 0);
+ else
+ arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2,
+ build_int_cst (TREE_TYPE (arg2),
+ TYPE_VECTOR_SUBPARTS (arg1_type)
+ - 1), 0);
+ decl = build_decl (loc, VAR_DECL, NULL_TREE, arg1_type);
+ DECL_EXTERNAL (decl) = 0;
+ TREE_PUBLIC (decl) = 0;
+ DECL_CONTEXT (decl) = current_function_decl;
+ TREE_USED (decl) = 1;
+ TREE_TYPE (decl) = arg1_type;
+ TREE_READONLY (decl) = TYPE_READONLY (arg1_type);
+ TREE_ADDRESSABLE (decl) = 1;
+ if (c_dialect_cxx ())
+ {
+ stmt = build4 (TARGET_EXPR, arg1_type, decl, arg1,
+ NULL_TREE, NULL_TREE);
+ SET_EXPR_LOCATION (stmt, loc);
+ }
+ else
+ {
+ DECL_INITIAL (decl) = arg1;
+ stmt = build1 (DECL_EXPR, arg1_type, decl);
+ SET_EXPR_LOCATION (stmt, loc);
+ stmt = build1 (COMPOUND_LITERAL_EXPR, arg1_type, stmt);
+ }
+
+ if (TARGET_VSX)
+ {
+ stmt = build_array_ref (loc, stmt, arg2);
+ stmt = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg0), stmt,
+ convert (TREE_TYPE (stmt), arg0));
+ stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl);
+ }
+ else
+ {
+ tree arg1_inner_type;
+ tree innerptrtype;
+ arg1_inner_type = TREE_TYPE (arg1_type);
+ innerptrtype = build_pointer_type (arg1_inner_type);
+
+ stmt = build_unary_op (loc, ADDR_EXPR, stmt, 0);
+ stmt = convert (innerptrtype, stmt);
+ stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1);
+ stmt = build_indirect_ref (loc, stmt, RO_NULL);
+ stmt = build2 (MODIFY_EXPR, TREE_TYPE (stmt), stmt,
+ convert (TREE_TYPE (stmt), arg0));
+ stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl);
+ }
+ return stmt;
+ }
+
+ unsigned int n;
+ for (n = 0;
+ !VOID_TYPE_P (TREE_VALUE (fnargs)) && n < nargs;
+ fnargs = TREE_CHAIN (fnargs), n++)
+ {
+ tree decl_type = TREE_VALUE (fnargs);
+ tree arg = (*arglist)[n];
+ tree type;
+
+ if (arg == error_mark_node)
+ return error_mark_node;
+
+ if (n >= MAX_OVLD_ARGS)
+ abort ();
+
+ arg = default_conversion (arg);
+
+ /* The C++ front-end converts float * to const void * using
+ NOP_EXPR<const void *> (NOP_EXPR<void *> (x)). */
+ type = TREE_TYPE (arg);
+ if (POINTER_TYPE_P (type)
+ && TREE_CODE (arg) == NOP_EXPR
+ && lang_hooks.types_compatible_p (TREE_TYPE (arg),
+ const_ptr_type_node)
+ && lang_hooks.types_compatible_p (TREE_TYPE (TREE_OPERAND (arg, 0)),
+ ptr_type_node))
+ {
+ arg = TREE_OPERAND (arg, 0);
+ type = TREE_TYPE (arg);
+ }
+
+ /* Remove the const from the pointers to simplify the overload
+ matching further down. */
+ if (POINTER_TYPE_P (decl_type)
+ && POINTER_TYPE_P (type)
+ && TYPE_QUALS (TREE_TYPE (type)) != 0)
+ {
+ if (TYPE_READONLY (TREE_TYPE (type))
+ && !TYPE_READONLY (TREE_TYPE (decl_type)))
+ warning (0, "passing argument %d of %qE discards const qualifier "
+ "from pointer target type", n + 1, fndecl);
+ type = build_qualified_type (TREE_TYPE (type), 0);
+ type = build_pointer_type (type);
+ arg = fold_convert (type, arg);
+ }
+
+ /* For RS6000_OVLD_VEC_LXVL, convert any const * to its non constant
+ equivalent to simplify the overload matching below. */
+ if (fcode == RS6000_OVLD_VEC_LXVL)
+ {
+ if (POINTER_TYPE_P (type)
+ && TYPE_READONLY (TREE_TYPE (type)))
+ {
+ type = build_qualified_type (TREE_TYPE (type), 0);
+ type = build_pointer_type (type);
+ arg = fold_convert (type, arg);
+ }
+ }
+
+ args[n] = arg;
+ types[n] = type;
+ }
+
+ /* If the number of arguments did not match the prototype, return NULL
+ and the generic code will issue the appropriate error message. */
+ if (!VOID_TYPE_P (TREE_VALUE (fnargs)) || n < nargs)
+ return NULL;
+
+ if (fcode == RS6000_OVLD_VEC_STEP)
+ {
+ if (TREE_CODE (types[0]) != VECTOR_TYPE)
+ goto bad;
+
+ return build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (types[0]));
+ }
+
+ {
+ bool unsupported_builtin = false;
+ enum rs6000_gen_builtins overloaded_code;
+ bool supported = false;
+ ovlddata *instance = rs6000_overload_info[adj_fcode].first_instance;
+ gcc_assert (instance != NULL);
+
+ /* Need to special case __builtin_cmpb because the overloaded forms
+ of this function take (unsigned int, unsigned int) or (unsigned
+ long long int, unsigned long long int). Since C conventions
+ allow the respective argument types to be implicitly coerced into
+ each other, the default handling does not provide adequate
+ discrimination between the desired forms of the function. */
+ if (fcode == RS6000_OVLD_SCAL_CMPB)
+ {
+ machine_mode arg1_mode = TYPE_MODE (types[0]);
+ machine_mode arg2_mode = TYPE_MODE (types[1]);
+
+ if (nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments", "__builtin_cmpb");
+ return error_mark_node;
+ }
+
+ /* If any supplied arguments are wider than 32 bits, resolve to
+ 64-bit variant of built-in function. */
+ if (GET_MODE_PRECISION (arg1_mode) > 32
+ || GET_MODE_PRECISION (arg2_mode) > 32)
+ /* Assure all argument and result types are compatible with
+ the built-in function represented by RS6000_BIF_CMPB. */
+ overloaded_code = RS6000_BIF_CMPB;
+ else
+ /* Assure all argument and result types are compatible with
+ the built-in function represented by RS6000_BIF_CMPB_32. */
+ overloaded_code = RS6000_BIF_CMPB_32;
+
+ while (instance && instance->bifid != overloaded_code)
+ instance = instance->next;
+
+ gcc_assert (instance != NULL);
+ tree fntype = rs6000_builtin_info_x[instance->bifid].fntype;
+ tree parmtype0 = TREE_VALUE (TYPE_ARG_TYPES (fntype));
+ tree parmtype1 = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
+
+ if (rs6000_new_builtin_type_compatible (types[0], parmtype0)
+ && rs6000_new_builtin_type_compatible (types[1], parmtype1))
+ {
+ if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+ && rs6000_new_builtin_is_supported (instance->bifid))
+ {
+ tree ret_type = TREE_TYPE (instance->fntype);
+ return altivec_build_new_resolved_builtin (args, n, fntype,
+ ret_type,
+ instance->bifid,
+ fcode);
+ }
+ else
+ unsupported_builtin = true;
+ }
+ }
+ else if (fcode == RS6000_OVLD_VEC_VSIE)
+ {
+ machine_mode arg1_mode = TYPE_MODE (types[0]);
+
+ if (nargs != 2)
+ {
+ error ("builtin %qs only accepts 2 arguments",
+ "scalar_insert_exp");
+ return error_mark_node;
+ }
+
+ /* If supplied first argument is wider than 64 bits, resolve to
+ 128-bit variant of built-in function. */
+ if (GET_MODE_PRECISION (arg1_mode) > 64)
+ {
+ /* If first argument is of float variety, choose variant
+ that expects __ieee128 argument. Otherwise, expect
+ __int128 argument. */
+ if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
+ overloaded_code = RS6000_BIF_VSIEQPF;
+ else
+ overloaded_code = RS6000_BIF_VSIEQP;
+ }
+ else
+ {
+ /* If first argument is of float variety, choose variant
+ that expects double argument. Otherwise, expect
+ long long int argument. */
+ if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
+ overloaded_code = RS6000_BIF_VSIEDPF;
+ else
+ overloaded_code = RS6000_BIF_VSIEDP;
+ }
+
+ while (instance && instance->bifid != overloaded_code)
+ instance = instance->next;
+
+ gcc_assert (instance != NULL);
+ tree fntype = rs6000_builtin_info_x[instance->bifid].fntype;
+ tree parmtype0 = TREE_VALUE (TYPE_ARG_TYPES (fntype));
+ tree parmtype1 = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
+
+ if (rs6000_new_builtin_type_compatible (types[0], parmtype0)
+ && rs6000_new_builtin_type_compatible (types[1], parmtype1))
+ {
+ if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+ && rs6000_new_builtin_is_supported (instance->bifid))
+ {
+ tree ret_type = TREE_TYPE (instance->fntype);
+ return altivec_build_new_resolved_builtin (args, n, fntype,
+ ret_type,
+ instance->bifid,
+ fcode);
+ }
+ else
+ unsupported_builtin = true;
+ }
+ }
+ else
+ {
+ /* Functions with no arguments can have only one overloaded
+ instance. */
+ gcc_assert (n > 0 || !instance->next);
+
+ for (; instance != NULL; instance = instance->next)
+ {
+ bool mismatch = false;
+ tree nextparm = TYPE_ARG_TYPES (instance->fntype);
+
+ for (unsigned int arg_i = 0;
+ arg_i < nargs && nextparm != NULL;
+ arg_i++)
+ {
+ tree parmtype = TREE_VALUE (nextparm);
+ if (!rs6000_new_builtin_type_compatible (types[arg_i],
+ parmtype))
+ {
+ mismatch = true;
+ break;
+ }
+ nextparm = TREE_CHAIN (nextparm);
+ }
+
+ if (mismatch)
+ continue;
+
+ supported = rs6000_new_builtin_is_supported (instance->bifid);
+ if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+ && supported)
+ {
+ tree fntype = rs6000_builtin_info_x[instance->bifid].fntype;
+ tree ret_type = TREE_TYPE (instance->fntype);
+ return altivec_build_new_resolved_builtin (args, n, fntype,
+ ret_type,
+ instance->bifid,
+ fcode);
+ }
+ else
+ {
+ unsupported_builtin = true;
+ break;
+ }
+ }
+ }
+
+ if (unsupported_builtin)
+ {
+ const char *name = rs6000_overload_info[adj_fcode].ovld_name;
+ if (!supported)
+ {
+ const char *internal_name
+ = rs6000_builtin_info_x[instance->bifid].bifname;
+ /* An error message making reference to the name of the
+ non-overloaded function has already been issued. Add
+ clarification of the previous message. */
+ rich_location richloc (line_table, input_location);
+ inform (&richloc, "builtin %qs requires builtin %qs",
+ name, internal_name);
+ }
+ else
+ error ("%qs is not supported in this compiler configuration", name);
+
+ return error_mark_node;
+ }
+ }
+ bad:
+ {
+ const char *name = rs6000_overload_info[adj_fcode].ovld_name;
+ error ("invalid parameter combination for AltiVec intrinsic %qs", name);
+ return error_mark_node;
+ }
+}
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 3a07118..2eceb2c7 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -69,6 +69,7 @@
#include "opts.h"
#include "rs6000-internal.h"
+#include "rs6000-builtins.h"
#if TARGET_MACHO
#include "gstab.h" /* for N_SLINE */
@@ -189,6 +190,7 @@ static tree builtin_function_type (machine_mode, machine_mode,
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
static void mma_init_builtins (void);
+static bool rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi);
/* Hash table to keep track of the argument types for builtin functions. */
@@ -6221,11 +6223,19 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
or vector type. If a non-floating point or vector type is found, or
if a floating point or vector type that doesn't match a non-VOIDmode
*MODEP is found, then return -1, otherwise return the count in the
- sub-tree. */
+ sub-tree.
+
+ There have been some ABI snafus along the way with C++. Modify
+ EMPTY_BASE_SEEN to a nonzero value iff a C++ empty base class makes
+ an appearance; separate flag bits indicate whether or not such a
+ field is marked "no unique address". Modify ZERO_WIDTH_BF_SEEN
+ to 1 iff a C++ zero-length bitfield makes an appearance, but
+ in this case otherwise treat this as still being a homogeneous
+ aggregate. */
static int
rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
- int *empty_base_seen)
+ int *empty_base_seen, int *zero_width_bf_seen)
{
machine_mode mode;
HOST_WIDE_INT size;
@@ -6296,7 +6306,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
return -1;
count = rs6000_aggregate_candidate (TREE_TYPE (type), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -6334,6 +6345,26 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
+ {
+ /* GCC 11 and earlier generated incorrect code in a rare
+ corner case for C++. When a RECORD_TYPE looks like a
+ homogeneous aggregate, except that it also contains
+ one or more zero-width bit fields, these earlier
+ compilers would incorrectly pass the fields in FPRs
+ or VSRs. This occurred because the front end wrongly
+ removed these bitfields from the RECORD_TYPE. In
+ GCC 12 and later, the front end flaw was corrected.
+ We want to diagnose this case. To do this, we pretend
+ that we don't see the zero-width bit fields (hence
+ the continue statement here), but pass back a flag
+ indicating what happened. The caller then diagnoses
+ the issue and rejects the RECORD_TYPE as a homogeneous
+ aggregate. */
+ *zero_width_bf_seen = 1;
+ continue;
+ }
+
if (DECL_FIELD_ABI_IGNORED (field))
{
if (lookup_attribute ("no_unique_address",
@@ -6345,7 +6376,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
}
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count += sub_count;
@@ -6379,7 +6411,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
continue;
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count = count > sub_count ? count : sub_count;
@@ -6421,8 +6454,10 @@ rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
{
machine_mode field_mode = VOIDmode;
int empty_base_seen = 0;
+ int zero_width_bf_seen = 0;
int field_count = rs6000_aggregate_candidate (type, &field_mode,
- &empty_base_seen);
+ &empty_base_seen,
+ &zero_width_bf_seen);
if (field_count > 0)
{
@@ -6458,6 +6493,25 @@ rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
last_reported_type_uid = uid;
}
}
+ if (zero_width_bf_seen && warn_psabi)
+ {
+ static unsigned last_reported_type_uid;
+ unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type));
+ if (uid != last_reported_type_uid)
+ {
+ inform (input_location,
+ "ELFv2 parameter passing for an argument "
+ "containing zero-width bit fields but that is "
+ "otherwise a homogeneous aggregate was "
+ "corrected in GCC 12");
+ last_reported_type_uid = uid;
+ }
+ if (elt_mode)
+ *elt_mode = mode;
+ if (n_elts)
+ *n_elts = 1;
+ return false;
+ }
return true;
}
}
@@ -12023,6 +12077,9 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi)
bool
rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
{
+ if (new_builtins_are_live)
+ return rs6000_gimple_fold_new_builtin (gsi);
+
gimple *stmt = gsi_stmt (*gsi);
tree fndecl = gimple_call_fndecl (stmt);
gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD);
@@ -12970,6 +13027,1257 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
return false;
}
+/* Helper function to sort out which built-ins may be valid without having
+ a LHS. */
+static bool
+rs6000_new_builtin_valid_without_lhs (enum rs6000_gen_builtins fn_code,
+ tree fndecl)
+{
+ if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
+ return true;
+
+ switch (fn_code)
+ {
+ case RS6000_BIF_STVX_V16QI:
+ case RS6000_BIF_STVX_V8HI:
+ case RS6000_BIF_STVX_V4SI:
+ case RS6000_BIF_STVX_V4SF:
+ case RS6000_BIF_STVX_V2DI:
+ case RS6000_BIF_STVX_V2DF:
+ case RS6000_BIF_STXVW4X_V16QI:
+ case RS6000_BIF_STXVW4X_V8HI:
+ case RS6000_BIF_STXVW4X_V4SF:
+ case RS6000_BIF_STXVW4X_V4SI:
+ case RS6000_BIF_STXVD2X_V2DF:
+ case RS6000_BIF_STXVD2X_V2DI:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Check whether a builtin function is supported in this target
+ configuration. */
+bool
+rs6000_new_builtin_is_supported (enum rs6000_gen_builtins fncode)
+{
+ switch (rs6000_builtin_info_x[(size_t) fncode].enable)
+ {
+ case ENB_ALWAYS:
+ return true;
+ case ENB_P5:
+ return TARGET_POPCNTB;
+ case ENB_P6:
+ return TARGET_CMPB;
+ case ENB_P7:
+ return TARGET_POPCNTD;
+ case ENB_P7_64:
+ return TARGET_POPCNTD && TARGET_POWERPC64;
+ case ENB_P8:
+ return TARGET_DIRECT_MOVE;
+ case ENB_P8V:
+ return TARGET_P8_VECTOR;
+ case ENB_P9:
+ return TARGET_MODULO;
+ case ENB_P9_64:
+ return TARGET_MODULO && TARGET_POWERPC64;
+ case ENB_P9V:
+ return TARGET_P9_VECTOR;
+ case ENB_P10:
+ return TARGET_POWER10;
+ case ENB_P10_64:
+ return TARGET_POWER10 && TARGET_POWERPC64;
+ case ENB_ALTIVEC:
+ return TARGET_ALTIVEC;
+ case ENB_VSX:
+ return TARGET_VSX;
+ case ENB_CELL:
+ return TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL;
+ case ENB_IEEE128_HW:
+ return TARGET_FLOAT128_HW;
+ case ENB_DFP:
+ return TARGET_DFP;
+ case ENB_CRYPTO:
+ return TARGET_CRYPTO;
+ case ENB_HTM:
+ return TARGET_HTM;
+ case ENB_MMA:
+ return TARGET_MMA;
+ default:
+ gcc_unreachable ();
+ }
+ gcc_unreachable ();
+}
+
+/* Expand the MMA built-ins early, so that we can convert the pass-by-reference
+ __vector_quad arguments into pass-by-value arguments, leading to more
+ efficient code generation. */
+static bool
+rs6000_gimple_fold_new_mma_builtin (gimple_stmt_iterator *gsi,
+ rs6000_gen_builtins fn_code)
+{
+ gimple *stmt = gsi_stmt (*gsi);
+ size_t fncode = (size_t) fn_code;
+
+ if (!bif_is_mma (rs6000_builtin_info_x[fncode]))
+ return false;
+
+ /* Each call that can be gimple-expanded has an associated built-in
+ function that it will expand into. If this one doesn't, we have
+ already expanded it! Exceptions: lxvp and stxvp. */
+ if (rs6000_builtin_info_x[fncode].assoc_bif == RS6000_BIF_NONE
+ && fncode != RS6000_BIF_LXVP
+ && fncode != RS6000_BIF_STXVP)
+ return false;
+
+ bifdata *bd = &rs6000_builtin_info_x[fncode];
+ unsigned nopnds = bd->nargs;
+ gimple_seq new_seq = NULL;
+ gimple *new_call;
+ tree new_decl;
+
+ /* Compatibility built-ins; we used to call these
+ __builtin_mma_{dis,}assemble_pair, but now we call them
+ __builtin_vsx_{dis,}assemble_pair. Handle the old versions. */
+ if (fncode == RS6000_BIF_ASSEMBLE_PAIR)
+ fncode = RS6000_BIF_ASSEMBLE_PAIR_V;
+ else if (fncode == RS6000_BIF_DISASSEMBLE_PAIR)
+ fncode = RS6000_BIF_DISASSEMBLE_PAIR_V;
+
+ if (fncode == RS6000_BIF_DISASSEMBLE_ACC
+ || fncode == RS6000_BIF_DISASSEMBLE_PAIR_V)
+ {
+ /* This is an MMA disassemble built-in function. */
+ push_gimplify_context (true);
+ unsigned nvec = (fncode == RS6000_BIF_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 = create_tmp_reg_or_ssa_name (TREE_TYPE (src_type));
+ gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq);
+
+ /* 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 == RS6000_BIF_DISASSEMBLE_ACC
+ && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_quad_type_node)
+ || (fncode == RS6000_BIF_DISASSEMBLE_PAIR_V
+ && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_pair_type_node))
+ {
+ tree dst = build_simple_mem_ref (build1 (VIEW_CONVERT_EXPR,
+ src_type, dst_ptr));
+ gimplify_assign (dst, src, &new_seq);
+ pop_gimplify_context (NULL);
+ gsi_replace_with_seq (gsi, new_seq, true);
+ return true;
+ }
+
+ /* If we're disassembling an accumulator into a different type, we need
+ to emit a xxmfacc instruction now, since we cannot do it later. */
+ if (fncode == RS6000_BIF_DISASSEMBLE_ACC)
+ {
+ new_decl = rs6000_builtin_decls_x[RS6000_BIF_XXMFACC_INTERNAL];
+ new_call = gimple_build_call (new_decl, 1, src);
+ src = create_tmp_reg_or_ssa_name (vector_quad_type_node);
+ gimple_call_set_lhs (new_call, src);
+ gimple_seq_add_stmt (&new_seq, new_call);
+ }
+
+ /* Copy the accumulator/pair vector by vector. */
+ new_decl
+ = rs6000_builtin_decls_x[rs6000_builtin_info_x[fncode].assoc_bif];
+ 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);
+ for (unsigned i = 0; i < nvec; i++)
+ {
+ 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));
+ tree dstssa = create_tmp_reg_or_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);
+ return true;
+ }
+
+ /* TODO: Do some factoring on these two chunks. */
+ if (fncode == RS6000_BIF_LXVP)
+ {
+ push_gimplify_context (true);
+ tree offset = gimple_call_arg (stmt, 0);
+ tree ptr = gimple_call_arg (stmt, 1);
+ tree lhs = gimple_call_lhs (stmt);
+ if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node)
+ ptr = build1 (VIEW_CONVERT_EXPR,
+ build_pointer_type (vector_pair_type_node), ptr);
+ tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (ptr), ptr, offset));
+ gimplify_assign (lhs, mem, &new_seq);
+ pop_gimplify_context (NULL);
+ gsi_replace_with_seq (gsi, new_seq, true);
+ return true;
+ }
+
+ if (fncode == RS6000_BIF_STXVP)
+ {
+ push_gimplify_context (true);
+ tree src = gimple_call_arg (stmt, 0);
+ tree offset = gimple_call_arg (stmt, 1);
+ tree ptr = gimple_call_arg (stmt, 2);
+ if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node)
+ ptr = build1 (VIEW_CONVERT_EXPR,
+ build_pointer_type (vector_pair_type_node), ptr);
+ tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (ptr), ptr, offset));
+ gimplify_assign (mem, src, &new_seq);
+ pop_gimplify_context (NULL);
+ gsi_replace_with_seq (gsi, new_seq, true);
+ return true;
+ }
+
+ /* Convert this built-in into an internal version that uses pass-by-value
+ arguments. The internal built-in is found in the assoc_bif field. */
+ new_decl = rs6000_builtin_decls_x[rs6000_builtin_info_x[fncode].assoc_bif];
+ tree lhs, op[MAX_MMA_OPERANDS];
+ tree acc = gimple_call_arg (stmt, 0);
+ push_gimplify_context (true);
+
+ if (bif_is_quad (*bd))
+ {
+ /* This built-in has a pass-by-reference accumulator input, so load it
+ into a temporary accumulator for use as a pass-by-value input. */
+ op[0] = create_tmp_reg_or_ssa_name (vector_quad_type_node);
+ for (unsigned i = 1; i < nopnds; i++)
+ op[i] = gimple_call_arg (stmt, i);
+ gimplify_assign (op[0], build_simple_mem_ref (acc), &new_seq);
+ }
+ else
+ {
+ /* This built-in does not use its pass-by-reference accumulator argument
+ as an input argument, so remove it from the input list. */
+ nopnds--;
+ for (unsigned i = 0; i < nopnds; i++)
+ op[i] = gimple_call_arg (stmt, i + 1);
+ }
+
+ switch (nopnds)
+ {
+ case 0:
+ new_call = gimple_build_call (new_decl, 0);
+ break;
+ case 1:
+ new_call = gimple_build_call (new_decl, 1, op[0]);
+ break;
+ case 2:
+ new_call = gimple_build_call (new_decl, 2, op[0], op[1]);
+ break;
+ case 3:
+ new_call = gimple_build_call (new_decl, 3, op[0], op[1], op[2]);
+ break;
+ case 4:
+ new_call = gimple_build_call (new_decl, 4, op[0], op[1], op[2], op[3]);
+ break;
+ case 5:
+ new_call = gimple_build_call (new_decl, 5, op[0], op[1], op[2], op[3],
+ op[4]);
+ break;
+ case 6:
+ new_call = gimple_build_call (new_decl, 6, op[0], op[1], op[2], op[3],
+ op[4], op[5]);
+ break;
+ case 7:
+ new_call = gimple_build_call (new_decl, 7, op[0], op[1], op[2], op[3],
+ op[4], op[5], op[6]);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (fncode == RS6000_BIF_BUILD_PAIR || fncode == RS6000_BIF_ASSEMBLE_PAIR_V)
+ lhs = create_tmp_reg_or_ssa_name (vector_pair_type_node);
+ else
+ lhs = create_tmp_reg_or_ssa_name (vector_quad_type_node);
+ gimple_call_set_lhs (new_call, lhs);
+ gimple_seq_add_stmt (&new_seq, new_call);
+ gimplify_assign (build_simple_mem_ref (acc), lhs, &new_seq);
+ pop_gimplify_context (NULL);
+ gsi_replace_with_seq (gsi, new_seq, true);
+
+ return true;
+}
+
+/* Fold a machine-dependent built-in in GIMPLE. (For folding into
+ a constant, use rs6000_fold_builtin.) */
+static bool
+rs6000_gimple_fold_new_builtin (gimple_stmt_iterator *gsi)
+{
+ gimple *stmt = gsi_stmt (*gsi);
+ tree fndecl = gimple_call_fndecl (stmt);
+ gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD);
+ enum rs6000_gen_builtins fn_code
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ tree arg0, arg1, lhs, temp;
+ enum tree_code bcode;
+ gimple *g;
+
+ size_t uns_fncode = (size_t) fn_code;
+ enum insn_code icode = rs6000_builtin_info_x[uns_fncode].icode;
+ const char *fn_name1 = rs6000_builtin_info_x[uns_fncode].bifname;
+ const char *fn_name2 = (icode != CODE_FOR_nothing)
+ ? get_insn_name ((int) icode)
+ : "nothing";
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_gimple_fold_new_builtin %d %s %s\n",
+ fn_code, fn_name1, fn_name2);
+
+ if (!rs6000_fold_gimple)
+ return false;
+
+ /* Prevent gimple folding for code that does not have a LHS, unless it is
+ allowed per the rs6000_new_builtin_valid_without_lhs helper function. */
+ if (!gimple_call_lhs (stmt)
+ && !rs6000_new_builtin_valid_without_lhs (fn_code, fndecl))
+ return false;
+
+ /* Don't fold invalid builtins, let rs6000_expand_builtin diagnose it. */
+ if (!rs6000_new_builtin_is_supported (fn_code))
+ return false;
+
+ if (rs6000_gimple_fold_new_mma_builtin (gsi, fn_code))
+ return true;
+
+ switch (fn_code)
+ {
+ /* Flavors of vec_add. We deliberately don't expand
+ RS6000_BIF_VADDUQM as it gets lowered from V1TImode to
+ TImode, resulting in much poorer code generation. */
+ case RS6000_BIF_VADDUBM:
+ case RS6000_BIF_VADDUHM:
+ case RS6000_BIF_VADDUWM:
+ case RS6000_BIF_VADDUDM:
+ case RS6000_BIF_VADDFP:
+ case RS6000_BIF_XVADDDP:
+ case RS6000_BIF_XVADDSP:
+ bcode = PLUS_EXPR;
+ do_binary:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (lhs)))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (lhs))))
+ {
+ /* Ensure the binary operation is performed in a type
+ that wraps if it is integral type. */
+ gimple_seq stmts = NULL;
+ tree type = unsigned_type_for (TREE_TYPE (lhs));
+ tree uarg0 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ type, arg0);
+ tree uarg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ type, arg1);
+ tree res = gimple_build (&stmts, gimple_location (stmt), bcode,
+ type, uarg0, uarg1);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR,
+ build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (lhs), res));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ g = gimple_build_assign (lhs, bcode, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_sub. We deliberately don't expand
+ RS6000_BIF_VSUBUQM. */
+ case RS6000_BIF_VSUBUBM:
+ case RS6000_BIF_VSUBUHM:
+ case RS6000_BIF_VSUBUWM:
+ case RS6000_BIF_VSUBUDM:
+ case RS6000_BIF_VSUBFP:
+ case RS6000_BIF_XVSUBDP:
+ case RS6000_BIF_XVSUBSP:
+ bcode = MINUS_EXPR;
+ goto do_binary;
+ case RS6000_BIF_XVMULSP:
+ case RS6000_BIF_XVMULDP:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, MULT_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Even element flavors of vec_mul (signed). */
+ case RS6000_BIF_VMULESB:
+ case RS6000_BIF_VMULESH:
+ case RS6000_BIF_VMULESW:
+ /* Even element flavors of vec_mul (unsigned). */
+ case RS6000_BIF_VMULEUB:
+ case RS6000_BIF_VMULEUH:
+ case RS6000_BIF_VMULEUW:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, VEC_WIDEN_MULT_EVEN_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Odd element flavors of vec_mul (signed). */
+ case RS6000_BIF_VMULOSB:
+ case RS6000_BIF_VMULOSH:
+ case RS6000_BIF_VMULOSW:
+ /* Odd element flavors of vec_mul (unsigned). */
+ case RS6000_BIF_VMULOUB:
+ case RS6000_BIF_VMULOUH:
+ case RS6000_BIF_VMULOUW:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, VEC_WIDEN_MULT_ODD_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_div (Integer). */
+ case RS6000_BIF_DIV_V2DI:
+ case RS6000_BIF_UDIV_V2DI:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, TRUNC_DIV_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_div (Float). */
+ case RS6000_BIF_XVDIVSP:
+ case RS6000_BIF_XVDIVDP:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, RDIV_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_and. */
+ case RS6000_BIF_VAND_V16QI_UNS:
+ case RS6000_BIF_VAND_V16QI:
+ case RS6000_BIF_VAND_V8HI_UNS:
+ case RS6000_BIF_VAND_V8HI:
+ case RS6000_BIF_VAND_V4SI_UNS:
+ case RS6000_BIF_VAND_V4SI:
+ case RS6000_BIF_VAND_V2DI_UNS:
+ case RS6000_BIF_VAND_V2DI:
+ case RS6000_BIF_VAND_V4SF:
+ case RS6000_BIF_VAND_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_andc. */
+ case RS6000_BIF_VANDC_V16QI_UNS:
+ case RS6000_BIF_VANDC_V16QI:
+ case RS6000_BIF_VANDC_V8HI_UNS:
+ case RS6000_BIF_VANDC_V8HI:
+ case RS6000_BIF_VANDC_V4SI_UNS:
+ case RS6000_BIF_VANDC_V4SI:
+ case RS6000_BIF_VANDC_V2DI_UNS:
+ case RS6000_BIF_VANDC_V2DI:
+ case RS6000_BIF_VANDC_V4SF:
+ case RS6000_BIF_VANDC_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
+ g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, temp);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_nand. */
+ case RS6000_BIF_NAND_V16QI_UNS:
+ case RS6000_BIF_NAND_V16QI:
+ case RS6000_BIF_NAND_V8HI_UNS:
+ case RS6000_BIF_NAND_V8HI:
+ case RS6000_BIF_NAND_V4SI_UNS:
+ case RS6000_BIF_NAND_V4SI:
+ case RS6000_BIF_NAND_V2DI_UNS:
+ case RS6000_BIF_NAND_V2DI:
+ case RS6000_BIF_NAND_V4SF:
+ case RS6000_BIF_NAND_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
+ g = gimple_build_assign (temp, BIT_AND_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_or. */
+ case RS6000_BIF_VOR_V16QI_UNS:
+ case RS6000_BIF_VOR_V16QI:
+ case RS6000_BIF_VOR_V8HI_UNS:
+ case RS6000_BIF_VOR_V8HI:
+ case RS6000_BIF_VOR_V4SI_UNS:
+ case RS6000_BIF_VOR_V4SI:
+ case RS6000_BIF_VOR_V2DI_UNS:
+ case RS6000_BIF_VOR_V2DI:
+ case RS6000_BIF_VOR_V4SF:
+ case RS6000_BIF_VOR_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* flavors of vec_orc. */
+ case RS6000_BIF_ORC_V16QI_UNS:
+ case RS6000_BIF_ORC_V16QI:
+ case RS6000_BIF_ORC_V8HI_UNS:
+ case RS6000_BIF_ORC_V8HI:
+ case RS6000_BIF_ORC_V4SI_UNS:
+ case RS6000_BIF_ORC_V4SI:
+ case RS6000_BIF_ORC_V2DI_UNS:
+ case RS6000_BIF_ORC_V2DI:
+ case RS6000_BIF_ORC_V4SF:
+ case RS6000_BIF_ORC_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
+ g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, temp);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_xor. */
+ case RS6000_BIF_VXOR_V16QI_UNS:
+ case RS6000_BIF_VXOR_V16QI:
+ case RS6000_BIF_VXOR_V8HI_UNS:
+ case RS6000_BIF_VXOR_V8HI:
+ case RS6000_BIF_VXOR_V4SI_UNS:
+ case RS6000_BIF_VXOR_V4SI:
+ case RS6000_BIF_VXOR_V2DI_UNS:
+ case RS6000_BIF_VXOR_V2DI:
+ case RS6000_BIF_VXOR_V4SF:
+ case RS6000_BIF_VXOR_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, BIT_XOR_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_nor. */
+ case RS6000_BIF_VNOR_V16QI_UNS:
+ case RS6000_BIF_VNOR_V16QI:
+ case RS6000_BIF_VNOR_V8HI_UNS:
+ case RS6000_BIF_VNOR_V8HI:
+ case RS6000_BIF_VNOR_V4SI_UNS:
+ case RS6000_BIF_VNOR_V4SI:
+ case RS6000_BIF_VNOR_V2DI_UNS:
+ case RS6000_BIF_VNOR_V2DI:
+ case RS6000_BIF_VNOR_V4SF:
+ case RS6000_BIF_VNOR_V2DF:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
+ g = gimple_build_assign (temp, BIT_IOR_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* flavors of vec_abs. */
+ case RS6000_BIF_ABS_V16QI:
+ case RS6000_BIF_ABS_V8HI:
+ case RS6000_BIF_ABS_V4SI:
+ case RS6000_BIF_ABS_V4SF:
+ case RS6000_BIF_ABS_V2DI:
+ case RS6000_BIF_XVABSDP:
+ case RS6000_BIF_XVABSSP:
+ arg0 = gimple_call_arg (stmt, 0);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0))))
+ return false;
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, ABS_EXPR, arg0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* flavors of vec_min. */
+ case RS6000_BIF_XVMINDP:
+ case RS6000_BIF_XVMINSP:
+ case RS6000_BIF_VMINSD:
+ case RS6000_BIF_VMINUD:
+ case RS6000_BIF_VMINSB:
+ case RS6000_BIF_VMINSH:
+ case RS6000_BIF_VMINSW:
+ case RS6000_BIF_VMINUB:
+ case RS6000_BIF_VMINUH:
+ case RS6000_BIF_VMINUW:
+ case RS6000_BIF_VMINFP:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, MIN_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* flavors of vec_max. */
+ case RS6000_BIF_XVMAXDP:
+ case RS6000_BIF_XVMAXSP:
+ case RS6000_BIF_VMAXSD:
+ case RS6000_BIF_VMAXUD:
+ case RS6000_BIF_VMAXSB:
+ case RS6000_BIF_VMAXSH:
+ case RS6000_BIF_VMAXSW:
+ case RS6000_BIF_VMAXUB:
+ case RS6000_BIF_VMAXUH:
+ case RS6000_BIF_VMAXUW:
+ case RS6000_BIF_VMAXFP:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, MAX_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_eqv. */
+ case RS6000_BIF_EQV_V16QI:
+ case RS6000_BIF_EQV_V8HI:
+ case RS6000_BIF_EQV_V4SI:
+ case RS6000_BIF_EQV_V4SF:
+ case RS6000_BIF_EQV_V2DF:
+ case RS6000_BIF_EQV_V2DI:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1));
+ g = gimple_build_assign (temp, BIT_XOR_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vec_rotate_left. */
+ case RS6000_BIF_VRLB:
+ case RS6000_BIF_VRLH:
+ case RS6000_BIF_VRLW:
+ case RS6000_BIF_VRLD:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ g = gimple_build_assign (lhs, LROTATE_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ /* Flavors of vector shift right algebraic.
+ vec_sra{b,h,w} -> vsra{b,h,w}. */
+ case RS6000_BIF_VSRAB:
+ case RS6000_BIF_VSRAH:
+ case RS6000_BIF_VSRAW:
+ case RS6000_BIF_VSRAD:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ tree arg1_type = TREE_TYPE (arg1);
+ tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+ tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+ location_t loc = gimple_location (stmt);
+ /* Force arg1 into the range valid matching the arg0 type. */
+ /* Build a vector consisting of the max valid bit-size values. */
+ int n_elts = VECTOR_CST_NELTS (arg1);
+ tree element_size = build_int_cst (unsigned_element_type,
+ 128 / n_elts);
+ tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
+ for (int i = 0; i < n_elts; i++)
+ elts.safe_push (element_size);
+ tree modulo_tree = elts.build ();
+ /* Modulo the provided shift value against that vector. */
+ gimple_seq stmts = NULL;
+ tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ unsigned_arg1_type, arg1);
+ tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+ unsigned_arg1_type, unsigned_arg1,
+ modulo_tree);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ /* And finally, do the shift. */
+ g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* Flavors of vector shift left.
+ builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}. */
+ case RS6000_BIF_VSLB:
+ case RS6000_BIF_VSLH:
+ case RS6000_BIF_VSLW:
+ case RS6000_BIF_VSLD:
+ {
+ location_t loc;
+ gimple_seq stmts = NULL;
+ arg0 = gimple_call_arg (stmt, 0);
+ tree arg0_type = TREE_TYPE (arg0);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (arg0_type))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0_type)))
+ return false;
+ arg1 = gimple_call_arg (stmt, 1);
+ tree arg1_type = TREE_TYPE (arg1);
+ tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+ tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+ loc = gimple_location (stmt);
+ lhs = gimple_call_lhs (stmt);
+ /* Force arg1 into the range valid matching the arg0 type. */
+ /* Build a vector consisting of the max valid bit-size values. */
+ int n_elts = VECTOR_CST_NELTS (arg1);
+ int tree_size_in_bits = TREE_INT_CST_LOW (size_in_bytes (arg1_type))
+ * BITS_PER_UNIT;
+ tree element_size = build_int_cst (unsigned_element_type,
+ tree_size_in_bits / n_elts);
+ tree_vector_builder elts (unsigned_type_for (arg1_type), n_elts, 1);
+ for (int i = 0; i < n_elts; i++)
+ elts.safe_push (element_size);
+ tree modulo_tree = elts.build ();
+ /* Modulo the provided shift value against that vector. */
+ tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ unsigned_arg1_type, arg1);
+ tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+ unsigned_arg1_type, unsigned_arg1,
+ modulo_tree);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ /* And finally, do the shift. */
+ g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, new_arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* Flavors of vector shift right. */
+ case RS6000_BIF_VSRB:
+ case RS6000_BIF_VSRH:
+ case RS6000_BIF_VSRW:
+ case RS6000_BIF_VSRD:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ tree arg1_type = TREE_TYPE (arg1);
+ tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+ tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+ location_t loc = gimple_location (stmt);
+ gimple_seq stmts = NULL;
+ /* Convert arg0 to unsigned. */
+ tree arg0_unsigned
+ = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ unsigned_type_for (TREE_TYPE (arg0)), arg0);
+ /* Force arg1 into the range valid matching the arg0 type. */
+ /* Build a vector consisting of the max valid bit-size values. */
+ int n_elts = VECTOR_CST_NELTS (arg1);
+ tree element_size = build_int_cst (unsigned_element_type,
+ 128 / n_elts);
+ tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
+ for (int i = 0; i < n_elts; i++)
+ elts.safe_push (element_size);
+ tree modulo_tree = elts.build ();
+ /* Modulo the provided shift value against that vector. */
+ tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ unsigned_arg1_type, arg1);
+ tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+ unsigned_arg1_type, unsigned_arg1,
+ modulo_tree);
+ /* Do the shift. */
+ tree res
+ = gimple_build (&stmts, RSHIFT_EXPR,
+ TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1);
+ /* Convert result back to the lhs type. */
+ res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ replace_call_with_value (gsi, res);
+ return true;
+ }
+ /* Vector loads. */
+ case RS6000_BIF_LVX_V16QI:
+ case RS6000_BIF_LVX_V8HI:
+ case RS6000_BIF_LVX_V4SI:
+ case RS6000_BIF_LVX_V4SF:
+ case RS6000_BIF_LVX_V2DI:
+ case RS6000_BIF_LVX_V2DF:
+ case RS6000_BIF_LVX_V1TI:
+ {
+ arg0 = gimple_call_arg (stmt, 0); // offset
+ arg1 = gimple_call_arg (stmt, 1); // address
+ lhs = gimple_call_lhs (stmt);
+ location_t loc = gimple_location (stmt);
+ /* Since arg1 may be cast to a different type, just use ptr_type_node
+ here instead of trying to enforce TBAA on pointer types. */
+ tree arg1_type = ptr_type_node;
+ tree lhs_type = TREE_TYPE (lhs);
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg0. The resulting type will match
+ the type of arg1. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg1_type, arg1, temp_offset);
+ /* Mask off any lower bits from the address. */
+ tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR,
+ arg1_type, temp_addr,
+ build_int_cst (arg1_type, -16));
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ if (!is_gimple_mem_ref_addr (aligned_addr))
+ {
+ tree t = make_ssa_name (TREE_TYPE (aligned_addr));
+ gimple *g = gimple_build_assign (t, aligned_addr);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ aligned_addr = t;
+ }
+ /* Use the build2 helper to set up the mem_ref. The MEM_REF could also
+ take an offset, but since we've already incorporated the offset
+ above, here we just pass in a zero. */
+ gimple *g
+ = gimple_build_assign (lhs, build2 (MEM_REF, lhs_type, aligned_addr,
+ build_int_cst (arg1_type, 0)));
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* Vector stores. */
+ case RS6000_BIF_STVX_V16QI:
+ case RS6000_BIF_STVX_V8HI:
+ case RS6000_BIF_STVX_V4SI:
+ case RS6000_BIF_STVX_V4SF:
+ case RS6000_BIF_STVX_V2DI:
+ case RS6000_BIF_STVX_V2DF:
+ {
+ arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */
+ arg1 = gimple_call_arg (stmt, 1); /* Offset. */
+ tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */
+ location_t loc = gimple_location (stmt);
+ tree arg0_type = TREE_TYPE (arg0);
+ /* Use ptr_type_node (no TBAA) for the arg2_type.
+ FIXME: (Richard) "A proper fix would be to transition this type as
+ seen from the frontend to GIMPLE, for example in a similar way we
+ do for MEM_REFs by piggy-backing that on an extra argument, a
+ constant zero pointer of the alias pointer type to use (which would
+ also serve as a type indicator of the store itself). I'd use a
+ target specific internal function for this (not sure if we can have
+ those target specific, but I guess if it's folded away then that's
+ fine) and get away with the overload set." */
+ tree arg2_type = ptr_type_node;
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg0. The resulting type will match
+ the type of arg2. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg2_type, arg2, temp_offset);
+ /* Mask off any lower bits from the address. */
+ tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR,
+ arg2_type, temp_addr,
+ build_int_cst (arg2_type, -16));
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ if (!is_gimple_mem_ref_addr (aligned_addr))
+ {
+ tree t = make_ssa_name (TREE_TYPE (aligned_addr));
+ gimple *g = gimple_build_assign (t, aligned_addr);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ aligned_addr = t;
+ }
+ /* The desired gimple result should be similar to:
+ MEM[(__vector floatD.1407 *)_1] = vf1D.2697; */
+ gimple *g
+ = gimple_build_assign (build2 (MEM_REF, arg0_type, aligned_addr,
+ build_int_cst (arg2_type, 0)), arg0);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* unaligned Vector loads. */
+ case RS6000_BIF_LXVW4X_V16QI:
+ case RS6000_BIF_LXVW4X_V8HI:
+ case RS6000_BIF_LXVW4X_V4SF:
+ case RS6000_BIF_LXVW4X_V4SI:
+ case RS6000_BIF_LXVD2X_V2DF:
+ case RS6000_BIF_LXVD2X_V2DI:
+ {
+ arg0 = gimple_call_arg (stmt, 0); // offset
+ arg1 = gimple_call_arg (stmt, 1); // address
+ lhs = gimple_call_lhs (stmt);
+ location_t loc = gimple_location (stmt);
+ /* Since arg1 may be cast to a different type, just use ptr_type_node
+ here instead of trying to enforce TBAA on pointer types. */
+ tree arg1_type = ptr_type_node;
+ tree lhs_type = TREE_TYPE (lhs);
+ /* In GIMPLE the type of the MEM_REF specifies the alignment. The
+ required alignment (power) is 4 bytes regardless of data type. */
+ tree align_ltype = build_aligned_type (lhs_type, 4);
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg0. The resulting type will match
+ the type of arg1. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg1_type, arg1, temp_offset);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ if (!is_gimple_mem_ref_addr (temp_addr))
+ {
+ tree t = make_ssa_name (TREE_TYPE (temp_addr));
+ gimple *g = gimple_build_assign (t, temp_addr);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ temp_addr = t;
+ }
+ /* Use the build2 helper to set up the mem_ref. The MEM_REF could also
+ take an offset, but since we've already incorporated the offset
+ above, here we just pass in a zero. */
+ gimple *g;
+ g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr,
+ build_int_cst (arg1_type, 0)));
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* unaligned Vector stores. */
+ case RS6000_BIF_STXVW4X_V16QI:
+ case RS6000_BIF_STXVW4X_V8HI:
+ case RS6000_BIF_STXVW4X_V4SF:
+ case RS6000_BIF_STXVW4X_V4SI:
+ case RS6000_BIF_STXVD2X_V2DF:
+ case RS6000_BIF_STXVD2X_V2DI:
+ {
+ arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */
+ arg1 = gimple_call_arg (stmt, 1); /* Offset. */
+ tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */
+ location_t loc = gimple_location (stmt);
+ tree arg0_type = TREE_TYPE (arg0);
+ /* Use ptr_type_node (no TBAA) for the arg2_type. */
+ tree arg2_type = ptr_type_node;
+ /* In GIMPLE the type of the MEM_REF specifies the alignment. The
+ required alignment (power) is 4 bytes regardless of data type. */
+ tree align_stype = build_aligned_type (arg0_type, 4);
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg1. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg2_type, arg2, temp_offset);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ if (!is_gimple_mem_ref_addr (temp_addr))
+ {
+ tree t = make_ssa_name (TREE_TYPE (temp_addr));
+ gimple *g = gimple_build_assign (t, temp_addr);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ temp_addr = t;
+ }
+ gimple *g;
+ g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr,
+ build_int_cst (arg2_type, 0)), arg0);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* Vector Fused multiply-add (fma). */
+ case RS6000_BIF_VMADDFP:
+ case RS6000_BIF_XVMADDDP:
+ case RS6000_BIF_XVMADDSP:
+ case RS6000_BIF_VMLADDUHM:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ tree arg2 = gimple_call_arg (stmt, 2);
+ lhs = gimple_call_lhs (stmt);
+ gcall *g = gimple_build_call_internal (IFN_FMA, 3, arg0, arg1, arg2);
+ gimple_call_set_lhs (g, lhs);
+ gimple_call_set_nothrow (g, true);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* Vector compares; EQ, NE, GE, GT, LE. */
+ case RS6000_BIF_VCMPEQUB:
+ case RS6000_BIF_VCMPEQUH:
+ case RS6000_BIF_VCMPEQUW:
+ case RS6000_BIF_VCMPEQUD:
+ /* We deliberately omit RS6000_BIF_VCMPEQUT for now, because gimple
+ folding produces worse code for 128-bit compares. */
+ fold_compare_helper (gsi, EQ_EXPR, stmt);
+ return true;
+
+ case RS6000_BIF_VCMPNEB:
+ case RS6000_BIF_VCMPNEH:
+ case RS6000_BIF_VCMPNEW:
+ /* We deliberately omit RS6000_BIF_VCMPNET for now, because gimple
+ folding produces worse code for 128-bit compares. */
+ fold_compare_helper (gsi, NE_EXPR, stmt);
+ return true;
+
+ case RS6000_BIF_CMPGE_16QI:
+ case RS6000_BIF_CMPGE_U16QI:
+ case RS6000_BIF_CMPGE_8HI:
+ case RS6000_BIF_CMPGE_U8HI:
+ case RS6000_BIF_CMPGE_4SI:
+ case RS6000_BIF_CMPGE_U4SI:
+ case RS6000_BIF_CMPGE_2DI:
+ case RS6000_BIF_CMPGE_U2DI:
+ /* We deliberately omit RS6000_BIF_CMPGE_1TI and RS6000_BIF_CMPGE_U1TI
+ for now, because gimple folding produces worse code for 128-bit
+ compares. */
+ fold_compare_helper (gsi, GE_EXPR, stmt);
+ return true;
+
+ case RS6000_BIF_VCMPGTSB:
+ case RS6000_BIF_VCMPGTUB:
+ case RS6000_BIF_VCMPGTSH:
+ case RS6000_BIF_VCMPGTUH:
+ case RS6000_BIF_VCMPGTSW:
+ case RS6000_BIF_VCMPGTUW:
+ case RS6000_BIF_VCMPGTUD:
+ case RS6000_BIF_VCMPGTSD:
+ /* We deliberately omit RS6000_BIF_VCMPGTUT and RS6000_BIF_VCMPGTST
+ for now, because gimple folding produces worse code for 128-bit
+ compares. */
+ fold_compare_helper (gsi, GT_EXPR, stmt);
+ return true;
+
+ case RS6000_BIF_CMPLE_16QI:
+ case RS6000_BIF_CMPLE_U16QI:
+ case RS6000_BIF_CMPLE_8HI:
+ case RS6000_BIF_CMPLE_U8HI:
+ case RS6000_BIF_CMPLE_4SI:
+ case RS6000_BIF_CMPLE_U4SI:
+ case RS6000_BIF_CMPLE_2DI:
+ case RS6000_BIF_CMPLE_U2DI:
+ /* We deliberately omit RS6000_BIF_CMPLE_1TI and RS6000_BIF_CMPLE_U1TI
+ for now, because gimple folding produces worse code for 128-bit
+ compares. */
+ fold_compare_helper (gsi, LE_EXPR, stmt);
+ return true;
+
+ /* flavors of vec_splat_[us]{8,16,32}. */
+ case RS6000_BIF_VSPLTISB:
+ case RS6000_BIF_VSPLTISH:
+ case RS6000_BIF_VSPLTISW:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ lhs = gimple_call_lhs (stmt);
+
+ /* Only fold the vec_splat_*() if the lower bits of arg 0 is a
+ 5-bit signed constant in range -16 to +15. */
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || !IN_RANGE (TREE_INT_CST_LOW (arg0), -16, 15))
+ return false;
+ gimple_seq stmts = NULL;
+ location_t loc = gimple_location (stmt);
+ tree splat_value = gimple_convert (&stmts, loc,
+ TREE_TYPE (TREE_TYPE (lhs)), arg0);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value);
+ g = gimple_build_assign (lhs, splat_tree);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* Flavors of vec_splat. */
+ /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */
+ case RS6000_BIF_VSPLTB:
+ case RS6000_BIF_VSPLTH:
+ case RS6000_BIF_VSPLTW:
+ case RS6000_BIF_XXSPLTD_V2DI:
+ case RS6000_BIF_XXSPLTD_V2DF:
+ {
+ arg0 = gimple_call_arg (stmt, 0); /* input vector. */
+ arg1 = gimple_call_arg (stmt, 1); /* index into arg0. */
+ /* Only fold the vec_splat_*() if arg1 is both a constant value and
+ is a valid index into the arg0 vector. */
+ unsigned int n_elts = VECTOR_CST_NELTS (arg0);
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) > (n_elts -1))
+ return false;
+ lhs = gimple_call_lhs (stmt);
+ tree lhs_type = TREE_TYPE (lhs);
+ tree arg0_type = TREE_TYPE (arg0);
+ tree splat;
+ if (TREE_CODE (arg0) == VECTOR_CST)
+ splat = VECTOR_CST_ELT (arg0, TREE_INT_CST_LOW (arg1));
+ else
+ {
+ /* Determine (in bits) the length and start location of the
+ splat value for a call to the tree_vec_extract helper. */
+ int splat_elem_size = TREE_INT_CST_LOW (size_in_bytes (arg0_type))
+ * BITS_PER_UNIT / n_elts;
+ int splat_start_bit = TREE_INT_CST_LOW (arg1) * splat_elem_size;
+ tree len = build_int_cst (bitsizetype, splat_elem_size);
+ tree start = build_int_cst (bitsizetype, splat_start_bit);
+ splat = tree_vec_extract (gsi, TREE_TYPE (lhs_type), arg0,
+ len, start);
+ }
+ /* And finally, build the new vector. */
+ tree splat_tree = build_vector_from_val (lhs_type, splat);
+ g = gimple_build_assign (lhs, splat_tree);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* vec_mergel (integrals). */
+ case RS6000_BIF_VMRGLH:
+ case RS6000_BIF_VMRGLW:
+ case RS6000_BIF_XXMRGLW_4SI:
+ case RS6000_BIF_VMRGLB:
+ case RS6000_BIF_VEC_MERGEL_V2DI:
+ case RS6000_BIF_XXMRGLW_4SF:
+ case RS6000_BIF_VEC_MERGEL_V2DF:
+ fold_mergehl_helper (gsi, stmt, 1);
+ return true;
+ /* vec_mergeh (integrals). */
+ case RS6000_BIF_VMRGHH:
+ case RS6000_BIF_VMRGHW:
+ case RS6000_BIF_XXMRGHW_4SI:
+ case RS6000_BIF_VMRGHB:
+ case RS6000_BIF_VEC_MERGEH_V2DI:
+ case RS6000_BIF_XXMRGHW_4SF:
+ case RS6000_BIF_VEC_MERGEH_V2DF:
+ fold_mergehl_helper (gsi, stmt, 0);
+ return true;
+
+ /* Flavors of vec_mergee. */
+ case RS6000_BIF_VMRGEW_V4SI:
+ case RS6000_BIF_VMRGEW_V2DI:
+ case RS6000_BIF_VMRGEW_V4SF:
+ case RS6000_BIF_VMRGEW_V2DF:
+ fold_mergeeo_helper (gsi, stmt, 0);
+ return true;
+ /* Flavors of vec_mergeo. */
+ case RS6000_BIF_VMRGOW_V4SI:
+ case RS6000_BIF_VMRGOW_V2DI:
+ case RS6000_BIF_VMRGOW_V4SF:
+ case RS6000_BIF_VMRGOW_V2DF:
+ fold_mergeeo_helper (gsi, stmt, 1);
+ return true;
+
+ /* d = vec_pack (a, b) */
+ case RS6000_BIF_VPKUDUM:
+ case RS6000_BIF_VPKUHUM:
+ case RS6000_BIF_VPKUWUM:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* d = vec_unpackh (a) */
+ /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call
+ in this code is sensitive to endian-ness, and needs to be inverted to
+ handle both LE and BE targets. */
+ case RS6000_BIF_VUPKHSB:
+ case RS6000_BIF_VUPKHSH:
+ case RS6000_BIF_VUPKHSW:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ lhs = gimple_call_lhs (stmt);
+ if (BYTES_BIG_ENDIAN)
+ g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+ else
+ g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* d = vec_unpackl (a) */
+ case RS6000_BIF_VUPKLSB:
+ case RS6000_BIF_VUPKLSH:
+ case RS6000_BIF_VUPKLSW:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ lhs = gimple_call_lhs (stmt);
+ if (BYTES_BIG_ENDIAN)
+ g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+ else
+ g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* There is no gimple type corresponding with pixel, so just return. */
+ case RS6000_BIF_VUPKHPX:
+ case RS6000_BIF_VUPKLPX:
+ return false;
+
+ /* vec_perm. */
+ case RS6000_BIF_VPERM_16QI:
+ case RS6000_BIF_VPERM_8HI:
+ case RS6000_BIF_VPERM_4SI:
+ case RS6000_BIF_VPERM_2DI:
+ case RS6000_BIF_VPERM_4SF:
+ case RS6000_BIF_VPERM_2DF:
+ case RS6000_BIF_VPERM_16QI_UNS:
+ case RS6000_BIF_VPERM_8HI_UNS:
+ case RS6000_BIF_VPERM_4SI_UNS:
+ case RS6000_BIF_VPERM_2DI_UNS:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ tree permute = gimple_call_arg (stmt, 2);
+ lhs = gimple_call_lhs (stmt);
+ location_t loc = gimple_location (stmt);
+ gimple_seq stmts = NULL;
+ // convert arg0 and arg1 to match the type of the permute
+ // for the VEC_PERM_EXPR operation.
+ tree permute_type = (TREE_TYPE (permute));
+ tree arg0_ptype = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
+ permute_type, arg0);
+ tree arg1_ptype = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
+ permute_type, arg1);
+ tree lhs_ptype = gimple_build (&stmts, loc, VEC_PERM_EXPR,
+ permute_type, arg0_ptype, arg1_ptype,
+ permute);
+ // Convert the result back to the desired lhs type upon completion.
+ tree temp = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR,
+ TREE_TYPE (lhs), lhs_ptype);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, temp);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ default:
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "gimple builtin intrinsic not matched:%d %s %s\n",
+ fn_code, fn_name1, fn_name2);
+ break;
+ }
+
+ return false;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -13296,15 +14604,23 @@ rs6000_init_builtins (void)
tree ftype;
tree t;
machine_mode mode;
+ const char *str;
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_init_builtins%s%s\n",
(TARGET_ALTIVEC) ? ", altivec" : "",
(TARGET_VSX) ? ", vsx" : "");
- V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector long"
- : "__vector long long",
- long_long_integer_type_node, 2);
+ if (new_builtins_are_live)
+ V2DI_type_node = rs6000_vector_type ("__vector long long",
+ long_long_integer_type_node, 2);
+ else
+ {
+ str = TARGET_POWERPC64 ? "__vector long" : "__vector long long";
+ V2DI_type_node = rs6000_vector_type (str,
+ long_long_integer_type_node,
+ 2);
+ }
ptr_V2DI_type_node
= build_pointer_type (build_qualified_type (V2DI_type_node,
TYPE_QUAL_CONST));
@@ -13355,10 +14671,19 @@ rs6000_init_builtins (void)
= build_pointer_type (build_qualified_type (unsigned_V4SI_type_node,
TYPE_QUAL_CONST));
- unsigned_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64
- ? "__vector unsigned long"
- : "__vector unsigned long long",
- long_long_unsigned_type_node, 2);
+ if (new_builtins_are_live)
+ unsigned_V2DI_type_node
+ = rs6000_vector_type ("__vector unsigned long long",
+ long_long_unsigned_type_node, 2);
+ else
+ {
+ str = TARGET_POWERPC64
+ ? "__vector unsigned long"
+ : "__vector unsigned long long";
+ unsigned_V2DI_type_node
+ = rs6000_vector_type (str, long_long_unsigned_type_node, 2);
+ }
+
ptr_unsigned_V2DI_type_node
= build_pointer_type (build_qualified_type (unsigned_V2DI_type_node,
TYPE_QUAL_CONST));
@@ -13533,32 +14858,29 @@ rs6000_init_builtins (void)
ieee128_float_type_node = ibm128_float_type_node = long_double_type_node;
/* Vector pair and vector quad support. */
- if (TARGET_EXTRA_BUILTINS)
- {
- 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");
- t = build_qualified_type (vector_pair_type_node, TYPE_QUAL_CONST);
- ptr_vector_pair_type_node = build_pointer_type (t);
-
- 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");
- t = build_qualified_type (vector_quad_type_node, TYPE_QUAL_CONST);
- ptr_vector_quad_type_node = build_pointer_type (t);
- }
+ 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");
+ t = build_qualified_type (vector_pair_type_node, TYPE_QUAL_CONST);
+ ptr_vector_pair_type_node = build_pointer_type (t);
+
+ 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");
+ t = build_qualified_type (vector_quad_type_node, TYPE_QUAL_CONST);
+ ptr_vector_quad_type_node = build_pointer_type (t);
/* Initialize the modes for builtin_function_type, mapping a machine mode to
tree type node. */
@@ -13647,6 +14969,17 @@ rs6000_init_builtins (void)
= build_pointer_type (build_qualified_type (void_type_node,
TYPE_QUAL_CONST));
+ /* Execute the autogenerated initialization code for builtins. */
+ rs6000_init_generated_builtins ();
+
+ if (new_builtins_are_live)
+ {
+#ifdef SUBTARGET_INIT_BUILTINS
+ SUBTARGET_INIT_BUILTINS;
+#endif
+ return;
+ }
+
/* Create Altivec, VSX and MMA builtins on machines with at least the
general purpose extensions (970 and newer) to allow the use of
the target attribute. */
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index 6758296..f5812da 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -90,7 +90,8 @@
| OPTION_MASK_P10_FUSION_2LOGICAL \
| OPTION_MASK_P10_FUSION_LOGADD \
| OPTION_MASK_P10_FUSION_ADDLOG \
- | OPTION_MASK_P10_FUSION_2ADD)
+ | OPTION_MASK_P10_FUSION_2ADD \
+ | OPTION_MASK_P10_FUSION_2STORE)
/* Flags that need to be turned off if -mno-power9-vector. */
#define OTHER_P9_VECTOR_MASKS (OPTION_MASK_FLOAT128_HW \
@@ -143,6 +144,7 @@
| OPTION_MASK_P10_FUSION_LOGADD \
| OPTION_MASK_P10_FUSION_ADDLOG \
| OPTION_MASK_P10_FUSION_2ADD \
+ | OPTION_MASK_P10_FUSION_2STORE \
| OPTION_MASK_HTM \
| OPTION_MASK_ISEL \
| OPTION_MASK_MFCRF \
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.c b/gcc/config/rs6000/rs6000-gen-builtins.c
index 000e5f9..7f71121 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.c
+++ b/gcc/config/rs6000/rs6000-gen-builtins.c
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
mma Needs special handling for MMA instructions
quad MMA instruction using a register quad as an input operand
pair MMA instruction using a register pair as an input operand
+ mmaint MMA instruction expanding to internal call at GIMPLE time
no32bit Not valid for TARGET_32BIT
32bit Requires different handling for TARGET_32BIT
cpu This is a "cpu_is" or "cpu_supports" builtin
@@ -369,6 +370,7 @@ struct attrinfo
bool ismma;
bool isquad;
bool ispair;
+ bool ismmaint;
bool isno32bit;
bool is32bit;
bool iscpu;
@@ -1363,6 +1365,8 @@ parse_bif_attrs (attrinfo *attrptr)
attrptr->isquad = 1;
else if (!strcmp (attrname, "pair"))
attrptr->ispair = 1;
+ else if (!strcmp (attrname, "mmaint"))
+ attrptr->ismmaint = 1;
else if (!strcmp (attrname, "no32bit"))
attrptr->isno32bit = 1;
else if (!strcmp (attrname, "32bit"))
@@ -1409,15 +1413,15 @@ parse_bif_attrs (attrinfo *attrptr)
(*diag) ("attribute set: init = %d, set = %d, extract = %d, nosoft = %d, "
"ldvec = %d, stvec = %d, reve = %d, pred = %d, htm = %d, "
"htmspr = %d, htmcr = %d, mma = %d, quad = %d, pair = %d, "
- "no32bit = %d, 32bit = %d, cpu = %d, ldstmask = %d, lxvrse = %d, "
- "lxvrze = %d, endian = %d.\n",
+ "mmaint = %d, no32bit = %d, 32bit = %d, cpu = %d, ldstmask = %d, "
+ "lxvrse = %d, lxvrze = %d, endian = %d.\n",
attrptr->isinit, attrptr->isset, attrptr->isextract,
attrptr->isnosoft, attrptr->isldvec, attrptr->isstvec,
attrptr->isreve, attrptr->ispred, attrptr->ishtm, attrptr->ishtmspr,
attrptr->ishtmcr, attrptr->ismma, attrptr->isquad, attrptr->ispair,
- attrptr->isno32bit, attrptr->is32bit, attrptr->iscpu,
- attrptr->isldstmask, attrptr->islxvrse, attrptr->islxvrze,
- attrptr->isendian);
+ attrptr->ismmaint, attrptr->isno32bit, attrptr->is32bit,
+ attrptr->iscpu, attrptr->isldstmask, attrptr->islxvrse,
+ attrptr->islxvrze, attrptr->isendian);
#endif
return PC_OK;
@@ -2223,13 +2227,14 @@ write_decls (void)
fprintf (header_file, "#define bif_mma_bit\t\t(0x00000800)\n");
fprintf (header_file, "#define bif_quad_bit\t\t(0x00001000)\n");
fprintf (header_file, "#define bif_pair_bit\t\t(0x00002000)\n");
- fprintf (header_file, "#define bif_no32bit_bit\t\t(0x00004000)\n");
- fprintf (header_file, "#define bif_32bit_bit\t\t(0x00008000)\n");
- fprintf (header_file, "#define bif_cpu_bit\t\t(0x00010000)\n");
- fprintf (header_file, "#define bif_ldstmask_bit\t(0x00020000)\n");
- fprintf (header_file, "#define bif_lxvrse_bit\t\t(0x00040000)\n");
- fprintf (header_file, "#define bif_lxvrze_bit\t\t(0x00080000)\n");
- fprintf (header_file, "#define bif_endian_bit\t\t(0x00100000)\n");
+ fprintf (header_file, "#define bif_mmaint_bit\t\t(0x00004000)\n");
+ fprintf (header_file, "#define bif_no32bit_bit\t\t(0x00008000)\n");
+ fprintf (header_file, "#define bif_32bit_bit\t\t(0x00010000)\n");
+ fprintf (header_file, "#define bif_cpu_bit\t\t(0x00020000)\n");
+ fprintf (header_file, "#define bif_ldstmask_bit\t(0x00040000)\n");
+ fprintf (header_file, "#define bif_lxvrse_bit\t\t(0x00080000)\n");
+ fprintf (header_file, "#define bif_lxvrze_bit\t\t(0x00100000)\n");
+ fprintf (header_file, "#define bif_endian_bit\t\t(0x00200000)\n");
fprintf (header_file, "\n");
fprintf (header_file,
"#define bif_is_init(x)\t\t((x).bifattrs & bif_init_bit)\n");
@@ -2260,6 +2265,8 @@ write_decls (void)
fprintf (header_file,
"#define bif_is_pair(x)\t\t((x).bifattrs & bif_pair_bit)\n");
fprintf (header_file,
+ "#define bif_is_mmaint(x)\t\t((x).bifattrs & bif_mmaint_bit)\n");
+ fprintf (header_file,
"#define bif_is_no32bit(x)\t((x).bifattrs & bif_no32bit_bit)\n");
fprintf (header_file,
"#define bif_is_32bit(x)\t((x).bifattrs & bif_32bit_bit)\n");
@@ -2312,9 +2319,9 @@ write_decls (void)
"extern ovlddata rs6000_instance_info[RS6000_INST_MAX];\n");
fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n");
- fprintf (header_file, "extern void rs6000_autoinit_builtins ();\n\n");
+ fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n");
fprintf (header_file,
- "extern bool rs6000_new_builtin_is_supported_p "
+ "extern bool rs6000_new_builtin_is_supported "
"(rs6000_gen_builtins);\n");
fprintf (header_file,
"extern tree rs6000_builtin_decl (unsigned, "
@@ -2491,6 +2498,8 @@ write_bif_static_init (void)
fprintf (init_file, " | bif_quad_bit");
if (bifp->attrs.ispair)
fprintf (init_file, " | bif_pair_bit");
+ if (bifp->attrs.ismmaint)
+ fprintf (init_file, " | bif_mmaint_bit");
if (bifp->attrs.isno32bit)
fprintf (init_file, " | bif_no32bit_bit");
if (bifp->attrs.is32bit)
@@ -2537,10 +2546,9 @@ write_bif_static_init (void)
: (bifp->kind == FNK_PURE ? "= pure"
: (bifp->kind == FNK_FPMATH ? "= fp, const"
: ""))));
- bool no_icode = !strcmp (bifp->patname, "nothing");
fprintf (init_file, " /* assoc_bif */\tRS6000_BIF_%s%s\n",
- bifp->attrs.ismma && no_icode ? bifp->idname : "NONE",
- bifp->attrs.ismma && no_icode ? "_INTERNAL" : "");
+ bifp->attrs.ismmaint ? bifp->idname : "NONE",
+ bifp->attrs.ismmaint ? "_INTERNAL" : "");
fprintf (init_file, " },\n");
}
fprintf (init_file, " };\n\n");
@@ -2794,7 +2802,7 @@ write_init_file (void)
fprintf (init_file, "\n");
fprintf (init_file, "void\n");
- fprintf (init_file, "rs6000_autoinit_builtins ()\n");
+ fprintf (init_file, "rs6000_init_generated_builtins ()\n");
fprintf (init_file, "{\n");
fprintf (init_file, " tree t;\n");
rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init);
diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c
index 07337c4..9965a8a 100644
--- a/gcc/config/rs6000/rs6000-logue.c
+++ b/gcc/config/rs6000/rs6000-logue.c
@@ -3293,10 +3293,13 @@ rs6000_emit_prologue (void)
/* If we need to save CR, put it into r12 or r11. Choose r12 except when
r12 will be needed by out-of-line gpr save. */
- cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && !(strategy & (SAVE_INLINE_GPRS
- | SAVE_NOINLINE_GPRS_SAVES_LR))
- ? 11 : 12);
+ if (DEFAULT_ABI == ABI_AIX
+ && !(strategy & (SAVE_INLINE_GPRS | SAVE_NOINLINE_GPRS_SAVES_LR)))
+ cr_save_regno = 11;
+ else if (DEFAULT_ABI == ABI_ELFv2)
+ cr_save_regno = 11;
+ else
+ cr_save_regno = 12;
if (!WORLD_SAVE_P (info)
&& info->cr_save_p
&& REGNO (frame_reg_rtx) != cr_save_regno
@@ -4812,6 +4815,10 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
else if (REGNO (frame_reg_rtx) == 12)
cr_save_regno = 11;
+ /* For ELFv2 r12 is already in use as the GEP. */
+ if (DEFAULT_ABI == ABI_ELFv2)
+ cr_save_regno = 11;
+
cr_save_reg = load_cr_save (cr_save_regno, frame_reg_rtx,
info->cr_save_offset + frame_off,
exit_func);
diff --git a/gcc/config/rs6000/rs6000-overload.def b/gcc/config/rs6000/rs6000-overload.def
index 141f831..4f58331 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -1154,9 +1154,9 @@
vus __builtin_vec_convert_4f32_8f16 (vf, vf);
CONVERT_4F32_8F16
-[VEC_COPYSIGN, vec_cpsgn, __builtin_vec_copysign]
+[VEC_COPYSIGN, SKIP, __builtin_vec_copysign]
vf __builtin_vec_copysign (vf, vf);
- CPSGNSP
+ COPYSIGN_V4SF
vd __builtin_vec_copysign (vd, vd);
CPSGNDP
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d02c1b6..01a9559 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -78,6 +78,7 @@
#include "case-cfn-macros.h"
#include "ppc-auxv.h"
#include "rs6000-internal.h"
+#include "rs6000-builtins.h"
#include "opts.h"
/* This file should be included last. */
@@ -3391,7 +3392,7 @@ darwin_rs6000_override_options (void)
&& !flag_apple_kext
&& strverscmp (darwin_macosx_version_min, "10.5") >= 0
&& ! (rs6000_isa_flags_explicit & OPTION_MASK_ALTIVEC)
- && ! global_options_set.x_rs6000_cpu_index)
+ && ! OPTION_SET_P (rs6000_cpu_index))
{
rs6000_isa_flags |= OPTION_MASK_ALTIVEC;
}
@@ -3470,18 +3471,18 @@ rs6000_override_options_after_change (void)
{
/* Explicit -funroll-loops turns -munroll-only-small-loops off, and
turns -frename-registers on. */
- if ((global_options_set.x_flag_unroll_loops && flag_unroll_loops)
- || (global_options_set.x_flag_unroll_all_loops
+ if ((OPTION_SET_P (flag_unroll_loops) && flag_unroll_loops)
+ || (OPTION_SET_P (flag_unroll_all_loops)
&& flag_unroll_all_loops))
{
- if (!global_options_set.x_unroll_only_small_loops)
+ if (!OPTION_SET_P (unroll_only_small_loops))
unroll_only_small_loops = 0;
- if (!global_options_set.x_flag_rename_registers)
+ if (!OPTION_SET_P (flag_rename_registers))
flag_rename_registers = 1;
- if (!global_options_set.x_flag_cunroll_grow_size)
+ if (!OPTION_SET_P (flag_cunroll_grow_size))
flag_cunroll_grow_size = 1;
}
- else if (!global_options_set.x_flag_cunroll_grow_size)
+ else if (!OPTION_SET_P (flag_cunroll_grow_size))
flag_cunroll_grow_size = flag_peel_loops || optimize >= 3;
}
@@ -3489,7 +3490,7 @@ rs6000_override_options_after_change (void)
static void
rs6000_linux64_override_options ()
{
- if (!global_options_set.x_rs6000_alignment_flags)
+ if (!OPTION_SET_P (rs6000_alignment_flags))
rs6000_alignment_flags = MASK_ALIGN_NATURAL;
if (rs6000_isa_flags & OPTION_MASK_64BIT)
{
@@ -3525,11 +3526,11 @@ rs6000_linux64_override_options ()
rs6000_isa_flags |= OPTION_MASK_POWERPC64;
error ("%<-m64%> requires a PowerPC64 cpu");
}
- if (!global_options_set.x_rs6000_current_cmodel)
+ if (!OPTION_SET_P (rs6000_current_cmodel))
SET_CMODEL (CMODEL_MEDIUM);
if ((rs6000_isa_flags_explicit & OPTION_MASK_MINIMAL_TOC) != 0)
{
- if (global_options_set.x_rs6000_current_cmodel
+ if (OPTION_SET_P (rs6000_current_cmodel)
&& rs6000_current_cmodel != CMODEL_SMALL)
error ("%<-mcmodel incompatible with other toc options%>");
if (TARGET_MINIMAL_TOC)
@@ -3544,14 +3545,14 @@ rs6000_linux64_override_options ()
}
if (rs6000_current_cmodel != CMODEL_SMALL)
{
- if (!global_options_set.x_TARGET_NO_FP_IN_TOC)
+ if (!OPTION_SET_P (TARGET_NO_FP_IN_TOC))
TARGET_NO_FP_IN_TOC = rs6000_current_cmodel == CMODEL_MEDIUM;
- if (!global_options_set.x_TARGET_NO_SUM_IN_TOC)
+ if (!OPTION_SET_P (TARGET_NO_SUM_IN_TOC))
TARGET_NO_SUM_IN_TOC = 0;
}
if (TARGET_PLTSEQ && DEFAULT_ABI != ABI_ELFv2)
{
- if (global_options_set.x_rs6000_pltseq)
+ if (OPTION_SET_P (rs6000_pltseq))
warning (0, "%qs unsupported for this ABI",
"-mpltseq");
rs6000_pltseq = false;
@@ -3566,7 +3567,7 @@ rs6000_linux64_override_options ()
profile_kernel = 0;
error (INVALID_32BIT, "profile-kernel");
}
- if (global_options_set.x_rs6000_current_cmodel)
+ if (OPTION_SET_P (rs6000_current_cmodel))
{
SET_CMODEL (CMODEL_SMALL);
error (INVALID_32BIT, "cmodel");
@@ -3626,7 +3627,7 @@ glibc_supports_ieee_128bit (void)
includes OPTION_TARGET_CPU_DEFAULT, representing the name of the
default CPU specified at build configure time, TARGET_DEFAULT,
representing the default set of option flags for the default
- target, and global_options_set.x_rs6000_isa_flags, representing
+ target, and OPTION_SET_P (rs6000_isa_flags), representing
which options were requested on the command line.
Upon return from this function:
@@ -3675,13 +3676,13 @@ rs6000_option_override_internal (bool global_init_p)
/* Remember the explicit arguments. */
if (global_init_p)
- rs6000_isa_flags_explicit = global_options_set.x_rs6000_isa_flags;
+ rs6000_isa_flags_explicit = OPTION_SET_P (rs6000_isa_flags);
/* On 64-bit Darwin, power alignment is ABI-incompatible with some C
library functions, so warn about it. The flag may be useful for
performance studies from time to time though, so don't disable it
entirely. */
- if (global_options_set.x_rs6000_alignment_flags
+ if (OPTION_SET_P (rs6000_alignment_flags)
&& rs6000_alignment_flags == MASK_ALIGN_POWER
&& DEFAULT_ABI == ABI_DARWIN
&& TARGET_64BIT)
@@ -3694,20 +3695,20 @@ rs6000_option_override_internal (bool global_init_p)
with enough (>= 32) registers. It is an expensive optimization.
So it is on only for peak performance. */
if (optimize >= 3 && global_init_p
- && !global_options_set.x_flag_ira_loop_pressure)
+ && !OPTION_SET_P (flag_ira_loop_pressure))
flag_ira_loop_pressure = 1;
/* -fsanitize=address needs to turn on -fasynchronous-unwind-tables in order
for tracebacks to be complete but not if any -fasynchronous-unwind-tables
options were already specified. */
if (flag_sanitize & SANITIZE_USER_ADDRESS
- && !global_options_set.x_flag_asynchronous_unwind_tables)
+ && !OPTION_SET_P (flag_asynchronous_unwind_tables))
flag_asynchronous_unwind_tables = 1;
/* -fvariable-expansion-in-unroller is a win for POWER whenever the
loop unroller is active. It is only checked during unrolling, so
we can just set it on by default. */
- if (!global_options_set.x_flag_variable_expansion_in_unroller)
+ if (!OPTION_SET_P (flag_variable_expansion_in_unroller))
flag_variable_expansion_in_unroller = 1;
/* Set the pointer size. */
@@ -3904,7 +3905,7 @@ rs6000_option_override_internal (bool global_init_p)
#ifdef XCOFF_DEBUGGING_INFO
/* For AIX default to 64-bit DWARF. */
- if (!global_options_set.x_dwarf_offset_size)
+ if (!OPTION_SET_P (dwarf_offset_size))
dwarf_offset_size = POINTER_SIZE_UNITS;
#endif
@@ -4128,7 +4129,7 @@ rs6000_option_override_internal (bool global_init_p)
else if (TARGET_ALLOW_MOVMISALIGN && !TARGET_VSX)
{
if (TARGET_ALLOW_MOVMISALIGN > 0
- && global_options_set.x_TARGET_ALLOW_MOVMISALIGN)
+ && OPTION_SET_P (TARGET_ALLOW_MOVMISALIGN))
error ("%qs requires %qs", "-mallow-movmisalign", "-mvsx");
TARGET_ALLOW_MOVMISALIGN = 0;
@@ -4183,7 +4184,7 @@ rs6000_option_override_internal (bool global_init_p)
: FLOAT_PRECISION_TFmode);
/* Set long double size before the IEEE 128-bit tests. */
- if (!global_options_set.x_rs6000_long_double_type_size)
+ if (!OPTION_SET_P (rs6000_long_double_type_size))
{
if (main_target_opt != NULL
&& (main_target_opt->x_rs6000_long_double_type_size
@@ -4196,7 +4197,7 @@ rs6000_option_override_internal (bool global_init_p)
; /* The option value can be seen when cl_target_option_restore is called. */
else if (rs6000_long_double_type_size == 128)
rs6000_long_double_type_size = FLOAT_PRECISION_TFmode;
- else if (global_options_set.x_rs6000_ieeequad)
+ else if (OPTION_SET_P (rs6000_ieeequad))
{
if (global_options.x_rs6000_ieeequad)
error ("%qs requires %qs", "-mabi=ieeelongdouble", "-mlong-double-128");
@@ -4209,7 +4210,7 @@ rs6000_option_override_internal (bool global_init_p)
explicitly redefine TARGET_IEEEQUAD and TARGET_IEEEQUAD_DEFAULT to 0, so
those systems will not pick up this default. Warn if the user changes the
default unless -Wno-psabi. */
- if (!global_options_set.x_rs6000_ieeequad)
+ if (!OPTION_SET_P (rs6000_ieeequad))
rs6000_ieeequad = TARGET_IEEEQUAD_DEFAULT;
else
@@ -4394,7 +4395,7 @@ rs6000_option_override_internal (bool global_init_p)
/* Enable Altivec ABI for AIX -maltivec. */
if (TARGET_XCOFF
&& (TARGET_ALTIVEC || TARGET_VSX)
- && !global_options_set.x_rs6000_altivec_abi)
+ && !OPTION_SET_P (rs6000_altivec_abi))
{
if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
error ("target attribute or pragma changes AltiVec ABI");
@@ -4407,7 +4408,7 @@ rs6000_option_override_internal (bool global_init_p)
be explicitly overridden in either case. */
if (TARGET_ELF)
{
- if (!global_options_set.x_rs6000_altivec_abi
+ if (!OPTION_SET_P (rs6000_altivec_abi)
&& (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX))
{
if (main_target_opt != NULL &&
@@ -4437,7 +4438,7 @@ rs6000_option_override_internal (bool global_init_p)
/* Place FP constants in the constant pool instead of TOC
if section anchors enabled. */
if (flag_section_anchors
- && !global_options_set.x_TARGET_NO_FP_IN_TOC)
+ && !OPTION_SET_P (TARGET_NO_FP_IN_TOC))
TARGET_NO_FP_IN_TOC = 1;
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
@@ -4498,6 +4499,10 @@ rs6000_option_override_internal (bool global_init_p)
&& (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_2ADD) == 0)
rs6000_isa_flags |= OPTION_MASK_P10_FUSION_2ADD;
+ if (TARGET_POWER10
+ && (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_2STORE) == 0)
+ rs6000_isa_flags |= OPTION_MASK_P10_FUSION_2STORE;
+
/* Turn off vector pair/mma options on non-power10 systems. */
else if (!TARGET_POWER10 && TARGET_MMA)
{
@@ -4590,7 +4595,7 @@ rs6000_option_override_internal (bool global_init_p)
}
/* Handle stack protector */
- if (!global_options_set.x_rs6000_stack_protector_guard)
+ if (!OPTION_SET_P (rs6000_stack_protector_guard))
#ifdef TARGET_THREAD_SSP_OFFSET
rs6000_stack_protector_guard = SSP_TLS;
#else
@@ -4602,7 +4607,7 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_stack_protector_guard_reg = TARGET_64BIT ? 13 : 2;
#endif
- if (global_options_set.x_rs6000_stack_protector_guard_offset_str)
+ if (OPTION_SET_P (rs6000_stack_protector_guard_offset_str))
{
char *endp;
const char *str = rs6000_stack_protector_guard_offset_str;
@@ -4621,7 +4626,7 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_stack_protector_guard_offset = offset;
}
- if (global_options_set.x_rs6000_stack_protector_guard_reg_str)
+ if (OPTION_SET_P (rs6000_stack_protector_guard_reg_str))
{
const char *str = rs6000_stack_protector_guard_reg_str;
int reg = decode_reg_name (str);
@@ -4649,7 +4654,7 @@ rs6000_option_override_internal (bool global_init_p)
/* Set aix_struct_return last, after the ABI is determined.
If -maix-struct-return or -msvr4-struct-return was explicitly
used, don't override with the ABI default. */
- if (!global_options_set.x_aix_struct_return)
+ if (!OPTION_SET_P (aix_struct_return))
aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
#if 0
@@ -5258,16 +5263,22 @@ rs6000_preferred_simd_mode (scalar_mode mode)
return word_mode;
}
-typedef struct _rs6000_cost_data
+struct rs6000_cost_data
{
struct loop *loop_info;
unsigned cost[3];
+ /* Total number of vectorized stmts (loop only). */
+ unsigned nstmts;
+ /* Total number of loads (loop only). */
+ unsigned nloads;
+ /* Possible extra penalized cost on vector construction (loop only). */
+ unsigned extra_ctor_cost;
/* For each vectorized loop, this var holds TRUE iff a non-memory vector
instruction is needed by the vectorization. */
bool vect_nonmem;
/* Indicates this is costing for the scalar version of a loop or block. */
bool costing_for_scalar;
-} rs6000_cost_data;
+};
/* Test for likely overcommitment of vector hardware resources. If a
loop iteration is relatively large, and too large a percentage of
@@ -5278,23 +5289,19 @@ typedef struct _rs6000_cost_data
static void
rs6000_density_test (rs6000_cost_data *data)
{
- const int DENSITY_PCT_THRESHOLD = 85;
- const int DENSITY_SIZE_THRESHOLD = 70;
- const int DENSITY_PENALTY = 10;
- struct loop *loop = data->loop_info;
- basic_block *bbs = get_loop_body (loop);
- int nbbs = loop->num_nodes;
- loop_vec_info loop_vinfo = loop_vec_info_for_loop (data->loop_info);
- int vec_cost = data->cost[vect_body], not_vec_cost = 0;
- int i, density_pct;
-
/* This density test only cares about the cost of vector version of the
loop, so immediately return if we are passed costing for the scalar
version (namely computing single scalar iteration cost). */
if (data->costing_for_scalar)
return;
- for (i = 0; i < nbbs; i++)
+ struct loop *loop = data->loop_info;
+ basic_block *bbs = get_loop_body (loop);
+ int nbbs = loop->num_nodes;
+ loop_vec_info loop_vinfo = loop_vec_info_for_loop (data->loop_info);
+ int vec_cost = data->cost[vect_body], not_vec_cost = 0;
+
+ for (int i = 0; i < nbbs; i++)
{
basic_block bb = bbs[i];
gimple_stmt_iterator gsi;
@@ -5314,17 +5321,51 @@ rs6000_density_test (rs6000_cost_data *data)
}
free (bbs);
- density_pct = (vec_cost * 100) / (vec_cost + not_vec_cost);
+ int density_pct = (vec_cost * 100) / (vec_cost + not_vec_cost);
- if (density_pct > DENSITY_PCT_THRESHOLD
- && vec_cost + not_vec_cost > DENSITY_SIZE_THRESHOLD)
+ if (density_pct > rs6000_density_pct_threshold
+ && vec_cost + not_vec_cost > rs6000_density_size_threshold)
{
- data->cost[vect_body] = vec_cost * (100 + DENSITY_PENALTY) / 100;
+ data->cost[vect_body] = vec_cost * (100 + rs6000_density_penalty) / 100;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"density %d%%, cost %d exceeds threshold, penalizing "
- "loop body cost by %d%%", density_pct,
- vec_cost + not_vec_cost, DENSITY_PENALTY);
+ "loop body cost by %u%%\n", density_pct,
+ vec_cost + not_vec_cost, rs6000_density_penalty);
+ }
+
+ /* Check whether we need to penalize the body cost to account
+ for excess strided or elementwise loads. */
+ if (data->extra_ctor_cost > 0)
+ {
+ gcc_assert (data->nloads <= data->nstmts);
+ unsigned int load_pct = (data->nloads * 100) / data->nstmts;
+
+ /* It's likely to be bounded by latency and execution resources
+ from many scalar loads which are strided or elementwise loads
+ into a vector if both conditions below are found:
+ 1. there are many loads, it's easy to result in a long wait
+ for load units;
+ 2. load has a big proportion of all vectorized statements,
+ it's not easy to schedule other statements to spread among
+ the loads.
+ One typical case is the innermost loop of the hotspot of SPEC2017
+ 503.bwaves_r without loop interchange. */
+ if (data->nloads > (unsigned int) rs6000_density_load_num_threshold
+ && load_pct > (unsigned int) rs6000_density_load_pct_threshold)
+ {
+ data->cost[vect_body] += data->extra_ctor_cost;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Found %u loads and "
+ "load pct. %u%% exceed "
+ "the threshold, "
+ "penalizing loop body "
+ "cost by extra cost %u "
+ "for ctor.\n",
+ data->nloads, load_pct,
+ data->extra_ctor_cost);
+ }
}
}
@@ -5333,12 +5374,15 @@ rs6000_density_test (rs6000_cost_data *data)
static void *
rs6000_init_cost (struct loop *loop_info, bool costing_for_scalar)
{
- rs6000_cost_data *data = XNEW (struct _rs6000_cost_data);
+ rs6000_cost_data *data = XNEW (rs6000_cost_data);
data->loop_info = loop_info;
data->cost[vect_prologue] = 0;
data->cost[vect_body] = 0;
data->cost[vect_epilogue] = 0;
data->vect_nonmem = false;
+ data->nstmts = 0;
+ data->nloads = 0;
+ data->extra_ctor_cost = 0;
data->costing_for_scalar = costing_for_scalar;
return data;
}
@@ -5366,6 +5410,70 @@ rs6000_adjust_vect_cost_per_stmt (enum vect_cost_for_stmt kind,
return 0;
}
+/* Helper function for add_stmt_cost. Check each statement cost
+ entry, gather information and update the target_cost fields
+ accordingly. */
+static void
+rs6000_update_target_cost_per_stmt (rs6000_cost_data *data,
+ enum vect_cost_for_stmt kind,
+ struct _stmt_vec_info *stmt_info,
+ enum vect_cost_model_location where,
+ int stmt_cost,
+ unsigned int orig_count)
+{
+
+ /* Check whether we're doing something other than just a copy loop.
+ Not all such loops may be profitably vectorized; see
+ rs6000_finish_cost. */
+ if (kind == vec_to_scalar
+ || kind == vec_perm
+ || kind == vec_promote_demote
+ || kind == vec_construct
+ || kind == scalar_to_vec
+ || (where == vect_body && kind == vector_stmt))
+ data->vect_nonmem = true;
+
+ /* Gather some information when we are costing the vectorized instruction
+ for the statements located in a loop body. */
+ if (!data->costing_for_scalar && data->loop_info && where == vect_body)
+ {
+ data->nstmts += orig_count;
+
+ if (kind == scalar_load || kind == vector_load
+ || kind == unaligned_load || kind == vector_gather_load)
+ data->nloads += orig_count;
+
+ /* Power processors do not currently have instructions for strided
+ and elementwise loads, and instead we must generate multiple
+ scalar loads. This leads to undercounting of the cost. We
+ account for this by scaling the construction cost by the number
+ of elements involved, and saving this as extra cost that we may
+ or may not need to apply. When finalizing the cost of the loop,
+ the extra penalty is applied when the load density heuristics
+ are satisfied. */
+ if (kind == vec_construct && stmt_info
+ && STMT_VINFO_TYPE (stmt_info) == load_vec_info_type
+ && (STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_ELEMENTWISE
+ || STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_STRIDED_SLP))
+ {
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ unsigned int nunits = vect_nunits_for_cost (vectype);
+ unsigned int extra_cost = nunits * stmt_cost;
+ /* As function rs6000_builtin_vectorization_cost shows, we have
+ priced much on V16QI/V8HI vector construction as their units,
+ if we penalize them with nunits * stmt_cost, it can result in
+ an unreliable body cost, eg: for V16QI on Power8, stmt_cost
+ is 20 and nunits is 16, the extra cost is 320 which looks
+ much exaggerated. So let's use one maximum bound for the
+ extra penalized cost for vector construction here. */
+ const unsigned int MAX_PENALIZED_COST_FOR_CTOR = 12;
+ if (extra_cost > MAX_PENALIZED_COST_FOR_CTOR)
+ extra_cost = MAX_PENALIZED_COST_FOR_CTOR;
+ data->extra_ctor_cost += extra_cost;
+ }
+ }
+}
+
/* Implement targetm.vectorize.add_stmt_cost. */
static unsigned
@@ -5385,6 +5493,7 @@ rs6000_add_stmt_cost (class vec_info *vinfo, void *data, int count,
/* Statements in an inner loop relative to the loop being
vectorized are weighted more heavily. The value here is
arbitrary and could potentially be improved with analysis. */
+ unsigned int orig_count = count;
if (where == vect_body && stmt_info
&& stmt_in_inner_loop_p (vinfo, stmt_info))
{
@@ -5396,14 +5505,8 @@ rs6000_add_stmt_cost (class vec_info *vinfo, void *data, int count,
retval = (unsigned) (count * stmt_cost);
cost_data->cost[where] += retval;
- /* Check whether we're doing something other than just a copy loop.
- Not all such loops may be profitably vectorized; see
- rs6000_finish_cost. */
- if ((kind == vec_to_scalar || kind == vec_perm
- || kind == vec_promote_demote || kind == vec_construct
- || kind == scalar_to_vec)
- || (where == vect_body && kind == vector_stmt))
- cost_data->vect_nonmem = true;
+ rs6000_update_target_cost_per_stmt (cost_data, kind, stmt_info, where,
+ stmt_cost, orig_count);
}
return retval;
@@ -5497,6 +5600,255 @@ rs6000_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
return nunroll;
}
+/* Returns a function decl for a vectorized version of the builtin function
+ with builtin function code FN and the result vector type TYPE, or NULL_TREE
+ if it is not available.
+
+ Implement targetm.vectorize.builtin_vectorized_function. */
+
+static tree
+rs6000_new_builtin_vectorized_function (unsigned int fn, tree type_out,
+ tree type_in)
+{
+ machine_mode in_mode, out_mode;
+ int in_n, out_n;
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_new_builtin_vectorized_function (%s, %s, %s)\n",
+ combined_fn_name (combined_fn (fn)),
+ GET_MODE_NAME (TYPE_MODE (type_out)),
+ GET_MODE_NAME (TYPE_MODE (type_in)));
+
+ /* TODO: Should this be gcc_assert? */
+ if (TREE_CODE (type_out) != VECTOR_TYPE
+ || TREE_CODE (type_in) != VECTOR_TYPE)
+ return NULL_TREE;
+
+ out_mode = TYPE_MODE (TREE_TYPE (type_out));
+ out_n = TYPE_VECTOR_SUBPARTS (type_out);
+ in_mode = TYPE_MODE (TREE_TYPE (type_in));
+ in_n = TYPE_VECTOR_SUBPARTS (type_in);
+
+ switch (fn)
+ {
+ CASE_CFN_COPYSIGN:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_CPSGNDP];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_CPSGNSP];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_COPYSIGN_V4SF];
+ break;
+ CASE_CFN_CEIL:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRDPIP];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRSPIP];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VRFIP];
+ break;
+ CASE_CFN_FLOOR:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRDPIM];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRSPIM];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VRFIM];
+ break;
+ CASE_CFN_FMA:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVMADDDP];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVMADDSP];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VMADDFP];
+ break;
+ CASE_CFN_TRUNC:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRDPIZ];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRSPIZ];
+ if (VECTOR_UNIT_ALTIVEC_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VRFIZ];
+ break;
+ CASE_CFN_NEARBYINT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && flag_unsafe_math_optimizations
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRDPI];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && flag_unsafe_math_optimizations
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRSPI];
+ break;
+ CASE_CFN_RINT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && !flag_trapping_math
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRDPIC];
+ if (VECTOR_UNIT_VSX_P (V4SFmode)
+ && !flag_trapping_math
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_XVRSPIC];
+ break;
+ default:
+ break;
+ }
+
+ /* Generate calls to libmass if appropriate. */
+ if (rs6000_veclib_handler)
+ return rs6000_veclib_handler (combined_fn (fn), type_out, type_in);
+
+ return NULL_TREE;
+}
+
+/* Implement targetm.vectorize.builtin_md_vectorized_function. */
+
+static tree
+rs6000_new_builtin_md_vectorized_function (tree fndecl, tree type_out,
+ tree type_in)
+{
+ machine_mode in_mode, out_mode;
+ int in_n, out_n;
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr,
+ "rs6000_new_builtin_md_vectorized_function (%s, %s, %s)\n",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)),
+ GET_MODE_NAME (TYPE_MODE (type_out)),
+ GET_MODE_NAME (TYPE_MODE (type_in)));
+
+ /* TODO: Should this be gcc_assert? */
+ if (TREE_CODE (type_out) != VECTOR_TYPE
+ || TREE_CODE (type_in) != VECTOR_TYPE)
+ return NULL_TREE;
+
+ out_mode = TYPE_MODE (TREE_TYPE (type_out));
+ out_n = TYPE_VECTOR_SUBPARTS (type_out);
+ in_mode = TYPE_MODE (TREE_TYPE (type_in));
+ in_n = TYPE_VECTOR_SUBPARTS (type_in);
+
+ enum rs6000_gen_builtins fn
+ = (enum rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl);
+ switch (fn)
+ {
+ case RS6000_BIF_RSQRTF:
+ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VRSQRTFP];
+ break;
+ case RS6000_BIF_RSQRT:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_RSQRT_2DF];
+ break;
+ case RS6000_BIF_RECIPF:
+ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
+ && out_mode == SFmode && out_n == 4
+ && in_mode == SFmode && in_n == 4)
+ return rs6000_builtin_decls_x[RS6000_BIF_VRECIPFP];
+ break;
+ case RS6000_BIF_RECIP:
+ if (VECTOR_UNIT_VSX_P (V2DFmode)
+ && out_mode == DFmode && out_n == 2
+ && in_mode == DFmode && in_n == 2)
+ return rs6000_builtin_decls_x[RS6000_BIF_RECIP_V2DF];
+ break;
+ default:
+ break;
+ }
+
+ machine_mode in_vmode = TYPE_MODE (type_in);
+ machine_mode out_vmode = TYPE_MODE (type_out);
+
+ /* Power10 supported vectorized built-in functions. */
+ if (TARGET_POWER10
+ && in_vmode == out_vmode
+ && VECTOR_UNIT_ALTIVEC_OR_VSX_P (in_vmode))
+ {
+ machine_mode exp_mode = DImode;
+ machine_mode exp_vmode = V2DImode;
+ enum rs6000_gen_builtins bif;
+ switch (fn)
+ {
+ case RS6000_BIF_DIVWE:
+ case RS6000_BIF_DIVWEU:
+ exp_mode = SImode;
+ exp_vmode = V4SImode;
+ if (fn == RS6000_BIF_DIVWE)
+ bif = RS6000_BIF_VDIVESW;
+ else
+ bif = RS6000_BIF_VDIVEUW;
+ break;
+ case RS6000_BIF_DIVDE:
+ case RS6000_BIF_DIVDEU:
+ if (fn == RS6000_BIF_DIVDE)
+ bif = RS6000_BIF_VDIVESD;
+ else
+ bif = RS6000_BIF_VDIVEUD;
+ break;
+ case RS6000_BIF_CFUGED:
+ bif = RS6000_BIF_VCFUGED;
+ break;
+ case RS6000_BIF_CNTLZDM:
+ bif = RS6000_BIF_VCLZDM;
+ break;
+ case RS6000_BIF_CNTTZDM:
+ bif = RS6000_BIF_VCTZDM;
+ break;
+ case RS6000_BIF_PDEPD:
+ bif = RS6000_BIF_VPDEPD;
+ break;
+ case RS6000_BIF_PEXTD:
+ bif = RS6000_BIF_VPEXTD;
+ break;
+ default:
+ return NULL_TREE;
+ }
+
+ if (in_mode == exp_mode && in_vmode == exp_vmode)
+ return rs6000_builtin_decls_x[bif];
+ }
+
+ return NULL_TREE;
+}
+
/* Handler for the Mathematical Acceleration Subsystem (mass) interface to a
library with vectorized intrinsics. */
@@ -5616,6 +5968,9 @@ rs6000_builtin_vectorized_function (unsigned int fn, tree type_out,
machine_mode in_mode, out_mode;
int in_n, out_n;
+ if (new_builtins_are_live)
+ return rs6000_new_builtin_vectorized_function (fn, type_out, type_in);
+
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_builtin_vectorized_function (%s, %s, %s)\n",
combined_fn_name (combined_fn (fn)),
@@ -5747,6 +6102,10 @@ rs6000_builtin_md_vectorized_function (tree fndecl, tree type_out,
machine_mode in_mode, out_mode;
int in_n, out_n;
+ if (new_builtins_are_live)
+ return rs6000_new_builtin_md_vectorized_function (fndecl, type_out,
+ type_in);
+
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_builtin_md_vectorized_function (%s, %s, %s)\n",
IDENTIFIER_POINTER (DECL_NAME (fndecl)),
@@ -5912,14 +6271,14 @@ rs6000_file_start (void)
start = "";
}
- if (global_options_set.x_rs6000_cpu_index)
+ if (OPTION_SET_P (rs6000_cpu_index))
{
fprintf (file, "%s -mcpu=%s", start,
processor_target_table[rs6000_cpu_index].name);
start = "";
}
- if (global_options_set.x_rs6000_tune_index)
+ if (OPTION_SET_P (rs6000_tune_index))
{
fprintf (file, "%s -mtune=%s", start,
processor_target_table[rs6000_tune_index].name);
@@ -18933,6 +19292,89 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
return cached_can_issue_more;
}
+/* Determine if INSN is a store to memory that can be fused with a similar
+ adjacent store. */
+
+static bool
+is_fusable_store (rtx_insn *insn, rtx *str_mem)
+{
+ /* Insn must be a non-prefixed base+disp form store. */
+ if (is_store_insn (insn, str_mem)
+ && get_attr_prefixed (insn) == PREFIXED_NO
+ && get_attr_update (insn) == UPDATE_NO
+ && get_attr_indexed (insn) == INDEXED_NO)
+ {
+ /* Further restrictions by mode and size. */
+ if (!MEM_SIZE_KNOWN_P (*str_mem))
+ return false;
+
+ machine_mode mode = GET_MODE (*str_mem);
+ HOST_WIDE_INT size = MEM_SIZE (*str_mem);
+
+ if (INTEGRAL_MODE_P (mode))
+ /* Must be word or dword size. */
+ return (size == 4 || size == 8);
+ else if (FLOAT_MODE_P (mode))
+ /* Must be dword size. */
+ return (size == 8);
+ }
+
+ return false;
+}
+
+/* Do Power10 specific reordering of the ready list. */
+
+static int
+power10_sched_reorder (rtx_insn **ready, int lastpos)
+{
+ rtx mem1;
+
+ /* Do store fusion during sched2 only. */
+ if (!reload_completed)
+ return cached_can_issue_more;
+
+ /* If the prior insn finished off a store fusion pair then simply
+ reset the counter and return, nothing more to do. */
+ if (load_store_pendulum != 0)
+ {
+ load_store_pendulum = 0;
+ return cached_can_issue_more;
+ }
+
+ /* Try to pair certain store insns to adjacent memory locations
+ so that the hardware will fuse them to a single operation. */
+ if (TARGET_P10_FUSION && TARGET_P10_FUSION_2STORE
+ && is_fusable_store (last_scheduled_insn, &mem1))
+ {
+
+ /* A fusable store was just scheduled. Scan the ready list for another
+ store that it can fuse with. */
+ int pos = lastpos;
+ while (pos >= 0)
+ {
+ rtx mem2;
+ /* GPR stores can be ascending or descending offsets, FPR/VSR stores
+ must be ascending only. */
+ if (is_fusable_store (ready[pos], &mem2)
+ && ((INTEGRAL_MODE_P (GET_MODE (mem1))
+ && adjacent_mem_locations (mem1, mem2))
+ || (FLOAT_MODE_P (GET_MODE (mem1))
+ && (adjacent_mem_locations (mem1, mem2) == mem1))))
+ {
+ /* Found a fusable store. Move it to the end of the ready list
+ so it is scheduled next. */
+ move_to_end_of_ready (ready, pos, lastpos);
+
+ load_store_pendulum = -1;
+ break;
+ }
+ pos--;
+ }
+ }
+
+ return cached_can_issue_more;
+}
+
/* We are about to begin issuing insns for this clock cycle. */
static int
@@ -18959,6 +19401,10 @@ rs6000_sched_reorder (FILE *dump ATTRIBUTE_UNUSED, int sched_verbose,
if (rs6000_tune == PROCESSOR_POWER6)
load_store_pendulum = 0;
+ /* Do Power10 dependent reordering. */
+ if (rs6000_tune == PROCESSOR_POWER10 && last_scheduled_insn)
+ power10_sched_reorder (ready, n_ready - 1);
+
return rs6000_issue_rate ();
}
@@ -18980,6 +19426,10 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx_insn **ready,
&& recog_memoized (last_scheduled_insn) >= 0)
return power9_sched_reorder2 (ready, *pn_ready - 1);
+ /* Do Power10 dependent reordering. */
+ if (rs6000_tune == PROCESSOR_POWER10 && last_scheduled_insn)
+ return power10_sched_reorder (ready, *pn_ready - 1);
+
return cached_can_issue_more;
}
@@ -20602,7 +21052,7 @@ rs6000_darwin_file_start (void)
if (rs6000_default_cpu != 0 && rs6000_default_cpu[0] != '\0')
cpu_id = rs6000_default_cpu;
- if (global_options_set.x_rs6000_cpu_index)
+ if (OPTION_SET_P (rs6000_cpu_index))
cpu_id = processor_target_table[rs6000_cpu_index].name;
/* Look through the mapping array. Pick the first name that either
@@ -21526,7 +21976,8 @@ rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
if (decl
&& DECL_P (decl)
&& VAR_OR_FUNCTION_DECL_P (decl)
- && symtab_node::get (decl)->alias == 0
+ && (symtab_node::get (decl) == NULL
+ || symtab_node::get (decl)->alias == 0)
&& symname[strlen (symname) - 1] != ']')
{
const char *smclass = NULL;
@@ -21972,7 +22423,7 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
break;
case UNSPEC:
- if (XINT (x, 1) == UNSPEC_MMA_XXSETACCZ)
+ if (XINT (x, 1) == UNSPECV_MMA_XXSETACCZ)
{
*total = 0;
return true;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a84438f..6bec2bd 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -4986,6 +4986,42 @@
[(set_attr "type" "fp")
(set_attr "isa" "*,<Fisa>")])
+(define_expand "fmod<mode>3"
+ [(use (match_operand:SFDF 0 "gpc_reg_operand"))
+ (use (match_operand:SFDF 1 "gpc_reg_operand"))
+ (use (match_operand:SFDF 2 "gpc_reg_operand"))]
+ "TARGET_HARD_FLOAT
+ && TARGET_FPRND
+ && flag_unsafe_math_optimizations"
+{
+ rtx div = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_div<mode>3 (div, operands[1], operands[2]));
+
+ rtx friz = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_btrunc<mode>2 (friz, div));
+
+ emit_insn (gen_nfms<mode>4 (operands[0], operands[2], friz, operands[1]));
+ DONE;
+ })
+
+(define_expand "remainder<mode>3"
+ [(use (match_operand:SFDF 0 "gpc_reg_operand"))
+ (use (match_operand:SFDF 1 "gpc_reg_operand"))
+ (use (match_operand:SFDF 2 "gpc_reg_operand"))]
+ "TARGET_HARD_FLOAT
+ && TARGET_FPRND
+ && flag_unsafe_math_optimizations"
+{
+ rtx div = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_div<mode>3 (div, operands[1], operands[2]));
+
+ rtx frin = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_round<mode>2 (frin, div));
+
+ emit_insn (gen_nfms<mode>4 (operands[0], operands[2], frin, operands[1]));
+ DONE;
+ })
+
(define_insn "*rsqrt<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")]
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 0538db3..9d7878f 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -514,6 +514,10 @@ mpower10-fusion-2add
Target Undocumented Mask(P10_FUSION_2ADD) Var(rs6000_isa_flags)
Fuse dependent pairs of add or vaddudm instructions for better performance on power10.
+mpower10-fusion-2store
+Target Undocumented Mask(P10_FUSION_2STORE) Var(rs6000_isa_flags)
+Fuse certain store operations together for better performance on power10.
+
mcrypto
Target Mask(CRYPTO) Var(rs6000_isa_flags)
Use ISA 2.07 Category:Vector.AES and Category:Vector.SHA2 instructions.
@@ -557,10 +561,6 @@ mpower9-minmax
Target Undocumented Mask(P9_MINMAX) Var(rs6000_isa_flags)
Use the new min/max instructions defined in ISA 3.0.
-mtoc-fusion
-Target Undocumented Mask(TOC_FUSION) Var(rs6000_isa_flags)
-Fuse medium/large code model toc references with the memory instruction.
-
mmodulo
Target Undocumented Mask(MODULO) Var(rs6000_isa_flags)
Generate the integer modulo instructions.
@@ -639,3 +639,41 @@ Enable instructions that guard against return-oriented programming attacks.
mprivileged
Target Var(rs6000_privileged) Init(0)
Generate code that will run in privileged state.
+
+-param=rs6000-density-pct-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_pct_threshold) Init(85) IntegerRange(0, 100) Param
+When costing for loop vectorization, we probably need to penalize the loop body
+cost if the existing cost model may not adequately reflect delays from
+unavailable vector resources. We collect the cost for vectorized statements
+and non-vectorized statements separately, check the proportion of vec_cost to
+total cost of vec_cost and non vec_cost, and penalize only if the proportion
+exceeds the threshold specified by this parameter. The default value is 85.
+
+-param=rs6000-density-size-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_size_threshold) Init(70) IntegerRange(0, 1000) Param
+Like parameter rs6000-density-pct-threshold, we also check the total sum of
+vec_cost and non vec_cost, and penalize only if the sum exceeds the threshold
+specified by this parameter. The default value is 70.
+
+-param=rs6000-density-penalty=
+Target Undocumented Joined UInteger Var(rs6000_density_penalty) Init(10) IntegerRange(0, 1000) Param
+When both heuristics with rs6000-density-pct-threshold and
+rs6000-density-size-threshold are satisfied, we decide to penalize the loop
+body cost by the value which is specified by this parameter. The default
+value is 10.
+
+-param=rs6000-density-load-pct-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_load_pct_threshold) Init(45) IntegerRange(0, 100) Param
+When costing for loop vectorization, we probably need to penalize the loop body
+cost by accounting for excess strided or elementwise loads. We collect the
+numbers for general statements and load statements according to the information
+for statements to be vectorized, check the proportion of load statements, and
+penalize only if the proportion exceeds the threshold specified by this
+parameter. The default value is 45.
+
+-param=rs6000-density-load-num-threshold=
+Target Undocumented Joined UInteger Var(rs6000_density_load_num_threshold) Init(20) IntegerRange(0, 1000) Param
+Like parameter rs6000-density-load-pct-threshold, we also check if the total
+number of load statements exceeds the threshold specified by this parameter,
+and penalize only if it's satisfied. The default value is 20.
+
diff --git a/gcc/config/rs6000/rtems.h b/gcc/config/rs6000/rtems.h
index 872cc28..6184c5f 100644
--- a/gcc/config/rs6000/rtems.h
+++ b/gcc/config/rs6000/rtems.h
@@ -116,14 +116,14 @@
if ((rs6000_isa_flags_explicit \
& OPTION_MASK_MINIMAL_TOC) != 0) \
{ \
- if (global_options_set.x_rs6000_current_cmodel \
+ if (OPTION_SET_P (rs6000_current_cmodel) \
&& rs6000_current_cmodel != CMODEL_SMALL) \
error ("%<-mcmodel%> incompatible with other toc options"); \
SET_CMODEL (CMODEL_SMALL); \
} \
else \
{ \
- if (!global_options_set.x_rs6000_current_cmodel) \
+ if (!OPTION_SET_P (rs6000_current_cmodel)) \
SET_CMODEL (CMODEL_MEDIUM); \
if (rs6000_current_cmodel != CMODEL_SMALL) \
{ \
diff --git a/gcc/config/rs6000/smmintrin.h b/gcc/config/rs6000/smmintrin.h
index 3767a67..90ce03d 100644
--- a/gcc/config/rs6000/smmintrin.h
+++ b/gcc/config/rs6000/smmintrin.h
@@ -203,34 +203,12 @@ _mm_testnzc_si128 (__m128i __A, __m128i __B)
return _mm_testz_si128 (__A, __B) == 0 && _mm_testc_si128 (__A, __B) == 0;
}
-__inline int
-__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
-_mm_test_all_zeros (__m128i __A, __m128i __mask)
-{
- const __v16qu __zero = {0};
- return vec_all_eq (vec_and ((__v16qu) __A, (__v16qu) __mask), __zero);
-}
+#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V))
-__inline int
-__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
-_mm_test_all_ones (__m128i __A)
-{
- const __v16qu __ones = vec_splats ((unsigned char) 0xff);
- return vec_all_eq ((__v16qu) __A, __ones);
-}
+#define _mm_test_all_ones(V) \
+ _mm_testc_si128 ((V), _mm_cmpeq_epi32 ((V), (V)))
-__inline int
-__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
-_mm_test_mix_ones_zeros (__m128i __A, __m128i __mask)
-{
- const __v16qu __zero = {0};
- const __v16qu __Amasked = vec_and ((__v16qu) __A, (__v16qu) __mask);
- const int any_ones = vec_any_ne (__Amasked, __zero);
- const __v16qu __notA = vec_nor ((__v16qu) __A, (__v16qu) __A);
- const __v16qu __notAmasked = vec_and ((__v16qu) __notA, (__v16qu) __mask);
- const int any_zeros = vec_any_ne (__notAmasked, __zero);
- return any_ones * any_zeros;
-}
+#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128 ((M), (V))
__inline __m128d
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
@@ -296,6 +274,225 @@ _mm_floor_ss (__m128 __A, __m128 __B)
return __r;
}
+#ifdef _ARCH_PWR8
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpeq_epi64 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_cmpeq ((__v2di) __X, (__v2di) __Y);
+}
+#endif
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_epi8 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_min ((__v16qi)__X, (__v16qi)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_epu16 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_min ((__v8hu)__X, (__v8hu)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_epi32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_min ((__v4si)__X, (__v4si)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_min_epu32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_min ((__v4su)__X, (__v4su)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_epi8 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_max ((__v16qi)__X, (__v16qi)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_epu16 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_max ((__v8hu)__X, (__v8hu)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_epi32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_max ((__v4si)__X, (__v4si)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_max_epu32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_max ((__v4su)__X, (__v4su)__Y);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mullo_epi32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_mul ((__v4su) __X, (__v4su) __Y);
+}
+
+#ifdef _ARCH_PWR8
+__inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mul_epi32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_mule ((__v4si) __X, (__v4si) __Y);
+}
+#endif
+
+__inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi8_epi16 (__m128i __A)
+{
+ return (__m128i) vec_unpackh ((__v16qi) __A);
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi8_epi32 (__m128i __A)
+{
+ __A = (__m128i) vec_unpackh ((__v16qi) __A);
+ return (__m128i) vec_unpackh ((__v8hi) __A);
+}
+
+#ifdef _ARCH_PWR8
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi8_epi64 (__m128i __A)
+{
+ __A = (__m128i) vec_unpackh ((__v16qi) __A);
+ __A = (__m128i) vec_unpackh ((__v8hi) __A);
+ return (__m128i) vec_unpackh ((__v4si) __A);
+}
+#endif
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi16_epi32 (__m128i __A)
+{
+ return (__m128i) vec_unpackh ((__v8hi) __A);
+}
+
+#ifdef _ARCH_PWR8
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi16_epi64 (__m128i __A)
+{
+ __A = (__m128i) vec_unpackh ((__v8hi) __A);
+ return (__m128i) vec_unpackh ((__v4si) __A);
+}
+#endif
+
+#ifdef _ARCH_PWR8
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepi32_epi64 (__m128i __A)
+{
+ return (__m128i) vec_unpackh ((__v4si) __A);
+}
+#endif
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu8_epi16 (__m128i __A)
+{
+ const __v16qu __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v16qu) __A, __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v16qu) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu8_epi32 (__m128i __A)
+{
+ const __v16qu __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v16qu) __A, __zero);
+ __A = (__m128i) vec_mergeh ((__v8hu) __A, (__v8hu) __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v16qu) __A);
+ __A = (__m128i) vec_mergeh ((__v8hu) __zero, (__v8hu) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu8_epi64 (__m128i __A)
+{
+ const __v16qu __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v16qu) __A, __zero);
+ __A = (__m128i) vec_mergeh ((__v8hu) __A, (__v8hu) __zero);
+ __A = (__m128i) vec_mergeh ((__v4su) __A, (__v4su) __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v16qu) __A);
+ __A = (__m128i) vec_mergeh ((__v8hu) __zero, (__v8hu) __A);
+ __A = (__m128i) vec_mergeh ((__v4su) __zero, (__v4su) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu16_epi32 (__m128i __A)
+{
+ const __v8hu __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v8hu) __A, __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v8hu) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu16_epi64 (__m128i __A)
+{
+ const __v8hu __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v8hu) __A, __zero);
+ __A = (__m128i) vec_mergeh ((__v4su) __A, (__v4su) __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v8hu) __A);
+ __A = (__m128i) vec_mergeh ((__v4su) __zero, (__v4su) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
+extern __inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtepu32_epi64 (__m128i __A)
+{
+ const __v4su __zero = {0};
+#ifdef __LITTLE_ENDIAN__
+ __A = (__m128i) vec_mergeh ((__v4su) __A, __zero);
+#else /* __BIG_ENDIAN__. */
+ __A = (__m128i) vec_mergeh (__zero, (__v4su) __A);
+#endif /* __BIG_ENDIAN__. */
+ return __A;
+}
+
/* Return horizontal packed word minimum and its index in bits [15:0]
and bits [18:16] respectively. */
__inline __m128i
@@ -323,4 +520,20 @@ _mm_minpos_epu16 (__m128i __A)
return __r.__m;
}
+__inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_packus_epi32 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_packsu ((__v4si) __X, (__v4si) __Y);
+}
+
+#ifdef _ARCH_PWR8
+__inline __m128i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpgt_epi64 (__m128i __X, __m128i __Y)
+{
+ return (__m128i) vec_cmpgt ((__v2di) __X, (__v2di) __Y);
+}
+#endif
+
#endif
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 23ff594..96ee552 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -70,7 +70,7 @@
#define SUBTARGET_OVERRIDE_OPTIONS \
do { \
- if (!global_options_set.x_g_switch_value) \
+ if (!OPTION_SET_P (g_switch_value)) \
g_switch_value = SDATA_DEFAULT_SIZE; \
\
if (rs6000_abi_name == NULL) \
@@ -197,16 +197,16 @@ do { \
} \
\
if (TARGET_PLTSEQ != rs6000_pltseq \
- && global_options_set.x_rs6000_pltseq) \
+ && OPTION_SET_P (rs6000_pltseq)) \
{ \
error ("%qs not supported by your assembler", "-mpltseq"); \
} \
\
if (DEFAULT_ABI == ABI_V4 && TARGET_PLTSEQ && !TARGET_SECURE_PLT) \
{ \
- if (global_options_set.x_rs6000_pltseq) \
+ if (OPTION_SET_P (rs6000_pltseq)) \
{ \
- if (global_options_set.x_secure_plt) \
+ if (OPTION_SET_P (secure_plt)) \
error ("%qs and %qs are incompatible", \
"-mpltseq", "-mbss-plt"); \
else \
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 92766d8..d48a4b1 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -44,15 +44,11 @@ rs6000-logue.o: $(srcdir)/config/rs6000/rs6000-logue.c
$(COMPILE) $<
$(POSTCOMPILE)
-rs6000-gen-builtins.o: $(srcdir)/config/rs6000/rs6000-gen-builtins.c
- $(COMPILE) $<
- $(POSTCOMPILE)
-
-rbtree.o: $(srcdir)/config/rs6000/rbtree.c
- $(COMPILE) $<
- $(POSTCOMPILE)
+build/rs6000-gen-builtins.o: $(srcdir)/config/rs6000/rs6000-gen-builtins.c
+build/rbtree.o: $(srcdir)/config/rs6000/rbtree.c
-rs6000-gen-builtins: rs6000-gen-builtins.o rbtree.o
+build/rs6000-gen-builtins$(build_exeext): build/rs6000-gen-builtins.o \
+ build/rbtree.o $(BUILD_LIBDEPS)
$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
$(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
@@ -62,10 +58,11 @@ rs6000-gen-builtins: rs6000-gen-builtins.o rbtree.o
# <recipe>
# For now, the header files depend on rs6000-builtins.c, which avoids
# races because the .c file is closed last in rs6000-gen-builtins.c.
-rs6000-builtins.c: rs6000-gen-builtins \
+rs6000-builtins.c: build/rs6000-gen-builtins$(build_exeext) \
$(srcdir)/config/rs6000/rs6000-builtin-new.def \
$(srcdir)/config/rs6000/rs6000-overload.def
- ./rs6000-gen-builtins $(srcdir)/config/rs6000/rs6000-builtin-new.def \
+ $(RUN_GEN) ./build/rs6000-gen-builtins$(build_exeext) \
+ $(srcdir)/config/rs6000/rs6000-builtin-new.def \
$(srcdir)/config/rs6000/rs6000-overload.def rs6000-builtins.h \
rs6000-builtins.c rs6000-vecdefines.h
diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h
index 5facbbb..ca21a3a 100644
--- a/gcc/config/rs6000/vxworks.h
+++ b/gcc/config/rs6000/vxworks.h
@@ -147,10 +147,6 @@ along with GCC; see the file COPYING3. If not see
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE,LABELNO) VXWORKS_FUNCTION_PROFILER(FILE,LABELNO)
-/* Initialize library function table. */
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS rs6000_vxworks_init_libfuncs
-
/* Nor sdata, for kernel mode. We use this in
SUBSUBTARGET_INITIALIZE_OPTIONS, after rs6000_rtp has been initialized. */
#undef SDATA_DEFAULT_SIZE
@@ -159,7 +155,7 @@ along with GCC; see the file COPYING3. If not see
#undef SUB3TARGET_OVERRIDE_OPTIONS
#define SUB3TARGET_OVERRIDE_OPTIONS \
do { \
- if (!global_options_set.x_g_switch_value) \
+ if (!OPTION_SET_P (g_switch_value)) \
g_switch_value = SDATA_DEFAULT_SIZE; \
VXWORKS_OVERRIDE_OPTIONS; \
} while (0)
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index 4078440..3cb411d 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -620,14 +620,8 @@ typedef unsigned int CUMULATIVE_ARGS;
/* Like REG_P except that this macro is true for SET expressions. */
#define SET_P(rtl) (GET_CODE (rtl) == SET)
-/* The AS100 assembler does not support .leb128 and .uleb128, but
- the compiler-build-time configure tests will have enabled their
- use because GAS supports them. So default to generating STABS
- debug information instead of DWARF2 when generating AS100
- compatible output. */
#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE (TARGET_AS100_SYNTAX \
- ? DBX_DEBUG : DWARF2_DEBUG)
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
#define DBX_DEBUGGING_INFO 1
#define DWARF2_DEBUGGING_INFO 1
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 4b03c6e..c161635 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -66,6 +66,8 @@ s390_asm_declare_function_size (FILE *asm_out_file,
const char *fnname ATTRIBUTE_UNUSED, tree decl);
#endif
+extern void s390_rawmemchr (machine_mode elt_mode, rtx dst, rtx src, rtx pat);
+
#ifdef RTX_CODE
extern int s390_extra_constraint_str (rtx, int, const char *);
extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 673a134..85dd78c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6414,6 +6414,15 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
if (bitsize + bitpos > GET_MODE_BITSIZE (mode))
return false;
+ /* Just a move. */
+ if (bitpos == 0
+ && bitsize == GET_MODE_BITSIZE (GET_MODE (src))
+ && mode == GET_MODE (src))
+ {
+ emit_move_insn (dest, src);
+ return true;
+ }
+
/* Generate INSERT IMMEDIATE (IILL et al). */
/* (set (ze (reg)) (const_int)). */
if (TARGET_ZARCH
@@ -6510,6 +6519,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
&& (bitpos & 32) == ((bitpos + bitsize - 1) & 32)
&& MEM_P (src)
&& (mode == DImode || mode == SImode)
+ && mode != smode
&& register_operand (dest, mode))
{
/* Emit a strict_low_part pattern if possible. */
@@ -15736,9 +15746,9 @@ s390_option_override (void)
{
/* Don't emit DWARF3/4 unless specifically selected. The TPF
debuggers do not yet support DWARF 3/4. */
- if (!global_options_set.x_dwarf_strict)
+ if (!OPTION_SET_P (dwarf_strict))
dwarf_strict = 1;
- if (!global_options_set.x_dwarf_version)
+ if (!OPTION_SET_P (dwarf_version))
dwarf_version = 2;
}
}
@@ -16549,6 +16559,9 @@ s390_excess_precision (enum excess_precision_type type)
ensure consistency with the implementation in glibc, report that
float is evaluated to the range and precision of double. */
return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
+ case EXCESS_PRECISION_TYPE_FLOAT16:
+ error ("%<-fexcess-precision=16%> is not supported on this target");
+ break;
default:
gcc_unreachable ();
}
@@ -16556,6 +16569,75 @@ s390_excess_precision (enum excess_precision_type type)
}
#endif
+void
+s390_rawmemchr (machine_mode elt_mode, rtx dst, rtx src, rtx pat)
+{
+ machine_mode vec_mode = mode_for_vector (as_a <scalar_int_mode> (elt_mode),
+ 16 / GET_MODE_SIZE (elt_mode)).require();
+ rtx lens = gen_reg_rtx (V16QImode);
+ rtx pattern = gen_reg_rtx (vec_mode);
+ rtx loop_start = gen_label_rtx ();
+ rtx loop_end = gen_label_rtx ();
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx offset = gen_reg_rtx (Pmode);
+ rtx loadlen = gen_reg_rtx (SImode);
+ rtx matchlen = gen_reg_rtx (SImode);
+ rtx mem;
+
+ pat = GEN_INT (trunc_int_for_mode (INTVAL (pat), elt_mode));
+ emit_insn (gen_rtx_SET (pattern, gen_rtx_VEC_DUPLICATE (vec_mode, pat)));
+
+ emit_move_insn (addr, XEXP (src, 0));
+
+ // alignment
+ emit_insn (gen_vlbb (lens, gen_rtx_MEM (BLKmode, addr), GEN_INT (6)));
+ emit_insn (gen_lcbb (loadlen, addr, GEN_INT (6)));
+ lens = convert_to_mode (vec_mode, lens, 1);
+ emit_insn (gen_vec_vfees (vec_mode, lens, lens, pattern, GEN_INT (0)));
+ lens = convert_to_mode (V4SImode, lens, 1);
+ emit_insn (gen_vec_extractv4sisi (matchlen, lens, GEN_INT (1)));
+ lens = convert_to_mode (vec_mode, lens, 1);
+ emit_cmp_and_jump_insns (matchlen, loadlen, LT, NULL_RTX, SImode, 1, loop_end);
+ force_expand_binop (Pmode, add_optab, addr, GEN_INT(16), addr, 1, OPTAB_DIRECT);
+ force_expand_binop (Pmode, and_optab, addr, GEN_INT(~HOST_WIDE_INT_UC(0xf)), addr, 1, OPTAB_DIRECT);
+ // now, addr is 16-byte aligned
+
+ mem = gen_rtx_MEM (vec_mode, addr);
+ set_mem_align (mem, 128);
+ emit_move_insn (lens, mem);
+ emit_insn (gen_vec_vfees (vec_mode, lens, lens, pattern, GEN_INT (VSTRING_FLAG_CS)));
+ add_int_reg_note (s390_emit_ccraw_jump (4, EQ, loop_end),
+ REG_BR_PROB,
+ profile_probability::very_unlikely ().to_reg_br_prob_note ());
+
+ emit_label (loop_start);
+ LABEL_NUSES (loop_start) = 1;
+
+ force_expand_binop (Pmode, add_optab, addr, GEN_INT (16), addr, 1, OPTAB_DIRECT);
+ mem = gen_rtx_MEM (vec_mode, addr);
+ set_mem_align (mem, 128);
+ emit_move_insn (lens, mem);
+ emit_insn (gen_vec_vfees (vec_mode, lens, lens, pattern, GEN_INT (VSTRING_FLAG_CS)));
+ add_int_reg_note (s390_emit_ccraw_jump (4, NE, loop_start),
+ REG_BR_PROB,
+ profile_probability::very_likely ().to_reg_br_prob_note ());
+
+ emit_label (loop_end);
+ LABEL_NUSES (loop_end) = 1;
+
+ if (TARGET_64BIT)
+ {
+ lens = convert_to_mode (V2DImode, lens, 1);
+ emit_insn (gen_vec_extractv2didi (offset, lens, GEN_INT (0)));
+ }
+ else
+ {
+ lens = convert_to_mode (V4SImode, lens, 1);
+ emit_insn (gen_vec_extractv4sisi (offset, lens, GEN_INT (1)));
+ }
+ force_expand_binop (Pmode, add_optab, addr, offset, dst, 1, OPTAB_DIRECT);
+}
+
/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */
static unsigned HOST_WIDE_INT
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 1b894a9..b8bdbae 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -12258,3 +12258,10 @@
UNSPECV_PPA)]
"TARGET_ZEC12"
"")
+
+(define_expand "rawmemchr<SINT:mode>"
+ [(match_operand 0 "register_operand")
+ (match_operand 1 "memory_operand")
+ (match_operand:SINT 2 "const_int_operand")]
+ "TARGET_VX"
+ "s390_rawmemchr(<SINT:MODE>mode, operands[0], operands[1], operands[2]); DONE;")
diff --git a/gcc/config/s390/tpf.md b/gcc/config/s390/tpf.md
index 297e9d1..35b3719 100644
--- a/gcc/config/s390/tpf.md
+++ b/gcc/config/s390/tpf.md
@@ -21,7 +21,8 @@
[(unspec_volatile [(match_operand 0 "const_int_operand" "J")
(match_operand 1 "const_int_operand" "J")]
UNSPECV_TPF_PROLOGUE)
- (clobber (reg:DI 1))]
+ (clobber (reg:DI 1))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_TPF_PROFILING"
"larl\t%%r1,.+14\;tm\t%0,255\;bnz\t%1"
[(set_attr "length" "14")])
@@ -31,7 +32,8 @@
[(unspec_volatile [(match_operand 0 "const_int_operand" "J")
(match_operand 1 "const_int_operand" "J")]
UNSPECV_TPF_EPILOGUE)
- (clobber (reg:DI 1))]
+ (clobber (reg:DI 1))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_TPF_PROFILING"
"larl\t%%r1,.+14\;tm\t%0,255\;bnz\t%1"
[(set_attr "length" "14")])
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 70274a6..1ed1d06 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1988,6 +1988,32 @@
"vll\t%v0,%1,%2"
[(set_attr "op_type" "VRS")])
+; vfeebs, vfeehs, vfeefs
+; vfeezbs, vfeezhs, vfeezfs
+(define_insn "@vec_vfees<mode>"
+ [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
+ (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
+ (match_operand:VI_HW_QHS 2 "register_operand" "v")
+ (match_operand:QI 3 "const_mask_operand" "C")]
+ UNSPEC_VEC_VFEE))
+ (set (reg:CCRAW CC_REGNUM)
+ (unspec:CCRAW [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_VEC_VFEECC))]
+ "TARGET_VX"
+{
+ unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
+
+ gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
+ flags &= ~VSTRING_FLAG_CS;
+
+ if (flags == VSTRING_FLAG_ZS)
+ return "vfeez<bhfgq>s\t%v0,%v1,%v2";
+ return "vfee<bhfgq>s\t%v0,%v1,%v2";
+}
+ [(set_attr "op_type" "VRR")])
+
; vfenebs, vfenehs, vfenefs
; vfenezbs, vfenezhs, vfenezfs
(define_insn "vec_vfenes<mode>"
diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index 3e7b854..efa7799 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -1366,32 +1366,6 @@
; Vector find element equal
-; vfeebs, vfeehs, vfeefs
-; vfeezbs, vfeezhs, vfeezfs
-(define_insn "*vfees<mode>"
- [(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
- (unspec:VI_HW_QHS [(match_operand:VI_HW_QHS 1 "register_operand" "v")
- (match_operand:VI_HW_QHS 2 "register_operand" "v")
- (match_operand:QI 3 "const_mask_operand" "C")]
- UNSPEC_VEC_VFEE))
- (set (reg:CCRAW CC_REGNUM)
- (unspec:CCRAW [(match_dup 1)
- (match_dup 2)
- (match_dup 3)]
- UNSPEC_VEC_VFEECC))]
- "TARGET_VX"
-{
- unsigned HOST_WIDE_INT flags = UINTVAL (operands[3]);
-
- gcc_assert (!(flags & ~(VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
- flags &= ~VSTRING_FLAG_CS;
-
- if (flags == VSTRING_FLAG_ZS)
- return "vfeez<bhfgq>s\t%v0,%v1,%v2";
- return "vfee<bhfgq>s\t%v0,%v1,%v2,%b3";
-}
- [(set_attr "op_type" "VRR")])
-
; vfeeb, vfeeh, vfeef
(define_insn "vfee<mode>"
[(set (match_operand:VI_HW_QHS 0 "register_operand" "=v")
diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h
index 7558d2f..b75a7b8 100644
--- a/gcc/config/sh/linux.h
+++ b/gcc/config/sh/linux.h
@@ -126,7 +126,7 @@ along with GCC; see the file COPYING3. If not see
do \
{ \
/* Set default atomic model if it hasn't been specified. */ \
- if (global_options_set.x_sh_atomic_model_str == 0) \
+ if (OPTION_SET_P (sh_atomic_model_str) == 0) \
{ \
if (TARGET_SH3) \
sh_atomic_model_str = "soft-gusa"; \
@@ -134,7 +134,7 @@ along with GCC; see the file COPYING3. If not see
sh_atomic_model_str = "soft-imask"; \
} \
/* Set -musermode if it hasn't been specified. */ \
- if (global_options_set.x_TARGET_USERMODE == 0) \
+ if (OPTION_SET_P (TARGET_USERMODE) == 0) \
TARGET_USERMODE = true; \
} \
while (0)
diff --git a/gcc/config/sh/netbsd-elf.h b/gcc/config/sh/netbsd-elf.h
index f0b7541..39eb773 100644
--- a/gcc/config/sh/netbsd-elf.h
+++ b/gcc/config/sh/netbsd-elf.h
@@ -85,7 +85,7 @@ while (0)
do \
{ \
/* Set -musermode if it hasn't been specified. */ \
- if (global_options_set.x_TARGET_USERMODE == 0) \
+ if (OPTION_SET_P (TARGET_USERMODE) == 0) \
TARGET_USERMODE = true; \
} \
while (0)
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 1564109..0628f05 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -893,7 +893,7 @@ sh_option_override (void)
}
/* Set -mzdcbranch for SH4 / SH4A if not otherwise specified by the user. */
- if (! global_options_set.x_TARGET_ZDCBRANCH && TARGET_HARD_SH4)
+ if (! OPTION_SET_P (TARGET_ZDCBRANCH) && TARGET_HARD_SH4)
TARGET_ZDCBRANCH = 1;
/* FDPIC code is a special form of PIC, and the vast majority of code
@@ -932,13 +932,13 @@ sh_option_override (void)
<http://gcc.gnu.org/ml/gcc-patches/2005-10/msg00816.html>. */
else if (flag_exceptions)
{
- if (flag_schedule_insns && global_options_set.x_flag_schedule_insns)
+ if (flag_schedule_insns && OPTION_SET_P (flag_schedule_insns))
warning (0, "ignoring %<-fschedule-insns%> because of exception "
"handling bug");
flag_schedule_insns = 0;
}
else if (flag_schedule_insns
- && !global_options_set.x_flag_schedule_insns)
+ && !OPTION_SET_P (flag_schedule_insns))
flag_schedule_insns = 0;
}
@@ -958,12 +958,12 @@ sh_option_override (void)
if (flag_unsafe_math_optimizations)
{
/* Enable fsca insn for SH4A if not otherwise specified by the user. */
- if (global_options_set.x_TARGET_FSCA == 0
+ if (OPTION_SET_P (TARGET_FSCA) == 0
&& (TARGET_SH4A_FP || TARGET_FPU_SH4_300))
TARGET_FSCA = 1;
/* Enable fsrra insn for SH4A if not otherwise specified by the user. */
- if (global_options_set.x_TARGET_FSRRA == 0
+ if (OPTION_SET_P (TARGET_FSRRA) == 0
&& (TARGET_SH4A_FP || TARGET_FPU_SH4_300))
TARGET_FSRRA = 1;
}
@@ -976,7 +976,7 @@ sh_option_override (void)
/* If the -mieee option was not explicitly set by the user, turn it on
unless -ffinite-math-only was specified. See also PR 33135. */
- if (! global_options_set.x_TARGET_IEEE)
+ if (! OPTION_SET_P (TARGET_IEEE))
TARGET_IEEE = ! flag_finite_math_only;
if (sh_fixed_range_str)
diff --git a/gcc/config/sol2.c b/gcc/config/sol2.c
index 1fbdbf5..517816a 100644
--- a/gcc/config/sol2.c
+++ b/gcc/config/sol2.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "varasm.h"
#include "output.h"
+#include "opts.h"
tree solaris_pending_aligns, solaris_pending_inits, solaris_pending_finis;
@@ -296,6 +297,6 @@ solaris_override_options (void)
{
/* Older versions of Solaris ld cannot handle CIE version 3 in .eh_frame.
Don't emit DWARF3/4 unless specifically selected if so. */
- if (!HAVE_LD_EH_FRAME_CIEV3 && !global_options_set.x_dwarf_version)
+ if (!HAVE_LD_EH_FRAME_CIEV3 && !OPTION_SET_P (dwarf_version))
dwarf_version = 2;
}
diff --git a/gcc/config/sparc/leon5.md b/gcc/config/sparc/leon5.md
new file mode 100644
index 0000000..6a065b1
--- /dev/null
+++ b/gcc/config/sparc/leon5.md
@@ -0,0 +1,103 @@
+;; Scheduling description for LEON5.
+;; Copyright (C) 2021 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/>.
+
+
+;; The LEON5 can often dual issue instructions from the same 64-bit aligned
+;; double word if there are no data dependencies.
+;;
+;; Avoid scheduling load/store, FPU, and multiply instructions back to
+;; back, regardless of data dependencies.
+;;
+;; Push comparisons away from the associated branch instruction.
+;;
+;; Avoid scheduling ALU instructions with data dependencies back to back.
+;;
+;; Schedule three instructions between load and dependent instruction.
+
+(define_automaton "leon5")
+
+(define_cpu_unit "leon5_memory" "leon5")
+(define_cpu_unit "leon5_mul" "leon5")
+(define_cpu_unit "grfpu_d" "grfpu")
+(define_cpu_unit "grfpu_s" "grfpu")
+
+(define_insn_reservation "leon5_load" 4
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "load,sload"))
+ "leon5_memory * 2, nothing * 2")
+
+(define_insn_reservation "leon5_fpload" 2
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpload"))
+ "leon5_memory * 2 + grfpu_alu * 2")
+
+(define_insn_reservation "leon5_store" 2
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "store"))
+ "leon5_memory * 2")
+
+(define_insn_reservation "leon5_fpstore" 2
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpstore"))
+ "leon5_memory * 2 + grfpu_alu * 2")
+
+(define_insn_reservation "leon5_ialu" 2
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "ialu, shift, ialuX"))
+ "nothing * 2")
+
+(define_insn_reservation "leon5_compare" 5
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "compare"))
+ "nothing * 5")
+
+(define_insn_reservation "leon5_imul" 4
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "imul"))
+ "leon5_mul * 2, nothing * 2")
+
+(define_insn_reservation "leon5_idiv" 35
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "imul"))
+ "nothing * 35")
+
+(define_insn_reservation "leon5_fp_alu" 5
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fp,fpcmp,fpmul,fpmove"))
+ "grfpu_alu * 2, nothing*3")
+
+(define_insn_reservation "leon5_fp_divs" 17
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpdivs"))
+ "grfpu_alu * 2 + grfpu_d*16, nothing")
+
+(define_insn_reservation "leon5_fp_divd" 18
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpdivd"))
+ "grfpu_alu * 2 + grfpu_d*17, nothing")
+
+(define_insn_reservation "leon5_fp_sqrts" 25
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpsqrts"))
+ "grfpu_alu * 2 + grfpu_s*24, nothing")
+
+(define_insn_reservation "leon5_fp_sqrtd" 26
+ (and (eq_attr "cpu" "leon5")
+ (eq_attr "type" "fpsqrtd"))
+ "grfpu_alu * 2 + grfpu_s*25, nothing")
diff --git a/gcc/config/sparc/sparc-modes.def b/gcc/config/sparc/sparc-modes.def
index 5cc4743..057c093 100644
--- a/gcc/config/sparc/sparc-modes.def
+++ b/gcc/config/sparc/sparc-modes.def
@@ -23,6 +23,9 @@ along with GCC; see the file COPYING3. If not see
/* 128-bit floating point */
FLOAT_MODE (TF, 16, ieee_quad_format);
+/* We need a 32-byte mode to return structures in the 64-bit ABI. */
+INT_MODE (OI, 32);
+
/* Add any extra modes needed to represent the condition code.
We have a CCNZ mode which is used for implicit comparisons with zero when
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
index 1af556e..9299cf6 100644
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -31,6 +31,7 @@ enum sparc_processor_type {
PROCESSOR_HYPERSPARC,
PROCESSOR_LEON,
PROCESSOR_LEON3,
+ PROCESSOR_LEON5,
PROCESSOR_LEON3V7,
PROCESSOR_SPARCLITE,
PROCESSOR_F930,
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 06f41d7..ca91be4 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -270,6 +270,31 @@ struct processor_costs leon3_costs = {
};
static const
+struct processor_costs leon5_costs = {
+ COSTS_N_INSNS (1), /* int load */
+ COSTS_N_INSNS (1), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (1), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (1), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (1), /* fmul */
+ COSTS_N_INSNS (17), /* fdivs */
+ COSTS_N_INSNS (18), /* fdivd */
+ COSTS_N_INSNS (25), /* fsqrts */
+ COSTS_N_INSNS (26), /* fsqrtd */
+ COSTS_N_INSNS (4), /* imul */
+ COSTS_N_INSNS (4), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (35), /* idiv */
+ COSTS_N_INSNS (35), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+ 3 /* branch cost */
+};
+
+static const
struct processor_costs sparclet_costs = {
COSTS_N_INSNS (3), /* int load */
COSTS_N_INSNS (3), /* int signed load */
@@ -575,6 +600,7 @@ static int function_arg_slotno (const CUMULATIVE_ARGS *, machine_mode,
static int supersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
static int hypersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
+static int leon5_adjust_cost (rtx_insn *, int, rtx_insn *, int);
static void sparc_emit_set_const32 (rtx, rtx);
static void sparc_emit_set_const64 (rtx, rtx);
@@ -1045,6 +1071,43 @@ atomic_insn_for_leon3_p (rtx_insn *insn)
}
}
+/* True if INSN is a store instruction. */
+
+static bool
+store_insn_p (rtx_insn *insn)
+{
+ if (GET_CODE (PATTERN (insn)) != SET)
+ return false;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_STORE:
+ case TYPE_FPSTORE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* True if INSN is a load instruction. */
+
+static bool
+load_insn_p (rtx_insn *insn)
+{
+ if (GET_CODE (PATTERN (insn)) != SET)
+ return false;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_LOAD:
+ case TYPE_SLOAD:
+ case TYPE_FPLOAD:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* We use a machine specific pass to enable workarounds for errata.
We need to have the (essentially) final form of the insn stream in order
@@ -1057,10 +1120,29 @@ atomic_insn_for_leon3_p (rtx_insn *insn)
&& GET_CODE (PATTERN (INSN)) != USE \
&& GET_CODE (PATTERN (INSN)) != CLOBBER)
+rtx_insn *
+next_active_non_empty_insn (rtx_insn *insn)
+{
+ insn = next_active_insn (insn);
+
+ while (insn
+ && (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+ || GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || (USEFUL_INSN_P (insn)
+ && (asm_noperands (PATTERN (insn)) >= 0)
+ && !strcmp (decode_asm_operands (PATTERN (insn),
+ NULL, NULL, NULL,
+ NULL, NULL), ""))))
+ insn = next_active_insn (insn);
+
+ return insn;
+}
+
static unsigned int
sparc_do_work_around_errata (void)
{
rtx_insn *insn, *next;
+ bool find_first_useful = true;
/* Force all instructions to be split into their final form. */
split_all_insns_noflow ();
@@ -1085,6 +1167,16 @@ sparc_do_work_around_errata (void)
else
jump = NULL;
+ /* Do not begin function with atomic instruction. */
+ if (sparc_fix_ut700
+ && find_first_useful
+ && USEFUL_INSN_P (insn))
+ {
+ find_first_useful = false;
+ if (atomic_insn_for_leon3_p (insn))
+ emit_insn_before (gen_nop (), insn);
+ }
+
/* Place a NOP at the branch target of an integer branch if it is a
floating-point operation or a floating-point branch. */
if (sparc_fix_gr712rc
@@ -1105,9 +1197,7 @@ sparc_do_work_around_errata (void)
instruction at branch target. */
if (sparc_fix_ut700
&& NONJUMP_INSN_P (insn)
- && (set = single_set (insn)) != NULL_RTX
- && mem_ref (SET_SRC (set))
- && REG_P (SET_DEST (set)))
+ && load_insn_p (insn))
{
if (jump && jump_to_label_p (jump))
{
@@ -1116,7 +1206,7 @@ sparc_do_work_around_errata (void)
emit_insn_before (gen_nop (), target);
}
- next = next_active_insn (insn);
+ next = next_active_non_empty_insn (insn);
if (!next)
break;
@@ -1212,30 +1302,19 @@ sparc_do_work_around_errata (void)
if (sparc_fix_b2bst
&& NONJUMP_INSN_P (insn)
&& (set = single_set (insn)) != NULL_RTX
- && MEM_P (SET_DEST (set)))
+ && store_insn_p (insn))
{
/* Sequence B begins with a double-word store. */
bool seq_b = GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8;
rtx_insn *after;
int i;
- next = next_active_insn (insn);
+ next = next_active_non_empty_insn (insn);
if (!next)
break;
for (after = next, i = 0; i < 2; i++)
{
- /* Skip empty assembly statements. */
- if ((GET_CODE (PATTERN (after)) == UNSPEC_VOLATILE)
- || (USEFUL_INSN_P (after)
- && (asm_noperands (PATTERN (after))>=0)
- && !strcmp (decode_asm_operands (PATTERN (after),
- NULL, NULL, NULL,
- NULL, NULL), "")))
- after = next_active_insn (after);
- if (!after)
- break;
-
/* If the insn is a branch, then it cannot be problematic. */
if (!NONJUMP_INSN_P (after)
|| GET_CODE (PATTERN (after)) == SEQUENCE)
@@ -1245,8 +1324,7 @@ sparc_do_work_around_errata (void)
if (seq_b)
{
/* Add NOP if followed by a store. */
- if ((set = single_set (after)) != NULL_RTX
- && MEM_P (SET_DEST (set)))
+ if (store_insn_p (after))
insert_nop = true;
/* Otherwise it is ok. */
@@ -1261,15 +1339,14 @@ sparc_do_work_around_errata (void)
&& (MEM_P (SET_DEST (set)) || mem_ref (SET_SRC (set))))
break;
- after = next_active_insn (after);
+ after = next_active_non_empty_insn (after);
if (!after)
break;
}
/* Add NOP if third instruction is a store. */
if (i == 1
- && (set = single_set (after)) != NULL_RTX
- && MEM_P (SET_DEST (set)))
+ && store_insn_p (after))
insert_nop = true;
}
}
@@ -1596,6 +1673,10 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "CBCOND ");
if (flags & MASK_DEPRECATED_V8_INSNS)
fprintf (stderr, "DEPRECATED_V8_INSNS ");
+ if (flags & MASK_LEON)
+ fprintf (stderr, "LEON ");
+ if (flags & MASK_LEON3)
+ fprintf (stderr, "LEON3 ");
if (flags & MASK_SPARCLET)
fprintf (stderr, "SPARCLET ");
if (flags & MASK_SPARCLITE)
@@ -1632,6 +1713,7 @@ sparc_option_override (void)
{ TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC },
{ TARGET_CPU_leon, PROCESSOR_LEON },
{ TARGET_CPU_leon3, PROCESSOR_LEON3 },
+ { TARGET_CPU_leon5, PROCESSOR_LEON5 },
{ TARGET_CPU_leon3v7, PROCESSOR_LEON3V7 },
{ TARGET_CPU_sparclite, PROCESSOR_F930 },
{ TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X },
@@ -1663,6 +1745,7 @@ sparc_option_override (void)
{ "hypersparc", MASK_ISA, MASK_V8 },
{ "leon", MASK_ISA|MASK_FSMULD, MASK_V8|MASK_LEON },
{ "leon3", MASK_ISA, MASK_V8|MASK_LEON3 },
+ { "leon5", MASK_ISA, MASK_V8|MASK_LEON3 },
{ "leon3v7", MASK_ISA, MASK_LEON3 },
{ "sparclite", MASK_ISA, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
@@ -1776,7 +1859,7 @@ sparc_option_override (void)
}
/* Set the default CPU if no -mcpu option was specified. */
- if (!global_options_set.x_sparc_cpu_and_features)
+ if (!OPTION_SET_P (sparc_cpu_and_features))
{
for (def = &cpu_default[0]; def->cpu != -1; ++def)
if (def->cpu == TARGET_CPU_DEFAULT)
@@ -1786,7 +1869,7 @@ sparc_option_override (void)
}
/* Set the default CPU if no -mtune option was specified. */
- if (!global_options_set.x_sparc_cpu)
+ if (!OPTION_SET_P (sparc_cpu))
sparc_cpu = sparc_cpu_and_features;
cpu = &cpu_table[(int) sparc_cpu_and_features];
@@ -1892,7 +1975,7 @@ sparc_option_override (void)
dump_target_flags ("Final target_flags", target_flags);
/* Set the code model if no -mcmodel option was specified. */
- if (global_options_set.x_sparc_code_model)
+ if (OPTION_SET_P (sparc_code_model))
{
if (TARGET_ARCH32)
error ("%<-mcmodel=%> is not supported in 32-bit mode");
@@ -1906,7 +1989,7 @@ sparc_option_override (void)
}
/* Set the memory model if no -mmemory-model option was specified. */
- if (!global_options_set.x_sparc_memory_model)
+ if (!OPTION_SET_P (sparc_memory_model))
{
/* Choose the memory model for the operating system. */
enum sparc_memory_model_type os_default = SUBTARGET_DEFAULT_MEMORY_MODEL;
@@ -1973,6 +2056,9 @@ sparc_option_override (void)
case PROCESSOR_LEON3V7:
sparc_costs = &leon3_costs;
break;
+ case PROCESSOR_LEON5:
+ sparc_costs = &leon5_costs;
+ break;
case PROCESSOR_SPARCLET:
case PROCESSOR_TSC701:
sparc_costs = &sparclet_costs;
@@ -2091,12 +2177,12 @@ sparc_option_override (void)
/* Disable save slot sharing for call-clobbered registers by default.
The IRA sharing algorithm works on single registers only and this
pessimizes for double floating-point registers. */
- if (!global_options_set.x_flag_ira_share_save_slots)
+ if (!OPTION_SET_P (flag_ira_share_save_slots))
flag_ira_share_save_slots = 0;
/* Only enable REE by default in 64-bit mode where it helps to eliminate
redundant 32-to-64-bit extensions. */
- if (!global_options_set.x_flag_ree && TARGET_ARCH32)
+ if (!OPTION_SET_P (flag_ree) && TARGET_ARCH32)
flag_ree = 0;
/* Do various machine dependent initializations. */
@@ -10120,11 +10206,64 @@ hypersparc_adjust_cost (rtx_insn *insn, int dtype, rtx_insn *dep_insn,
}
static int
+leon5_adjust_cost (rtx_insn *insn, int dtype, rtx_insn *dep_insn,
+ int cost)
+{
+ enum attr_type insn_type, dep_type;
+ rtx pat = PATTERN (insn);
+ rtx dep_pat = PATTERN (dep_insn);
+
+ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
+ return cost;
+
+ insn_type = get_attr_type (insn);
+ dep_type = get_attr_type (dep_insn);
+
+ switch (dtype)
+ {
+ case REG_DEP_TRUE:
+ /* Data dependency; DEP_INSN writes a register that INSN reads some
+ cycles later. */
+
+ switch (insn_type)
+ {
+ case TYPE_STORE:
+ /* Try to schedule three instructions between the store and
+ the ALU instruction that generated the data. */
+ if (dep_type == TYPE_IALU || dep_type == TYPE_SHIFT)
+ {
+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
+ break;
+
+ if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
+ return 4;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case REG_DEP_ANTI:
+ /* Penalize anti-dependencies for FPU instructions. */
+ if (fpop_insn_p (insn) || insn_type == TYPE_FPLOAD)
+ return 4;
+ break;
+ default:
+ break;
+ }
+
+ return cost;
+}
+
+static int
sparc_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep, int cost,
unsigned int)
{
switch (sparc_cpu)
{
+ case PROCESSOR_LEON5:
+ cost = leon5_adjust_cost (insn, dep_type, dep, cost);
+ break;
case PROCESSOR_SUPERSPARC:
cost = supersparc_adjust_cost (insn, dep_type, dep, cost);
break;
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 4da5a06..edafa99 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -120,21 +120,22 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_CPU_leon 4
#define TARGET_CPU_leon3 5
#define TARGET_CPU_leon3v7 6
-#define TARGET_CPU_sparclite 7
-#define TARGET_CPU_f930 7 /* alias */
-#define TARGET_CPU_f934 7 /* alias */
-#define TARGET_CPU_sparclite86x 8
-#define TARGET_CPU_sparclet 9
-#define TARGET_CPU_tsc701 9 /* alias */
-#define TARGET_CPU_v9 10 /* generic v9 implementation */
-#define TARGET_CPU_sparcv9 10 /* alias */
-#define TARGET_CPU_sparc64 10 /* alias */
-#define TARGET_CPU_ultrasparc 11
-#define TARGET_CPU_ultrasparc3 12
-#define TARGET_CPU_niagara 13
-#define TARGET_CPU_niagara2 14
-#define TARGET_CPU_niagara3 15
-#define TARGET_CPU_niagara4 16
+#define TARGET_CPU_leon5 7
+#define TARGET_CPU_sparclite 8
+#define TARGET_CPU_f930 8 /* alias */
+#define TARGET_CPU_f934 8 /* alias */
+#define TARGET_CPU_sparclite86x 9
+#define TARGET_CPU_sparclet 10
+#define TARGET_CPU_tsc701 10 /* alias */
+#define TARGET_CPU_v9 11 /* generic v9 implementation */
+#define TARGET_CPU_sparcv9 11 /* alias */
+#define TARGET_CPU_sparc64 11 /* alias */
+#define TARGET_CPU_ultrasparc 12
+#define TARGET_CPU_ultrasparc3 13
+#define TARGET_CPU_niagara 14
+#define TARGET_CPU_niagara2 15
+#define TARGET_CPU_niagara3 16
+#define TARGET_CPU_niagara4 17
#define TARGET_CPU_niagara7 19
#define TARGET_CPU_m8 20
@@ -229,7 +230,8 @@ along with GCC; see the file COPYING3. If not see
#endif
#if TARGET_CPU_DEFAULT == TARGET_CPU_leon \
- || TARGET_CPU_DEFAULT == TARGET_CPU_leon3
+ || TARGET_CPU_DEFAULT == TARGET_CPU_leon3 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_leon5
#define CPP_CPU32_DEFAULT_SPEC "-D__leon__ -D__sparc_v8__"
#define ASM_CPU32_DEFAULT_SPEC AS_LEON_FLAG
#endif
@@ -285,6 +287,7 @@ along with GCC; see the file COPYING3. If not see
%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
%{mcpu=leon:-D__leon__ -D__sparc_v8__} \
%{mcpu=leon3:-D__leon__ -D__sparc_v8__} \
+%{mcpu=leon5:-D__leon__ -D__sparc_v8__} \
%{mcpu=leon3v7:-D__leon__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
@@ -337,6 +340,7 @@ along with GCC; see the file COPYING3. If not see
%{mcpu=hypersparc:-Av8} \
%{mcpu=leon:" AS_LEON_FLAG "} \
%{mcpu=leon3:" AS_LEON_FLAG "} \
+%{mcpu=leon5:" AS_LEON_FLAG "} \
%{mcpu=leon3v7:" AS_LEONV7_FLAG "} \
%{mv8plus:-Av8plus} \
%{mcpu=v9:-Av9} \
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 24b76e0..294c918 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -233,6 +233,7 @@
hypersparc,
leon,
leon3,
+ leon5,
leon3v7,
sparclite,
f930,
@@ -638,6 +639,7 @@
(include "supersparc.md")
(include "hypersparc.md")
(include "leon.md")
+(include "leon5.md")
(include "sparclet.md")
(include "ultra1_2.md")
(include "ultra3.md")
@@ -8353,9 +8355,15 @@ visl")
(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
(set (match_scratch:SI 2 "=&r") (const_int 0))]
"TARGET_ARCH32"
- "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
+{
+ if (sparc_fix_b2bst)
+ return "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2\;nop";
+ else
+ return "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2";
+}
[(set_attr "type" "multi")
- (set_attr "length" "3")])
+ (set (attr "length") (if_then_else (eq_attr "fix_b2bst" "true")
+ (const_int 4) (const_int 3)))])
(define_insn "stack_protect_set64"
[(set (match_operand:DI 0 "memory_operand" "=m")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index fb79267..658a187 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -176,6 +176,9 @@ EnumValue
Enum(sparc_processor) String(leon3v7) Value(PROCESSOR_LEON3V7)
EnumValue
+Enum(sparc_processor) String(leon5) Value(PROCESSOR_LEON5)
+
+EnumValue
Enum(sparc_processor) String(sparclite) Value(PROCESSOR_SPARCLITE)
EnumValue
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 64e28f6..08d1126 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -56,6 +56,7 @@
#include "tilegx-builtins.h"
#include "tilegx-multiply.h"
#include "builtins.h"
+#include "opts.h"
/* This file should be included last. */
#include "target-def.h"
@@ -76,7 +77,7 @@ static bool output_memory_autoinc_first;
static void
tilegx_option_override (void)
{
- if (global_options_set.x_tilegx_cmodel)
+ if (OPTION_SET_P (tilegx_cmodel))
{
switch (tilegx_cmodel)
{
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index 58e5355..ffa2243 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -443,7 +443,7 @@ visium_option_override (void)
}
/* Set -mtune from -mcpu if not specified. */
- if (!global_options_set.x_visium_cpu)
+ if (!OPTION_SET_P (visium_cpu))
visium_cpu = visium_cpu_and_features;
/* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
diff --git a/gcc/config/vxworks.c b/gcc/config/vxworks.c
index 51f4675..29ec060 100644
--- a/gcc/config/vxworks.c
+++ b/gcc/config/vxworks.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "memmodel.h"
#include "optabs.h"
+#include "opts.h"
#if !HAVE_INITFINI_ARRAY_SUPPORT
/* Like default_named_section_asm_out_constructor, except that even
@@ -167,10 +168,10 @@ vxworks_override_options (void)
dwarf up to certain version. Default dwarf control to friendly
values for these. */
- if (!global_options_set.x_dwarf_strict)
+ if (!OPTION_SET_P (dwarf_strict))
dwarf_strict = 1;
- if (!global_options_set.x_dwarf_version)
+ if (!OPTION_SET_P (dwarf_version))
dwarf_version = VXWORKS_DWARF_VERSION_DEFAULT;
}
diff --git a/gcc/config/xtensa/t-xtensa b/gcc/config/xtensa/t-xtensa
index 973815c..d06e492 100644
--- a/gcc/config/xtensa/t-xtensa
+++ b/gcc/config/xtensa/t-xtensa
@@ -16,4 +16,5 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
+TM_H += $(srcdir)/../include/xtensa-config.h
$(out_object_file): gt-xtensa.h
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index f4f8f19..8d67551 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -1084,7 +1084,8 @@ xtensa_emit_move_sequence (rtx *operands, machine_mode mode)
{
/* Try to emit MOVI + SLLI sequence, that is smaller
than L32R + literal. */
- if (optimize_size && mode == SImode && register_operand (dst, mode))
+ if (optimize_size && mode == SImode && CONST_INT_P (src)
+ && register_operand (dst, mode))
{
HOST_WIDE_INT srcval = INTVAL (src);
int shift = ctz_hwi (srcval);
diff --git a/gcc/configure b/gcc/configure
index 500e3f6..8790153 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -753,10 +753,6 @@ FGREP
SED
LIBTOOL
collect2
-NO_PIE_FLAG_FOR_BUILD
-NO_PIE_CFLAGS_FOR_BUILD
-BUILD_NO_PIE_FLAG
-BUILD_NO_PIE_CFLAGS
STMP_FIXINC
BUILD_LDFLAGS
BUILD_CXXFLAGS
@@ -958,7 +954,6 @@ enable_checking
enable_coverage
enable_gather_detailed_mem_stats
enable_valgrind_annotations
-with_stabs
enable_multilib
enable_multiarch
with_stack_clash_protection_guard_size
@@ -1820,7 +1815,6 @@ Optional Packages:
pathname)
--with-gnu-as arrange to work with GNU as
--with-as arrange to use the specified as (full pathname)
- --with-stabs arrange to use stabs instead of host debug format
--with-stack-clash-protection-guard-size=size
Set the default stack clash protection guard size
for specific targets as a power of two in bytes.
@@ -1832,7 +1826,8 @@ Optional Packages:
Root for documentation URLs
--with-changes-root-url=URL
Root for GCC changes URLs
- --with-multilib-list select multilibs (AArch64, SH and x86-64 only)
+ --with-multilib-list select multilibs (AArch64, ARM, OR1K, RISC-V, 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.
@@ -7604,16 +7599,6 @@ fi
# Miscenalleous configure options
# -------------------------------
-# With stabs
-
-# Check whether --with-stabs was given.
-if test "${with_stabs+set}" = set; then :
- withval=$with_stabs; stabs="$with_stabs"
-else
- stabs=no
-fi
-
-
# Determine whether or not multilibs are enabled.
# Check whether --enable-multilib was given.
if test "${enable_multilib+set}" = set; then :
@@ -13336,24 +13321,14 @@ BUILD_CXXFLAGS='$(ALL_CXXFLAGS)'
BUILD_LDFLAGS='$(LDFLAGS)'
STMP_FIXINC=stmp-fixinc
-BUILD_NO_PIE_CFLAGS='$(NO_PIE_CFLAGS)'
-BUILD_NO_PIE_FLAG='$(NO_PIE_FLAG)'
-
# And these apply if build != host, or we are generating coverage data
if test x$build != x$host || test "x$coverage_flags" != x
then
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CFLAGS_FOR_BUILD)'
BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CXXFLAGS_FOR_BUILD)'
BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
-
- NO_PIE_CFLAGS_FOR_BUILD=${NO_PIE_CFLAGS_FOR_BUILD-${NO_PIE_CFLAGS}}
- NO_PIE_FLAG_FOR_BUILD=${NO_PIE_FLAG_FOR_BUILD-${NO_PIE_FLAG}}
- BUILD_NO_PIE_CFLAGS='$(NO_PIE_CFLAGS_FOR_BUILD)'
- BUILD_NO_PIE_FLAG='$(NO_PIE_FLAG_FOR_BUILD)'
fi
-
-
# Expand extra_headers to include complete path.
# This substitutes for lots of t-* files.
extra_headers_list=
@@ -19480,7 +19455,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19483 "configure"
+#line 19458 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19586,7 +19561,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19589 "configure"
+#line 19564 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -28782,22 +28757,241 @@ esac
case "$target" in
amdgcn-* | gcn-*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for fiji" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for fiji... " >&6; }
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v2/3 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v2/3 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v3_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v3_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack -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_gcn_asm_v3_syntax=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_gcn_asm_v3_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v3_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V3_SYNTAX 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v4 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v4 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v4_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v4_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack -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_gcn_asm_v4_syntax=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_gcn_asm_v4_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v4_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V4_SYNTAX 1" >>confdefs.h
+
+fi
+
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ as_fn_error $? "Unrecognised assembler version" "$LINENO" 5
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for fiji... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_fiji+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_fiji=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=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_gcn_xnack_ecc_fiji" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_fiji" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_fiji = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_FIJI 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx900... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx900+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx900=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=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_gcn_xnack_ecc_gfx900" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx900" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx900 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX900 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx906... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx906+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx906=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=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_gcn_xnack_ecc_gfx906" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx906" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx906 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX906 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx908... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx908+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx908=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=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_gcn_xnack_ecc_gfx908" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx908" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx908 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX908 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for fiji... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_fiji+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_fiji=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err -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_gcn_sram_ecc_fiji=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_fiji=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28813,22 +29007,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_FIJI 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx900" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx900... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx900... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx900+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx900=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err -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_gcn_sram_ecc_gfx900=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28844,22 +29040,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX900 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx906" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx906... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx906... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx906+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx906=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err -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_gcn_sram_ecc_gfx906=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28875,22 +29073,24 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX906 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx908" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx908... " >&6; }
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx908... " >&6; }
if ${gcc_cv_as_gcn_sram_ecc_gfx908+:} false; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_gcn_sram_ecc_gfx908=no
if test x$gcc_cv_as != x; then
- $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err -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_gcn_sram_ecc_gfx908=yes
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -28906,7 +29106,43 @@ $as_echo "#define HAVE_GCN_SRAM_ECC_GFX908 1" >>confdefs.h
fi
+ rm -f conftest.err
;;
+ arm*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler for arm accepts context-specific architecture extensions" >&5
+$as_echo_n "checking assembler for assembler for arm accepts context-specific architecture extensions... " >&6; }
+if ${gcc_cv_as_arm_option_extensions+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_arm_option_extensions=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .thumb
+ .syntax unified
+ vmov.f32 s0, s1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=armv8.1-m.main+mve -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_arm_option_extensions=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_arm_option_extensions" >&5
+$as_echo "$gcc_cv_as_arm_option_extensions" >&6; }
+if test $gcc_cv_as_arm_option_extensions = yes; then
+
+$as_echo "#define HAVE_GAS_ARM_EXTENDED_ARCH 1" >>confdefs.h
+
+fi
+
esac
# ??? Not all targets support dwarf2 debug_line, even within a version
@@ -30481,7 +30717,7 @@ $as_echo "#define HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE 1" >>confdefs.h
esac
case "$target:$tm_file" in
- powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
+ powerpc64*-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in
*le-*-linux*)
emul_name="-melf64lppc"
diff --git a/gcc/configure.ac b/gcc/configure.ac
index c651db7..c2cad0a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -845,13 +845,6 @@ fi
# Miscenalleous configure options
# -------------------------------
-# With stabs
-AC_ARG_WITH(stabs,
-[AS_HELP_STRING([--with-stabs],
- [arrange to use stabs instead of host debug format])],
-stabs="$with_stabs",
-stabs=no)
-
# Determine whether or not multilibs are enabled.
AC_ARG_ENABLE(multilib,
[AS_HELP_STRING([--enable-multilib],
@@ -1176,7 +1169,7 @@ if test "x$enable_offload_defaulted" = xyes; then
fi
AC_ARG_WITH(multilib-list,
-[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, SH and x86-64 only)])],
+[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, ARM, OR1K, RISC-V, SH and x86-64 only)])],
:,
with_multilib_list=default)
@@ -2473,23 +2466,13 @@ BUILD_CXXFLAGS='$(ALL_CXXFLAGS)' AC_SUBST(BUILD_CXXFLAGS)
BUILD_LDFLAGS='$(LDFLAGS)' AC_SUBST(BUILD_LDFLAGS)
STMP_FIXINC=stmp-fixinc AC_SUBST(STMP_FIXINC)
-BUILD_NO_PIE_CFLAGS='$(NO_PIE_CFLAGS)' AC_SUBST(BUILD_NO_PIE_CFLAGS)
-BUILD_NO_PIE_FLAG='$(NO_PIE_FLAG)' AC_SUBST(BUILD_NO_PIE_FLAG)
-
# And these apply if build != host, or we are generating coverage data
if test x$build != x$host || test "x$coverage_flags" != x
then
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CFLAGS_FOR_BUILD)'
BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CXXFLAGS_FOR_BUILD)'
BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
-
- NO_PIE_CFLAGS_FOR_BUILD=${NO_PIE_CFLAGS_FOR_BUILD-${NO_PIE_CFLAGS}}
- NO_PIE_FLAG_FOR_BUILD=${NO_PIE_FLAG_FOR_BUILD-${NO_PIE_FLAG}}
- BUILD_NO_PIE_CFLAGS='$(NO_PIE_CFLAGS_FOR_BUILD)'
- BUILD_NO_PIE_FLAG='$(NO_PIE_FLAG_FOR_BUILD)'
fi
-AC_SUBST(NO_PIE_CFLAGS_FOR_BUILD)
-AC_SUBST(NO_PIE_FLAG_FOR_BUILD)
# Expand extra_headers to include complete path.
# This substitutes for lots of t-* files.
@@ -4709,7 +4692,7 @@ foo: nop
case $target_os in
darwin2[[0-9]]* | darwin19*)
gcc_GAS_CHECK_FEATURE([llvm assembler x86-pad-for-align option],
- gcc_cv_as_mllvm_x86_pad_for_align,,
+ gcc_cv_as_mllvm_x86_pad_for_align,
[-mllvm -x86-pad-for-align=false], [.text],,
[AC_DEFINE(HAVE_AS_MLLVM_X86_PAD_FOR_ALIGN, 1,
[Define if your Mac OS X assembler supports -mllvm -x86-pad-for-align=false.])])
@@ -5349,31 +5332,117 @@ esac
case "$target" in
amdgcn-* | gcn-*)
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for fiji],
- gcc_cv_as_gcn_sram_ecc_fiji,,
- [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"],,
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v2/3 syntax],
+ gcc_cv_as_gcn_asm_v3_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V3_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908+xnack syntax.])])
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v4 syntax],
+ gcc_cv_as_gcn_asm_v4_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V4_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908:xnack+ syntax.])])
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ AC_MSG_ERROR([Unrecognised assembler version])
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for fiji],
+ gcc_cv_as_gcn_xnack_ecc_fiji,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_FIJI, 1,
+ [Define if your assembler allows -mattr=+xnack for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx900],
+ gcc_cv_as_gcn_xnack_ecc_gfx900,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX900, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx906],
+ gcc_cv_as_gcn_xnack_ecc_gfx906,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX906, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx908],
+ gcc_cv_as_gcn_xnack_ecc_gfx908,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX908, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx908.])])
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for fiji],
+ gcc_cv_as_gcn_sram_ecc_fiji,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_fiji=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_FIJI, 1,
- [Define if your assembler allows -mattr=+sram-ecc for fiji.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx900],
- gcc_cv_as_gcn_sram_ecc_gfx900,,
- [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"],,
+ [Define if your assembler allows -mattr=+sramecc for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx900],
+ gcc_cv_as_gcn_sram_ecc_gfx900,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX900, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx900.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx906],
- gcc_cv_as_gcn_sram_ecc_gfx906,,
- [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"],,
+ [Define if your assembler allows -mattr=+sramecc for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx906],
+ gcc_cv_as_gcn_sram_ecc_gfx906,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX906, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx906.])])
- gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx908],
- gcc_cv_as_gcn_sram_ecc_gfx908,,
- [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc],
- [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"],,
+ [Define if your assembler allows -mattr=+sramecc for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx908],
+ gcc_cv_as_gcn_sram_ecc_gfx908,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=yes],
[AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX908, 1,
- [Define if your assembler allows -mattr=+sram-ecc for gfx908.])])
+ [Define if your assembler allows -mattr=+sramecc for gfx908.])])
+ rm -f conftest.err
;;
+ arm*)
+ gcc_GAS_CHECK_FEATURE([assembler for arm accepts context-specific architecture extensions],
+ gcc_cv_as_arm_option_extensions,
+ [-march=armv8.1-m.main+mve],
+ [.text
+ .thumb
+ .syntax unified
+ vmov.f32 s0, s1],,
+ [AC_DEFINE(HAVE_GAS_ARM_EXTENDED_ARCH, 1,
+ [Define if your Arm assembler permits context-specific feature extensions.])])
esac
# ??? Not all targets support dwarf2 debug_line, even within a version
@@ -6446,7 +6515,7 @@ EOF
esac
case "$target:$tm_file" in
- powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
+ powerpc64*-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in
*le-*-linux*)
emul_name="-melf64lppc"
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 726fcad..b4f530d 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -425,7 +425,8 @@ enum excess_precision_type
{
EXCESS_PRECISION_TYPE_IMPLICIT,
EXCESS_PRECISION_TYPE_STANDARD,
- EXCESS_PRECISION_TYPE_FAST
+ EXCESS_PRECISION_TYPE_FAST,
+ EXCESS_PRECISION_TYPE_FLOAT16
};
/* Level of size optimization. */
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 10d7f83..4467f1e 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -129,16 +129,7 @@ static const char *const ctr_names[GCOV_COUNTERS] = {
#undef DEF_GCOV_COUNTER
/* Forward declarations. */
-static void read_counts_file (void);
static tree build_var (tree, tree, int);
-static void build_fn_info_type (tree, unsigned, tree);
-static void build_info_type (tree, tree);
-static tree build_fn_info (const struct coverage_data *, tree, tree);
-static tree build_info (tree, tree);
-static bool coverage_obj_init (void);
-static vec<constructor_elt, va_gc> *coverage_obj_fn
-(vec<constructor_elt, va_gc> *, tree, struct coverage_data const *);
-static void coverage_obj_finish (vec<constructor_elt, va_gc> *);
/* Return the type node for gcov_type. */
@@ -218,6 +209,9 @@ read_counts_file (void)
tag = gcov_read_unsigned ();
bbg_file_stamp = crc32_unsigned (bbg_file_stamp, tag);
+ /* Read checksum. */
+ gcov_read_unsigned ();
+
counts_hash = new hash_table<counts_entry> (10);
while ((tag = gcov_read_unsigned ()))
{
@@ -935,6 +929,12 @@ build_info_type (tree type, tree fn_info_ptr_type)
DECL_CHAIN (field) = fields;
fields = field;
+ /* Checksum. */
+ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
+ get_gcov_unsigned_t ());
+ DECL_CHAIN (field) = fields;
+ fields = field;
+
/* Filename */
field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
build_pointer_type (build_qualified_type
@@ -977,7 +977,7 @@ build_info_type (tree type, tree fn_info_ptr_type)
function info objects. */
static tree
-build_info (tree info_type, tree fn_ary)
+build_info (tree info_type, tree fn_ary, unsigned object_checksum)
{
tree info_fields = TYPE_FIELDS (info_type);
tree merge_fn_type, n_funcs;
@@ -996,13 +996,19 @@ build_info (tree info_type, tree fn_ary)
/* next -- NULL */
CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
info_fields = DECL_CHAIN (info_fields);
-
+
/* stamp */
CONSTRUCTOR_APPEND_ELT (v1, info_fields,
build_int_cstu (TREE_TYPE (info_fields),
bbg_file_stamp));
info_fields = DECL_CHAIN (info_fields);
+ /* Checksum. */
+ CONSTRUCTOR_APPEND_ELT (v1, info_fields,
+ build_int_cstu (TREE_TYPE (info_fields),
+ object_checksum));
+ info_fields = DECL_CHAIN (info_fields);
+
/* Filename */
da_file_name_len = strlen (da_file_name);
filename_string = build_string (da_file_name_len + 1, da_file_name);
@@ -1214,7 +1220,8 @@ coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
function objects from CTOR. Generate the gcov_info initializer. */
static void
-coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
+coverage_obj_finish (vec<constructor_elt, va_gc> *ctor,
+ unsigned object_checksum)
{
unsigned n_functions = vec_safe_length (ctor);
tree fn_info_ary_type = build_array_type
@@ -1231,7 +1238,7 @@ coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
varpool_node::finalize_decl (fn_info_ary);
DECL_INITIAL (gcov_info_var)
- = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
+ = build_info (TREE_TYPE (gcov_info_var), fn_info_ary, object_checksum);
varpool_node::finalize_decl (gcov_info_var);
}
@@ -1300,7 +1307,6 @@ coverage_init (const char *filename)
strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
bbg_file_stamp = local_tick;
-
if (flag_auto_profile)
read_autofdo_file ();
else if (flag_branch_probabilities)
@@ -1328,6 +1334,8 @@ coverage_init (const char *filename)
gcov_write_unsigned (GCOV_NOTE_MAGIC);
gcov_write_unsigned (GCOV_VERSION);
gcov_write_unsigned (bbg_file_stamp);
+ /* Use an arbitrary checksum */
+ gcov_write_unsigned (0);
gcov_write_string (getpwd ());
/* Do not support has_unexecuted_blocks for Ada. */
@@ -1353,14 +1361,24 @@ coverage_finish (void)
cannot uniquely stamp it. If we can stamp it, libgcov will DTRT. */
unlink (da_file_name);
+ /* Global GCDA checksum that aggregates all functions. */
+ unsigned object_checksum = 0;
+
if (coverage_obj_init ())
{
vec<constructor_elt, va_gc> *fn_ctor = NULL;
struct coverage_data *fn;
for (fn = functions_head; fn; fn = fn->next)
- fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
- coverage_obj_finish (fn_ctor);
+ {
+ fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
+
+ object_checksum = crc32_unsigned (object_checksum, fn->ident);
+ object_checksum = crc32_unsigned (object_checksum,
+ fn->lineno_checksum);
+ object_checksum = crc32_unsigned (object_checksum, fn->cfg_checksum);
+ }
+ coverage_obj_finish (fn_ctor, object_checksum);
}
XDELETEVEC (da_file_name);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0b92ee4..ffdb690 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,706 @@
+2021-10-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/51851
+ PR c++/101402
+ PR c++/102033
+ PR c++/102034
+ PR c++/102039
+ PR c++/102044
+ * pt.c (determine_specialization): Remove redundant code.
+ (fn_type_unification): Check for mismatched length.
+ (type_unification_real): Ignore terminal void.
+ (get_bindings): Don't stop at void_list_node.
+ * class.c (resolve_address_of_overloaded_function): Likewise.
+
+2021-10-15 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_bind_parameters_in_call): Replace
+ new_call parameter with fun.
+ (cxx_eval_call_expression): Call it before instantiation.
+ (cxx_eval_outermost_constant_expr): Only instantiate fns
+ when manifestly_const_eval.
+ * typeck2.c (check_narrowing): This context is manifestly
+ constant-evaluated.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * decl.c (omp_declare_variant_finalize_one): Change call from
+ c_omp_mark_declare_variant to omp_mark_declare_variant.
+ * parser.c (cp_finish_omp_declare_variant): Change call from
+ c_omp_check_context_selector to omp_check_context_selector.
+
+2021-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_structured_block): Remove disallow_omp_attrs
+ argument.
+ (cp_parser_omp_structured_block_sequence): New function.
+ (cp_parser_omp_scan_loop_body): Use it.
+ (cp_parser_omp_sections_scope): Likewise.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * constexpr.c (maybe_warn_about_constant_value): Use new macro
+ OPTION_SET_P.
+ * decl.c (redeclaration_error_message): Likewise.
+ (cxx_init_decl_processing): Likewise.
+
+2021-10-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102640
+ * parser.c (handle_omp_declare_target_clause): New function.
+ (cp_parser_omp_declare_target): Use it.
+
+2021-10-07 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/61355
+ * pt.c (convert_template_argument): Perform array/function to
+ pointer conversion on the substituted type of an NTTP.
+
+2021-10-07 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99904
+ * pt.c (is_compatible_template_arg): Set processing_template_decl
+ around tsubst_constraint_info.
+
+2021-10-07 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/102482
+ * init.c (maybe_warn_list_ctor): Do not warn for a reference to
+ a non-const std::initializer_list.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * parser.c (cp_parser_jump_statement): Implement C++23 P2242R3.
+ Allow goto expressions in constexpr function bodies for C++23.
+ Adjust error message for older standards to mention it.
+ * decl.c (start_decl): Allow static and thread_local declarations
+ in constexpr function bodies for C++23. Adjust error message for
+ older standards to mention it.
+ * constexpr.c (ensure_literal_type_for_constexpr_object): Allow
+ declarations of variables with non-literal type in constexpr function
+ bodies for C++23. Adjust error message for older standards to mention
+ it.
+ (cxx_eval_constant_expression) <case DECL_EXPR>: Diagnose declarations
+ of initialization of static or thread_local vars.
+ (cxx_eval_constant_expression) <case GOTO_EXPR>: Diagnose goto
+ statements for C++23.
+ (potential_constant_expression_1) <case DECL_EXPR>: Swap the
+ CP_DECL_THREAD_LOCAL_P and TREE_STATIC checks.
+ (potential_constant_expression_1) <case LABEL_EXPR>: Allow labels for
+ C++23. Adjust error message for older standards to mention it.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/98712
+ PR c++/102490
+ * cp-tree.h (maybe_synthesize_method): Declare.
+ * method.c (genericize_spaceship): Use
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED instead of
+ LOOKUP_NORMAL for flags.
+ (comp_info): Remove defining member. Add complain, code, retcat.
+ (comp_info::comp_info): Adjust.
+ (do_one_comp): Split out from build_comparison_op. Use
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED instead of
+ LOOKUP_NORMAL for flags.
+ (build_comparison_op): Add defining argument. Adjust comp_info
+ construction. Use defining instead of info.defining. Assert that
+ if defining, ctype is a complete type. Walk base binfos.
+ (synthesize_method, maybe_explain_implicit_delete,
+ explain_implicit_non_constexpr): Adjust build_comparison_op callers.
+ (maybe_synthesize_method): New function.
+ * class.c (check_bases_and_members): Don't call defaulted_late_check
+ for sfk_comparison.
+ (finish_struct_1): Call it here instead after class has been
+ completed.
+ * pt.c (maybe_instantiate_noexcept): Call maybe_synthesize_method
+ instead of synthesize_method.
+
+2021-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102548
+ * tree.c (apply_identity_attributes): Fix handling of the
+ case where an attribute in the list doesn't affect type
+ identity but some attribute before it does.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102547
+ * constexpr.c (potential_constant_expression_1): Handle
+ NONTYPE_ARGUMENT_PACK.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98930
+ * pt.c (has_value_dependent_address): Return true for a static
+ local variable from a function template.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * typeck.c (cp_build_binary_op): Call do_warn_array_compare.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101765
+ * coroutines.cc (register_local_var_uses): Emit a sorry if
+ we encounter a VLA in the coroutine local variables.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99710
+ * coroutines.cc (await_statement_walker): Report an error if
+ an await expression is found in a handler body.
+
+2021-10-03 John Eivind Helset <jehelset@gmail.com>
+
+ PR c++/100673
+ * coroutines.cc (build_co_await): Guard against NULL
+ await_suspend types.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101133
+ * coroutines.cc (build_co_await): Mark co_await_expr trees
+ with TREE_SIDE_EFFECTS, also mark any containing expression.
+ (finish_co_await_expr): Mark type-dependent co_await_expr
+ trees with TREE_SIDE_EFFECTS.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99575
+ * coroutines.cc (build_co_await): Strip NOPs from
+ candidate awaiter expressions before testing to see
+ if they need a temporary.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * typeck.c (warn_for_null_address): Enhance.
+ (cp_build_binary_op): Call it also for member pointers.
+
+2021-10-01 qingzhe huang <nickhuang99@hotmail.com>
+
+ PR c++/101783
+ * tree.c (cp_build_qualified_type_real): Exclude typedef from
+ error.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * typeck.c (cp_build_binary_op): Call ubsan_instrument_division
+ for division even for SANITIZE_SI_OVERFLOW.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_order): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for explicit reproducible: modifier.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102496
+ * name-lookup.c (push_local_extern_decl_alias): Return early even for
+ tls vars with non-dependent type when processing_template_decl. For
+ CP_DECL_THREAD_LOCAL_P vars call set_decl_tls_model on alias.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102535
+ * method.c (is_xible_helper): Don't exit early for multi-arg
+ ctors in C++20.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ * parser.c (cp_parser_trait_expr): Call nreverse on the reversed
+ list of trailing arguments.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95567
+ * method.c (build_comparison_op): Skip DECL_VIRTUAL_P fields.
+
+2021-09-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99909
+ * pt.c (coerce_template_template_parms): Keep
+ processing_template_decl set around the call to unify as well.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/102454
+ * coroutines.cc (analyze_fn_parms): Clean up synthetic names for
+ unnamed function params.
+ (morph_fn_to_coro): Do not try to set a guard variable for param
+ DTORs in the ramp, unless we have exceptions active.
+
+2021-09-27 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102479
+ * pt.c (rewrite_template_parm): Handle single-level tsubst_args.
+ Avoid a tree cycle when assigning the DECL_TEMPLATE_PARMS for a
+ rewritten ttp.
+ (alias_ctad_tweaks): Set current_template_parms accordingly.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ * parser.c (cp_keyword_starts_decl_specifier_p): Do not
+ handle RID_ATTRIBUTE.
+ (cp_parser_constructor_declarator_p): Remove now-redundant
+ checks.
+ (cp_parser_lambda_declarator_opt): Likewise.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ PR c++/77565
+ * parser.c (cp_keyword_starts_decl_specifier_p): Handle more
+ decl-specifiers (typedef/inline/cv/explicit/virtual/friend).
+
+2021-09-23 Patrick Palka <ppalka@redhat.com>
+
+ * ptree.c (cxx_print_decl): Dump the DECL_TEMPLATE_RESULT of
+ a TEMPLATE_DECL. Dump the DECL_TEMPLATE_INFO rather than just
+ printing its pointer value.
+
+2021-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102413
+ * parser.c (cp_parser_omp_directive_args): Diagnose if omp::directive
+ is not followed by a balanced token sequence starting with open paren.
+
+2021-09-22 Patrick Palka <ppalka@redhat.com>
+
+ DR 2446
+ PR c++/102412
+ * constexpr.c (cxx_eval_constant_expression)
+ <case TEMPLATE_ID_EXPR>: Check value_dependent_expression_p
+ instead of processing_template_decl.
+ * pt.c (value_dependent_expression_p) <case TEMPLATE_ID_EXPR>:
+ Return true only if any_dependent_template_arguments_p.
+ (instantiation_dependent_r) <case CALL_EXPR>: Remove this case.
+ <case TEMPLATE_ID_EXPR>: Likewise.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_allocate): Parse allocate clause
+ modifiers.
+ * semantics.c (finish_omp_clauses) <OMP_CLAUSE_ALLOCATE>: Perform
+ semantic analysis of OMP_CLAUSE_ALLOCATE_ALIGN.
+ * pt.c (tsubst_omp_clauses) <case OMP_CLAUSE_ALLOCATE>: Handle
+ also OMP_CLAUSE_ALLOCATE_ALIGN.
+
+2021-09-22 Barrett Adair <barrettellisadair@gmail.com>
+
+ * pt.c (find_parm_usage_r): New walk_tree callback to find func
+ parms.
+ (any_template_arguments_need_structural_equality_p): New special
+ case.
+
+2021-09-21 wangpc <pc.wang@linux.alibaba.com>
+
+ * decl.c (start_decl_1): Move verify_type_context to ...
+ (cp_finish_decl): ... to here.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_order): Parse unconstrained
+ and reproducible modifiers.
+ (OMP_DISTRIBUTE_CLAUSE_MASK): Add order clause.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_default): Handle private and
+ firstprivate arguments, adjust diagnostics on unknown argument.
+ * cp-gimplify.c (cxx_omp_finish_clause): Handle OMP_CLAUSE_PRIVATE.
+
+2021-09-18 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (dependentish_scope_p): Declare.
+ * pt.c (dependentish_scope_p): New.
+ * parser.c (cp_parser_lookup_name): Return a TYPENAME_TYPE
+ for lookup of a type in a dependent object.
+ (cp_parser_template_id): Handle TYPENAME_TYPE.
+ (cp_parser_template_name): If we're looking for a type,
+ a name followed by < names a template.
+
+2021-09-18 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h: Fix typo in LANG_FLAG list.
+
+2021-09-17 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (finish_omp_atomic): Add r and weak arguments.
+ * parser.c (cp_parser_omp_atomic): Update function comment for
+ OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and
+ weak clauses.
+ * semantics.c (finish_omp_atomic): Add r and weak arguments, handle
+ them, handle COND_EXPRs.
+ * pt.c (tsubst_expr): Adjust for COND_EXPR forms that
+ finish_omp_atomic can now produce.
+
+2021-09-16 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98486
+ * constraint.cc (get_normalized_constraints_from_decl): Always
+ look up constraints using the most general template.
+ * decl.c (grokdeclarator): Set constraints on a static data
+ member template.
+ * pt.c (determine_specialization): Check constraints on a
+ variable template.
+
+2021-09-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (await_statement_walker): Code cleanups.
+
+2021-09-16 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_outermost_constant_expr): Use
+ protected_set_expr_location.
+
+2021-09-15 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101904
+ * call.c (build_user_type_conversion_1): Add tf_conv to complain.
+ (add_candidates): When in a SFINAE context, instead of adding a
+ candidate to bad_fns just mark it unviable.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (parsing_function_declarator): Declare.
+ * name-lookup.c (set_decl_context_in_fn): Use it.
+ * parser.c (cp_parser_direct_declarator): Use it.
+ (parsing_function_declarator): New.
+
+2021-09-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/88578
+ PR c++/102295
+ * typeck2.c (split_nonconstant_init_1): Don't throw away empty
+ initializers of flexible array members if they have non-zero type
+ size.
+
+2021-09-15 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102050
+ * decl.c (grok_special_member_properties): Set
+ TYPE_HAS_COPY_CTOR, TYPE_HAS_DEFAULT_CONSTRUCTOR
+ and TYPE_HAS_LIST_CTOR independently from each other.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ * decl.c (cxx_init_decl_processing): Only warn about odd
+ interference sizes if they were specified with --param.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/48396
+ * cp-tree.h (enum cp_tree_index): Remove CPTI_TYPE_INFO_PTR_TYPE.
+ (type_info_ptr_type): Remove.
+ * rtti.c (init_rtti_processing): Don't predeclare std::type_info.
+ (typeid_ok_p): Check for null const_type_info_type_node.
+ (type_info_ptr_type, get_void_tinfo_ptr): New fns.
+ (get_tinfo_decl_dynamic, get_tinfo_ptr): Use them.
+ (ptr_initializer, ptm_initializer, get_pseudo_ti_init): Use them.
+ (get_tinfo_desc): Use const_ptr_type_node.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_template_name): Move object type.
+ (cp_parser_pre_parsed_nested_name_specifier): Likewise.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_unqualified_id): Only complain about ~A<T> in
+ a declarator.
+
+2021-09-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (struct param_info): Add copy_var.
+ (build_actor_fn): Use simplified param references.
+ (register_param_uses): Likewise.
+ (rewrite_param_uses): Likewise.
+ (analyze_fn_parms): New function.
+ (coro_rewrite_function_body): Add proxies for the fn
+ parameters to the outer bind scope of the rewritten code.
+ (morph_fn_to_coro): Use simplified version of param ref.
+
+2021-09-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (coro_resume_fn_id, coro_destroy_fn_id,
+ coro_promise_id, coro_frame_needs_free_id, coro_resume_index_id,
+ coro_self_handle_id, coro_actor_continue_id,
+ coro_frame_i_a_r_c_id): New.
+ (coro_init_identifiers): Initialize new name identifiers.
+ (coro_promise_type_found_p): Use pre-built identifiers.
+ (struct await_xform_data): Remove unused fields.
+ (transform_await_expr): Delete code that is now unused.
+ (build_actor_fn): Simplify interface, use pre-built identifiers and
+ remove transforms that are no longer needed.
+ (build_destroy_fn): Use revised field names.
+ (register_local_var_uses): Use pre-built identifiers.
+ (coro_rewrite_function_body): Simplify interface, use pre-built
+ identifiers. Generate proxy vars in the outer bind expr scope for the
+ implementation state that we wish to expose.
+ (morph_fn_to_coro): Adjust comments for new variable names, use pre-
+ built identifiers. Remove unused code to generate frame entries for
+ the implementation state. Adjust call for build_actor_fn.
+
+2021-09-14 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102163
+ * constexpr.c (cxx_eval_call_expression): After evaluating a
+ subobject constructor call for an empty union member, produce a
+ side effect that makes sure the member gets activated.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102295
+ * decl.c (layout_var_decl): For aggregates ending with a flexible
+ array member, add the size of the initializer for that member to
+ DECL_SIZE and DECL_SIZE_UNIT.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102305
+ * method.c (is_xible_helper): Call complete_type on to.
+
+2021-09-14 Jason Merrill <jason@redhat.com>
+
+ * decl.c (cxx_init_decl_processing): Don't warn if L1 cache line
+ size is smaller than maxalign.
+
+2021-09-13 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (maybe_warn_about_constant_value):
+ Complain about std::hardware_destructive_interference_size.
+ (cxx_eval_constant_expression): Call it.
+ * decl.c (cxx_init_decl_processing): Check
+ --param *-interference-size values.
+
+2021-09-13 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101764
+ * cp-tree.h (PACK_EXPANSION_FORCE_EXTRA_ARGS_P): New accessor
+ macro.
+ * pt.c (has_extra_args_mechanism_p): New function.
+ (find_parameter_pack_data::found_extra_args_tree_p): New data
+ member.
+ (find_parameter_packs_r): Set ppd->found_extra_args_tree_p
+ appropriately.
+ (make_pack_expansion): Set PACK_EXPANSION_FORCE_EXTRA_ARGS_P if
+ ppd.found_extra_args_tree_p.
+ (use_pack_expansion_extra_args_p): Return true if there were
+ unsubstituted packs and PACK_EXPANSION_FORCE_EXTRA_ARGS_P.
+ (tsubst_pack_expansion): Pass the pack expansion to
+ use_pack_expansion_extra_args_p.
+
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_atomic): Allow acq_rel on atomic read/write
+ and acq_rel/acquire clauses on update.
+ * semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller.
+
+2021-09-08 Richard Biener <rguenther@suse.de>
+
+ PR c++/102228
+ * cp-tree.h (ANON_AGGR_TYPE_FIELD): New define.
+ * decl.c (fixup_anonymous_aggr): Wipe RTTI info put in
+ place on invalid code.
+ * decl2.c (reset_type_linkage): Guard CLASSTYPE_TYPEINFO_VAR
+ access.
+ * module.cc (trees_in::read_class_def): Likewise. Reconstruct
+ ANON_AGGR_TYPE_FIELD.
+ * semantics.c (finish_member_declaration): Populate
+ ANON_AGGR_TYPE_FIELD for anon aggregate typed members.
+ * typeck.c (lookup_anon_field): Remove DFS search and return
+ ANON_AGGR_TYPE_FIELD directly.
+
+2021-09-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/100495
+ * constexpr.c (maybe_save_constexpr_fundef): Save body even for
+ constexpr deleting dtors.
+ (cxx_eval_call_expression): Don't use DECL_CLONED_FUNCTION for
+ deleting dtors.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * parser.c (cp_parser_omp_flush): Parse 'seq_cst' clause on 'flush'
+ directive.
+ * semantics.c (finish_omp_flush): Handle MEMMODEL_SEQ_CST.
+
+2021-09-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (register_local_var_uses): Do not mangle
+ frame entries for the outermost scope. Record the outer
+ scope as nesting depth 0.
+
+2021-09-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (coro_build_artificial_var): New.
+ (build_actor_fn): Use var builder, rename vars to use
+ implementation namespace.
+ (coro_rewrite_function_body): Likewise.
+ (morph_fn_to_coro): Likewise.
+
+2021-09-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (transform_local_var_uses): Record
+ frame offset expressions as DECL_VALUE_EXPRs instead of
+ rewriting them.
+
+2021-09-03 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101904
+ * call.c (build_this_conversion): New function, split out from
+ add_function_candidate.
+ (add_function_candidate): New parameter shortcut_bad_convs.
+ Document it. Use build_this_conversion. Stop at the first bad
+ argument conversion when shortcut_bad_convs is true.
+ (add_template_candidate_real): New parameter shortcut_bad_convs.
+ Use build_this_conversion to check the 'this' conversion before
+ attempting deduction. When the rejection reason code is
+ rr_bad_arg_conversion, pass -1 instead of 0 as the viable
+ parameter to add_candidate. Pass 'convs' to add_candidate.
+ (add_template_candidate): New parameter shortcut_bad_convs.
+ (add_template_conv_candidate): Pass false as shortcut_bad_convs
+ to add_template_candidate_real.
+ (add_candidates): Prefer to shortcut bad conversions during
+ overload resolution under the assumption that we'll eventually
+ see a strictly viable candidate. If this assumption turns out
+ to be false, re-process the non-strictly viable candidates
+ without shortcutting those bad conversions.
+
+2021-09-03 Jason Merrill <jason@redhat.com>
+
+ * pt.c (limit_bad_template_recursion): Suppress -Wunused for decls
+ we decide not to instantiate.
+
+2021-09-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102024
+ * class.c (build_base_field): Use SET_DECL_FIELD_ABI_IGNORED
+ instead of writing to DECL_FIELD_ABI_IGNORED.
+ (layout_class_type): Likewise. In the place where zero-width
+ bitfields used to be removed, use
+ SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD on those fields instead.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * call.c (build_over_call): Handle unavailable state in addition to
+ deprecation.
+ * class.c (type_build_ctor_call): Likewise.
+ (type_build_dtor_call): Likewise.
+ * cp-tree.h: Rename cp_warn_deprecated_use to
+ cp_handle_deprecated_or_unavailable.
+ * decl.c (duplicate_decls): Merge unavailability.
+ (grokdeclarator): Handle unavailability in addition to deprecation.
+ (type_is_unavailable): New.
+ (grokparms): Handle unavailability in addition to deprecation.
+ * decl.h (enum deprecated_states): Add
+ UNAVAILABLE_DEPRECATED_SUPPRESS.
+ * decl2.c (cplus_decl_attributes): Propagate unavailability to
+ templates.
+ (cp_warn_deprecated_use): Rename to ...
+ (cp_handle_deprecated_or_unavailable): ... this and amend to handle
+ the unavailable case. It remains a warning in the case of deprecation
+ but becomes an error in the case of unavailability.
+ (cp_warn_deprecated_use_scopes): Handle unavailability.
+ (mark_used): Likewise.
+ * parser.c (cp_parser_template_name): Likewise.
+ (cp_parser_template_argument): Likewise.
+ (cp_parser_parameter_declaration_list): Likewise.
+ * typeck.c (build_class_member_access_expr): Likewise.
+ (finish_class_member_access_expr): Likewise.
+ * typeck2.c (build_functional_cast_1): Likewise.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (build_actor_fn): Add begin/finish clauses
+ to the initial test in the actor function.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (await_statement_walker): Use build_stmt and
+ add_stmt instead of build1 and finish_expr_stmt.
+
+2021-08-31 Jason Merrill <jason@redhat.com>
+
+ * coroutines.cc (flatten_await_stmt): Fix copyo.
+ * decl.c (reshape_init_class): Simplify.
+ * module.cc (module_state::read_language): Add null check.
+ * parser.c (build_range_temp): Avoid type_uses_auto.
+ (cp_parser_class_specifier_1): Add null check.
+
+2021-08-31 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/12672
+ * call.c (rejection_reason::call_varargs_p): Rename this
+ previously unused member to ...
+ (rejection_reason::least_p): ... this.
+ (arity_rejection): Add least_p parameter.
+ (add_template_candidate_real): When there are explicit
+ template arguments, check that the arity of the call agrees with
+ the arity of the function before attempting deduction.
+ (print_arity_information): Add least_p parameter.
+ (print_z_candidate): Adjust call to print_arity_information.
+
+2021-08-31 Martin Sebor <msebor@redhat.com>
+
+ * parser.c (cp_parser_selection_statement): Use direct initialization
+ instead of copy.
+
+2021-08-31 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (explain_invalid_constexpr_fn): Use iloc_sentinel.
+
+2021-08-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/92193
+ * cp-tree.h (FNDECL_MANIFESTLY_CONST_EVALUATED): New.
+ * constexpr.c (cxx_eval_call_expression): Set it.
+ * pt.c (neglectable_inst_p): Check it.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * parser.c (cp_parser_omp_clause_device): Parse device-modifiers 'device_num'
+ and 'ancestor' in 'target device' clauses.
+ * semantics.c (finish_omp_clauses): Error handling. Constant device ids must
+ evaluate to '1' if 'ancestor' is used.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/96286
+ * cp-tree.h (struct lang_type): Add erroneous bit-field.
+ (CLASSTYPE_ERRONEOUS): New.
+ * pt.c (limit_bad_template_recursion): Check it.
+ (instantiate_class_template_1): Set it.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_outermost_constant_expr): Copy
+ expr location to result.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/101460
+ * cp-tree.h (cxx_constant_value_sfinae): Declare.
+ * constexpr.c (cxx_constant_value_sfinae): New.
+ * pt.c (fold_targs_r, maybe_fold_fn_template_args): New.
+ (tsubst_copy_and_build) [CALL_EXPR]: Call
+ maybe_fold_fn_template_args.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_simple_requirement): Warn about missing
+ requires.
+
+2021-08-27 Jason Merrill <jason@redhat.com>
+
+ * typeck2.c (build_x_arrow): Do set TREE_TYPE when operand is
+ a dependent pointer.
+
2021-08-25 Andrew Pinski <apinski@marvell.com>
PR c++/66590
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4df72e..c5601d9 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -175,17 +175,17 @@ static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
- tree, tree, tree, int, unification_kind_t, tsubst_flags_t);
+ tree, tree, tree, int, unification_kind_t, bool, tsubst_flags_t);
static struct z_candidate *add_template_candidate_real
(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
- tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t);
+ tree, tree, tree, int, tree, unification_kind_t, bool, tsubst_flags_t);
static bool is_complete (tree);
static struct z_candidate *add_conv_candidate
(struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree,
tree, tsubst_flags_t);
static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
- tree, int, conversion**, tsubst_flags_t);
+ tree, int, conversion**, bool, tsubst_flags_t);
static conversion *implicit_conversion (tree, tree, tree, bool, int,
tsubst_flags_t);
static conversion *reference_binding (tree, tree, tree, bool, int,
@@ -455,8 +455,8 @@ struct rejection_reason {
int expected;
/* The actual number of arguments in the call. */
int actual;
- /* Whether the call was a varargs call. */
- bool call_varargs_p;
+ /* Whether EXPECTED should be treated as a lower bound. */
+ bool least_p;
} arity;
/* Information about an argument conversion mismatch. */
struct conversion_info conversion;
@@ -628,12 +628,13 @@ alloc_rejection (enum rejection_reason_code code)
}
static struct rejection_reason *
-arity_rejection (tree first_arg, int expected, int actual)
+arity_rejection (tree first_arg, int expected, int actual, bool least_p = false)
{
struct rejection_reason *r = alloc_rejection (rr_arity);
int adjust = first_arg != NULL_TREE;
r->u.arity.expected = expected - adjust;
r->u.arity.actual = actual - adjust;
+ r->u.arity.least_p = least_p;
return r;
}
@@ -2241,6 +2242,56 @@ conv_flags (int i, int nargs, tree fn, tree arg, int flags)
return lflags;
}
+/* Build an appropriate 'this' conversion for the method FN and class
+ type CTYPE from the value ARG (having type ARGTYPE) to the type PARMTYPE.
+ This function modifies PARMTYPE, ARGTYPE and ARG. */
+
+static conversion *
+build_this_conversion (tree fn, tree ctype,
+ tree& parmtype, tree& argtype, tree& arg,
+ int flags, tsubst_flags_t complain)
+{
+ gcc_assert (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn));
+
+ /* The type of the implicit object parameter ('this') for
+ overload resolution is not always the same as for the
+ function itself; conversion functions are considered to
+ be members of the class being converted, and functions
+ introduced by a using-declaration are considered to be
+ members of the class that uses them.
+
+ Since build_over_call ignores the ICS for the `this'
+ parameter, we can just change the parm type. */
+ parmtype = cp_build_qualified_type (ctype,
+ cp_type_quals (TREE_TYPE (parmtype)));
+ bool this_p = true;
+ if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn)))
+ {
+ /* If the function has a ref-qualifier, the implicit
+ object parameter has reference type. */
+ bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn));
+ parmtype = cp_build_reference_type (parmtype, rv);
+ /* The special handling of 'this' conversions in compare_ics
+ does not apply if there is a ref-qualifier. */
+ this_p = false;
+ }
+ else
+ {
+ parmtype = build_pointer_type (parmtype);
+ /* We don't use build_this here because we don't want to
+ capture the object argument until we've chosen a
+ non-static member function. */
+ arg = build_address (arg);
+ argtype = lvalue_type (arg);
+ }
+ flags |= LOOKUP_ONLYCONVERTING;
+ conversion *t = implicit_conversion (parmtype, argtype, arg,
+ /*c_cast_p=*/false, flags, complain);
+ t->this_p = this_p;
+ return t;
+}
+
/* Create an overload candidate for the function or method FN called
with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
FLAGS is passed on to implicit_conversion.
@@ -2248,7 +2299,14 @@ conv_flags (int i, int nargs, tree fn, tree arg, int flags)
This does not change ARGS.
CTYPE, if non-NULL, is the type we want to pretend this function
- comes from for purposes of overload resolution. */
+ comes from for purposes of overload resolution.
+
+ SHORTCUT_BAD_CONVS controls how we handle "bad" argument conversions.
+ If true, we stop computing conversions upon seeing the first bad
+ conversion. This is used by add_candidates to avoid computing
+ more conversions than necessary in the presence of a strictly viable
+ candidate, while preserving the defacto behavior of overload resolution
+ when it turns out there are only non-strictly viable candidates. */
static struct z_candidate *
add_function_candidate (struct z_candidate **candidates,
@@ -2256,6 +2314,7 @@ add_function_candidate (struct z_candidate **candidates,
const vec<tree, va_gc> *args, tree access_path,
tree conversion_path, int flags,
conversion **convs,
+ bool shortcut_bad_convs,
tsubst_flags_t complain)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
@@ -2377,8 +2436,6 @@ add_function_candidate (struct z_candidate **candidates,
{
tree argtype, to_type;
tree arg;
- conversion *t;
- int is_this;
if (parmnode == void_list_node)
break;
@@ -2397,54 +2454,23 @@ add_function_candidate (struct z_candidate **candidates,
(*args)[i + skip - (first_arg != NULL_TREE ? 1 : 0)]);
argtype = lvalue_type (arg);
- is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && ! DECL_CONSTRUCTOR_P (fn));
-
+ conversion *t;
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
-
- parmnode = TREE_CHAIN (parmnode);
-
- /* The type of the implicit object parameter ('this') for
- overload resolution is not always the same as for the
- function itself; conversion functions are considered to
- be members of the class being converted, and functions
- introduced by a using-declaration are considered to be
- members of the class that uses them.
-
- Since build_over_call ignores the ICS for the `this'
- parameter, we can just change the parm type. */
- if (ctype && is_this)
+ if (i == 0
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn))
+ t = build_this_conversion (fn, ctype, parmtype, argtype, arg,
+ flags, complain);
+ else
{
- parmtype = cp_build_qualified_type
- (ctype, cp_type_quals (TREE_TYPE (parmtype)));
- if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn)))
- {
- /* If the function has a ref-qualifier, the implicit
- object parameter has reference type. */
- bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn));
- parmtype = cp_build_reference_type (parmtype, rv);
- /* The special handling of 'this' conversions in compare_ics
- does not apply if there is a ref-qualifier. */
- is_this = false;
- }
- else
- {
- parmtype = build_pointer_type (parmtype);
- /* We don't use build_this here because we don't want to
- capture the object argument until we've chosen a
- non-static member function. */
- arg = build_address (arg);
- argtype = lvalue_type (arg);
- }
+ int lflags = conv_flags (i, len-skip, fn, arg, flags);
+ t = implicit_conversion (parmtype, argtype, arg,
+ /*c_cast_p=*/false, lflags, complain);
}
-
- int lflags = conv_flags (i, len-skip, fn, arg, flags);
-
- t = implicit_conversion (parmtype, argtype, arg,
- /*c_cast_p=*/false, lflags, complain);
to_type = parmtype;
+ parmnode = TREE_CHAIN (parmnode);
}
else
{
@@ -2453,9 +2479,6 @@ add_function_candidate (struct z_candidate **candidates,
to_type = argtype;
}
- if (t && is_this)
- t->this_p = true;
-
convs[i] = t;
if (! t)
{
@@ -2470,7 +2493,8 @@ add_function_candidate (struct z_candidate **candidates,
viable = -1;
reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type,
EXPR_LOCATION (arg));
-
+ if (shortcut_bad_convs)
+ break;
}
}
@@ -3354,7 +3378,9 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
This does not change ARGLIST. The RETURN_TYPE is the desired type
for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are
as for add_function_candidate. If an OBJ is supplied, FLAGS and
- CTYPE are ignored, and OBJ is as for add_conv_candidate. */
+ CTYPE are ignored, and OBJ is as for add_conv_candidate.
+
+ SHORTCUT_BAD_CONVS is as in add_function_candidate. */
static struct z_candidate*
add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
@@ -3362,7 +3388,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
const vec<tree, va_gc> *arglist, tree return_type,
tree access_path, tree conversion_path,
int flags, tree obj, unification_kind_t strict,
- tsubst_flags_t complain)
+ bool shortcut_bad_convs, tsubst_flags_t complain)
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
@@ -3452,9 +3478,73 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
}
gcc_assert (ia == nargs_without_in_chrg);
+ if (!obj && explicit_targs)
+ {
+ /* Check that there's no obvious arity mismatch before proceeding with
+ deduction. This avoids substituting explicit template arguments
+ into the template (which could result in an error outside the
+ immediate context) when the resulting candidate would be unviable
+ anyway. */
+ int min_arity = 0, max_arity = 0;
+ tree parms = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
+ parms = skip_artificial_parms_for (tmpl, parms);
+ for (; parms != void_list_node; parms = TREE_CHAIN (parms))
+ {
+ if (!parms || PACK_EXPANSION_P (TREE_VALUE (parms)))
+ {
+ max_arity = -1;
+ break;
+ }
+ if (TREE_PURPOSE (parms))
+ /* A parameter with a default argument. */
+ ++max_arity;
+ else
+ ++min_arity, ++max_arity;
+ }
+ if (ia < (unsigned)min_arity)
+ {
+ /* Too few arguments. */
+ reason = arity_rejection (NULL_TREE, min_arity, ia,
+ /*least_p=*/(max_arity == -1));
+ goto fail;
+ }
+ else if (max_arity != -1 && ia > (unsigned)max_arity)
+ {
+ /* Too many arguments. */
+ reason = arity_rejection (NULL_TREE, max_arity, ia);
+ goto fail;
+ }
+ }
+
errs = errorcount+sorrycount;
if (!obj)
- convs = alloc_conversions (nargs);
+ {
+ convs = alloc_conversions (nargs);
+
+ if (shortcut_bad_convs
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl)
+ && !DECL_CONSTRUCTOR_P (tmpl))
+ {
+ /* Check the 'this' conversion before proceeding with deduction.
+ This is effectively an extension of the DR 1391 resolution
+ that we perform in check_non_deducible_conversions, though it's
+ convenient to do this extra check here instead of there. */
+ tree parmtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (tmpl)));
+ tree argtype = lvalue_type (first_arg);
+ tree arg = first_arg;
+ conversion *t = build_this_conversion (tmpl, ctype,
+ parmtype, argtype, arg,
+ flags, complain);
+ convs[0] = t;
+ if (t->bad_p)
+ {
+ reason = bad_arg_conversion_rejection (first_arg, 0,
+ arg, parmtype,
+ EXPR_LOCATION (arg));
+ goto fail;
+ }
+ }
+ }
fn = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
nargs_without_in_chrg,
@@ -3501,7 +3591,8 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
else
cand = add_function_candidate (candidates, fn, ctype,
first_arg, arglist, access_path,
- conversion_path, flags, convs, complain);
+ conversion_path, flags, convs,
+ shortcut_bad_convs, complain);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
@@ -3527,8 +3618,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
return cand;
fail:
- return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL,
- access_path, conversion_path, 0, reason, flags);
+ int viable = (reason->code == rr_bad_arg_conversion ? -1 : 0);
+ return add_candidate (candidates, tmpl, first_arg, arglist, nargs, convs,
+ access_path, conversion_path, viable, reason, flags);
}
@@ -3537,13 +3629,15 @@ add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
tree explicit_targs, tree first_arg,
const vec<tree, va_gc> *arglist, tree return_type,
tree access_path, tree conversion_path, int flags,
- unification_kind_t strict, tsubst_flags_t complain)
+ unification_kind_t strict, bool shortcut_bad_convs,
+ tsubst_flags_t complain)
{
return
add_template_candidate_real (candidates, tmpl, ctype,
explicit_targs, first_arg, arglist,
return_type, access_path, conversion_path,
- flags, NULL_TREE, strict, complain);
+ flags, NULL_TREE, strict, shortcut_bad_convs,
+ complain);
}
/* Create an overload candidate for the conversion function template TMPL,
@@ -3569,7 +3663,7 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
NULL_TREE, arglist, return_type, access_path,
conversion_path, 0, obj, DEDUCE_CALL,
- complain);
+ /*shortcut_bad_convs=*/false, complain);
}
/* The CANDS are the set of candidates that were considered for
@@ -3725,12 +3819,19 @@ print_conversion_rejection (location_t loc, struct conversion_info *info,
HAVE. */
static void
-print_arity_information (location_t loc, unsigned int have, unsigned int want)
-{
- inform_n (loc, want,
- " candidate expects %d argument, %d provided",
- " candidate expects %d arguments, %d provided",
- want, have);
+print_arity_information (location_t loc, unsigned int have, unsigned int want,
+ bool least_p)
+{
+ if (least_p)
+ inform_n (loc, want,
+ " candidate expects at least %d argument, %d provided",
+ " candidate expects at least %d arguments, %d provided",
+ want, have);
+ else
+ inform_n (loc, want,
+ " candidate expects %d argument, %d provided",
+ " candidate expects %d arguments, %d provided",
+ want, have);
}
/* Print information about one overload candidate CANDIDATE. MSGSTR
@@ -3794,7 +3895,8 @@ print_z_candidate (location_t loc, const char *msgstr,
{
case rr_arity:
print_arity_information (cloc, r->u.arity.actual,
- r->u.arity.expected);
+ r->u.arity.expected,
+ r->u.arity.least_p);
break;
case rr_arg_conversion:
print_conversion_rejection (cloc, &r->u.conversion, fn);
@@ -4073,6 +4175,9 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
flags |= LOOKUP_NO_CONVERSION;
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
flags |= LOOKUP_NO_NARROWING;
+ /* Prevent add_candidates from treating a non-strictly viable candidate
+ as unviable. */
+ complain |= tf_conv;
/* It's OK to bind a temporary for converting constructor arguments, but
not in converting the return value of a conversion operator. */
@@ -6013,6 +6118,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
/* Delay creating the implicit this parameter until it is needed. */
non_static_args = NULL;
+ bool seen_strictly_viable = any_strictly_viable (*candidates);
/* If there's a non-template perfect match, we don't need to consider
templates. So check non-templates first. This optimization is only
really needed for the defaulted copy constructor of tuple and the like
@@ -6024,6 +6130,19 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
else /*if (flags & LOOKUP_DEFAULTED)*/
which = non_templates;
+ /* During overload resolution, we first consider each function under the
+ assumption that we'll eventually find a strictly viable candidate.
+ This allows us to circumvent our defacto behavior when checking
+ argument conversions and shortcut consideration of the candidate
+ upon encountering the first bad conversion. If this assumption
+ turns out to be false, and all candidates end up being non-strictly
+ viable, then we reconsider such candidates under the defacto behavior.
+ This trick is important for pruning member function overloads according
+ to their const/ref-qualifiers (since all 'this' conversions are at
+ worst bad) without breaking -fpermissive. */
+ tree bad_fns = NULL_TREE;
+ bool shortcut_bad_convs = true;
+
again:
for (tree fn : lkp_range (fns))
{
@@ -6070,18 +6189,22 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
}
if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (candidates,
- fn,
- ctype,
- explicit_targs,
- fn_first_arg,
- fn_args,
- return_type,
- access_path,
- conversion_path,
- flags,
- strict,
- complain);
+ {
+ if (!add_template_candidate (candidates,
+ fn,
+ ctype,
+ explicit_targs,
+ fn_first_arg,
+ fn_args,
+ return_type,
+ access_path,
+ conversion_path,
+ flags,
+ strict,
+ shortcut_bad_convs,
+ complain))
+ continue;
+ }
else
{
add_function_candidate (candidates,
@@ -6093,16 +6216,57 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
conversion_path,
flags,
NULL,
+ shortcut_bad_convs,
complain);
if (perfect_candidate_p (*candidates))
seen_perfect = true;
}
+
+ z_candidate *cand = *candidates;
+ if (cand->viable == 1)
+ seen_strictly_viable = true;
+
+ if (cand->viable == -1
+ && shortcut_bad_convs
+ && !cand->convs[cand->reversed () ? 0 : cand->num_convs - 1])
+ {
+ /* This candidate has been tentatively marked non-strictly viable,
+ and we didn't compute all argument conversions for it (having
+ stopped at the first bad conversion). Add the function to BAD_FNS
+ to fully reconsider later if we don't find any strictly viable
+ candidates. */
+ if (complain & (tf_error | tf_conv))
+ {
+ bad_fns = lookup_add (fn, bad_fns);
+ *candidates = (*candidates)->next;
+ }
+ else
+ /* But if we're in a SFINAE context, just mark this candidate as
+ unviable outright and avoid potentially reconsidering it.
+ This is safe to do because in a SFINAE context, performing a bad
+ conversion is always an error (even with -fpermissive), so a
+ non-strictly viable candidate is effectively unviable anyway. */
+ cand->viable = 0;
+ }
}
if (which == non_templates && !seen_perfect)
{
which = templates;
goto again;
}
+ else if (which == templates
+ && !seen_strictly_viable
+ && shortcut_bad_convs
+ && bad_fns)
+ {
+ /* None of the candidates are strictly viable, so consider again those
+ functions in BAD_FNS, this time without shortcutting bad conversions
+ so that all their argument conversions are computed. */
+ which = either;
+ fns = bad_fns;
+ shortcut_bad_convs = false;
+ goto again;
+ }
}
/* Returns 1 if P0145R2 says that the LHS of operator CODE is evaluated first,
@@ -9459,7 +9623,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
already_used = true;
}
else
- cp_warn_deprecated_use (fn, complain);
+ cp_handle_deprecated_or_unavailable (fn, complain);
if (eliding_temp && DECL_BASE_CONSTRUCTOR_P (fn)
&& !make_base_init_ok (arg))
@@ -9533,7 +9697,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
suppress_warning (val, OPT_Wunused);
}
- cp_warn_deprecated_use (fn, complain);
+ cp_handle_deprecated_or_unavailable (fn, complain);
return val;
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 7138e30..f16e50b 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4634,7 +4634,7 @@ build_base_field (record_layout_info rli, tree binfo, tree access,
DECL_FIELD_OFFSET (decl) = BINFO_OFFSET (binfo);
DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT);
- DECL_FIELD_ABI_IGNORED (decl) = 1;
+ SET_DECL_FIELD_ABI_IGNORED (decl, 1);
}
/* An empty virtual base causes a class to be non-empty
@@ -5719,6 +5719,7 @@ type_build_ctor_call (tree t)
tree fn = *iter;
if (!DECL_ARTIFICIAL (fn)
|| TREE_DEPRECATED (fn)
+ || TREE_UNAVAILABLE (fn)
|| DECL_DELETED_FN (fn))
return true;
}
@@ -5747,6 +5748,7 @@ type_build_dtor_call (tree t)
tree fn = *iter;
if (!DECL_ARTIFICIAL (fn)
|| TREE_DEPRECATED (fn)
+ || TREE_UNAVAILABLE (fn)
|| DECL_DELETED_FN (fn))
return true;
}
@@ -6117,6 +6119,10 @@ check_bases_and_members (tree t)
&& !DECL_ARTIFICIAL (fn)
&& DECL_DEFAULTED_IN_CLASS_P (fn))
{
+ /* ...except handle comparisons later, in finish_struct_1. */
+ if (special_function_p (fn) == sfk_comparison)
+ continue;
+
int copy = copy_fn_p (fn);
if (copy > 0)
{
@@ -6656,7 +6662,7 @@ layout_class_type (tree t, tree *virtuals_p)
}
else if (might_overlap && is_empty_class (type))
{
- DECL_FIELD_ABI_IGNORED (field) = 1;
+ SET_DECL_FIELD_ABI_IGNORED (field, 1);
layout_empty_base_or_field (rli, field, empty_base_offsets);
}
else
@@ -6744,6 +6750,23 @@ layout_class_type (tree t, tree *virtuals_p)
normalize_rli (rli);
}
+ /* We used to remove zero width bitfields at this point since PR42217,
+ while the C FE never did that. That caused ABI differences on various
+ targets. Set the DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD flag on them
+ instead, so that the backends can emit -Wpsabi warnings in the cases
+ where the ABI changed. */
+ for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && DECL_C_BIT_FIELD (field)
+ /* We should not be confused by the fact that grokbitfield
+ temporarily sets the width of the bit field into
+ DECL_BIT_FIELD_REPRESENTATIVE (field).
+ check_bitfield_decl eventually sets DECL_SIZE (field)
+ to that width. */
+ && (DECL_SIZE (field) == NULL_TREE
+ || integer_zerop (DECL_SIZE (field))))
+ SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field, 1);
+
if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
/* T needs a different layout as a base (eliding virtual bases
@@ -7448,7 +7471,14 @@ finish_struct_1 (tree t)
for any static member objects of the type we're working on. */
for (x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
if (DECL_DECLARES_FUNCTION_P (x))
- DECL_IN_AGGR_P (x) = false;
+ {
+ /* Synthesize constexpr defaulted comparisons. */
+ if (!DECL_ARTIFICIAL (x)
+ && DECL_DEFAULTED_IN_CLASS_P (x)
+ && special_function_p (x) == sfk_comparison)
+ defaulted_late_check (x);
+ DECL_IN_AGGR_P (x) = false;
+ }
else if (VAR_P (x) && TREE_STATIC (x)
&& TREE_TYPE (x) != error_mark_node
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t))
@@ -8352,7 +8382,7 @@ resolve_address_of_overloaded_function (tree target_type,
nargs = list_length (target_arg_types);
args = XALLOCAVEC (tree, nargs);
for (arg = target_arg_types, ia = 0;
- arg != NULL_TREE && arg != void_list_node;
+ arg != NULL_TREE;
arg = TREE_CHAIN (arg), ++ia)
args[ia] = TREE_VALUE (arg);
nargs = ia;
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index b9c0062..c5f01b9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const-call.h"
#include "stor-layout.h"
#include "cgraph.h"
+#include "opts.h"
static bool verify_constant (tree, bool, bool *, bool *);
#define VERIFY_CONSTANT(X) \
@@ -109,14 +110,15 @@ ensure_literal_type_for_constexpr_object (tree decl)
explain_non_literal_class (type);
decl = error_mark_node;
}
- else
+ else if (cxx_dialect < cxx23)
{
if (!is_instantiation_of_constexpr (current_function_decl))
{
auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (decl),
"variable %qD of non-literal type %qT in "
- "%<constexpr%> function", decl, type);
+ "%<constexpr%> function only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>", decl, type);
explain_non_literal_class (type);
decl = error_mark_node;
}
@@ -865,7 +867,7 @@ maybe_save_constexpr_fundef (tree fun)
if (processing_template_decl
|| !DECL_DECLARED_CONSTEXPR_P (fun)
|| cp_function_chain->invalid_constexpr
- || DECL_CLONED_FUNCTION_P (fun))
+ || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)))
return;
if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
@@ -942,7 +944,6 @@ explain_invalid_constexpr_fn (tree fun)
{
static hash_set<tree> *diagnosed;
tree body;
- location_t save_loc;
/* Only diagnose defaulted functions, lambdas, or instantiations. */
if (!DECL_DEFAULTED_FN (fun)
&& !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun))
@@ -957,7 +958,7 @@ explain_invalid_constexpr_fn (tree fun)
/* Already explained. */
return;
- save_loc = input_location;
+ iloc_sentinel ils = input_location;
if (!lambda_static_thunk_p (fun))
{
/* Diagnostics should completely ignore the static thunk, so leave
@@ -985,7 +986,6 @@ explain_invalid_constexpr_fn (tree fun)
cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
}
}
- input_location = save_loc;
}
/* Objects of this type represent calls to constexpr functions
@@ -1609,24 +1609,24 @@ addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data)
all arguments and bind their values to correspondings
parameters, making up the NEW_CALL context. */
-static void
-cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
- constexpr_call *new_call,
+static tree
+cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
bool *non_constant_p, bool *overflow_p,
bool *non_constant_args)
{
const int nargs = call_expr_nargs (t);
- tree fun = new_call->fundef->decl;
- tree parms = new_call->fundef->parms;
+ tree parms = DECL_ARGUMENTS (fun);
int i;
/* We don't record ellipsis args below. */
int nparms = list_length (parms);
int nbinds = nargs < nparms ? nargs : nparms;
- tree binds = new_call->bindings = make_tree_vec (nbinds);
+ tree binds = make_tree_vec (nbinds);
for (i = 0; i < nargs; ++i)
{
tree x, arg;
tree type = parms ? TREE_TYPE (parms) : void_type_node;
+ if (parms && DECL_BY_REFERENCE (parms))
+ type = TREE_TYPE (type);
x = get_nth_callarg (t, i);
/* For member function, the first argument is a pointer to the implied
object. For a constructor, it might still be a dummy object, in
@@ -1647,7 +1647,7 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p);
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p && ctx->quiet)
- return;
+ break;
/* Just discard ellipsis args after checking their constantitude. */
if (!parms)
continue;
@@ -1698,6 +1698,8 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
}
parms = TREE_CHAIN (parms);
}
+
+ return binds;
}
/* Variables and functions to manage constexpr call expansion context.
@@ -2374,7 +2376,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
return t;
}
- if (DECL_CLONED_FUNCTION_P (fun))
+ if (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun))
fun = DECL_CLONED_FUNCTION (fun);
if (is_ubsan_builtin_p (fun))
@@ -2564,6 +2566,26 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
}
}
+ bool non_constant_args = false;
+ new_call.bindings
+ = cxx_bind_parameters_in_call (ctx, t, fun, non_constant_p,
+ overflow_p, &non_constant_args);
+
+ /* We build up the bindings list before we know whether we already have this
+ call cached. If we don't end up saving these bindings, ggc_free them when
+ this function exits. */
+ class free_bindings
+ {
+ tree *bindings;
+ public:
+ free_bindings (tree &b): bindings (&b) { }
+ ~free_bindings () { if (bindings) ggc_free (*bindings); }
+ void preserve () { bindings = NULL; }
+ } fb (new_call.bindings);
+
+ if (*non_constant_p)
+ return t;
+
/* We can't defer instantiating the function any longer. */
if (!DECL_INITIAL (fun)
&& DECL_TEMPLOID_INSTANTIATION (fun)
@@ -2572,6 +2594,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
location_t save_loc = input_location;
input_location = loc;
++function_depth;
+ if (ctx->manifestly_const_eval)
+ FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true;
instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
--function_depth;
input_location = save_loc;
@@ -2613,25 +2637,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
}
}
- bool non_constant_args = false;
- cxx_bind_parameters_in_call (ctx, t, &new_call,
- non_constant_p, overflow_p, &non_constant_args);
-
- /* We build up the bindings list before we know whether we already have this
- call cached. If we don't end up saving these bindings, ggc_free them when
- this function exits. */
- class free_bindings
- {
- tree *bindings;
- public:
- free_bindings (tree &b): bindings (&b) { }
- ~free_bindings () { if (bindings) ggc_free (*bindings); }
- void preserve () { bindings = NULL; }
- } fb (new_call.bindings);
-
- if (*non_constant_p)
- return t;
-
depth_ok = push_cx_call_context (t);
/* Remember the object we are constructing or destructing. */
@@ -2787,12 +2792,34 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
&jump_target);
if (DECL_CONSTRUCTOR_P (fun))
- /* This can be null for a subobject constructor call, in
- which case what we care about is the initialization
- side-effects rather than the value. We could get at the
- value by evaluating *this, but we don't bother; there's
- no need to put such a call in the hash table. */
- result = lval ? ctx->object : ctx->ctor;
+ {
+ /* This can be null for a subobject constructor call, in
+ which case what we care about is the initialization
+ side-effects rather than the value. We could get at the
+ value by evaluating *this, but we don't bother; there's
+ no need to put such a call in the hash table. */
+ result = lval ? ctx->object : ctx->ctor;
+
+ /* If we've just evaluated a subobject constructor call for an
+ empty union member, it might not have produced a side effect
+ that actually activated the union member. So produce such a
+ side effect now to ensure the union appears initialized. */
+ if (!result && new_obj
+ && TREE_CODE (new_obj) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE
+ (TREE_OPERAND (new_obj, 0))) == UNION_TYPE
+ && is_really_empty_class (TREE_TYPE (new_obj),
+ /*ignore_vptr*/false))
+ {
+ tree activate = build2 (MODIFY_EXPR, TREE_TYPE (new_obj),
+ new_obj,
+ build_constructor (TREE_TYPE (new_obj),
+ NULL));
+ cxx_eval_constant_expression (ctx, activate, lval,
+ non_constant_p, overflow_p);
+ ggc_free (activate);
+ }
+ }
else if (VOID_TYPE_P (TREE_TYPE (res)))
result = void_node;
else
@@ -6075,6 +6102,37 @@ inline_asm_in_constexpr_error (location_t loc)
"%<constexpr%> function in C++20");
}
+/* We're getting the constant value of DECL in a manifestly constant-evaluated
+ context; maybe complain about that. */
+
+static void
+maybe_warn_about_constant_value (location_t loc, tree decl)
+{
+ static bool explained = false;
+ if (cxx_dialect >= cxx17
+ && warn_interference_size
+ && !OPTION_SET_P (param_destruct_interfere_size)
+ && DECL_CONTEXT (decl) == std_node
+ && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size")
+ && (LOCATION_FILE (input_location) != main_input_filename
+ || module_exporting_p ())
+ && warning_at (loc, OPT_Winterference_size, "use of %qD", decl)
+ && !explained)
+ {
+ explained = true;
+ inform (loc, "its value can vary between compiler versions or "
+ "with different %<-mtune%> or %<-mcpu%> flags");
+ inform (loc, "if this use is part of a public ABI, change it to "
+ "instead use a constant variable you define");
+ inform (loc, "the default value for the current CPU tuning "
+ "is %d bytes", param_destruct_interfere_size);
+ inform (loc, "you can stabilize this value with %<--param "
+ "hardware_destructive_interference_size=%d%>, or disable "
+ "this warning with %<-Wno-interference-size%>",
+ param_destruct_interfere_size);
+ }
+}
+
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -6219,6 +6277,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = *p;
break;
}
+ if (ctx->manifestly_const_eval)
+ maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
@@ -6290,6 +6350,26 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = void_node;
break;
}
+
+ if (VAR_P (r)
+ && (TREE_STATIC (r) || CP_DECL_THREAD_LOCAL_P (r))
+ /* Allow __FUNCTION__ etc. */
+ && !DECL_ARTIFICIAL (r))
+ {
+ gcc_assert (cxx_dialect >= cxx23);
+ if (!ctx->quiet)
+ {
+ if (CP_DECL_THREAD_LOCAL_P (r))
+ error_at (loc, "control passes through declaration of %qD "
+ "with thread storage duration", r);
+ else
+ error_at (loc, "control passes through declaration of %qD "
+ "with static storage duration", r);
+ }
+ *non_constant_p = true;
+ break;
+ }
+
if (AGGREGATE_TYPE_P (TREE_TYPE (r))
|| VECTOR_TYPE_P (TREE_TYPE (r)))
{
@@ -6994,10 +7074,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case GOTO_EXPR:
- *jump_target = TREE_OPERAND (t, 0);
- gcc_assert (breaks (jump_target) || continues (jump_target)
- /* Allow for jumping to a cdtor_label. */
- || returns (jump_target));
+ if (breaks (&TREE_OPERAND (t, 0))
+ || continues (&TREE_OPERAND (t, 0))
+ /* Allow for jumping to a cdtor_label. */
+ || returns (&TREE_OPERAND (t, 0)))
+ *jump_target = TREE_OPERAND (t, 0);
+ else
+ {
+ gcc_assert (cxx_dialect >= cxx23);
+ if (!ctx->quiet)
+ error_at (loc, "%<goto%> is not a constant expression");
+ *non_constant_p = true;
+ }
break;
case LOOP_EXPR:
@@ -7062,7 +7150,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
}
- if (!processing_template_decl
+ if (!value_dependent_expression_p (t)
&& !uid_sensitive_constexpr_evaluation_p ())
r = evaluate_concept_check (t);
else
@@ -7309,7 +7397,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
auto_vec<tree, 16> cleanups;
global_ctx.cleanups = &cleanups;
- instantiate_constexpr_fns (r);
+ if (manifestly_const_eval)
+ instantiate_constexpr_fns (r);
r = cxx_eval_constant_expression (&ctx, r,
false, &non_constant_p, &overflow_p);
@@ -7445,6 +7534,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
}
}
+ /* Remember the original location if that wouldn't need a wrapper. */
+ if (location_t loc = EXPR_LOCATION (t))
+ protected_set_expr_location (r, loc);
+
return r;
}
@@ -7458,6 +7551,18 @@ cxx_constant_value (tree t, tree decl)
return cxx_eval_outermost_constant_expr (t, false, true, true, false, decl);
}
+/* As above, but respect SFINAE. */
+
+tree
+cxx_constant_value_sfinae (tree t, tsubst_flags_t complain)
+{
+ bool sfinae = !(complain & tf_error);
+ tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true);
+ if (sfinae && !TREE_CONSTANT (r))
+ r = error_mark_node;
+ return r;
+}
+
/* Like cxx_constant_value, but used for evaluation of constexpr destructors
of constexpr variables. The actual initializer of DECL is not modified. */
@@ -8665,18 +8770,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
tmp = DECL_EXPR_DECL (t);
if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
{
- if (TREE_STATIC (tmp))
+ if (CP_DECL_THREAD_LOCAL_P (tmp))
{
if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
- "%<static%> in %<constexpr%> context", tmp);
+ "%<thread_local%> in %<constexpr%> context", tmp);
return false;
}
- else if (CP_DECL_THREAD_LOCAL_P (tmp))
+ else if (TREE_STATIC (tmp))
{
if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
- "%<thread_local%> in %<constexpr%> context", tmp);
+ "%<static%> in %<constexpr%> context", tmp);
return false;
}
else if (!check_for_uninitialized_const_var
@@ -8954,10 +9059,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case LABEL_EXPR:
t = LABEL_EXPR_LABEL (t);
- if (DECL_ARTIFICIAL (t))
+ if (DECL_ARTIFICIAL (t) || cxx_dialect >= cxx23)
return true;
else if (flags & tf_error)
- error_at (loc, "label definition is not a constant expression");
+ error_at (loc, "label definition in %<constexpr%> function only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>");
return false;
case ANNOTATE_EXPR:
@@ -8972,6 +9078,16 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case CO_RETURN_EXPR:
return false;
+ case NONTYPE_ARGUMENT_PACK:
+ {
+ tree args = ARGUMENT_PACK_ARGS (t);
+ int len = TREE_VEC_LENGTH (args);
+ for (int i = 0; i < len; ++i)
+ if (!RECUR (TREE_VEC_ELT (args, i), any))
+ return false;
+ return true;
+ }
+
default:
if (objc_non_constant_expr_p (t))
return false;
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 1aaf1e2..2896efd 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -918,20 +918,22 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
tmpl = most_general_template (tmpl);
}
+ d = tmpl ? tmpl : decl;
+
/* If we're not diagnosing errors, use cached constraints, if any. */
if (!diag)
- if (tree *p = hash_map_safe_get (normalized_map, tmpl))
+ if (tree *p = hash_map_safe_get (normalized_map, d))
return *p;
tree norm = NULL_TREE;
- if (tree ci = get_constraints (decl))
+ if (tree ci = get_constraints (d))
{
push_access_scope_guard pas (decl);
norm = get_normalized_constraints_from_info (ci, tmpl, diag);
}
if (!diag)
- hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
+ hash_map_safe_put<hm_ggc> (normalized_map, d, norm);
return norm;
}
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 47c79e5..9017902 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -215,7 +215,19 @@ static GTY(()) tree coro_await_ready_identifier;
static GTY(()) tree coro_await_suspend_identifier;
static GTY(()) tree coro_await_resume_identifier;
-/* Create the identifiers used by the coroutines library interfaces. */
+/* Accessors for the coroutine frame state used by the implementation. */
+
+static GTY(()) tree coro_resume_fn_id;
+static GTY(()) tree coro_destroy_fn_id;
+static GTY(()) tree coro_promise_id;
+static GTY(()) tree coro_frame_needs_free_id;
+static GTY(()) tree coro_resume_index_id;
+static GTY(()) tree coro_self_handle_id;
+static GTY(()) tree coro_actor_continue_id;
+static GTY(()) tree coro_frame_i_a_r_c_id;
+
+/* Create the identifiers used by the coroutines library interfaces and
+ the implementation frame state. */
static void
coro_init_identifiers ()
@@ -241,6 +253,16 @@ coro_init_identifiers ()
coro_await_ready_identifier = get_identifier ("await_ready");
coro_await_suspend_identifier = get_identifier ("await_suspend");
coro_await_resume_identifier = get_identifier ("await_resume");
+
+ /* Coroutine state frame field accessors. */
+ coro_resume_fn_id = get_identifier ("_Coro_resume_fn");
+ coro_destroy_fn_id = get_identifier ("_Coro_destroy_fn");
+ coro_promise_id = get_identifier ("_Coro_promise");
+ coro_frame_needs_free_id = get_identifier ("_Coro_frame_needs_free");
+ coro_frame_i_a_r_c_id = get_identifier ("_Coro_initial_await_resume_called");
+ coro_resume_index_id = get_identifier ("_Coro_resume_index");
+ coro_self_handle_id = get_identifier ("_Coro_self_handle");
+ coro_actor_continue_id = get_identifier ("_Coro_actor_continue");
}
/* Trees we only need to set up once. */
@@ -513,12 +535,12 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
/* Build a proxy for a handle to "self" as the param to
await_suspend() calls. */
coro_info->self_h_proxy
- = build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
+ = build_lang_decl (VAR_DECL, coro_self_handle_id,
coro_info->handle_type);
/* Build a proxy for the promise so that we can perform lookups. */
coro_info->promise_proxy
- = build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
+ = build_lang_decl (VAR_DECL, coro_promise_id,
coro_info->promise_type);
/* Note where we first saw a coroutine keyword. */
@@ -986,6 +1008,7 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
}
/* Only build a temporary if we need it. */
+ STRIP_NOPS (e_proxy);
if (TREE_CODE (e_proxy) == PARM_DECL
|| (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
{
@@ -1030,7 +1053,8 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
else if (same_type_p (susp_return_type, boolean_type_node))
ok = true;
else if (TREE_CODE (susp_return_type) == RECORD_TYPE
- && CLASS_TYPE_P (susp_return_type))
+ && CLASS_TYPE_P (susp_return_type)
+ && CLASSTYPE_TEMPLATE_INFO (susp_return_type))
{
tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
if (tt == coro_handle_templ)
@@ -1094,13 +1118,15 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
a, e_proxy, o, awaiter_calls,
build_int_cst (integer_type_node,
(int) suspend_kind));
+ TREE_SIDE_EFFECTS (await_expr) = true;
if (te)
{
TREE_OPERAND (te, 1) = await_expr;
+ TREE_SIDE_EFFECTS (te) = true;
await_expr = te;
}
- tree t = convert_from_reference (await_expr);
- return t;
+ SET_EXPR_LOCATION (await_expr, loc);
+ return convert_from_reference (await_expr);
}
tree
@@ -1126,8 +1152,13 @@ finish_co_await_expr (location_t kw, tree expr)
co_await with the expression unchanged. */
tree functype = TREE_TYPE (current_function_decl);
if (dependent_type_p (functype) || type_dependent_expression_p (expr))
- return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
- NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
+ {
+ tree aw_expr = build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
+ NULL_TREE, NULL_TREE, NULL_TREE,
+ integer_zero_node);
+ TREE_SIDE_EFFECTS (aw_expr) = true;
+ return aw_expr;
+ }
/* We must be able to look up the "await_transform" method in the scope of
the promise type, and obtain its return type. */
@@ -1164,14 +1195,7 @@ finish_co_await_expr (location_t kw, tree expr)
}
/* Now we want to build co_await a. */
- tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
- if (op != error_mark_node)
- {
- TREE_SIDE_EFFECTS (op) = 1;
- SET_EXPR_LOCATION (op, kw);
- }
-
- return op;
+ return build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
}
/* Take the EXPR given and attempt to build:
@@ -1474,6 +1498,29 @@ coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
return coro_build_expr_stmt (t, loc);
}
+/* Helpers to build an artificial var, with location LOC, NAME and TYPE, in
+ CTX, and with initializer INIT. */
+
+static tree
+coro_build_artificial_var (location_t loc, tree name, tree type, tree ctx,
+ tree init)
+{
+ tree res = build_lang_decl (VAR_DECL, name, type);
+ DECL_SOURCE_LOCATION (res) = loc;
+ DECL_CONTEXT (res) = ctx;
+ DECL_ARTIFICIAL (res) = true;
+ DECL_INITIAL (res) = init;
+ return res;
+}
+
+static tree
+coro_build_artificial_var (location_t loc, const char *name, tree type,
+ tree ctx, tree init)
+{
+ return coro_build_artificial_var (loc, get_identifier (name),
+ type, ctx, init);
+}
+
/* Helpers for label creation:
1. Create a named label in the specified context. */
@@ -1841,10 +1888,6 @@ struct await_xform_data
{
tree actor_fn; /* Decl for context. */
tree actor_frame;
- tree promise_proxy;
- tree real_promise;
- tree self_h_proxy;
- tree real_self_h;
};
/* When we built the await expressions, we didn't know the coro frame
@@ -1865,7 +1908,6 @@ transform_await_expr (tree await_expr, await_xform_data *xform)
/* So, on entry, we have:
in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
We no longer need a [it had diagnostic value, maybe?]
- We need to replace the promise proxy in all elements
We need to replace the e_proxy in the awr_call. */
tree coro_frame_type = TREE_TYPE (xform->actor_frame);
@@ -1891,16 +1933,6 @@ transform_await_expr (tree await_expr, await_xform_data *xform)
TREE_OPERAND (await_expr, 1) = as;
}
- /* Now do the self_handle. */
- data.from = xform->self_h_proxy;
- data.to = xform->real_self_h;
- cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
-
- /* Now do the promise. */
- data.from = xform->promise_proxy;
- data.to = xform->real_promise;
- cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
-
return await_expr;
}
@@ -1934,6 +1966,7 @@ transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
struct param_info
{
tree field_id; /* The name of the copy in the coroutine frame. */
+ tree copy_var; /* The local var proxy for the frame copy. */
vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
tree frame_type; /* The type used to represent this parm in the frame. */
tree orig_type; /* The original type of the parm (not as passed). */
@@ -1974,8 +2007,7 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
local_vars_transform *lvd = (local_vars_transform *) d;
/* For each var in this bind expr (that has a frame id, which means it was
- accessed), build a frame reference for each and then walk the bind expr
- statements, substituting the frame ref for the original var. */
+ accessed), build a frame reference and add it as the DECL_VALUE_EXPR. */
if (TREE_CODE (*stmt) == BIND_EXPR)
{
@@ -1991,13 +2023,9 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
/* Re-write the variable's context to be in the actor func. */
DECL_CONTEXT (lvar) = lvd->context;
- /* For capture proxies, this could include the decl value expr. */
- if (local_var.is_lambda_capture || local_var.has_value_expr_p)
- {
- tree ve = DECL_VALUE_EXPR (lvar);
- cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
+ /* For capture proxies, this could include the decl value expr. */
+ if (local_var.is_lambda_capture || local_var.has_value_expr_p)
continue; /* No frame entry for this. */
- }
/* TODO: implement selective generation of fields when vars are
known not-used. */
@@ -2011,103 +2039,13 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
lvd->actor_frame, fld_ref, NULL_TREE);
local_var.field_idx = fld_idx;
- }
- /* FIXME: we should be able to do this in the loop above, but (at least
- for range for) there are cases where the DECL_INITIAL contains
- forward references.
- So, now we've built the revised var in the frame, substitute uses of
- it in initializers and the bind expr body. */
- for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
- lvar = DECL_CHAIN (lvar))
- {
- /* we need to walk some of the decl trees, which might contain
- references to vars replaced at a higher level. */
- cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
- NULL);
- cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
- cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
- NULL);
+ SET_DECL_VALUE_EXPR (lvar, fld_idx);
+ DECL_HAS_VALUE_EXPR_P (lvar) = true;
}
cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
-
- /* Now we have processed and removed references to the original vars,
- we can drop those from the bind - leaving capture proxies alone. */
- for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
- {
- bool existed;
- local_var_info &local_var
- = lvd->local_var_uses->get_or_insert (*pvar, &existed);
- gcc_checking_assert (existed);
-
- /* Leave lambda closure captures alone, we replace the *this
- pointer with the frame version and let the normal process
- deal with the rest.
- Likewise, variables with their value found elsewhere.
- Skip past unused ones too. */
- if (local_var.is_lambda_capture
- || local_var.has_value_expr_p
- || local_var.field_id == NULL_TREE)
- {
- pvar = &DECL_CHAIN (*pvar);
- continue;
- }
-
- /* Discard this one, we replaced it. */
- *pvar = DECL_CHAIN (*pvar);
- }
-
*do_subtree = 0; /* We've done the body already. */
return NULL_TREE;
}
-
- tree var_decl = *stmt;
- /* Look inside cleanups, we don't want to wrap a statement list in a
- cleanup. */
- bool needs_cleanup = true;
- if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
- var_decl = TREE_OPERAND (var_decl, 0);
- else
- needs_cleanup = false;
-
- /* Look inside the decl_expr for the actual var. */
- bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
- if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
- var_decl = DECL_EXPR_DECL (var_decl);
- else if (TREE_CODE (var_decl) != VAR_DECL)
- return NULL_TREE;
-
- /* VAR_DECLs that are not recorded can belong to the proxies we've placed
- for the promise and coroutine handle(s), to global vars or to compiler
- temporaries. Skip past these, we will handle them later. */
- local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
-
- if (local_var_i == NULL)
- return NULL_TREE;
-
- if (local_var_i->is_lambda_capture
- || local_var_i->is_static
- || local_var_i->has_value_expr_p)
- return NULL_TREE;
-
- /* This is our revised 'local' i.e. a frame slot. */
- tree revised = local_var_i->field_idx;
- gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
-
- if (decl_expr_p && DECL_INITIAL (var_decl))
- {
- location_t loc = DECL_SOURCE_LOCATION (var_decl);
- tree r
- = cp_build_modify_expr (loc, revised, INIT_EXPR,
- DECL_INITIAL (var_decl), tf_warning_or_error);
- if (needs_cleanup)
- r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
- *stmt = r;
- }
- else
- *stmt = revised;
-
- if (decl_expr_p)
- *do_subtree = 0; /* We've accounted for the nested use. */
return NULL_TREE;
}
@@ -2182,15 +2120,13 @@ coro_get_frame_dtor (tree coro_fp, tree orig, tree frame_size,
static void
build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
- tree orig, hash_map<tree, param_info> *param_uses,
- hash_map<tree, local_var_info> *local_var_uses,
- vec<tree, va_gc> *param_dtor_list, tree resume_fn_field,
- tree resume_idx_field, unsigned body_count, tree frame_size)
+ tree orig, hash_map<tree, local_var_info> *local_var_uses,
+ vec<tree, va_gc> *param_dtor_list,
+ tree resume_idx_var, unsigned body_count, tree frame_size)
{
verify_stmt_tree (fnbody);
/* Some things we inherit from the original function. */
tree handle_type = get_coroutine_handle_type (orig);
- tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
tree promise_type = get_coroutine_promise_type (orig);
tree promise_proxy = get_coroutine_promise_proxy (orig);
@@ -2208,13 +2144,12 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
tree top_block = make_node (BLOCK);
BIND_EXPR_BLOCK (actor_bind) = top_block;
- tree continuation = build_lang_decl (VAR_DECL,
- get_identifier ("actor.continue"),
- void_coro_handle_type);
- DECL_ARTIFICIAL (continuation) = 1;
- DECL_IGNORED_P (continuation) = 1;
- DECL_CONTEXT (continuation) = actor;
+ tree continuation = coro_build_artificial_var (loc, coro_actor_continue_id,
+ void_coro_handle_type, actor,
+ NULL_TREE);
+
BIND_EXPR_VARS (actor_bind) = continuation;
+ BLOCK_VARS (top_block) = BIND_EXPR_VARS (actor_bind) ;
/* Link in the block associated with the outer scope of the re-written
function body. */
@@ -2237,44 +2172,13 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Declare the continuation handle. */
add_decl_expr (continuation);
- /* Re-write param references in the body, no code should be generated
- here. */
- if (DECL_ARGUMENTS (orig))
- {
- tree arg;
- for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
- {
- bool existed;
- param_info &parm = param_uses->get_or_insert (arg, &existed);
- if (!parm.body_uses)
- continue; /* Wasn't used in the original function body. */
-
- tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
- /*protect=*/1, /*want_type=*/0,
- tf_warning_or_error);
- tree fld_idx = build3_loc (loc, COMPONENT_REF, parm.frame_type,
- actor_frame, fld_ref, NULL_TREE);
-
- /* We keep these in the frame as a regular pointer, so convert that
- back to the type expected. */
- if (parm.pt_ref)
- fld_idx = build1_loc (loc, CONVERT_EXPR, TREE_TYPE (arg), fld_idx);
-
- int i;
- tree *puse;
- FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
- *puse = fld_idx;
- }
- }
-
/* Re-write local vars, similarly. */
local_vars_transform xform_vars_data
= {actor, actor_frame, coro_frame_type, loc, local_var_uses};
cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
- tree resume_idx_name = get_identifier ("__resume_at");
- tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
- tf_warning_or_error);
+ tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
+ 1, 0, tf_warning_or_error);
tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
rat_field, NULL_TREE);
@@ -2331,6 +2235,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
finish_switch_stmt (destroy_dispatcher);
finish_then_clause (lsb_if);
+ begin_else_clause (lsb_if);
tree dispatcher = begin_switch_stmt ();
finish_switch_cond (rat, dispatcher);
@@ -2368,20 +2273,15 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Insert the prototype dispatcher. */
finish_switch_stmt (dispatcher);
+ finish_else_clause (lsb_if);
finish_if_stmt (lsb_if);
tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
add_stmt (r);
- /* actor's version of the promise. */
- tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
- tf_warning_or_error);
- tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
- tf_warning_or_error);
-
/* actor's coroutine 'self handle'. */
- tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
+ tree ash_m = lookup_member (coro_frame_type, coro_self_handle_id, 1,
0, tf_warning_or_error);
tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
false, tf_warning_or_error);
@@ -2401,37 +2301,13 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Now we know the real promise, and enough about the frame layout to
decide where to put things. */
- await_xform_data xform
- = {actor, actor_frame, promise_proxy, ap, self_h_proxy, ash};
+ await_xform_data xform = {actor, actor_frame};
/* Transform the await expressions in the function body. Only do each
await tree once! */
hash_set<tree> pset;
cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
- /* Now replace the promise proxy with its real value. */
- proxy_replace p_data;
- p_data.from = promise_proxy;
- p_data.to = ap;
- cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
-
- /* The rewrite of the function adds code to set the __resume field to
- nullptr when the coroutine is done and also the index to zero when
- calling an unhandled exception. These are represented by two proxies
- in the function, so rewrite them to the proper frame access. */
- tree resume_m
- = lookup_member (coro_frame_type, get_identifier ("__resume"),
- /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
- tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
- false, tf_warning_or_error);
- p_data.from = resume_fn_field;
- p_data.to = res_x;
- cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
-
- p_data.from = resume_idx_field;
- p_data.to = rat;
- cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
-
/* Add in our function body with the co_returns rewritten to final form. */
add_stmt (fnbody);
@@ -2440,7 +2316,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
add_stmt (r);
/* Destructors for the things we built explicitly. */
- r = build_special_member_call (ap, complete_dtor_identifier, NULL,
+ r = build_special_member_call (promise_proxy, complete_dtor_identifier, NULL,
promise_type, LOOKUP_NORMAL,
tf_warning_or_error);
add_stmt (r);
@@ -2453,7 +2329,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Here deallocate the frame (if we allocated it), which we will have at
present. */
tree fnf_m
- = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
+ = lookup_member (coro_frame_type, coro_frame_needs_free_id, 1,
0, tf_warning_or_error);
tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
false, tf_warning_or_error);
@@ -2532,18 +2408,10 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
add_stmt (r);
- /* We will need to know which resume point number should be encoded. */
- tree res_idx_m
- = lookup_member (coro_frame_type, resume_idx_name,
- /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
- tree resume_pt_number
- = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
- tf_warning_or_error);
-
/* We've now rewritten the tree and added the initial and final
co_awaits. Now pass over the tree and expand the co_awaits. */
- coro_aw_data data = {actor, actor_fp, resume_pt_number, NULL_TREE,
+ coro_aw_data data = {actor, actor_fp, resume_idx_var, NULL_TREE,
ash, del_promise_label, ret_label,
continue_label, continuation, 2};
cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
@@ -2557,7 +2425,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
}
/* The prototype 'destroy' function :
- frame->__resume_at |= 1;
+ frame->__Coro_resume_index |= 1;
actor (frame); */
static void
@@ -2576,11 +2444,10 @@ build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
- tree resume_idx_name = get_identifier ("__resume_at");
- tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
- tf_warning_or_error);
- tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
- rat_field, NULL_TREE);
+ tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
+ 1, 0, tf_warning_or_error);
+ tree rat = build3 (COMPONENT_REF, short_unsigned_type_node,
+ destr_frame, rat_field, NULL_TREE);
/* _resume_at |= 1 */
tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
@@ -2905,7 +2772,7 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
tree else_cl = COND_EXPR_ELSE (old_expr);
if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
{
- gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
+ gcc_checking_assert (TREE_CODE (else_cl) != STATEMENT_LIST);
else_cl
= build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
var, else_cl);
@@ -3547,16 +3414,11 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
return NULL_TREE;
}
- /* We have something to be handled as a single statement. */
- bool has_cleanup_wrapper = TREE_CODE (*stmt) == CLEANUP_POINT_EXPR;
- hash_set<tree> visited;
- awpts->saw_awaits = 0;
- hash_set<tree> truth_aoif_to_expand;
- awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
- awpts->needs_truth_if_exp = false;
- awpts->has_awaiter_init = false;
+ /* We have something to be handled as a single statement. We have to handle
+ a few statements specially where await statements have to be moved out of
+ constructs. */
tree expr = *stmt;
- if (has_cleanup_wrapper)
+ if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
expr = TREE_OPERAND (expr, 0);
STRIP_NOPS (expr);
@@ -3572,6 +3434,8 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
transforms can be implemented. */
case IF_STMT:
{
+ tree *await_ptr;
+ hash_set<tree> visited;
/* Transform 'if (cond with awaits) then stmt1 else stmt2' into
bool cond = cond with awaits.
if (cond) then stmt1 else stmt2. */
@@ -3579,10 +3443,8 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
/* We treat the condition as if it was a stand-alone statement,
to see if there are any await expressions which will be analyzed
and registered. */
- if ((res = cp_walk_tree (&IF_COND (if_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- if (!awpts->saw_awaits)
+ if (!(cp_walk_tree (&IF_COND (if_stmt),
+ find_any_await, &await_ptr, &visited)))
return NULL_TREE; /* Nothing special to do here. */
gcc_checking_assert (!awpts->bind_stack->is_empty());
@@ -3598,7 +3460,7 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
/* We want to initialize the new variable with the expression
that contains the await(s) and potentially also needs to
have truth_if expressions expanded. */
- tree new_s = build2_loc (sloc, MODIFY_EXPR, boolean_type_node,
+ tree new_s = build2_loc (sloc, INIT_EXPR, boolean_type_node,
newvar, cond_inner);
finish_expr_stmt (new_s);
IF_COND (if_stmt) = newvar;
@@ -3612,25 +3474,27 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
break;
case FOR_STMT:
{
+ tree *await_ptr;
+ hash_set<tree> visited;
/* for loops only need special treatment if the condition or the
iteration expression contain a co_await. */
tree for_stmt = *stmt;
- /* Sanity check. */
- if ((res = cp_walk_tree (&FOR_INIT_STMT (for_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- gcc_checking_assert (!awpts->saw_awaits);
-
- if ((res = cp_walk_tree (&FOR_COND (for_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- bool for_cond_await = awpts->saw_awaits != 0;
- unsigned save_awaits = awpts->saw_awaits;
-
- if ((res = cp_walk_tree (&FOR_EXPR (for_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- bool for_expr_await = awpts->saw_awaits > save_awaits;
+ /* At present, the FE always generates a separate initializer for
+ the FOR_INIT_STMT, when the expression has an await. Check that
+ this assumption holds in the future. */
+ gcc_checking_assert
+ (!(cp_walk_tree (&FOR_INIT_STMT (for_stmt), find_any_await,
+ &await_ptr, &visited)));
+
+ visited.empty ();
+ bool for_cond_await
+ = cp_walk_tree (&FOR_COND (for_stmt), find_any_await,
+ &await_ptr, &visited);
+
+ visited.empty ();
+ bool for_expr_await
+ = cp_walk_tree (&FOR_EXPR (for_stmt), find_any_await,
+ &await_ptr, &visited);
/* If the condition has an await, then we will need to rewrite the
loop as
@@ -3673,7 +3537,12 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
= create_named_label_with_ctx (sloc, buf, NULL_TREE);
free (buf);
add_stmt (build_stmt (sloc, LABEL_EXPR, it_expr_label));
- add_stmt (FOR_EXPR (for_stmt));
+ tree for_expr = FOR_EXPR (for_stmt);
+ /* Present the iteration expression as a statement. */
+ if (TREE_CODE (for_expr) == CLEANUP_POINT_EXPR)
+ for_expr = TREE_OPERAND (for_expr, 0);
+ STRIP_NOPS (for_expr);
+ finish_expr_stmt (for_expr);
FOR_EXPR (for_stmt) = NULL_TREE;
FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
/* rewrite continue statements to goto label. */
@@ -3700,11 +3569,11 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
break;
stmt..
} */
+ tree *await_ptr;
+ hash_set<tree> visited;
tree while_stmt = *stmt;
- if ((res = cp_walk_tree (&WHILE_COND (while_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- if (!awpts->saw_awaits)
+ if (!(cp_walk_tree (&WHILE_COND (while_stmt),
+ find_any_await, &await_ptr, &visited)))
return NULL_TREE; /* Nothing special to do here. */
tree insert_list = push_stmt_list ();
@@ -3730,10 +3599,10 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
break;
} while (true); */
tree do_stmt = *stmt;
- if ((res = cp_walk_tree (&DO_COND (do_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- if (!awpts->saw_awaits)
+ tree *await_ptr;
+ hash_set<tree> visited;
+ if (!(cp_walk_tree (&DO_COND (do_stmt),
+ find_any_await, &await_ptr, &visited)))
return NULL_TREE; /* Nothing special to do here. */
tree insert_list = push_stmt_list ();
@@ -3756,10 +3625,10 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
switch_type cond = cond with awaits
switch (cond) stmt. */
tree sw_stmt = *stmt;
- if ((res = cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
- analyze_expression_awaits, d, &visited)))
- return res;
- if (!awpts->saw_awaits)
+ tree *await_ptr;
+ hash_set<tree> visited;
+ if (!(cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
+ find_any_await, &await_ptr, &visited)))
return NULL_TREE; /* Nothing special to do here. */
gcc_checking_assert (!awpts->bind_stack->is_empty());
@@ -3800,9 +3669,6 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
{ expr; p.return_void(); goto final_suspend;}
- for co_return [non void expr];
{ p.return_value(expr); goto final_suspend; } */
- if ((res = cp_walk_tree (stmt, analyze_expression_awaits,
- d, &visited)))
- return res;
location_t loc = EXPR_LOCATION (expr);
tree call = TREE_OPERAND (expr, 1);
expr = TREE_OPERAND (expr, 0);
@@ -3810,39 +3676,48 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
/* [stmt.return.coroutine], 2.2
If expr is present and void, it is placed immediately before
the call for return_void; */
- tree *maybe_await_stmt = NULL;
if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
- {
- finish_expr_stmt (expr);
- /* If the return argument was a void expression, then any
- awaits must be contained in that. */
- maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
- }
+ finish_expr_stmt (expr);
/* Insert p.return_{void,value(expr)}. */
finish_expr_stmt (call);
- /* Absent a return of a void expression, any awaits must be in
- the parameter to return_value(). */
- if (!maybe_await_stmt)
- maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
- expr = build1_loc (loc, GOTO_EXPR, void_type_node, awpts->fs_label);
- finish_expr_stmt (expr);
+ TREE_USED (awpts->fs_label) = 1;
+ add_stmt (build_stmt (loc, GOTO_EXPR, awpts->fs_label));
*stmt = pop_stmt_list (ret_list);
+ res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
/* Once this is complete, we will have processed subtrees. */
*do_subtree = 0;
- if (awpts->saw_awaits)
- {
- gcc_checking_assert (maybe_await_stmt);
- res = cp_walk_tree (maybe_await_stmt, await_statement_walker,
- d, NULL);
- if (res)
- return res;
- }
- return NULL_TREE; /* Done. */
+ return res;
}
- break;
+ break;
+ case HANDLER:
+ {
+ /* [expr.await] An await-expression shall appear only in a
+ potentially-evaluated expression within the compound-statement
+ of a function-body outside of a handler. */
+ tree *await_ptr;
+ hash_set<tree> visited;
+ if (!(cp_walk_tree (&HANDLER_BODY (expr), find_any_await,
+ &await_ptr, &visited)))
+ return NULL_TREE; /* All OK. */
+ location_t loc = EXPR_LOCATION (*await_ptr);
+ error_at (loc, "await expressions are not permitted in handlers");
+ return NULL_TREE; /* This is going to fail later anyway. */
+ }
+ break;
}
else if (EXPR_P (expr))
{
+ hash_set<tree> visited;
+ tree *await_ptr;
+ if (!(cp_walk_tree (stmt, find_any_await, &await_ptr, &visited)))
+ return NULL_TREE; /* Nothing special to do here. */
+
+ visited.empty ();
+ awpts->saw_awaits = 0;
+ hash_set<tree> truth_aoif_to_expand;
+ awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
+ awpts->needs_truth_if_exp = false;
+ awpts->has_awaiter_init = false;
if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
return res;
*do_subtree = 0; /* Done subtrees. */
@@ -3877,11 +3752,11 @@ struct param_frame_data
bool param_seen;
};
-/* A tree-walk callback that records the use of parameters (to allow for
- optimizations where handling unused parameters may be omitted). */
+/* A tree walk callback that rewrites each parm use to the local variable
+ that represents its copy in the frame. */
static tree
-register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
+rewrite_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
{
param_frame_data *data = (param_frame_data *) d;
@@ -3889,7 +3764,7 @@ register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
{
tree t = DECL_VALUE_EXPR (*stmt);
- return cp_walk_tree (&t, register_param_uses, d, NULL);
+ return cp_walk_tree (&t, rewrite_param_uses, d, NULL);
}
if (TREE_CODE (*stmt) != PARM_DECL)
@@ -3903,16 +3778,88 @@ register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
gcc_checking_assert (existed);
- if (!parm.body_uses)
+ *stmt = parm.copy_var;
+ return NULL_TREE;
+}
+
+/* Build up a set of info that determines how each param copy will be
+ handled. */
+
+static hash_map<tree, param_info> *
+analyze_fn_parms (tree orig)
+{
+ if (!DECL_ARGUMENTS (orig))
+ return NULL;
+
+ hash_map<tree, param_info> *param_uses = new hash_map<tree, param_info>;
+
+ /* Build a hash map with an entry for each param.
+ The key is the param tree.
+ Then we have an entry for the frame field name.
+ Then a cache for the field ref when we come to use it.
+ Then a tree list of the uses.
+ The second two entries start out empty - and only get populated
+ when we see uses. */
+ bool lambda_p = LAMBDA_FUNCTION_P (orig);
+
+ unsigned no_name_parm = 0;
+ for (tree arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
{
- vec_alloc (parm.body_uses, 4);
- parm.body_uses->quick_push (stmt);
- data->param_seen = true;
+ bool existed;
+ param_info &parm = param_uses->get_or_insert (arg, &existed);
+ gcc_checking_assert (!existed);
+ parm.body_uses = NULL;
+ tree actual_type = TREE_TYPE (arg);
+ actual_type = complete_type_or_else (actual_type, orig);
+ if (actual_type == NULL_TREE)
+ actual_type = error_mark_node;
+ parm.orig_type = actual_type;
+ parm.by_ref = parm.pt_ref = parm.rv_ref = false;
+ if (TREE_CODE (actual_type) == REFERENCE_TYPE)
+ {
+ /* If the user passes by reference, then we will save the
+ pointer to the original. As noted in
+ [dcl.fct.def.coroutine] / 13, if the lifetime of the
+ referenced item ends and then the coroutine is resumed,
+ we have UB; well, the user asked for it. */
+ if (TYPE_REF_IS_RVALUE (actual_type))
+ parm.rv_ref = true;
+ else
+ parm.pt_ref = true;
+ }
+ else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
+ parm.by_ref = true;
+
+ parm.frame_type = actual_type;
+
+ parm.this_ptr = is_this_parameter (arg);
+ parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
+
+ tree name = DECL_NAME (arg);
+ if (!name)
+ {
+ char *buf = xasprintf ("_Coro_unnamed_parm_%d", no_name_parm++);
+ name = get_identifier (buf);
+ free (buf);
+ }
+ parm.field_id = name;
+
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
+ {
+ char *buf = xasprintf ("%s%s_live", DECL_NAME (arg) ? "_Coro_" : "",
+ IDENTIFIER_POINTER (name));
+ parm.guard_var
+ = coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
+ boolean_type_node, orig,
+ boolean_false_node);
+ free (buf);
+ parm.trivial_dtor = false;
+ }
+ else
+ parm.trivial_dtor = true;
}
- else
- parm.body_uses->safe_push (stmt);
- return NULL_TREE;
+ return param_uses;
}
/* Small helper for the repetitive task of adding a new field to the coro
@@ -3957,8 +3904,6 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
if (TREE_CODE (*stmt) == BIND_EXPR)
{
- lvd->bind_indx++;
- lvd->nest_depth++;
tree lvar;
for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
lvar = DECL_CHAIN (lvar))
@@ -3982,6 +3927,16 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
if (local_var.is_static)
continue;
+ poly_uint64 size;
+ if (TREE_CODE (lvtype) == ARRAY_TYPE
+ && !poly_int_tree_p (DECL_SIZE_UNIT (lvar), &size))
+ {
+ sorry_at (local_var.def_loc, "variable length arrays are not"
+ " yet supported in coroutines");
+ /* Ignore it, this is broken anyway. */
+ continue;
+ }
+
lvd->local_var_seen = true;
/* If this var is a lambda capture proxy, we want to leave it alone,
and later rewrite the DECL_VALUE_EXPR to indirect through the
@@ -3997,14 +3952,21 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
continue;
/* Make names depth+index unique, so that we can support nested
- scopes with identically named locals. */
+ scopes with identically named locals and still be able to
+ identify them in the coroutine frame. */
tree lvname = DECL_NAME (lvar);
char *buf;
- if (lvname != NULL_TREE)
- buf = xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname),
+
+ /* The outermost bind scope contains the artificial variables that
+ we inject to implement the coro state machine. We want to be able
+ to inspect these in debugging. */
+ if (lvname != NULL_TREE && lvd->nest_depth == 0)
+ buf = xasprintf ("%s", IDENTIFIER_POINTER (lvname));
+ else if (lvname != NULL_TREE)
+ buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
lvd->nest_depth, lvd->bind_indx);
else
- buf = xasprintf ("_D%u.%u.%u", DECL_UID (lvar), lvd->nest_depth,
+ buf = xasprintf ("_D%u_%u_%u", DECL_UID (lvar), lvd->nest_depth,
lvd->bind_indx);
/* TODO: Figure out if we should build a local type that has any
excess alignment or size from the original decl. */
@@ -4014,6 +3976,8 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
/* We don't walk any of the local var sub-trees, they won't contain
any bind exprs. */
}
+ lvd->bind_indx++;
+ lvd->nest_depth++;
cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
*do_subtree = 0; /* We've done this. */
lvd->nest_depth--;
@@ -4089,8 +4053,9 @@ coro_build_actor_or_destroy_function (tree orig, tree fn_type,
static tree
coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
- tree resume_fn_ptr_type, tree& resume_fn_field,
- tree& resume_idx_field, tree& fs_label)
+ hash_map<tree, param_info> *param_uses,
+ tree resume_fn_ptr_type,
+ tree& resume_idx_var, tree& fs_label)
{
/* This will be our new outer scope. */
tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
@@ -4123,7 +4088,6 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
/* Wrap the function body in a try {} catch (...) {} block, if exceptions
are enabled. */
- tree promise = get_coroutine_promise_proxy (orig);
tree var_list = NULL_TREE;
tree initial_await = build_init_or_final_await (fn_start, false);
@@ -4134,24 +4098,94 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
tree return_void
= get_coroutine_return_void_expr (current_function_decl, fn_start, false);
+ /* The pointer to the resume function. */
+ tree resume_fn_ptr
+ = coro_build_artificial_var (fn_start, coro_resume_fn_id,
+ resume_fn_ptr_type, orig, NULL_TREE);
+ DECL_CHAIN (resume_fn_ptr) = var_list;
+ var_list = resume_fn_ptr;
+ add_decl_expr (resume_fn_ptr);
+
/* We will need to be able to set the resume function pointer to nullptr
to signal that the coroutine is 'done'. */
- resume_fn_field
- = build_lang_decl (VAR_DECL, get_identifier ("resume.fn.ptr.proxy"),
- resume_fn_ptr_type);
- DECL_ARTIFICIAL (resume_fn_field) = true;
tree zero_resume
= build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
- zero_resume
- = build2 (INIT_EXPR, resume_fn_ptr_type, resume_fn_field, zero_resume);
- /* Likewise, the resume index needs to be reset. */
- resume_idx_field
- = build_lang_decl (VAR_DECL, get_identifier ("resume.index.proxy"),
- short_unsigned_type_node);
- DECL_ARTIFICIAL (resume_idx_field) = true;
- tree zero_resume_idx = build_int_cst (short_unsigned_type_node, 0);
- zero_resume_idx = build2 (INIT_EXPR, short_unsigned_type_node,
- resume_idx_field, zero_resume_idx);
+
+ /* The pointer to the destroy function. */
+ tree var = coro_build_artificial_var (fn_start, coro_destroy_fn_id,
+ resume_fn_ptr_type, orig, NULL_TREE);
+ DECL_CHAIN (var) = var_list;
+ var_list = var;
+ add_decl_expr (var);
+
+ /* The promise was created on demand when parsing we now link it into
+ our scope. */
+ tree promise = get_coroutine_promise_proxy (orig);
+ DECL_CONTEXT (promise) = orig;
+ DECL_SOURCE_LOCATION (promise) = fn_start;
+ DECL_CHAIN (promise) = var_list;
+ var_list = promise;
+ add_decl_expr (promise);
+
+ /* We need a handle to this coroutine, which is passed to every
+ await_suspend(). This was created on demand when parsing we now link it
+ into our scope. */
+ var = get_coroutine_self_handle_proxy (orig);
+ DECL_CONTEXT (var) = orig;
+ DECL_SOURCE_LOCATION (var) = fn_start;
+ DECL_CHAIN (var) = var_list;
+ var_list = var;
+ add_decl_expr (var);
+
+ /* If we have function parms, then these will be copied to the coroutine
+ frame. Create a local (proxy) variable for each parm, since the original
+ parms will be out of scope once the ramp has finished. The proxy vars will
+ get DECL_VALUE_EXPRs pointing to the frame copies, so that we can interact
+ with them in the debugger. */
+ if (param_uses)
+ {
+ gcc_checking_assert (DECL_ARGUMENTS (orig));
+ /* Add a local var for each parm. */
+ for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
+ arg = DECL_CHAIN (arg))
+ {
+ param_info *parm_i = param_uses->get (arg);
+ gcc_checking_assert (parm_i);
+ parm_i->copy_var
+ = build_lang_decl (VAR_DECL, parm_i->field_id, TREE_TYPE (arg));
+ DECL_SOURCE_LOCATION (parm_i->copy_var) = DECL_SOURCE_LOCATION (arg);
+ DECL_CONTEXT (parm_i->copy_var) = orig;
+ DECL_ARTIFICIAL (parm_i->copy_var) = true;
+ DECL_CHAIN (parm_i->copy_var) = var_list;
+ var_list = parm_i->copy_var;
+ add_decl_expr (parm_i->copy_var);
+ }
+
+ /* Now replace all uses of the parms in the function body with the proxy
+ vars. We want to this to apply to every instance of param's use, so
+ don't include a 'visited' hash_set on the tree walk, however we will
+ arrange to visit each containing expression only once. */
+ hash_set<tree *> visited;
+ param_frame_data param_data = {NULL, param_uses,
+ &visited, fn_start, false};
+ cp_walk_tree (&fnbody, rewrite_param_uses, &param_data, NULL);
+ }
+
+ /* We create a resume index, this is initialized in the ramp. */
+ resume_idx_var
+ = coro_build_artificial_var (fn_start, coro_resume_index_id,
+ short_unsigned_type_node, orig, NULL_TREE);
+ DECL_CHAIN (resume_idx_var) = var_list;
+ var_list = resume_idx_var;
+ add_decl_expr (resume_idx_var);
+
+ /* If the coroutine has a frame that needs to be freed, this will be set by
+ the ramp. */
+ var = coro_build_artificial_var (fn_start, coro_frame_needs_free_id,
+ boolean_type_node, orig, NULL_TREE);
+ DECL_CHAIN (var) = var_list;
+ var_list = var;
+ add_decl_expr (var);
if (flag_exceptions)
{
@@ -4162,12 +4196,12 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
fn_start, NULL, /*musthave=*/true);
/* Create and initialize the initial-await-resume-called variable per
[dcl.fct.def.coroutine] / 5.3. */
- tree i_a_r_c = build_lang_decl (VAR_DECL, get_identifier ("i_a_r_c"),
- boolean_type_node);
- DECL_ARTIFICIAL (i_a_r_c) = true;
+ tree i_a_r_c
+ = coro_build_artificial_var (fn_start, coro_frame_i_a_r_c_id,
+ boolean_type_node, orig,
+ boolean_false_node);
DECL_CHAIN (i_a_r_c) = var_list;
var_list = i_a_r_c;
- DECL_INITIAL (i_a_r_c) = boolean_false_node;
add_decl_expr (i_a_r_c);
/* Start the try-catch. */
tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
@@ -4216,10 +4250,14 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
If the unhandled exception method returns, then we continue
to the final await expression (which duplicates the clearing of
the field). */
- finish_expr_stmt (zero_resume);
- finish_expr_stmt (zero_resume_idx);
- ueh = maybe_cleanup_point_expr_void (ueh);
- add_stmt (ueh);
+ tree r = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
+ zero_resume);
+ finish_expr_stmt (r);
+ tree short_zero = build_int_cst (short_unsigned_type_node, 0);
+ r = build2 (MODIFY_EXPR, short_unsigned_type_node, resume_idx_var,
+ short_zero);
+ finish_expr_stmt (r);
+ finish_expr_stmt (ueh);
finish_handler (handler);
TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
}
@@ -4254,6 +4292,8 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
/* Before entering the final suspend point, we signal that this point has
been reached by setting the resume function pointer to zero (this is
what the 'done()' builtin tests) as per the current ABI. */
+ zero_resume = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
+ zero_resume);
finish_expr_stmt (zero_resume);
finish_expr_stmt (build_init_or_final_await (fn_start, true));
BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
@@ -4281,15 +4321,15 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
declare a dummy coro frame.
struct _R_frame {
using handle_type = coro::coroutine_handle<coro1::promise_type>;
- void (*__resume)(_R_frame *);
- void (*__destroy)(_R_frame *);
- coro1::promise_type __p;
- bool frame_needs_free; free the coro frame mem if set.
- bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
- short __resume_at;
- handle_type self_handle;
- (maybe) parameter copies.
- (maybe) local variables saved (including awaitables)
+ void (*_Coro_resume_fn)(_R_frame *);
+ void (*_Coro_destroy_fn)(_R_frame *);
+ coro1::promise_type _Coro_promise;
+ bool _Coro_frame_needs_free; free the coro frame mem if set.
+ bool _Coro_i_a_r_c; [dcl.fct.def.coroutine] / 5.3
+ short _Coro_resume_index;
+ handle_type _Coro_self_handle;
+ parameter copies (were required).
+ local variables saved (including awaitables)
(maybe) trailing space.
}; */
@@ -4381,7 +4421,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* 2. Types we need to define or look up. */
- tree fr_name = get_fn_local_identifier (orig, "frame");
+ tree fr_name = get_fn_local_identifier (orig, "Frame");
tree coro_frame_type = xref_tag (record_type, fr_name);
DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
tree coro_frame_ptr = build_pointer_type (coro_frame_type);
@@ -4398,121 +4438,18 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* Construct the wrapped function body; we will analyze this to determine
the requirements for the coroutine frame. */
- tree resume_fn_field = NULL_TREE;
- tree resume_idx_field = NULL_TREE;
+ tree resume_idx_var = NULL_TREE;
tree fs_label = NULL_TREE;
- fnbody = coro_rewrite_function_body (fn_start, fnbody, orig,
- act_des_fn_ptr, resume_fn_field,
- resume_idx_field, fs_label);
+ hash_map<tree, param_info> *param_uses = analyze_fn_parms (orig);
+
+ fnbody = coro_rewrite_function_body (fn_start, fnbody, orig, param_uses,
+ act_des_fn_ptr,
+ resume_idx_var, fs_label);
/* Build our dummy coro frame layout. */
coro_frame_type = begin_class_definition (coro_frame_type);
+ /* The fields for the coro frame. */
tree field_list = NULL_TREE;
- tree resume_name
- = coro_make_frame_entry (&field_list, "__resume",
- act_des_fn_ptr, fn_start);
- tree destroy_name
- = coro_make_frame_entry (&field_list, "__destroy",
- act_des_fn_ptr, fn_start);
- tree promise_name
- = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
- tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
- boolean_type_node, fn_start);
- tree resume_idx_name
- = coro_make_frame_entry (&field_list, "__resume_at",
- short_unsigned_type_node, fn_start);
-
- /* We need a handle to this coroutine, which is passed to every
- await_suspend(). There's no point in creating it over and over. */
- (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
-
- /* Now add in fields for function params (if there are any).
- We do not attempt elision of copies at this stage, we do analyze the
- uses and build worklists to replace those when the state machine is
- lowered. */
-
- hash_map<tree, param_info> *param_uses = NULL;
- if (DECL_ARGUMENTS (orig))
- {
- /* Build a hash map with an entry for each param.
- The key is the param tree.
- Then we have an entry for the frame field name.
- Then a cache for the field ref when we come to use it.
- Then a tree list of the uses.
- The second two entries start out empty - and only get populated
- when we see uses. */
- param_uses = new hash_map<tree, param_info>;
- bool lambda_p = LAMBDA_FUNCTION_P (orig);
-
- unsigned no_name_parm = 0;
- for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
- arg = DECL_CHAIN (arg))
- {
- bool existed;
- param_info &parm = param_uses->get_or_insert (arg, &existed);
- gcc_checking_assert (!existed);
- parm.body_uses = NULL;
- tree actual_type = TREE_TYPE (arg);
- actual_type = complete_type_or_else (actual_type, orig);
- if (actual_type == NULL_TREE)
- actual_type = error_mark_node;
- parm.orig_type = actual_type;
- parm.by_ref = parm.pt_ref = parm.rv_ref = false;
- if (TREE_CODE (actual_type) == REFERENCE_TYPE)
- {
- /* If the user passes by reference, then we will save the
- pointer to the original. As noted in
- [dcl.fct.def.coroutine] / 13, if the lifetime of the
- referenced item ends and then the coroutine is resumed,
- we have UB; well, the user asked for it. */
- if (TYPE_REF_IS_RVALUE (actual_type))
- parm.rv_ref = true;
- else
- parm.pt_ref = true;
- }
- else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
- parm.by_ref = true;
-
- parm.frame_type = actual_type;
-
- parm.this_ptr = is_this_parameter (arg);
- parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
-
- char *buf;
- if (DECL_NAME (arg))
- {
- tree pname = DECL_NAME (arg);
- buf = xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname));
- }
- else
- buf = xasprintf ("__unnamed_parm.%d", no_name_parm++);
-
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
- {
- char *gbuf = xasprintf ("%s.live", buf);
- parm.guard_var
- = build_lang_decl (VAR_DECL, get_identifier (gbuf),
- boolean_type_node);
- free (gbuf);
- DECL_ARTIFICIAL (parm.guard_var) = true;
- DECL_INITIAL (parm.guard_var) = boolean_false_node;
- parm.trivial_dtor = false;
- }
- else
- parm.trivial_dtor = true;
- parm.field_id = coro_make_frame_entry
- (&field_list, buf, actual_type, DECL_SOURCE_LOCATION (arg));
- free (buf);
- }
-
- /* We want to record every instance of param's use, so don't include
- a 'visited' hash_set on the tree walk, but only record a containing
- expression once. */
- hash_set<tree *> visited;
- param_frame_data param_data
- = {&field_list, param_uses, &visited, fn_start, false};
- cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
- }
/* We need to know, and inspect, each suspend point in the function
in several places. It's convenient to place this map out of line
@@ -4552,8 +4489,10 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
add_stmt (ramp_bind);
tree ramp_body = push_stmt_list ();
- tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
- coro_frame_ptr);
+ tree zeroinit = build1_loc (fn_start, CONVERT_EXPR,
+ coro_frame_ptr, integer_zero_node);
+ tree coro_fp = coro_build_artificial_var (fn_start, "_Coro_frameptr",
+ coro_frame_ptr, orig, zeroinit);
tree varlist = coro_fp;
/* To signal that we need to cleanup copied function args. */
@@ -4571,21 +4510,19 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* Signal that we need to clean up the promise object on exception. */
tree coro_promise_live
- = build_lang_decl (VAR_DECL, get_identifier ("coro.promise.live"),
- boolean_type_node);
- DECL_ARTIFICIAL (coro_promise_live) = true;
+ = coro_build_artificial_var (fn_start, "_Coro_promise_live",
+ boolean_type_node, orig, boolean_false_node);
DECL_CHAIN (coro_promise_live) = varlist;
varlist = coro_promise_live;
- DECL_INITIAL (coro_promise_live) = boolean_false_node;
+
/* When the get-return-object is in the RETURN slot, we need to arrange for
cleanup on exception. */
tree coro_gro_live
- = build_lang_decl (VAR_DECL, get_identifier ("coro.gro.live"),
- boolean_type_node);
- DECL_ARTIFICIAL (coro_gro_live) = true;
+ = coro_build_artificial_var (fn_start, "_Coro_gro_live",
+ boolean_type_node, orig, boolean_false_node);
+
DECL_CHAIN (coro_gro_live) = varlist;
varlist = coro_gro_live;
- DECL_INITIAL (coro_gro_live) = boolean_false_node;
/* Collected the scope vars we need ... only one for now. */
BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
@@ -4601,8 +4538,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* The decl_expr for the coro frame pointer, initialize to zero so that we
can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
directly apparently). This avoids a "used uninitialized" warning. */
- tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
- DECL_INITIAL (coro_fp) = zeroinit;
+
add_decl_expr (coro_fp);
if (flag_exceptions && DECL_ARGUMENTS (orig))
for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
@@ -4827,8 +4763,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* For now, once allocation has succeeded we always assume that this needs
destruction, there's no impl. for frame allocation elision. */
- tree fnf_m
- = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
+ tree fnf_m = lookup_member (coro_frame_type, coro_frame_needs_free_id,
+ 1, 0,tf_warning_or_error);
tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
false, tf_warning_or_error);
r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
@@ -4839,24 +4775,22 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
tree resume_m
- = lookup_member (coro_frame_type, resume_name,
+ = lookup_member (coro_frame_type, coro_resume_fn_id,
/*protect=*/1, /*want_type=*/0, tf_warning_or_error);
tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
false, tf_warning_or_error);
r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
- r = coro_build_cvt_void_expr_stmt (r, fn_start);
- add_stmt (r);
+ finish_expr_stmt (r);
tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
tree destroy_m
- = lookup_member (coro_frame_type, destroy_name,
+ = lookup_member (coro_frame_type, coro_destroy_fn_id,
/*protect=*/1, /*want_type=*/0, tf_warning_or_error);
tree destroy_x
= build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
tf_warning_or_error);
r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
- r = coro_build_cvt_void_expr_stmt (r, fn_start);
- add_stmt (r);
+ finish_expr_stmt (r);
/* [dcl.fct.def.coroutine] /13
When a coroutine is invoked, a copy is created for each coroutine
@@ -4936,18 +4870,21 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
NULL, parm.frame_type,
LOOKUP_NORMAL,
tf_warning_or_error);
- /* This var is now live. */
- r = build_modify_expr (fn_start, parm.guard_var,
- boolean_type_node, INIT_EXPR, fn_start,
- boolean_true_node, boolean_type_node);
- finish_expr_stmt (r);
+ if (flag_exceptions)
+ {
+ /* This var is now live. */
+ r = build_modify_expr (fn_start, parm.guard_var,
+ boolean_type_node, INIT_EXPR, fn_start,
+ boolean_true_node, boolean_type_node);
+ finish_expr_stmt (r);
+ }
}
}
}
/* Set up the promise. */
tree promise_m
- = lookup_member (coro_frame_type, promise_name,
+ = lookup_member (coro_frame_type, coro_promise_id,
/*protect=*/1, /*want_type=*/0, tf_warning_or_error);
tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
@@ -5062,10 +4999,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
{
/* ... or ... Construct an object that will be used as the single
param to the CTOR for the return object. */
- gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"), gro_type);
- DECL_CONTEXT (gro) = current_scope ();
- DECL_ARTIFICIAL (gro) = true;
- DECL_IGNORED_P (gro) = true;
+ gro = coro_build_artificial_var (fn_start, "_Coro_gro", gro_type, orig,
+ NULL_TREE);
add_decl_expr (gro);
gro_bind_vars = gro;
r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
@@ -5095,9 +5030,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
boolean_type_node);
finish_expr_stmt (r);
}
- /* Initialize the resume_idx_name to 0, meaning "not started". */
+ /* Initialize the resume_idx_var to 0, meaning "not started". */
tree resume_idx_m
- = lookup_member (coro_frame_type, resume_idx_name,
+ = lookup_member (coro_frame_type, coro_resume_index_id,
/*protect=*/1, /*want_type=*/0, tf_warning_or_error);
tree resume_idx
= build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
@@ -5240,9 +5175,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
push_deferring_access_checks (dk_no_check);
/* Build the actor... */
- build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
- &local_var_uses, param_dtor_list, resume_fn_field,
- resume_idx_field, body_aw_points.await_number, frame_size);
+ build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig,
+ &local_var_uses, param_dtor_list,
+ resume_idx_var, body_aw_points.await_number, frame_size);
/* Destroyer ... */
build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index bf928a8..c86a5fe 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2060,6 +2060,7 @@ cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
bool make_shared = false;
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE
|| !OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)))
return;
@@ -2080,9 +2081,10 @@ cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
Save the results, because later we won't be in the right context
for making these queries. */
bool first = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE;
+ bool last = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE;
if (!make_shared
&& CLASS_TYPE_P (inner_type)
- && cxx_omp_create_clause_info (c, inner_type, !first, first, !first,
+ && cxx_omp_create_clause_info (c, inner_type, !first, first, last,
true))
make_shared = true;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 75ee887..5248ecd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -204,12 +204,11 @@ enum cp_tree_index
/* 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_CONST_TYPE_INFO_TYPE,
CPTI_GET_EXCEPTION_PTR_FN,
CPTI_BEGIN_CATCH_FN,
CPTI_END_CATCH_FN,
@@ -251,7 +250,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define abi_node cp_global_trees[CPTI_ABI]
#define global_namespace cp_global_trees[CPTI_GLOBAL]
#define const_type_info_type_node cp_global_trees[CPTI_CONST_TYPE_INFO_TYPE]
-#define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE]
#define conv_op_marker cp_global_trees[CPTI_CONV_OP_MARKER]
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
@@ -471,7 +469,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
- TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
+ TYPENAME_IS_RESOLVING_P (in TYPENAME_TYPE)
TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
FNDECL_USED_AUTO (in FUNCTION_DECL)
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
@@ -493,6 +491,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
OVL_NESTED_P (in OVERLOAD)
DECL_MODULE_EXPORT_P (in _DECL)
+ PACK_EXPANSION_FORCE_EXTRA_ARGS_P (in *_PACK_EXPANSION)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
@@ -500,6 +499,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
OVL_LOOKUP_P (in OVERLOAD)
LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL)
+ FNDECL_MANIFESTLY_CONST_EVALUATED (in FUNCTION_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)
@@ -2336,6 +2336,7 @@ struct GTY(()) lang_type {
unsigned has_constexpr_ctor : 1;
unsigned unique_obj_representations : 1;
unsigned unique_obj_representations_set : 1;
+ bool erroneous : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@@ -2344,7 +2345,7 @@ struct GTY(()) lang_type {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 5;
+ unsigned dummy : 4;
tree primary_base;
vec<tree_pair_s, va_gc> *vcall_indices;
@@ -2660,6 +2661,10 @@ struct GTY(()) lang_type {
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->debug_requested)
+
+/* True if we saw errors while instantiating this class. */
+#define CLASSTYPE_ERRONEOUS(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->erroneous)
/* Additional macros for inheritance information. */
@@ -3897,6 +3902,10 @@ struct GTY(()) lang_decl {
/* True iff this pack expansion is for auto... in lambda init-capture. */
#define PACK_EXPANSION_AUTO_P(NODE) TREE_LANG_FLAG_2 (NODE)
+/* True if we must use PACK_EXPANSION_EXTRA_ARGS and avoid partial
+ instantiation of this pack expansion. */
+#define PACK_EXPANSION_FORCE_EXTRA_ARGS_P(NODE) TREE_LANG_FLAG_3 (NODE)
+
/* True iff the wildcard can match a template parameter pack. */
#define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE)
@@ -4208,6 +4217,13 @@ 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 needed for a manifestly constant-evaluated expression.
+ This doesn't especially need to be a flag, since currently it's only
+ used for error recovery; if we run out of function flags it could move
+ to an attribute. */
+#define FNDECL_MANIFESTLY_CONST_EVALUATED(NODE) \
+ TREE_LANG_FLAG_4 (FUNCTION_DECL_CHECK (NODE))
+
/* True for artificial decls added for OpenMP privatized non-static
data members. */
#define DECL_OMP_PRIVATIZED_MEMBER(NODE) \
@@ -4787,6 +4803,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define ANON_UNION_TYPE_P(NODE) \
(TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE))
+/* For an ANON_AGGR_TYPE_P the single FIELD_DECL it is used with. */
+#define ANON_AGGR_TYPE_FIELD(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->typeinfo_var)
+
/* Define fields and accessors for nodes representing declared names. */
/* True if TYPE is an unnamed structured type with a typedef for
@@ -6536,7 +6556,7 @@ extern void validate_conversion_obstack (void);
extern void mark_versions_used (tree);
extern int unsafe_return_slot_p (tree);
extern bool make_safe_copy_elision (tree, tree);
-extern bool cp_warn_deprecated_use (tree, tsubst_flags_t = tf_warning_or_error);
+extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = tf_warning_or_error);
extern void cp_warn_deprecated_use_scopes (tree);
extern tree get_function_version_dispatcher (tree);
@@ -6993,6 +7013,7 @@ extern void explain_implicit_non_constexpr (tree);
extern bool deduce_inheriting_ctor (tree);
extern bool decl_remember_implicit_trigger_p (tree);
extern void synthesize_method (tree);
+extern void maybe_synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind,
tree);
extern tree skip_artificial_parms_for (const_tree, tree);
@@ -7116,6 +7137,7 @@ extern void cp_convert_omp_range_for (tree &, vec<tree, va_gc> *, tree &,
tree &, tree &, tree &, tree &, tree &);
extern void cp_finish_omp_range_for (tree, tree);
extern bool parsing_nsdmi (void);
+extern bool parsing_function_declarator ();
extern bool parsing_default_capturing_generic_lambda_in_template (void);
extern void inject_this_parameter (tree, cp_cv_quals);
extern location_t defparse_location (tree);
@@ -7242,6 +7264,7 @@ extern tree maybe_get_template_decl_from_type_decl (tree);
extern int processing_template_parmlist;
extern bool dependent_type_p (tree);
extern bool dependent_scope_p (tree);
+extern bool dependentish_scope_p (tree);
extern bool any_dependent_template_arguments_p (const_tree);
extern bool any_erroneous_template_args_p (const_tree);
extern bool dependent_template_p (tree);
@@ -7561,8 +7584,8 @@ extern tree finish_omp_for (location_t, enum tree_code,
extern tree finish_omp_for_block (tree, tree);
extern void finish_omp_atomic (location_t, enum tree_code,
enum tree_code, tree, tree,
- tree, tree, tree, tree,
- enum omp_memory_order);
+ tree, tree, tree, tree, tree,
+ enum omp_memory_order, bool);
extern void finish_omp_barrier (void);
extern void finish_omp_depobj (location_t, tree,
enum omp_clause_depend_kind,
@@ -8266,6 +8289,7 @@ extern bool require_constant_expression (tree);
extern bool require_rvalue_constant_expression (tree);
extern bool require_potential_rvalue_constant_expression (tree);
extern tree cxx_constant_value (tree, tree = NULL_TREE);
+extern tree cxx_constant_value_sfinae (tree, tsubst_flags_t);
extern void cxx_constant_dtor (tree, tree);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3414cbd..242429d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h" /* For 'g'. */
#include "omp-general.h"
#include "omp-offload.h" /* For offload_vars. */
+#include "opts.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
@@ -2418,6 +2419,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
+ /* Merge unavailability. */
+ if (TREE_UNAVAILABLE (newdecl))
+ TREE_UNAVAILABLE (olddecl) = 1;
+
/* Preserve function specific target and optimization options */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@@ -3224,7 +3229,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
{
DECL_EXTERNAL (newdecl) = 1;
/* For now, only warn with explicit -Wdeprecated. */
- if (global_options_set.x_warn_deprecated)
+ if (OPTION_SET_P (warn_deprecated))
{
auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated,
@@ -4748,6 +4753,43 @@ cxx_init_decl_processing (void)
/* Show we use EH for cleanups. */
if (flag_exceptions)
using_eh_for_cleanups ();
+
+ /* Check that the hardware interference sizes are at least
+ alignof(max_align_t), as required by the standard. */
+ const int max_align = max_align_t_align () / BITS_PER_UNIT;
+ if (OPTION_SET_P (param_destruct_interfere_size))
+ {
+ if (param_destruct_interfere_size < max_align)
+ error ("%<--param destructive-interference-size=%d%> is less than "
+ "%d", param_destruct_interfere_size, max_align);
+ else if (param_destruct_interfere_size < param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param destructive-interference-size=%d%> "
+ "is less than %<--param l1-cache-line-size=%d%>",
+ param_destruct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_destruct_interfere_size)
+ /* Assume the internal value is OK. */;
+ else if (param_l1_cache_line_size >= max_align)
+ param_destruct_interfere_size = param_l1_cache_line_size;
+ /* else leave it unset. */
+
+ if (OPTION_SET_P (param_construct_interfere_size))
+ {
+ if (param_construct_interfere_size < max_align)
+ error ("%<--param constructive-interference-size=%d%> is less than "
+ "%d", param_construct_interfere_size, max_align);
+ else if (param_construct_interfere_size > param_l1_cache_line_size
+ && param_l1_cache_line_size >= max_align)
+ warning (OPT_Winterference_size,
+ "%<--param constructive-interference-size=%d%> "
+ "is greater than %<--param l1-cache-line-size=%d%>",
+ param_construct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_construct_interfere_size)
+ /* Assume the internal value is OK. */;
+ else if (param_l1_cache_line_size >= max_align)
+ param_construct_interfere_size = param_l1_cache_line_size;
}
/* Enter an abi node in global-module context. returns a cookie to
@@ -5092,6 +5134,9 @@ fixup_anonymous_aggr (tree t)
(*vec)[store++] = elt;
vec_safe_truncate (vec, store);
+ /* Wipe RTTI info. */
+ CLASSTYPE_TYPEINFO_VAR (t) = NULL_TREE;
+
/* Anonymous aggregates cannot have fields with ctors, dtors or complex
assignment operators (because they cannot have these methods themselves).
For anonymous unions this is already checked because they are not allowed
@@ -5665,17 +5710,20 @@ start_decl (const cp_declarator *declarator,
}
if (current_function_decl && VAR_P (decl)
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && cxx_dialect < cxx23)
{
bool ok = false;
if (CP_DECL_THREAD_LOCAL_P (decl))
error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared %<thread_local%> in %qs function", decl,
+ "%qD declared %<thread_local%> in %qs function only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl,
DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
? "consteval" : "constexpr");
else if (TREE_STATIC (decl))
error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared %<static%> in %qs function", decl,
+ "%qD declared %<static%> in %qs function only available "
+ "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl,
DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
? "consteval" : "constexpr");
else
@@ -5728,14 +5776,6 @@ start_decl_1 (tree decl, bool initialized)
cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
}
- if (is_global_var (decl))
- {
- type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
- ? TCTX_THREAD_STORAGE
- : 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? */
{
@@ -6084,6 +6124,38 @@ layout_var_decl (tree decl)
error_at (DECL_SOURCE_LOCATION (decl),
"storage size of %qD isn%'t constant", decl);
TREE_TYPE (decl) = error_mark_node;
+ type = error_mark_node;
+ }
+ }
+
+ /* If the final element initializes a flexible array field, add the size of
+ that initializer to DECL's size. */
+ if (type != error_mark_node
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
+ && !vec_safe_is_empty (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)))
+ && DECL_SIZE (decl) != NULL_TREE
+ && TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
+ && TYPE_SIZE (type) != NULL_TREE
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && tree_int_cst_equal (DECL_SIZE (decl), TYPE_SIZE (type)))
+ {
+ constructor_elt &elt = CONSTRUCTOR_ELTS (DECL_INITIAL (decl))->last ();
+ if (elt.index)
+ {
+ tree itype = TREE_TYPE (elt.index);
+ tree vtype = TREE_TYPE (elt.value);
+ if (TREE_CODE (itype) == ARRAY_TYPE
+ && TYPE_DOMAIN (itype) == NULL
+ && TREE_CODE (vtype) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (vtype))
+ {
+ DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+ }
}
}
}
@@ -6563,8 +6635,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
continue_:
if (base_binfo)
{
- BINFO_BASE_ITERATE (binfo, ++binfo_idx, base_binfo);
- if (base_binfo)
+ if (BINFO_BASE_ITERATE (binfo, ++binfo_idx, base_binfo))
field = base_binfo;
else
field = next_initializable_field (TYPE_FIELDS (type));
@@ -7697,7 +7768,7 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
else
{
tree construct = omp_get_context_selector (ctx, "construct", NULL);
- c_omp_mark_declare_variant (match_loc, variant, construct);
+ omp_mark_declare_variant (match_loc, variant, construct);
if (!omp_context_selector_matches (ctx))
return true;
TREE_PURPOSE (TREE_VALUE (attr)) = variant;
@@ -7902,6 +7973,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& DECL_INITIALIZED_IN_CLASS_P (decl))
check_static_variable_definition (decl, type);
+ if (!processing_template_decl && VAR_P (decl) && is_global_var (decl))
+ {
+ type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
+ ? TCTX_THREAD_STORAGE
+ : TCTX_STATIC_STORAGE);
+ verify_type_context (input_location, context, TREE_TYPE (decl));
+ }
+
if (init && TREE_CODE (decl) == FUNCTION_DECL)
{
tree clone;
@@ -11758,20 +11837,24 @@ grokdeclarator (const cp_declarator *declarator,
if (attrlist && *attrlist == error_mark_node)
*attrlist = NULL_TREE;
- /* An object declared as __attribute__((deprecated)) suppresses
- warnings of uses of other deprecated items. */
+ /* An object declared as __attribute__((unavailable)) suppresses
+ any reports of being declared with unavailable or deprecated
+ items. An object declared as __attribute__((deprecated))
+ suppresses warnings of uses of other deprecated items. */
auto ds = make_temp_override (deprecated_state);
- if (attrlist && lookup_attribute ("deprecated", *attrlist))
+ if (attrlist && lookup_attribute ("unavailable", *attrlist))
+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
+ else if (attrlist && lookup_attribute ("deprecated", *attrlist))
deprecated_state = DEPRECATED_SUPPRESS;
- cp_warn_deprecated_use (type);
+ cp_handle_deprecated_or_unavailable (type);
if (type && TREE_CODE (type) == TYPE_DECL)
{
cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type));
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
if (DECL_ARTIFICIAL (typedef_decl))
- cp_warn_deprecated_use (type);
+ cp_handle_deprecated_or_unavailable (type);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
@@ -13901,6 +13984,17 @@ grokdeclarator (const cp_declarator *declarator,
if (declspecs->gnu_thread_keyword_p)
SET_DECL_GNU_TLS_P (decl);
}
+
+ /* Set the constraints on the declaration. */
+ bool memtmpl = (processing_template_decl
+ > template_class_depth (current_class_type));
+ if (memtmpl)
+ {
+ tree tmpl_reqs
+ = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
+ tree ci = build_constraints (tmpl_reqs, NULL_TREE);
+ set_constraints (decl, ci);
+ }
}
else
{
@@ -14418,6 +14512,43 @@ type_is_deprecated (tree type)
return NULL_TREE;
}
+/* Returns an unavailable type used within TYPE, or NULL_TREE if none. */
+
+static tree
+type_is_unavailable (tree type)
+{
+ enum tree_code code;
+ if (TREE_UNAVAILABLE (type))
+ return type;
+ if (TYPE_NAME (type))
+ {
+ if (TREE_UNAVAILABLE (TYPE_NAME (type)))
+ return type;
+ else
+ {
+ cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type)));
+ return NULL_TREE;
+ }
+ }
+
+ /* Do warn about using typedefs to a deprecated class. */
+ if (OVERLOAD_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+ return type_is_deprecated (TYPE_MAIN_VARIANT (type));
+
+ code = TREE_CODE (type);
+
+ if (code == POINTER_TYPE || code == REFERENCE_TYPE
+ || code == OFFSET_TYPE || code == FUNCTION_TYPE
+ || code == METHOD_TYPE || code == ARRAY_TYPE)
+ return type_is_unavailable (TREE_TYPE (type));
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ return type_is_unavailable
+ (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+ return NULL_TREE;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
@@ -14477,11 +14608,18 @@ grokparms (tree parmlist, tree *parms)
if (type != error_mark_node)
{
- if (deprecated_state != DEPRECATED_SUPPRESS)
+ if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
+ {
+ tree unavailtype = type_is_unavailable (type);
+ if (unavailtype)
+ cp_handle_deprecated_or_unavailable (unavailtype);
+ }
+ if (deprecated_state != DEPRECATED_SUPPRESS
+ && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
{
tree deptype = type_is_deprecated (type);
if (deptype)
- cp_warn_deprecated_use (deptype);
+ cp_handle_deprecated_or_unavailable (deptype);
}
/* [dcl.fct] "A parameter with volatile-qualified type is
@@ -14724,9 +14862,11 @@ grok_special_member_properties (tree decl)
if (ctor > 1)
TYPE_HAS_CONST_COPY_CTOR (class_type) = 1;
}
- else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
+
+ if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
- else if (is_list_ctor (decl))
+
+ if (is_list_ctor (decl))
TYPE_HAS_LIST_CTOR (class_type) = 1;
if (DECL_DECLARED_CONSTEXPR_P (decl)
diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h
index 387d807..4a9b399 100644
--- a/gcc/cp/decl.h
+++ b/gcc/cp/decl.h
@@ -44,7 +44,8 @@ extern void name_unnamed_type (tree, tree);
enum deprecated_states {
DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
+ DEPRECATED_SUPPRESS,
+ UNAVAILABLE_DEPRECATED_SUPPRESS
};
extern enum deprecated_states deprecated_state;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0c9d2f4..a79a70b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1635,6 +1635,17 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
if (*decl == pattern)
TREE_DEPRECATED (tmpl) = true;
}
+
+ /* Likewise, propagate unavailability out to the template. */
+ if (TREE_UNAVAILABLE (*decl))
+ if (tree ti = get_template_info (*decl))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+ tree pattern = (TYPE_P (*decl) ? TREE_TYPE (tmpl)
+ : DECL_TEMPLATE_RESULT (tmpl));
+ if (*decl == pattern)
+ TREE_UNAVAILABLE (tmpl) = true;
+ }
}
/* Walks through the namespace- or function-scope anonymous union
@@ -2966,14 +2977,15 @@ reset_type_linkage (tree type)
SET_DECL_ASSEMBLER_NAME (vt, name);
reset_decl_linkage (vt);
}
- if (tree ti = CLASSTYPE_TYPEINFO_VAR (type))
- {
- tree name = mangle_typeinfo_for_type (type);
- DECL_NAME (ti) = name;
- SET_DECL_ASSEMBLER_NAME (ti, name);
- TREE_TYPE (name) = type;
- reset_decl_linkage (ti);
- }
+ if (!ANON_AGGR_TYPE_P (type))
+ if (tree ti = CLASSTYPE_TYPEINFO_VAR (type))
+ {
+ tree name = mangle_typeinfo_for_type (type);
+ DECL_NAME (ti) = name;
+ SET_DECL_ASSEMBLER_NAME (ti, name);
+ TREE_TYPE (name) = type;
+ reset_decl_linkage (ti);
+ }
for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m))
{
tree mem = STRIP_TEMPLATE (m);
@@ -5498,14 +5510,47 @@ maybe_instantiate_decl (tree decl)
}
}
-/* Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns whether or
- not a warning was emitted. */
+/* Error if the DECL is unavailable (unless this is currently suppressed).
+ Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns true if
+ an error or warning was emitted. */
bool
-cp_warn_deprecated_use (tree decl, tsubst_flags_t complain)
+cp_handle_deprecated_or_unavailable (tree decl, tsubst_flags_t complain)
{
- if (!(complain & tf_warning) || !decl
- || deprecated_state == DEPRECATED_SUPPRESS)
+ if (!decl)
+ return false;
+
+ if ((complain & tf_error)
+ && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
+ {
+ if (TREE_UNAVAILABLE (decl))
+ {
+ error_unavailable_use (decl, NULL_TREE);
+ return true;
+ }
+ else
+ {
+ /* Perhaps this is an unavailable typedef. */
+ if (TYPE_P (decl)
+ && TYPE_NAME (decl)
+ && TREE_UNAVAILABLE (TYPE_NAME (decl)))
+ {
+ decl = TYPE_NAME (decl);
+ /* Don't error within members of a unavailable type. */
+ if (TYPE_P (decl)
+ && currently_open_class (decl))
+ return false;
+
+ error_unavailable_use (decl, NULL_TREE);
+ return true;
+ }
+ }
+ /* Carry on to consider deprecatedness. */
+ }
+
+ if (!(complain & tf_warning)
+ || deprecated_state == DEPRECATED_SUPPRESS
+ || deprecated_state == UNAVAILABLE_DEPRECATED_SUPPRESS)
return false;
if (!TREE_DEPRECATED (decl))
@@ -5565,7 +5610,7 @@ cp_warn_deprecated_use_scopes (tree scope)
&& scope != global_namespace)
{
if ((TREE_CODE (scope) == NAMESPACE_DECL || OVERLOAD_TYPE_P (scope))
- && cp_warn_deprecated_use (scope))
+ && cp_handle_deprecated_or_unavailable (scope))
return;
if (TYPE_P (scope))
scope = CP_TYPE_CONTEXT (scope);
@@ -5677,7 +5722,7 @@ mark_used (tree decl, tsubst_flags_t complain)
TREE_USED (decl) = true;
}
- cp_warn_deprecated_use (decl, complain);
+ cp_handle_deprecated_or_unavailable (decl, complain);
/* We can only check DECL_ODR_USED on variables or functions with
DECL_LANG_SPECIFIC set, and these are also the only decls that we
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1426f9a..771a19b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -749,8 +749,15 @@ maybe_warn_list_ctor (tree member, tree init)
|| !is_list_ctor (current_function_decl))
return;
- tree parms = FUNCTION_FIRST_USER_PARMTYPE (current_function_decl);
- tree initlist = non_reference (TREE_VALUE (parms));
+ tree parm = FUNCTION_FIRST_USER_PARMTYPE (current_function_decl);
+ parm = TREE_VALUE (parm);
+ tree initlist = non_reference (parm);
+
+ /* Do not warn if the parameter is an lvalue reference to non-const. */
+ if (TYPE_REF_P (parm) && !TYPE_REF_IS_RVALUE (parm)
+ && !CP_TYPE_CONST_P (initlist))
+ return;
+
tree targs = CLASSTYPE_TI_ARGS (initlist);
tree elttype = TREE_VEC_ELT (targs, 0);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 353046d..1023aef 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1288,21 +1288,19 @@ struct comp_info
{
tree fndecl;
location_t loc;
- bool defining;
+ tsubst_flags_t complain;
+ tree_code code;
+ comp_cat_tag retcat;
bool first_time;
bool constexp;
bool was_constexp;
bool noex;
- comp_info (tree fndecl, tsubst_flags_t &complain)
- : fndecl (fndecl)
+ comp_info (tree fndecl, tsubst_flags_t complain)
+ : fndecl (fndecl), complain (complain)
{
loc = DECL_SOURCE_LOCATION (fndecl);
- /* We only have tf_error set when we're called from
- explain_invalid_constexpr_fn or maybe_explain_implicit_delete. */
- defining = !(complain & tf_error);
-
first_time = DECL_MAYBE_DELETED (fndecl);
DECL_MAYBE_DELETED (fndecl) = false;
@@ -1358,23 +1356,99 @@ struct comp_info
}
};
+/* Subroutine of build_comparison_op, to compare a single subobject. */
+
+static tree
+do_one_comp (location_t loc, const comp_info &info, tree sub, tree lhs, tree rhs)
+{
+ const tree_code code = info.code;
+ const tree fndecl = info.fndecl;
+ const comp_cat_tag retcat = info.retcat;
+ const tsubst_flags_t complain = info.complain;
+
+ tree overload = NULL_TREE;
+ int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED;
+ /* If we have an explicit comparison category return type we can fall back
+ to </=, so don't give an error yet if <=> lookup fails. */
+ bool tentative = retcat != cc_last;
+ tree comp = build_new_op (loc, code, flags, lhs, rhs,
+ NULL_TREE, &overload,
+ tentative ? tf_none : complain);
+
+ if (code != SPACESHIP_EXPR)
+ return comp;
+
+ tree rettype = TREE_TYPE (TREE_TYPE (fndecl));
+
+ if (comp == error_mark_node)
+ {
+ if (overload == NULL_TREE && (tentative || complain))
+ {
+ /* No viable <=>, try using op< and op==. */
+ tree lteq = genericize_spaceship (loc, rettype, lhs, rhs);
+ 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 (tentative && complain)
+ /* No usable < and ==, give an error for op<=>. */
+ build_new_op (loc, code, flags, lhs, rhs, complain);
+ }
+ if (comp == error_mark_node)
+ return error_mark_node;
+ }
+
+ 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 (loc,
+ "three-way comparison of %qD has type %qT, not a "
+ "comparison category type", sub, TREE_TYPE (comp));
+ return error_mark_node;
+ }
+ else if (!FNDECL_USED_AUTO (fndecl)
+ && !can_convert (rettype, TREE_TYPE (comp), complain))
+ {
+ if (complain & tf_error)
+ error_at (loc,
+ "three-way comparison of %qD has type %qT, which "
+ "does not convert to %qT",
+ sub, TREE_TYPE (comp), rettype);
+ return error_mark_node;
+ }
+
+ return comp;
+}
+
/* Build up the definition of a defaulted comparison operator. Unlike other
defaulted functions that use synthesized_method_walk to determine whether
the function is e.g. deleted, for comparisons we use the same code. We try
to use synthesize_method at the earliest opportunity and bail out if the
function ends up being deleted. */
-static void
-build_comparison_op (tree fndecl, tsubst_flags_t complain)
+void
+build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain)
{
comp_info info (fndecl, complain);
- if (!info.defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl))
+ if (!defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl))
return;
int flags = LOOKUP_NORMAL;
const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (fndecl));
- tree_code code = op->tree_code;
+ tree_code code = info.code = op->tree_code;
tree lhs = DECL_ARGUMENTS (fndecl);
tree rhs = DECL_CHAIN (lhs);
@@ -1384,6 +1458,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
lhs = convert_from_reference (lhs);
rhs = convert_from_reference (rhs);
tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs));
+ gcc_assert (!defining || COMPLETE_TYPE_P (ctype));
iloc_sentinel ils (info.loc);
@@ -1399,7 +1474,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
}
tree compound_stmt = NULL_TREE;
- if (info.defining)
+ if (defining)
compound_stmt = begin_compound_stmt (0);
else
++cp_unevaluated_operand;
@@ -1413,19 +1488,44 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
if (code == EQ_EXPR || code == SPACESHIP_EXPR)
{
- comp_cat_tag retcat = cc_last;
+ comp_cat_tag &retcat = (info.retcat = cc_last);
if (code == SPACESHIP_EXPR && !FNDECL_USED_AUTO (fndecl))
retcat = cat_tag_for (rettype);
bool bad = false;
auto_vec<tree> comps;
- /* Compare each of the subobjects. Note that we get bases from
- next_initializable_field because we're past C++17. */
+ /* Compare the base subobjects. We handle them this way, rather than in
+ the field loop below, because maybe_instantiate_noexcept might bring
+ us here before we've built the base fields. */
+ for (tree base_binfo : BINFO_BASE_BINFOS (TYPE_BINFO (ctype)))
+ {
+ tree lhs_base
+ = build_base_path (PLUS_EXPR, lhs, base_binfo, 0, complain);
+ tree rhs_base
+ = build_base_path (PLUS_EXPR, rhs, base_binfo, 0, complain);
+
+ location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (ctype));
+ tree comp = do_one_comp (loc, info, BINFO_TYPE (base_binfo),
+ lhs_base, rhs_base);
+ if (comp == error_mark_node)
+ {
+ bad = true;
+ continue;
+ }
+
+ comps.safe_push (comp);
+ }
+
+ /* Now compare the field subobjects. */
for (tree field = next_initializable_field (TYPE_FIELDS (ctype));
field;
field = next_initializable_field (DECL_CHAIN (field)))
{
+ if (DECL_VIRTUAL_P (field) || DECL_FIELD_IS_BASE (field))
+ /* We ignore the vptr, and we already handled bases. */
+ continue;
+
tree expr_type = TREE_TYPE (field);
location_t field_loc = DECL_SOURCE_LOCATION (field);
@@ -1474,8 +1574,8 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
break;
tree idx;
/* [1] array, no loop needed, just add [0] ARRAY_REF.
- Similarly if !info.defining. */
- if (integer_zerop (maxval) || !info.defining)
+ Similarly if !defining. */
+ if (integer_zerop (maxval) || !defining)
idx = size_zero_node;
/* Some other array, will need runtime loop. */
else
@@ -1492,69 +1592,13 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
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);
+ tree comp = do_one_comp (field_loc, info, field, lhs_mem, rhs_mem);
if (comp == error_mark_node)
{
- 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)
- ;
- 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 (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
@@ -1584,7 +1628,7 @@ 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 (defining)
{
if (TREE_CODE (comp) == TREE_LIST)
{
@@ -1632,7 +1676,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
comp = build_static_cast (input_location, rettype, comp,
complain);
info.check (comp);
- if (info.defining)
+ if (defining)
{
tree var = create_temporary_var (rettype);
pushdecl (var);
@@ -1645,7 +1689,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
}
tree ceq = contextual_conv_bool (eq, complain);
info.check (ceq);
- if (info.defining)
+ if (defining)
{
finish_if_stmt_cond (ceq, if_);
finish_then_clause (if_);
@@ -1658,7 +1702,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
finish_for_stmt (TREE_VALUE (loop_index));
}
}
- if (info.defining)
+ if (defining)
{
tree val;
if (code == EQ_EXPR)
@@ -1679,7 +1723,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
NULL_TREE, NULL, complain);
comp = contextual_conv_bool (comp, complain);
info.check (comp);
- if (info.defining)
+ if (defining)
{
tree neg = build1 (TRUTH_NOT_EXPR, boolean_type_node, comp);
finish_return_stmt (neg);
@@ -1692,12 +1736,12 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
tree comp2 = build_new_op (info.loc, code, flags, comp, integer_zero_node,
NULL_TREE, NULL, complain);
info.check (comp2);
- if (info.defining)
+ if (defining)
finish_return_stmt (comp2);
}
out:
- if (info.defining)
+ if (defining)
finish_compound_stmt (compound_stmt);
else
--cp_unevaluated_operand;
@@ -1776,7 +1820,7 @@ synthesize_method (tree fndecl)
else if (sfk == sfk_comparison)
{
/* Pass tf_none so the function is just deleted if there's a problem. */
- build_comparison_op (fndecl, tf_none);
+ build_comparison_op (fndecl, true, tf_none);
need_body = false;
}
@@ -1810,6 +1854,32 @@ synthesize_method (tree fndecl)
fndecl);
}
+/* Like synthesize_method, but don't actually synthesize defaulted comparison
+ methods if their class is still incomplete. Just deduce the return
+ type in that case. */
+
+void
+maybe_synthesize_method (tree fndecl)
+{
+ if (special_function_p (fndecl) == sfk_comparison)
+ {
+ tree lhs = DECL_ARGUMENTS (fndecl);
+ if (is_this_parameter (lhs))
+ lhs = cp_build_fold_indirect_ref (lhs);
+ else
+ lhs = convert_from_reference (lhs);
+ tree ctype = TYPE_MAIN_VARIANT (TREE_TYPE (lhs));
+ if (!COMPLETE_TYPE_P (ctype))
+ {
+ push_deferring_access_checks (dk_no_deferred);
+ build_comparison_op (fndecl, false, tf_none);
+ pop_deferring_access_checks ();
+ return;
+ }
+ }
+ return synthesize_method (fndecl);
+}
+
/* Build a reference to type TYPE with cv-quals QUALS, which is an
rvalue if RVALUE is true. */
@@ -2081,6 +2151,7 @@ constructible_expr (tree to, tree from)
static tree
is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
{
+ to = complete_type (to);
deferring_access_check_sentinel acs (dk_no_deferred);
if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to)
|| (from && FUNC_OR_METHOD_TYPE_P (from)
@@ -2089,8 +2160,10 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
tree expr;
if (code == MODIFY_EXPR)
expr = assignable_expr (to, from);
- else if (trivial && from && TREE_CHAIN (from))
+ else if (trivial && from && TREE_CHAIN (from)
+ && cxx_dialect < cxx20)
return error_mark_node; // only 0- and 1-argument ctors can be trivial
+ // before C++20 aggregate paren init
else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to))
return error_mark_node; // can't construct an array of unknown bound
else
@@ -2746,7 +2819,7 @@ maybe_explain_implicit_delete (tree decl)
inform (DECL_SOURCE_LOCATION (decl),
"%q#D is implicitly deleted because the default "
"definition would be ill-formed:", decl);
- build_comparison_op (decl, tf_warning_or_error);
+ build_comparison_op (decl, false, tf_warning_or_error);
}
else if (!informed)
{
@@ -2807,7 +2880,7 @@ explain_implicit_non_constexpr (tree decl)
if (sfk == sfk_comparison)
{
DECL_DECLARED_CONSTEXPR_P (decl) = true;
- build_comparison_op (decl, tf_warning_or_error);
+ build_comparison_op (decl, false, tf_warning_or_error);
DECL_DECLARED_CONSTEXPR_P (decl) = false;
}
else
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index ccbde29..71d0fab 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -11859,8 +11859,9 @@ trees_in::read_class_def (tree defn, tree maybe_template)
{
CLASSTYPE_BEFRIENDING_CLASSES (type_dup)
= CLASSTYPE_BEFRIENDING_CLASSES (type);
- CLASSTYPE_TYPEINFO_VAR (type_dup)
- = CLASSTYPE_TYPEINFO_VAR (type);
+ if (!ANON_AGGR_TYPE_P (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;
@@ -11891,6 +11892,11 @@ trees_in::read_class_def (tree defn, tree maybe_template)
*chain = decl;
chain = &DECL_CHAIN (decl);
+ if (TREE_CODE (decl) == FIELD_DECL
+ && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+ ANON_AGGR_TYPE_FIELD
+ (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl;
+
if (TREE_CODE (decl) == USING_DECL
&& TREE_CODE (USING_DECL_SCOPE (decl)) == RECORD_TYPE)
{
@@ -17977,7 +17983,7 @@ module_state::read_language (bool outermost)
function_depth++; /* Prevent unexpected GCs. */
- if (counts[MSC_entities] != entity_num)
+ if (ok && counts[MSC_entities] != entity_num)
ok = false;
if (ok && counts[MSC_entities]
&& !read_entities (counts[MSC_entities],
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8e9c61e..c414a10 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3363,12 +3363,9 @@ set_decl_context_in_fn (tree ctx, tree decl)
if (!DECL_CONTEXT (decl)
/* When parsing the parameter list of a function declarator,
- don't set DECL_CONTEXT to an enclosing function. When we
- push the PARM_DECLs in order to process the function body,
- current_binding_level->this_entity will be set. */
+ don't set DECL_CONTEXT to an enclosing function. */
&& !(TREE_CODE (decl) == PARM_DECL
- && current_binding_level->kind == sk_function_parms
- && current_binding_level->this_entity == NULL))
+ && parsing_function_declarator ()))
DECL_CONTEXT (decl) = ctx;
}
@@ -3378,7 +3375,10 @@ set_decl_context_in_fn (tree ctx, tree decl)
void
push_local_extern_decl_alias (tree decl)
{
- if (dependent_type_p (TREE_TYPE (decl)))
+ if (dependent_type_p (TREE_TYPE (decl))
+ || (processing_template_decl
+ && VAR_P (decl)
+ && CP_DECL_THREAD_LOCAL_P (decl)))
return;
/* EH specs were not part of the function type prior to c++17, but
we still can't go pushing dependent eh specs into the namespace. */
@@ -3474,6 +3474,8 @@ push_local_extern_decl_alias (tree decl)
push_nested_namespace (ns);
alias = do_pushdecl (alias, /* hiding= */true);
pop_nested_namespace (ns);
+ if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl))
+ set_decl_tls_model (alias, DECL_TLS_MODEL (decl));
}
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a959c71..865778e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1051,8 +1051,17 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_FLOAT:
case RID_DOUBLE:
case RID_VOID:
+ /* CV qualifiers. */
+ case RID_CONST:
+ case RID_VOLATILE:
+ /* Function specifiers. */
+ case RID_EXPLICIT:
+ case RID_VIRTUAL:
+ /* friend/typdef/inline specifiers. */
+ case RID_FRIEND:
+ case RID_TYPEDEF:
+ case RID_INLINE:
/* GNU extensions. */
- case RID_ATTRIBUTE:
case RID_TYPEOF:
/* C++11 extensions. */
case RID_DECLTYPE:
@@ -6379,7 +6388,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
declarator-id of a constructor or destructor. */
- if (token->type == CPP_TEMPLATE_ID && cxx_dialect >= cxx20)
+ if (token->type == CPP_TEMPLATE_ID && declarator_p
+ && cxx_dialect >= cxx20)
{
if (!cp_parser_simulate_error (parser))
error_at (tilde_loc, "template-id not allowed for destructor");
@@ -10822,6 +10832,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
return error_mark_node;
type2 = tree_cons (NULL_TREE, elt, type2);
}
+ type2 = nreverse (type2);
}
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -11455,8 +11466,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
/* In the decl-specifier-seq of the lambda-declarator, each
decl-specifier shall either be mutable or constexpr. */
int declares_class_or_enum;
- if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
- && !cp_next_tokens_can_be_gnu_attribute_p (parser))
+ if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
&lambda_specs, &declares_class_or_enum);
@@ -12848,7 +12858,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
IF_STMT_CONSTEVAL_P (statement) = true;
condition = finish_if_stmt_cond (boolean_false_node, statement);
- gcc_rich_location richloc = tok->location;
+ gcc_rich_location richloc (tok->location);
bool non_compound_stmt_p = false;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
{
@@ -12876,7 +12886,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
RID_ELSE))
{
cp_token *else_tok = cp_lexer_peek_token (parser->lexer);
- gcc_rich_location else_richloc = else_tok->location;
+ gcc_rich_location else_richloc (else_tok->location);
guard_tinfo = get_token_indent_info (else_tok);
/* Consume the `else' keyword. */
cp_lexer_consume_token (parser->lexer);
@@ -13474,17 +13484,15 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
static tree
build_range_temp (tree range_expr)
{
- tree range_type, range_temp;
-
/* Find out the type deduced by the declaration
`auto &&__range = range_expr'. */
- range_type = cp_build_reference_type (make_auto (), true);
- range_type = do_auto_deduction (range_type, range_expr,
- type_uses_auto (range_type));
+ tree auto_node = make_auto ();
+ tree range_type = cp_build_reference_type (auto_node, true);
+ range_type = do_auto_deduction (range_type, range_expr, auto_node);
/* Create the __range variable. */
- range_temp = build_decl (input_location, VAR_DECL, for_range__identifier,
- range_type);
+ tree range_temp = build_decl (input_location, VAR_DECL,
+ for_range__identifier, range_type);
TREE_USED (range_temp) = 1;
DECL_ARTIFICIAL (range_temp) = 1;
@@ -14168,9 +14176,11 @@ cp_parser_jump_statement (cp_parser* parser)
case RID_GOTO:
if (parser->in_function_body
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && cxx_dialect < cxx23)
{
- error ("%<goto%> in %<constexpr%> function");
+ error ("%<goto%> in %<constexpr%> function only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>");
cp_function_chain->invalid_constexpr = true;
}
@@ -18188,6 +18198,16 @@ cp_parser_template_id (cp_parser *parser,
if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)
SET_EXPR_LOCATION (template_id, combined_loc);
}
+ else if (TREE_CODE (templ) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (templ)) == TYPENAME_TYPE)
+ {
+ /* Some type template in dependent scope. */
+ tree &name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (templ));
+ name = build_min_nt_loc (combined_loc,
+ TEMPLATE_ID_EXPR,
+ name, arguments);
+ template_id = templ;
+ }
else
{
/* If it's not a class-template or a template-template, it should be
@@ -18406,6 +18426,7 @@ cp_parser_template_name (cp_parser* parser,
{
/* We're optimizing away the call to cp_parser_lookup_name, but
we still need to do this. */
+ parser->object_scope = parser->context->object_type;
parser->context->object_type = NULL_TREE;
return identifier;
}
@@ -18413,8 +18434,8 @@ cp_parser_template_name (cp_parser* parser,
}
/* cp_parser_lookup_name clears OBJECT_TYPE. */
- const bool scoped_p = ((parser->scope ? parser->scope
- : parser->context->object_type) != NULL_TREE);
+ tree scope = (parser->scope ? parser->scope
+ : parser->context->object_type);
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
@@ -18427,30 +18448,47 @@ cp_parser_template_name (cp_parser* parser,
decl = strip_using_decl (decl);
+ /* 13.3 [temp.names] A < is interpreted as the delimiter of a
+ template-argument-list if it follows a name that is not a
+ conversion-function-id and
+ - that follows the keyword template or a ~ after a nested-name-specifier or
+ in a class member access expression, or
+ - for which name lookup finds the injected-class-name of a class template
+ or finds any declaration of a template, or
+ - that is an unqualified name for which name lookup either finds one or
+ more functions or finds nothing, or
+ - that is a terminal name in a using-declarator (9.9), in a declarator-id
+ (9.3.4), or in a type-only context other than a nested-name-specifier
+ (13.8). */
+
/* If DECL is a template, then the name was a template-name. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (TREE_DEPRECATED (decl)
- && deprecated_state != DEPRECATED_SUPPRESS)
+ if ((TREE_DEPRECATED (decl) || TREE_UNAVAILABLE (decl))
+ && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
{
tree d = DECL_TEMPLATE_RESULT (decl);
tree attr;
if (TREE_CODE (d) == TYPE_DECL)
- attr = lookup_attribute ("deprecated",
- TYPE_ATTRIBUTES (TREE_TYPE (d)));
+ attr = TYPE_ATTRIBUTES (TREE_TYPE (d));
else
- attr = lookup_attribute ("deprecated",
- DECL_ATTRIBUTES (d));
- warn_deprecated_use (decl, attr);
+ attr = DECL_ATTRIBUTES (d);
+ if (TREE_UNAVAILABLE (decl))
+ {
+ attr = lookup_attribute ("unavailable", attr);
+ error_unavailable_use (decl, attr);
+ }
+ else if (TREE_DEPRECATED (decl)
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ {
+ attr = lookup_attribute ("deprecated", attr);
+ warn_deprecated_use (decl, attr);
+ }
}
}
else
{
- /* The standard does not explicitly indicate whether a name that
- names a set of overloaded declarations, some of which are
- templates, is a template-name. However, such a name should
- be a template-name; otherwise, there is no way to form a
- template-id for the overloaded templates. */
+ /* Look through an overload set for any templates. */
bool found = false;
for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (decl));
@@ -18458,34 +18496,41 @@ cp_parser_template_name (cp_parser* parser,
if (TREE_CODE (*iter) == TEMPLATE_DECL)
found = true;
+ /* "an unqualified name for which name lookup either finds one or more
+ functions or finds nothing". */
if (!found
&& (cxx_dialect > cxx17)
- && !scoped_p
+ && !scope
&& cp_lexer_next_token_is (parser->lexer, CPP_LESS)
&& tag_type == none_type)
{
- /* [temp.names] says "A name is also considered to refer to a template
- if it is an unqualified-id followed by a < and name lookup finds
- either one or more functions or finds nothing." */
-
/* The "more functions" case. Just use the OVERLOAD as normally.
We don't use is_overloaded_fn here to avoid considering
BASELINKs. */
if (TREE_CODE (decl) == OVERLOAD
/* Name lookup found one function. */
- || TREE_CODE (decl) == FUNCTION_DECL)
+ || TREE_CODE (decl) == FUNCTION_DECL
+ /* Name lookup found nothing. */
+ || decl == error_mark_node)
found = true;
- /* Name lookup found nothing. */
- else if (decl == error_mark_node)
- return identifier;
}
+ /* "in a type-only context" */
+ if (!found && scope
+ && tag_type != none_type
+ && dependentish_scope_p (scope)
+ && cp_parser_nth_token_starts_template_argument_list_p (parser, 1))
+ found = true;
+
if (!found)
{
/* The name does not name a template. */
cp_parser_error (parser, "expected template-name");
return error_mark_node;
}
+ else if (decl == error_mark_node)
+ /* Repeat the lookup at instantiation time. */
+ decl = identifier;
}
return decl;
@@ -18692,7 +18737,9 @@ cp_parser_template_argument (cp_parser* parser)
}
if (cp_parser_parse_definitely (parser))
{
- if (TREE_DEPRECATED (argument))
+ if (TREE_UNAVAILABLE (argument))
+ error_unavailable_use (argument, NULL_TREE);
+ else if (TREE_DEPRECATED (argument))
warn_deprecated_use (argument, NULL_TREE);
return argument;
}
@@ -23097,7 +23144,7 @@ cp_parser_direct_declarator (cp_parser* parser,
else if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
/* Let compute_array_index_type diagnose this. */;
else if (!parser->in_function_body
- || current_binding_level->kind == sk_function_parms)
+ || parsing_function_declarator ())
{
/* Normally, the array bound must be an integral constant
expression. However, as an extension, we allow VLAs
@@ -23821,6 +23868,17 @@ parsing_nsdmi (void)
return false;
}
+/* True if we're parsing a function declarator. */
+
+bool
+parsing_function_declarator ()
+{
+ /* this_entity is NULL for a function parameter scope while parsing the
+ declarator; it is set when parsing the body of the function. */
+ return (current_binding_level->kind == sk_function_parms
+ && !current_binding_level->this_entity);
+}
+
/* Parse a late-specified return type, if any. This is not a separate
non-terminal, but part of a function declarator, which looks like
@@ -24353,9 +24411,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
/*template_parm_p=*/false,
&parenthesized_p);
- /* We don't know yet if the enclosing context is deprecated, so wait
- and warn in grokparms if appropriate. */
- deprecated_state = DEPRECATED_SUPPRESS;
+ /* We don't know yet if the enclosing context is unavailable or deprecated,
+ so wait and deal with it in grokparms if appropriate. */
+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
if (parameter && !cp_parser_error_occurred (parser))
{
@@ -25910,7 +25968,8 @@ cp_parser_class_specifier_1 (cp_parser* parser)
so that maybe_instantiate_noexcept can tsubst the NOEXCEPT_EXPR
in the pattern. */
for (tree i : DEFPARSE_INSTANTIATIONS (def_parse))
- DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i)) = TREE_PURPOSE (spec);
+ DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i))
+ = spec ? TREE_PURPOSE (spec) : error_mark_node;
/* Restore the state of local_variables_forbidden_p. */
parser->local_variables_forbidden_p = local_variables_forbidden_p;
@@ -28580,7 +28639,16 @@ cp_parser_omp_directive_args (cp_parser *parser, tree attribute)
TREE_VALUE (attribute) = NULL_TREE;
return;
}
- for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 2; n; --n)
+ size_t n = cp_parser_skip_balanced_tokens (parser, 1);
+ if (n == 1)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ error_at (first->location, "expected attribute argument as balanced "
+ "token sequence");
+ TREE_VALUE (attribute) = NULL_TREE;
+ return;
+ }
+ for (n = n - 2; n; --n)
cp_lexer_consume_token (parser->lexer);
cp_token *last = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
@@ -29911,6 +29979,25 @@ cp_parser_simple_requirement (cp_parser *parser)
if (expr.get_location() == UNKNOWN_LOCATION)
expr.set_location (start);
+ for (tree t = expr; ; )
+ {
+ if (TREE_CODE (t) == TRUTH_ANDIF_EXPR
+ || TREE_CODE (t) == TRUTH_ORIF_EXPR)
+ {
+ t = TREE_OPERAND (t, 0);
+ continue;
+ }
+ if (concept_check_p (t))
+ {
+ gcc_rich_location richloc (get_start (start));
+ richloc.add_fixit_insert_before (start, "requires ");
+ warning_at (&richloc, OPT_Wmissing_requires, "testing "
+ "if a concept-id is a valid expression; add "
+ "%<requires%> to check satisfaction");
+ }
+ break;
+ }
+
return finish_simple_requirement (expr.get_location (), expr);
}
@@ -30332,6 +30419,17 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
consider class templates. */
: is_template ? LOOK_want::TYPE
: prefer_type_arg (tag_type));
+
+ /* If we know we're looking for a type (e.g. A in p->A::x),
+ mock up a typename. */
+ if (!decl && object_type && tag_type != none_type
+ && dependentish_scope_p (object_type))
+ {
+ tree type = build_typename_type (object_type, name, name,
+ typename_type);
+ decl = TYPE_NAME (type);
+ }
+
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
}
@@ -30747,23 +30845,22 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
/* A parameter declaration begins with a decl-specifier,
which is either the "attribute" keyword, a storage class
specifier, or (usually) a type-specifier. */
- && (!cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
- /* GNU attributes can actually appear both at the start of
- a parameter and parenthesized declarator.
- S (__attribute__((unused)) int);
- is a constructor, but
- S (__attribute__((unused)) foo) (int);
- is a function declaration. */
- || (cp_parser_allow_gnu_extensions_p (parser)
- && cp_next_tokens_can_be_gnu_attribute_p (parser)))
- /* A parameter declaration can also begin with [[attribute]]. */
+ && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
+ /* GNU attributes can actually appear both at the start of
+ a parameter and parenthesized declarator.
+ S (__attribute__((unused)) int);
+ is a constructor, but
+ S (__attribute__((unused)) foo) (int);
+ is a function declaration. [[attribute]] can appear in the
+ first form too, but not in the second form. */
&& !cp_next_tokens_can_be_std_attribute_p (parser))
{
tree type;
tree pushed_scope = NULL_TREE;
unsigned saved_num_template_parameter_lists;
- if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && cp_next_tokens_can_be_gnu_attribute_p (parser))
{
unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, 1);
while (--n)
@@ -33546,7 +33643,8 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
/* Set the scope from the stored value. */
parser->scope = saved_checks_value (check_value);
parser->qualifying_scope = check_value->qualifying_scope;
- parser->object_scope = NULL_TREE;
+ parser->object_scope = parser->context->object_type;
+ parser->context->object_type = NULL_TREE;
}
/* Consume tokens up through a non-nested END token. Returns TRUE if we
@@ -36909,6 +37007,9 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
/* OpenMP 2.5:
default ( none | shared )
+ OpenMP 5.1:
+ default ( private | firstprivate )
+
OpenACC:
default ( none | present ) */
@@ -36922,7 +37023,12 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ if (!is_oacc && cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE))
+ {
+ kind = OMP_CLAUSE_DEFAULT_PRIVATE;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
@@ -36941,6 +37047,12 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
kind = OMP_CLAUSE_DEFAULT_PRESENT;
break;
+ case 'f':
+ if (strcmp ("firstprivate", p) != 0 || is_oacc)
+ goto invalid_kind;
+ kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
+ break;
+
case 's':
if (strcmp ("shared", p) != 0 || is_oacc)
goto invalid_kind;
@@ -36959,7 +37071,8 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
if (is_oacc)
cp_parser_error (parser, "expected %<none%> or %<present%>");
else
- cp_parser_error (parser, "expected %<none%> or %<shared%>");
+ cp_parser_error (parser, "expected %<none%>, %<shared%>, "
+ "%<private%> or %<firstprivate%>");
}
if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED
@@ -37609,18 +37722,45 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
}
/* OpenMP 5.0:
- order ( concurrent ) */
+ order ( concurrent )
+
+ OpenMP 5.1:
+ order ( order-modifier : concurrent )
+
+ order-modifier:
+ reproducible
+ unconstrained */
static tree
cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
{
tree c, id;
const char *p;
+ bool unconstrained = false;
+ bool reproducible = false;
matching_parens parens;
if (!parens.require_open (parser))
return list;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ {
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "unconstrained") == 0)
+ unconstrained = true;
+ else if (strcmp (p, "reproducible") == 0)
+ reproducible = true;
+ else
+ {
+ cp_parser_error (parser, "expected %<reproducible%> or "
+ "%<unconstrained%>");
+ goto out_err;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
cp_parser_error (parser, "expected %<concurrent%>");
@@ -37640,8 +37780,10 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
if (!parens.require_close (parser))
goto out_err;
- /* check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location); */
+ check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location);
c = build_omp_clause (location, OMP_CLAUSE_ORDER);
+ OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -38218,13 +38360,21 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
{
- tree nlist, c, allocator = NULL_TREE;
- bool colon;
+ tree nlist, c, allocator = NULL_TREE, align = NULL_TREE;
+ bool colon, has_modifiers = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -38233,7 +38383,51 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree 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);
+ for (int mod = 0; mod < 2; mod++)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "allocator") != 0 && strcmp (p, "align") != 0)
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ matching_parens parens2;
+ if (!parens2.require_open (parser))
+ break;
+ if (strcmp (p, "allocator") == 0)
+ {
+ if (allocator != NULL_TREE)
+ break;
+ allocator = cp_parser_assignment_expression (parser);
+ }
+ else
+ {
+ if (align != NULL_TREE)
+ break;
+ align = cp_parser_assignment_expression (parser);
+ }
+ if (!parens2.require_close (parser))
+ break;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ has_modifiers = true;
+ break;
+ }
+ if (mod != 0 || cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ break;
+ if (!has_modifiers)
+ {
+ cp_parser_abort_tentative_parse (parser);
+ align = NULL_TREE;
+ allocator = NULL_TREE;
+ cp_parser_parse_tentatively (parser);
+ 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))
{
@@ -38241,18 +38435,25 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
cp_lexer_consume_token (parser->lexer);
if (allocator == error_mark_node)
allocator = NULL_TREE;
+ if (align == error_mark_node)
+ align = NULL_TREE;
}
else
{
cp_parser_abort_tentative_parse (parser);
allocator = NULL_TREE;
+ align = 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;
+ if (allocator || align)
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
return nlist;
}
@@ -39030,18 +39231,57 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
}
/* OpenMP 4.0:
- device ( expression ) */
+ device ( expression )
+
+ OpenMP 5.0:
+ device ( [device-modifier :] integer-expression )
+
+ device-modifier:
+ ancestor | device_num */
static tree
cp_parser_omp_clause_device (cp_parser *parser, tree list,
location_t location)
{
tree t, c;
+ bool ancestor = false;
matching_parens parens;
if (!parens.require_open (parser))
return list;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ {
+ cp_token *tok = cp_lexer_peek_token (parser->lexer);
+ const char *p = IDENTIFIER_POINTER (tok->u.value);
+ if (strcmp ("ancestor", p) == 0)
+ {
+ ancestor = true;
+
+ /* A requires directive with the reverse_offload clause must be
+ specified. */
+ if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
+ {
+ error_at (tok->location, "%<ancestor%> device modifier not "
+ "preceded by %<requires%> directive "
+ "with %<reverse_offload%> clause");
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ return list;
+ }
+ }
+ else if (strcmp ("device_num", p) == 0)
+ ;
+ else
+ {
+ error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ return list;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+
t = cp_parser_assignment_expression (parser);
if (t == error_mark_node
@@ -39056,6 +39296,7 @@ cp_parser_omp_clause_device (cp_parser *parser, tree list,
c = build_omp_clause (location, OMP_CLAUSE_DEVICE);
OMP_CLAUSE_DEVICE_ID (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
+ OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
return c;
}
@@ -39895,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
}
static tree
-cp_parser_omp_structured_block (cp_parser *parser, bool *if_p,
- bool disallow_omp_attrs = true)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
{
tree stmt = begin_omp_structured_block ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
- if (disallow_omp_attrs)
- parser->omp_attrs_forbidden_p = true;
+ parser->omp_attrs_forbidden_p = true;
cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
@@ -40000,19 +40239,56 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok)
capture-block:
{ v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
- where x and v are lvalue expressions with scalar type. */
+ OpenMP 5.1:
+ # pragma omp atomic compare new-line
+ conditional-update-atomic
+
+ # pragma omp atomic compare capture new-line
+ conditional-update-capture-atomic
+
+ conditional-update-atomic:
+ cond-expr-stmt | cond-update-stmt
+ cond-expr-stmt:
+ x = expr ordop x ? expr : x;
+ x = x ordop expr ? expr : x;
+ x = x == e ? d : x;
+ cond-update-stmt:
+ if (expr ordop x) { x = expr; }
+ if (x ordop expr) { x = expr; }
+ if (x == e) { x = d; }
+ ordop:
+ <, >
+ conditional-update-capture-atomic:
+ v = cond-expr-stmt
+ { v = x; cond-expr-stmt }
+ { cond-expr-stmt v = x; }
+ { v = x; cond-update-stmt }
+ { cond-update-stmt v = x; }
+ if (x == e) { x = d; } else { v = x; }
+ { r = x == e; if (r) { x = d; } }
+ { r = x == e; if (r) { x = d; } else { v = x; } }
+
+ where x, r and v are lvalue expressions with scalar type,
+ expr, e and d are expressions with scalar type and e might be
+ the same as v. */
static void
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;
+ tree rhs1 = NULL_TREE, orig_lhs, r = NULL_TREE;
location_t loc = pragma_tok->location;
enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
bool structured_block = false;
bool first = true;
tree clauses = NULL_TREE;
+ bool capture = false;
+ bool compare = false;
+ bool weak = false;
+ enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool no_semicolon = false;
+ bool extra_scope = false;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
@@ -40032,6 +40308,10 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
enum tree_code new_code = ERROR_MARK;
enum omp_memory_order new_memory_order
= OMP_MEMORY_ORDER_UNSPECIFIED;
+ bool new_capture = false;
+ bool new_compare = false;
+ bool new_weak = false;
+ enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
if (!strcmp (p, "read"))
new_code = OMP_ATOMIC_READ;
@@ -40039,7 +40319,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
new_code = NOP_EXPR;
else if (!strcmp (p, "update"))
new_code = OMP_ATOMIC;
- else if (!strcmp (p, "capture"))
+ else if (openacc && !strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
else if (openacc)
{
@@ -40047,6 +40327,52 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
"or %<capture%> clause");
}
+ else if (!strcmp (p, "capture"))
+ new_capture = true;
+ else if (!strcmp (p, "compare"))
+ new_compare = true;
+ else if (!strcmp (p, "weak"))
+ new_weak = true;
+ else if (!strcmp (p, "fail"))
+ {
+ matching_parens parens;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!parens.require_open (parser))
+ continue;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *q = IDENTIFIER_POINTER (id);
+
+ if (!strcmp (q, "seq_cst"))
+ new_fail = OMP_MEMORY_ORDER_SEQ_CST;
+ else if (!strcmp (q, "acquire"))
+ new_fail = OMP_MEMORY_ORDER_ACQUIRE;
+ else if (!strcmp (q, "relaxed"))
+ new_fail = OMP_MEMORY_ORDER_RELAXED;
+ }
+
+ if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ error_at (cloc, "too many %qs clauses", "fail");
+ else
+ fail = new_fail;
+ }
+ else
+ cp_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
+ "or %<relaxed%>");
+ if (new_fail == OMP_MEMORY_ORDER_UNSPECIFIED
+ || !parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ continue;
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -40067,8 +40393,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
{
p = NULL;
error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
- "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
- "%<release%>, %<relaxed%> or %<hint%> clause");
+ "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
+ "%<seq_cst%>, %<acq_rel%>, %<release%>, "
+ "%<relaxed%> or %<hint%> clause");
}
if (p)
{
@@ -40091,6 +40418,27 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
else
memory_order = new_memory_order;
}
+ else if (new_capture)
+ {
+ if (capture)
+ error_at (cloc, "too many %qs clauses", "capture");
+ else
+ capture = true;
+ }
+ else if (new_compare)
+ {
+ if (compare)
+ error_at (cloc, "too many %qs clauses", "compare");
+ else
+ compare = true;
+ }
+ else if (new_weak)
+ {
+ if (weak)
+ error_at (cloc, "too many %qs clauses", "weak");
+ else
+ weak = true;
+ }
cp_lexer_consume_token (parser->lexer);
continue;
}
@@ -40101,6 +40449,30 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
+ if (capture)
+ {
+ if (code != OMP_ATOMIC)
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "capture");
+ else
+ code = OMP_ATOMIC_CAPTURE_NEW;
+ }
+ if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
+ "clauses", "compare");
+ compare = false;
+ }
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
+ fail = OMP_MEMORY_ORDER_UNSPECIFIED;
+ }
+ if (weak && !compare)
+ {
+ error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
+ weak = false;
+ }
if (openacc)
memory_order = OMP_MEMORY_ORDER_RELAXED;
else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
@@ -40125,7 +40497,6 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- case OMP_ATOMIC:
memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
@@ -40141,35 +40512,32 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
switch (code)
{
case OMP_ATOMIC_READ:
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_RELEASE)
+ if (memory_order == OMP_MEMORY_ORDER_RELEASE)
{
error_at (loc, "%<#pragma omp atomic read%> incompatible with "
- "%<acq_rel%> or %<release%> clauses");
+ "%<release%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
break;
case NOP_EXPR: /* atomic write */
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+ if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
{
error_at (loc, "%<#pragma omp atomic write%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- }
- break;
- case OMP_ATOMIC:
- if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
- || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
- {
- error_at (loc, "%<#pragma omp atomic update%> incompatible with "
- "%<acq_rel%> or %<acquire%> clauses");
+ "%<acquire%> clause");
memory_order = OMP_MEMORY_ORDER_SEQ_CST;
}
+ else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
break;
default:
break;
}
+ if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
+ memory_order
+ = (enum omp_memory_order) (memory_order
+ | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
switch (code)
{
@@ -40202,6 +40570,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
cp_lexer_consume_token (parser->lexer);
structured_block = true;
}
+ else if (compare
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+ break;
else
{
v = cp_parser_unary_expression (parser);
@@ -40209,12 +40580,179 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
goto saw_error;
if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
goto saw_error;
+ if (compare
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+ {
+ location_t eloc = cp_lexer_peek_token (parser->lexer)->location;
+ error_at (eloc, "expected expression");
+ goto saw_error;
+ }
}
default:
break;
}
restart:
+ if (compare && cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ goto saw_error;
+ location_t eloc = cp_lexer_peek_token (parser->lexer)->location;
+ tree cmp_expr;
+ if (r)
+ cmp_expr = cp_parser_unary_expression (parser);
+ else
+ cmp_expr = cp_parser_binary_expression (parser, false, true,
+ PREC_NOT_OPERATOR, NULL);
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ if (cmp_expr == error_mark_node)
+ goto saw_error;
+ if (r)
+ {
+ if (!cp_tree_equal (cmp_expr, r))
+ goto bad_if;
+ cmp_expr = rhs;
+ rhs = NULL_TREE;
+ gcc_assert (TREE_CODE (cmp_expr) == EQ_EXPR);
+ }
+ if (TREE_CODE (cmp_expr) == EQ_EXPR)
+ ;
+ else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc),
+ "expected %<==%> comparison in %<if%> condition");
+ goto saw_error;
+ }
+ else if (TREE_CODE (cmp_expr) != GT_EXPR
+ && TREE_CODE (cmp_expr) != LT_EXPR)
+ {
+ error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc),
+ "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
+ "condition");
+ goto saw_error;
+ }
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ goto saw_error;
+
+ extra_scope = true;
+ eloc = cp_lexer_peek_token (parser->lexer)->location;
+ lhs = cp_parser_unary_expression (parser);
+ orig_lhs = lhs;
+ if (lhs == error_mark_node)
+ goto saw_error;
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ {
+ cp_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ eloc = cp_lexer_peek_token (parser->lexer)->location;
+ if (TREE_CODE (cmp_expr) == EQ_EXPR)
+ rhs1 = cp_parser_expression (parser);
+ else
+ rhs1 = cp_parser_simple_cast_expression (parser);
+
+ if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ goto saw_error;
+
+ if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+ goto saw_error;
+
+ extra_scope = false;
+ no_semicolon = true;
+
+ if (cp_tree_equal (TREE_OPERAND (cmp_expr, 0), lhs))
+ {
+ if (TREE_CODE (cmp_expr) == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs = TREE_OPERAND (cmp_expr, 1);
+ }
+ else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr) == GT_EXPR
+ ? MIN_EXPR : MAX_EXPR);
+ rhs = rhs1;
+ rhs1 = TREE_OPERAND (cmp_expr, 0);
+ }
+ else
+ goto bad_if;
+ }
+ else if (TREE_CODE (cmp_expr) == EQ_EXPR)
+ goto bad_if;
+ else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), lhs)
+ && cp_tree_equal (TREE_OPERAND (cmp_expr, 0), rhs1))
+ {
+ opcode = (TREE_CODE (cmp_expr) == GT_EXPR
+ ? MAX_EXPR : MIN_EXPR);
+ rhs = rhs1;
+ rhs1 = TREE_OPERAND (cmp_expr, 1);
+ }
+ else
+ {
+ bad_if:
+ cp_parser_error (parser,
+ "invalid form of %<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+ {
+ if (code != OMP_ATOMIC_CAPTURE_NEW
+ || (structured_block && r == NULL_TREE)
+ || TREE_CODE (cmp_expr) != EQ_EXPR)
+ {
+ eloc = cp_lexer_peek_token (parser->lexer)->location;
+ error_at (eloc, "unexpected %<else%>");
+ goto saw_error;
+ }
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ goto saw_error;
+
+ extra_scope = true;
+ v = cp_parser_unary_expression (parser);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ goto saw_error;
+
+ tree expr = cp_parser_simple_cast_expression (parser);
+
+ if (!cp_tree_equal (expr, lhs))
+ goto bad_if;
+
+ if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ goto saw_error;
+
+ if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+ goto saw_error;
+
+ extra_scope = false;
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ if (r == NULL_TREE)
+ /* Signal to c_finish_omp_atomic that in
+ if (x == e) { x = d; } else { v = x; }
+ case the store to v should be conditional. */
+ r = void_list_node;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+ {
+ cp_parser_error (parser, "expected %<else%>");
+ goto saw_error;
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_NEW
+ && r != NULL_TREE
+ && v == NULL_TREE)
+ code = OMP_ATOMIC;
+ goto stmt_done;
+ }
lhs = cp_parser_unary_expression (parser);
orig_lhs = lhs;
switch (TREE_CODE (lhs))
@@ -40230,6 +40768,8 @@ restart:
lhs = TREE_OPERAND (lhs, 0);
opcode = PLUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case POSTDECREMENT_EXPR:
@@ -40240,6 +40780,8 @@ restart:
lhs = TREE_OPERAND (lhs, 0);
opcode = MINUS_EXPR;
rhs = integer_one_node;
+ if (compare)
+ goto invalid_compare;
break;
case COMPOUND_EXPR:
@@ -40268,11 +40810,18 @@ restart:
&& !structured_block
&& TREE_CODE (orig_lhs) == COMPOUND_EXPR)
code = OMP_ATOMIC_CAPTURE_OLD;
+ if (compare)
+ goto invalid_compare;
break;
}
}
/* FALLTHRU */
default:
+ if (compare && !cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ {
+ cp_parser_error (parser, "expected %<=%>");
+ goto saw_error;
+ }
switch (cp_lexer_peek_token (parser->lexer)->type)
{
case CPP_MULT_EQ:
@@ -40340,6 +40889,8 @@ restart:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
+ if (compare)
+ break;
if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)))
{
if (cp_parser_parse_definitely (parser))
@@ -40353,11 +40904,91 @@ restart:
goto saw_error;
}
break;
+ case EQ_EXPR:
+ if (!compare
+ || code != OMP_ATOMIC_CAPTURE_NEW
+ || !structured_block
+ || v
+ || r)
+ break;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ && cp_lexer_nth_token_is_keyword (parser->lexer,
+ 2, RID_IF))
+ {
+ if (cp_parser_parse_definitely (parser))
+ {
+ r = lhs;
+ lhs = NULL_TREE;
+ rhs1 = NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ goto restart;
+ }
+ }
+ break;
+ case GT_EXPR:
+ case LT_EXPR:
+ if (compare
+ && cp_lexer_next_token_is (parser->lexer, CPP_QUERY)
+ && cp_tree_equal (lhs, TREE_OPERAND (rhs, 1))
+ && cp_parser_parse_definitely (parser))
+ {
+ opcode = TREE_CODE (rhs);
+ rhs1 = TREE_OPERAND (rhs, 0);
+ rhs = TREE_OPERAND (rhs, 1);
+ cond_expr:
+ cp_lexer_consume_token (parser->lexer);
+ bool saved_colon_corrects_to_scope_p
+ = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+ tree e1 = cp_parser_expression (parser);
+ parser->colon_corrects_to_scope_p
+ = saved_colon_corrects_to_scope_p;
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ tree e2 = cp_parser_simple_cast_expression (parser);
+ if (cp_tree_equal (lhs, e2))
+ {
+ if (cp_tree_equal (lhs, rhs1))
+ {
+ if (opcode == EQ_EXPR)
+ {
+ opcode = COND_EXPR;
+ rhs1 = e1;
+ goto stmt_done;
+ }
+ if (cp_tree_equal (rhs, e1))
+ {
+ opcode
+ = opcode == GT_EXPR ? MIN_EXPR : MAX_EXPR;
+ rhs = e1;
+ goto stmt_done;
+ }
+ }
+ else
+ {
+ gcc_assert (opcode != EQ_EXPR);
+ if (cp_tree_equal (rhs1, e1))
+ {
+ opcode
+ = opcode == GT_EXPR ? MAX_EXPR : MIN_EXPR;
+ rhs1 = rhs;
+ rhs = e1;
+ goto stmt_done;
+ }
+ }
+ }
+ cp_parser_error (parser,
+ "invalid form of "
+ "%<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
+ break;
default:
break;
}
cp_parser_abort_tentative_parse (parser);
- if (structured_block && code == OMP_ATOMIC_CAPTURE_OLD)
+ if (structured_block
+ && code == OMP_ATOMIC_CAPTURE_OLD
+ && !compare)
{
rhs = cp_parser_expression (parser);
if (rhs == error_mark_node)
@@ -40385,7 +41016,7 @@ restart:
cp_lexer_consume_token (parser->lexer);
goto restart;
}
- else if (structured_block)
+ else if (structured_block && !compare)
{
opcode = NOP_EXPR;
rhs = rhs1;
@@ -40422,11 +41053,28 @@ restart:
case CPP_XOR:
opcode = BIT_XOR_EXPR;
break;
+ case CPP_EQ_EQ:
+ opcode = EQ_EXPR;
+ break;
+ case CPP_GREATER:
+ opcode = GT_EXPR;
+ break;
+ case CPP_LESS:
+ opcode = LT_EXPR;
+ break;
default:
cp_parser_error (parser,
"invalid operator for %<#pragma omp atomic%>");
goto saw_error;
}
+ if (compare
+ && TREE_CODE_CLASS (opcode) != tcc_comparison)
+ {
+ cp_parser_error (parser,
+ "invalid form of "
+ "%<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
oprec = TOKEN_PRECEDENCE (token);
gcc_assert (oprec != PREC_NOT_OPERATOR);
if (commutative_tree_code (opcode))
@@ -40436,8 +41084,18 @@ restart:
oprec, NULL);
if (rhs == error_mark_node)
goto saw_error;
+ if (compare)
+ {
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
+ {
+ cp_parser_error (parser,
+ "invalid form of "
+ "%<#pragma omp atomic compare%>");
+ goto saw_error;
+ }
+ goto cond_expr;
+ }
goto stmt_done;
- /* FALLTHROUGH */
default:
cp_parser_error (parser,
"invalid operator for %<#pragma omp atomic%>");
@@ -40451,10 +41109,12 @@ restart:
break;
}
stmt_done:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
{
- if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ if (!no_semicolon
+ && !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
goto saw_error;
+ no_semicolon = false;
v = cp_parser_unary_expression (parser);
if (v == error_mark_node)
goto saw_error;
@@ -40466,19 +41126,30 @@ stmt_done:
}
if (structured_block)
{
- cp_parser_consume_semicolon_at_end_of_statement (parser);
+ if (!no_semicolon)
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
done:
+ if (weak && opcode != COND_EXPR)
+ {
+ error_at (loc, "%<weak%> clause requires atomic equality comparison");
+ weak = false;
+ }
clauses = finish_omp_clauses (clauses, C_ORT_OMP);
finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1,
- rhs1, clauses, memory_order);
- if (!structured_block)
+ rhs1, r, clauses, memory_order, weak);
+ if (!structured_block && !no_semicolon)
cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
+ invalid_compare:
+ error ("invalid form of %<pragma omp atomic compare%>");
+ /* FALLTHRU */
saw_error:
cp_parser_skip_to_end_of_block_or_statement (parser);
+ if (extra_scope && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ cp_lexer_consume_token (parser->lexer);
if (structured_block)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
@@ -40674,7 +41345,9 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
- if (!strcmp (p, "acq_rel"))
+ if (!strcmp (p, "seq_cst"))
+ mo = MEMMODEL_SEQ_CST;
+ else if (!strcmp (p, "acq_rel"))
mo = MEMMODEL_ACQ_REL;
else if (!strcmp (p, "release"))
mo = MEMMODEL_RELEASE;
@@ -40682,7 +41355,8 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
mo = MEMMODEL_ACQUIRE;
else
error_at (cp_lexer_peek_token (parser->lexer)->location,
- "expected %<acq_rel%>, %<release%> or %<acquire%>");
+ "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
+ "%<acquire%>");
cp_lexer_consume_token (parser->lexer);
}
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -41325,6 +41999,43 @@ cp_parser_omp_section_scan (cp_parser *parser, const char *directive,
return true;
}
+/* Parse an OpenMP structured block sequence. KIND is the corresponding
+ separating directive. */
+
+static tree
+cp_parser_omp_structured_block_sequence (cp_parser *parser,
+ enum pragma_kind kind)
+{
+ tree stmt = begin_omp_structured_block ();
+ unsigned int save = cp_parser_begin_omp_structured_block (parser);
+
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
+ while (true)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_CLOSE_BRACE
+ || token->type == CPP_EOF
+ || token->type == CPP_PRAGMA_EOL
+ || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END)
+ || (kind != PRAGMA_NONE
+ && cp_parser_pragma_kind (token) == kind))
+ break;
+
+ if (kind != PRAGMA_NONE
+ && cp_parser_omp_section_scan (parser,
+ kind == PRAGMA_OMP_SCAN
+ ? "scan" : "section", false))
+ break;
+
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
+ }
+
+ cp_parser_end_omp_structured_block (parser, save);
+ return finish_omp_structured_block (stmt);
+}
+
+
/* OpenMP 5.0:
scan-loop-body:
@@ -41339,11 +42050,10 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
if (!braces.require_open (parser))
return;
- substmt = cp_parser_omp_structured_block (parser, NULL, false);
+ substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
add_stmt (substmt);
- cp_parser_omp_section_scan (parser, "scan", false);
cp_token *tok = cp_lexer_peek_token (parser->lexer);
if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
{
@@ -41379,7 +42089,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
error ("expected %<#pragma omp scan%>");
clauses = finish_omp_clauses (clauses, C_ORT_OMP);
- substmt = cp_parser_omp_structured_block (parser, NULL, false);
+ substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
clauses);
add_stmt (substmt);
@@ -42248,7 +42958,8 @@ cp_parser_omp_sections_scope (cp_parser *parser)
!= PRAGMA_OMP_SECTION
&& !cp_parser_omp_section_scan (parser, "section", true))
{
- substmt = cp_parser_omp_structured_block (parser, NULL, false);
+ substmt = cp_parser_omp_structured_block_sequence (parser,
+ PRAGMA_OMP_SECTION);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -42275,7 +42986,8 @@ cp_parser_omp_sections_scope (cp_parser *parser)
error_suppress = true;
}
- substmt = cp_parser_omp_structured_block (parser, NULL, false);
+ substmt = cp_parser_omp_structured_block_sequence (parser,
+ PRAGMA_OMP_SECTION);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -42777,7 +43489,8 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok,
| (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))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
@@ -44606,7 +45319,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
tree ctx = cp_parser_omp_context_selector_specification (parser, true);
if (ctx == error_mark_node)
goto fail;
- ctx = c_omp_check_context_selector (match_loc, ctx);
+ ctx = omp_check_context_selector (match_loc, ctx);
if (ctx != error_mark_node && variant != error_mark_node)
{
tree match_loc_node = maybe_wrap_with_location (integer_zero_node,
@@ -44828,6 +45541,71 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
return attrs;
}
+/* Helper for cp_parser_omp_declare_target, handle one to or link clause
+ on #pragma omp declare target. Return false if errors were reported. */
+
+static bool
+handle_omp_declare_target_clause (tree c, tree t, int device_type)
+{
+ tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
+ tree at2 = lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t));
+ tree id;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
+ {
+ id = get_identifier ("omp declare target link");
+ std::swap (at1, at2);
+ }
+ else
+ id = get_identifier ("omp declare target");
+ if (at2)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified both in declare target %<link%> and %<to%>"
+ " clauses", t);
+ return false;
+ }
+ if (!at1)
+ {
+ DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
+ return true;
+
+ symtab_node *node = symtab_node::get (t);
+ if (node != NULL)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ {
+ g->have_offload = true;
+ if (is_a <varpool_node *> (node))
+ vec_safe_push (offload_vars, t);
+ }
+ }
+ }
+ if (TREE_CODE (t) != FUNCTION_DECL)
+ return true;
+ if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
+ {
+ tree at3 = lookup_attribute ("omp declare target host",
+ DECL_ATTRIBUTES (t));
+ if (at3 == NULL_TREE)
+ {
+ id = get_identifier ("omp declare target host");
+ DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ }
+ }
+ if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
+ {
+ tree at3 = lookup_attribute ("omp declare target nohost",
+ DECL_ATTRIBUTES (t));
+ if (at3 == NULL_TREE)
+ {
+ id = get_identifier ("omp declare target nohost");
+ DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ }
+ }
+ return true;
+}
/* OpenMP 4.0:
# pragma omp declare target new-line
@@ -44880,67 +45658,16 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
{
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
continue;
- tree t = OMP_CLAUSE_DECL (c), id;
- tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
- tree at2 = lookup_attribute ("omp declare target link",
- DECL_ATTRIBUTES (t));
+ tree t = OMP_CLAUSE_DECL (c);
only_device_type = false;
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
- {
- id = get_identifier ("omp declare target link");
- std::swap (at1, at2);
- }
- else
- id = get_identifier ("omp declare target");
- if (at2)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qD specified both in declare target %<link%> and %<to%>"
- " clauses", t);
- continue;
- }
- if (!at1)
- {
- DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
- continue;
-
- symtab_node *node = symtab_node::get (t);
- if (node != NULL)
- {
- node->offloadable = 1;
- if (ENABLE_OFFLOADING)
- {
- g->have_offload = true;
- if (is_a <varpool_node *> (node))
- vec_safe_push (offload_vars, t);
- }
- }
- }
- if (TREE_CODE (t) != FUNCTION_DECL)
+ if (!handle_omp_declare_target_clause (c, t, device_type))
continue;
- if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
- {
- tree at3 = lookup_attribute ("omp declare target host",
- DECL_ATTRIBUTES (t));
- if (at3 == NULL_TREE)
- {
- id = get_identifier ("omp declare target host");
- DECL_ATTRIBUTES (t)
- = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- }
- }
- if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
- {
- tree at3 = lookup_attribute ("omp declare target nohost",
- DECL_ATTRIBUTES (t));
- if (at3 == NULL_TREE)
- {
- id = get_identifier ("omp declare target nohost");
- DECL_ATTRIBUTES (t)
- = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- }
- }
+ if (VAR_OR_FUNCTION_DECL_P (t)
+ && DECL_LOCAL_DECL_P (t)
+ && DECL_LANG_SPECIFIC (t)
+ && DECL_LOCAL_DECL_ALIAS (t))
+ handle_omp_declare_target_clause (c, DECL_LOCAL_DECL_ALIAS (t),
+ device_type);
}
if (device_type && only_device_type)
warning_at (OMP_CLAUSE_LOCATION (clauses), 0,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 020a4bf..287cf4c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2218,7 +2218,8 @@ determine_specialization (tree template_id,
targs = coerce_template_parms (parms, explicit_targs, fns,
tf_warning_or_error,
/*req_all*/true, /*use_defarg*/true);
- if (targs != error_mark_node)
+ if (targs != error_mark_node
+ && constraints_satisfied_p (fns, targs))
templates = tree_cons (targs, fns, templates);
}
else for (lkp_iterator iter (fns); iter; ++iter)
@@ -2229,7 +2230,6 @@ determine_specialization (tree template_id,
{
tree decl_arg_types;
tree fn_arg_types;
- tree insttype;
/* In case of explicit specialization, we need to check if
the number of template headers appearing in the specialization
@@ -2355,20 +2355,6 @@ determine_specialization (tree template_id,
template argument. */
continue;
- /* Remove, from the set of candidates, all those functions
- whose constraints are not satisfied. */
- if (flag_concepts && !constraints_satisfied_p (fn, targs))
- continue;
-
- // Then, try to form the new function type.
- insttype = tsubst (TREE_TYPE (fn), targs, tf_fndecl_type, NULL_TREE);
- if (insttype == error_mark_node)
- continue;
- fn_arg_types
- = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype));
- if (!compparms (fn_arg_types, decl_arg_types))
- continue;
-
/* Save this template, and the arguments deduced. */
templates = tree_cons (targs, fn, templates);
}
@@ -3855,6 +3841,18 @@ expand_builtin_pack_call (tree call, tree args, tsubst_flags_t complain,
return NULL_TREE;
}
+/* Return true if the tree T has the extra args mechanism for
+ avoiding partial instantiation. */
+
+static bool
+has_extra_args_mechanism_p (const_tree t)
+{
+ return (PACK_EXPANSION_P (t) /* PACK_EXPANSION_EXTRA_ARGS */
+ || TREE_CODE (t) == REQUIRES_EXPR /* REQUIRES_EXPR_EXTRA_ARGS */
+ || (TREE_CODE (t) == IF_STMT
+ && IF_STMT_CONSTEXPR_P (t))); /* IF_STMT_EXTRA_ARGS */
+}
+
/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{
@@ -3867,6 +3865,9 @@ struct find_parameter_pack_data
/* True iff we're making a type pack expansion. */
bool type_pack_expansion_p;
+
+ /* True iff we found a subtree that has the extra args mechanism. */
+ bool found_extra_args_tree_p = false;
};
/* Identifies all of the argument packs that occur in a template
@@ -3968,6 +3969,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
*ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
}
+ if (has_extra_args_mechanism_p (t) && !PACK_EXPANSION_P (t))
+ ppd->found_extra_args_tree_p = true;
+
if (TYPE_P (t))
cp_walk_tree (&TYPE_CONTEXT (t),
&find_parameter_packs_r, ppd, ppd->visited);
@@ -4229,6 +4233,14 @@ make_pack_expansion (tree arg, tsubst_flags_t complain)
PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+ if (ppd.found_extra_args_tree_p)
+ /* If the pattern of this pack expansion contains a subtree that has
+ the extra args mechanism for avoiding partial instantiation, then
+ force this pack expansion to also use extra args. Otherwise
+ partial instantiation of this pack expansion may not lower the
+ level of some parameter packs within the pattern, which would
+ confuse tsubst_pack_expansion later (PR101764). */
+ PACK_EXPANSION_FORCE_EXTRA_ARGS_P (result) = true;
return result;
}
@@ -6733,8 +6745,15 @@ has_value_dependent_address (tree op)
if (DECL_P (op))
{
tree ctx = CP_DECL_CONTEXT (op);
+
if (TYPE_P (ctx) && dependent_type_p (ctx))
return true;
+
+ if (VAR_P (op)
+ && TREE_STATIC (op)
+ && TREE_CODE (ctx) == FUNCTION_DECL
+ && type_dependent_expression_p (ctx))
+ return true;
}
return false;
@@ -7967,12 +7986,12 @@ coerce_template_template_parms (tree parm_parms,
/* So coerce P's args to apply to A's parms, and then deduce between A's
args and the converted args. If that succeeds, A is at least as
specialized as P, so they match.*/
+ processing_template_decl_sentinel ptds (/*reset*/false);
+ ++processing_template_decl;
tree pargs = template_parms_level_to_args (parm_parms);
pargs = add_outermost_template_args (outer_args, pargs);
- ++processing_template_decl;
pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none,
/*require_all*/true, /*use_default*/true);
- --processing_template_decl;
if (pargs != error_mark_node)
{
tree targs = make_tree_vec (nargs);
@@ -8196,8 +8215,10 @@ is_compatible_template_arg (tree parm, tree arg)
{
tree aparms = DECL_INNERMOST_TEMPLATE_PARMS (arg);
new_args = template_parms_level_to_args (aparms);
+ ++processing_template_decl;
parm_cons = tsubst_constraint_info (parm_cons, new_args,
tf_none, NULL_TREE);
+ --processing_template_decl;
if (parm_cons == error_mark_node)
return false;
}
@@ -8494,6 +8515,10 @@ convert_template_argument (tree parm,
else
t = tsubst (t, args, complain, in_decl);
+ /* Perform array-to-pointer and function-to-pointer conversion
+ as per [temp.param]/10. */
+ t = type_decays_to (t);
+
if (invalid_nontype_parm_type_p (t, complain))
return error_mark_node;
@@ -10873,7 +10898,8 @@ neglectable_inst_p (tree d)
{
return (d && DECL_P (d)
&& !undeduced_auto_decl (d)
- && !(TREE_CODE (d) == FUNCTION_DECL ? DECL_DECLARED_CONSTEXPR_P (d)
+ && !(TREE_CODE (d) == FUNCTION_DECL
+ ? FNDECL_MANIFESTLY_CONST_EVALUATED (d)
: decl_maybe_constant_var_p (d)));
}
@@ -10885,14 +10911,31 @@ limit_bad_template_recursion (tree decl)
{
struct tinst_level *lev = current_tinst_level;
int errs = errorcount + sorrycount;
- if (lev == NULL || errs == 0 || !neglectable_inst_p (decl))
+ if (errs == 0 || !neglectable_inst_p (decl))
return false;
- for (; lev; lev = lev->next)
- if (neglectable_inst_p (lev->maybe_get_node ()))
- break;
+ /* Avoid instantiating members of an ill-formed class. */
+ bool refuse
+ = (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_ERRONEOUS (DECL_CONTEXT (decl)));
- return (lev && errs > lev->errors);
+ if (!refuse)
+ {
+ for (; lev; lev = lev->next)
+ if (neglectable_inst_p (lev->maybe_get_node ()))
+ break;
+ refuse = (lev && errs > lev->errors);
+ }
+
+ if (refuse)
+ {
+ /* Don't warn about it not being defined. */
+ suppress_warning (decl, OPT_Wunused);
+ tree clone;
+ FOR_EACH_CLONE (clone, decl)
+ suppress_warning (clone, OPT_Wunused);
+ }
+ return refuse;
}
static int tinst_depth;
@@ -12212,6 +12255,13 @@ instantiate_class_template_1 (tree type)
finish_struct_1 (type);
TYPE_BEING_DEFINED (type) = 0;
+ /* Remember if instantiating this class ran into errors, so we can avoid
+ instantiating member functions in limit_bad_template_recursion. We set
+ this flag even if the problem was in another instantiation triggered by
+ this one, as that will likely also cause trouble for member functions. */
+ if (errorcount + sorrycount > current_tinst_level->errors)
+ CLASSTYPE_ERRONEOUS (type) = true;
+
/* We don't instantiate default arguments for member functions. 14.7.1:
The implicit instantiation of a class template specialization causes
@@ -12380,10 +12430,15 @@ make_argument_pack_select (tree arg_pack, unsigned index)
substitution. */
static bool
-use_pack_expansion_extra_args_p (tree parm_packs,
+use_pack_expansion_extra_args_p (tree t,
+ tree parm_packs,
int arg_pack_len,
bool has_empty_arg)
{
+ if (has_empty_arg
+ && PACK_EXPANSION_FORCE_EXTRA_ARGS_P (t))
+ return true;
+
/* If one pack has an expansion and another pack has a normal
argument or if one pack has an empty argument and an another
one hasn't then tsubst_pack_expansion cannot perform the
@@ -13136,7 +13191,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* We cannot expand this expansion expression, because we don't have
all of the argument packs we need. */
- if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs))
+ if (use_pack_expansion_extra_args_p (t, packs, len, unsubstituted_packs))
{
/* We got some full packs, but we can't substitute them in until we
have values for all the packs. So remember these until then. */
@@ -17432,6 +17487,13 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
break;
case OMP_CLAUSE_GANG:
case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl, NULL);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
case OMP_CLAUSE_ALLOCATE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
@@ -17439,6 +17501,9 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 2)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
break;
case OMP_CLAUSE_LINEAR:
OMP_CLAUSE_DECL (nc)
@@ -18973,23 +19038,42 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
{
tree op1 = TREE_OPERAND (t, 1);
tree rhs1 = NULL_TREE;
+ tree r = NULL_TREE;
tree lhs, rhs;
if (TREE_CODE (op1) == COMPOUND_EXPR)
{
rhs1 = RECUR (TREE_OPERAND (op1, 0));
op1 = TREE_OPERAND (op1, 1);
}
- lhs = RECUR (TREE_OPERAND (op1, 0));
- rhs = RECUR (TREE_OPERAND (op1, 1));
+ if (TREE_CODE (op1) == COND_EXPR)
+ {
+ gcc_assert (rhs1 == NULL_TREE);
+ tree c = TREE_OPERAND (op1, 0);
+ if (TREE_CODE (c) == MODIFY_EXPR)
+ {
+ r = RECUR (TREE_OPERAND (c, 0));
+ c = TREE_OPERAND (c, 1);
+ }
+ gcc_assert (TREE_CODE (c) == EQ_EXPR);
+ rhs = RECUR (TREE_OPERAND (c, 1));
+ lhs = RECUR (TREE_OPERAND (op1, 2));
+ rhs1 = RECUR (TREE_OPERAND (op1, 1));
+ }
+ else
+ {
+ lhs = RECUR (TREE_OPERAND (op1, 0));
+ rhs = RECUR (TREE_OPERAND (op1, 1));
+ }
finish_omp_atomic (EXPR_LOCATION (t), OMP_ATOMIC, TREE_CODE (op1),
- lhs, rhs, NULL_TREE, NULL_TREE, rhs1, tmp,
- OMP_ATOMIC_MEMORY_ORDER (t));
+ lhs, rhs, NULL_TREE, NULL_TREE, rhs1, r,
+ tmp, OMP_ATOMIC_MEMORY_ORDER (t),
+ OMP_ATOMIC_WEAK (t));
}
else
{
tree op1 = TREE_OPERAND (t, 1);
tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
- tree rhs1 = NULL_TREE;
+ tree rhs1 = NULL_TREE, r = NULL_TREE;
enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
enum tree_code opcode = NOP_EXPR;
if (code == OMP_ATOMIC_READ)
@@ -19008,8 +19092,25 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
rhs1 = RECUR (TREE_OPERAND (op11, 0));
op11 = TREE_OPERAND (op11, 1);
}
- lhs = RECUR (TREE_OPERAND (op11, 0));
- rhs = RECUR (TREE_OPERAND (op11, 1));
+ if (TREE_CODE (op11) == COND_EXPR)
+ {
+ gcc_assert (rhs1 == NULL_TREE);
+ tree c = TREE_OPERAND (op11, 0);
+ if (TREE_CODE (c) == MODIFY_EXPR)
+ {
+ r = RECUR (TREE_OPERAND (c, 0));
+ c = TREE_OPERAND (c, 1);
+ }
+ gcc_assert (TREE_CODE (c) == EQ_EXPR);
+ rhs = RECUR (TREE_OPERAND (c, 1));
+ lhs = RECUR (TREE_OPERAND (op11, 2));
+ rhs1 = RECUR (TREE_OPERAND (op11, 1));
+ }
+ else
+ {
+ lhs = RECUR (TREE_OPERAND (op11, 0));
+ rhs = RECUR (TREE_OPERAND (op11, 1));
+ }
opcode = TREE_CODE (op11);
if (opcode == MODIFY_EXPR)
opcode = NOP_EXPR;
@@ -19021,7 +19122,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
rhs = RECUR (TREE_OPERAND (op1, 1));
}
finish_omp_atomic (EXPR_LOCATION (t), code, opcode, lhs, rhs, v,
- lhs1, rhs1, tmp, OMP_ATOMIC_MEMORY_ORDER (t));
+ lhs1, rhs1, r, tmp,
+ OMP_ATOMIC_MEMORY_ORDER (t), OMP_ATOMIC_WEAK (t));
}
break;
@@ -19465,6 +19567,63 @@ out:
return r;
}
+/* Subroutine of maybe_fold_fn_template_args. */
+
+static bool
+fold_targs_r (tree targs, tsubst_flags_t complain)
+{
+ int len = TREE_VEC_LENGTH (targs);
+ for (int i = 0; i < len; ++i)
+ {
+ tree &elt = TREE_VEC_ELT (targs, i);
+ if (!elt || TYPE_P (elt)
+ || TREE_CODE (elt) == TEMPLATE_DECL)
+ continue;
+ if (TREE_CODE (elt) == NONTYPE_ARGUMENT_PACK)
+ {
+ if (!fold_targs_r (ARGUMENT_PACK_ARGS (elt), complain))
+ return false;
+ }
+ else if (/* We can only safely preevaluate scalar prvalues. */
+ SCALAR_TYPE_P (TREE_TYPE (elt))
+ && !glvalue_p (elt)
+ && !TREE_CONSTANT (elt))
+ {
+ elt = cxx_constant_value_sfinae (elt, complain);
+ if (elt == error_mark_node)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Try to do constant evaluation of any explicit template arguments in FN
+ before overload resolution, to get any errors only once. Return true iff
+ we didn't have any problems folding. */
+
+static bool
+maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain)
+{
+ if (processing_template_decl || fn == NULL_TREE)
+ return true;
+ if (fn == error_mark_node)
+ return false;
+ if (TREE_CODE (fn) == OFFSET_REF
+ || TREE_CODE (fn) == COMPONENT_REF)
+ fn = TREE_OPERAND (fn, 1);
+ if (BASELINK_P (fn))
+ fn = BASELINK_FUNCTIONS (fn);
+ if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
+ return true;
+ tree targs = TREE_OPERAND (fn, 1);
+ if (targs == NULL_TREE)
+ return true;
+ if (targs == error_mark_node)
+ return false;
+ return fold_targs_r (targs, complain);
+}
+
/* Like tsubst but deals with expressions and performs semantic
analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)" or
"F<TARGS> (ARGS)". */
@@ -20343,6 +20502,9 @@ tsubst_copy_and_build (tree t,
&& !mark_used (function, complain) && !(complain & tf_error))
RETURN (error_mark_node);
+ if (!maybe_fold_fn_template_args (function, complain))
+ return error_mark_node;
+
/* Put back tf_decltype for the actual call. */
complain |= decltype_flag;
@@ -21685,6 +21847,15 @@ fn_type_unification (tree fn,
TREE_VALUE (sarg));
goto fail;
}
+ if ((i < nargs || sarg)
+ /* add_candidates uses DEDUCE_EXACT for x.operator foo(), but args
+ doesn't contain the trailing void, and conv fns are always (). */
+ && !DECL_CONV_FN_P (decl))
+ {
+ unsigned nsargs = i + list_length (sarg);
+ unify_arity (explain_p, nargs, nsargs);
+ goto fail;
+ }
}
/* After doing deduction with the inherited constructor, actually return an
@@ -22208,6 +22379,10 @@ type_unification_real (tree tparms,
args = xargs;
nargs = xnargs;
+ /* Only fn_type_unification cares about terminal void. */
+ if (nargs && args[nargs-1] == void_type_node)
+ --nargs;
+
ia = 0;
while (parms && parms != void_list_node
&& ia < nargs)
@@ -24709,7 +24884,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
nargs = list_length (decl_arg_types);
args = XALLOCAVEC (tree, nargs);
for (arg = decl_arg_types, ix = 0;
- arg != NULL_TREE && arg != void_list_node;
+ arg != NULL_TREE;
arg = TREE_CHAIN (arg), ++ix)
args[ix] = TREE_VALUE (arg);
@@ -25602,7 +25777,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
return true;
++function_depth;
- synthesize_method (fn);
+ maybe_synthesize_method (fn);
--function_depth;
return !DECL_MAYBE_DELETED (fn);
}
@@ -26816,6 +26991,15 @@ dependent_scope_p (tree scope)
&& !currently_open_class (scope));
}
+/* True if we might find more declarations in SCOPE during instantiation than
+ we can when parsing the template. */
+
+bool
+dependentish_scope_p (tree scope)
+{
+ return dependent_scope_p (scope) || any_dependent_bases_p (scope);
+}
+
/* T is a SCOPE_REF. Return whether it represents a non-static member of
an unknown base of 'this' (and is therefore instantiation-dependent). */
@@ -27074,7 +27258,8 @@ value_dependent_expression_p (tree expression)
}
case TEMPLATE_ID_EXPR:
- return concept_definition_p (TREE_OPERAND (expression, 0));
+ return concept_definition_p (TREE_OPERAND (expression, 0))
+ && any_dependent_template_arguments_p (TREE_OPERAND (expression, 1));
case CONSTRUCTOR:
{
@@ -27481,18 +27666,6 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
case REQUIRES_EXPR:
return *tp;
- case CALL_EXPR:
- /* Treat concept checks as dependent. */
- if (concept_check_p (*tp))
- return *tp;
- break;
-
- case TEMPLATE_ID_EXPR:
- /* Treat concept checks as dependent. */
- if (concept_check_p (*tp))
- return *tp;
- break;
-
case CONSTRUCTOR:
if (CONSTRUCTOR_IS_DEPENDENT (*tp))
return *tp;
@@ -27650,6 +27823,20 @@ dependent_template_arg_p (tree arg)
return value_dependent_expression_p (arg);
}
+/* Identify any expressions that use function parms. */
+
+static tree
+find_parm_usage_r (tree *tp, int *walk_subtrees, void*)
+{
+ tree t = *tp;
+ if (TREE_CODE (t) == PARM_DECL)
+ {
+ *walk_subtrees = 0;
+ return t;
+ }
+ return NULL_TREE;
+}
+
/* Returns true if ARGS (a collection of template arguments) contains
any types that require structural equality testing. */
@@ -27694,6 +27881,13 @@ any_template_arguments_need_structural_equality_p (tree args)
else if (!TYPE_P (arg) && TREE_TYPE (arg)
&& TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (arg)))
return true;
+ /* Checking current_function_decl because this structural
+ comparison is only necessary for redeclaration. */
+ else if (!current_function_decl
+ && dependent_template_arg_p (arg)
+ && (cp_walk_tree_without_duplicates
+ (&arg, find_parm_usage_r, NULL)))
+ return true;
}
}
}
@@ -28571,7 +28765,7 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
const int depth = TMPL_ARGS_DEPTH (tsubst_args);
tree ttargs = make_tree_vec (depth + 1);
for (int i = 0; i < depth; ++i)
- TREE_VEC_ELT (ttargs, i) = TREE_VEC_ELT (tsubst_args, i);
+ TREE_VEC_ELT (ttargs, i) = TMPL_ARGS_LEVEL (tsubst_args, i + 1);
TREE_VEC_ELT (ttargs, depth)
= template_parms_level_to_args (ttparms);
// Substitute ttargs into ttparms to fix references to
@@ -28584,8 +28778,17 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
ttparms = tsubst_template_parms_level (ttparms, ttargs,
complain);
// Finally, tack the adjusted parms onto tparms.
- ttparms = tree_cons (size_int (depth), ttparms,
- current_template_parms);
+ ttparms = tree_cons (size_int (level + 1), ttparms,
+ copy_node (current_template_parms));
+ // As with all template template parms, the parameter list captured
+ // by this template template parm that corresponds to its own level
+ // should be empty. This avoids infinite recursion when structurally
+ // comparing two such rewritten template template parms (PR102479).
+ gcc_assert (!TREE_VEC_LENGTH
+ (TREE_VALUE (TREE_CHAIN (DECL_TEMPLATE_PARMS (olddecl)))));
+ gcc_assert (TMPL_PARMS_DEPTH (TREE_CHAIN (ttparms)) == level);
+ TREE_VALUE (TREE_CHAIN (ttparms)) = make_tree_vec (0);
+ // All done.
DECL_TEMPLATE_PARMS (newdecl) = ttparms;
}
}
@@ -29083,6 +29286,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
++ndlen;
tree gtparms = make_tree_vec (natparms + ndlen);
+ /* Set current_template_parms as in build_deduction_guide. */
+ auto ctp = make_temp_override (current_template_parms);
+ current_template_parms = copy_node (DECL_TEMPLATE_PARMS (tmpl));
+ TREE_VALUE (current_template_parms) = gtparms;
+
/* First copy over the parms of A. */
for (j = 0; j < natparms; ++j)
TREE_VEC_ELT (gtparms, j) = TREE_VEC_ELT (atparms, j);
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 7f140f5..1dcd764 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -51,6 +51,7 @@ cxx_print_decl (FILE *file, tree node, int indent)
}
else if (TREE_CODE (node) == TEMPLATE_DECL)
{
+ print_node (file, "result", DECL_TEMPLATE_RESULT (node), indent + 4);
print_node (file, "parms", DECL_TEMPLATE_PARMS (node), indent + 4);
indent_to (file, indent + 3);
fprintf (file, " full-name \"%s\"",
@@ -115,13 +116,8 @@ cxx_print_decl (FILE *file, tree node, int indent)
if (VAR_OR_FUNCTION_DECL_P (node)
&& DECL_TEMPLATE_INFO (node))
- {
- if (need_indent)
- indent_to (file, indent + 3);
- fprintf (file, " template-info %p",
- (void *) DECL_TEMPLATE_INFO (node));
- need_indent = false;
- }
+ print_node (file, "template-info", DECL_TEMPLATE_INFO (node),
+ indent + 4);
}
void
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index fcb3308..9c5066b 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -125,7 +125,6 @@ static tree tinfo_name (tree, bool);
static tree build_dynamic_cast_1 (location_t, tree, tree, tsubst_flags_t);
static tree throw_bad_cast (void);
static tree throw_bad_typeid (void);
-static tree get_tinfo_ptr (tree);
static bool typeid_ok_p (void);
static int qualifier_flags (tree);
static bool target_incomplete_p (tree);
@@ -142,22 +141,11 @@ static bool typeinfo_in_lib_p (tree);
static int doing_runtime = 0;
-/* Declare language defined type_info type and a pointer to const
- type_info. This is incomplete here, and will be completed when
- the user #includes <typeinfo>. There are language defined
- restrictions on what can be done until that is included. Create
- the internal versions of the ABI types. */
+/* Create the internal versions of the ABI types. */
void
init_rtti_processing (void)
{
- push_nested_namespace (std_node);
- 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);
- type_info_ptr_type = build_pointer_type (const_type_info_type_node);
-
vec_alloc (unemitted_tinfo_decls, 124);
create_tinfo_types ();
@@ -238,6 +226,33 @@ throw_bad_typeid (void)
return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
}
+/* const type_info*. */
+
+inline tree
+type_info_ptr_type ()
+{
+ return build_pointer_type (const_type_info_type_node);
+}
+
+/* Return a pointer to a type_info object describing TYPE, suitably
+ cast to the language defined type (for typeid) or void (for building
+ up the descriptors). */
+
+static tree
+get_tinfo_ptr (tree type, bool voidp = false)
+{
+ tree decl = get_tinfo_decl (type);
+ mark_used (decl);
+
+ tree ptype = voidp ? const_ptr_type_node : type_info_ptr_type ();
+ return build_nop (ptype, build_address (decl));
+}
+static inline tree
+get_void_tinfo_ptr (tree type)
+{
+ return get_tinfo_ptr (type, true);
+}
+
/* Return an lvalue expression whose type is "const std::type_info"
and whose value indicates the type of the expression EXP. If EXP
is a reference to a polymorphic class, return the dynamic type;
@@ -278,7 +293,7 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain)
index = build_int_cst (NULL_TREE,
-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
t = build_vtbl_ref (exp, index);
- t = convert (type_info_ptr_type, t);
+ t = convert (type_info_ptr_type (), t);
}
else
/* Otherwise return the type_info for the static type of the expr. */
@@ -296,15 +311,22 @@ typeid_ok_p (void)
return false;
}
- if (!COMPLETE_TYPE_P (const_type_info_type_node))
+ if (!const_type_info_type_node)
{
- gcc_rich_location richloc (input_location);
- maybe_add_include_fixit (&richloc, "<typeinfo>", false);
- error_at (&richloc,
- "must %<#include <typeinfo>%> before using"
- " %<typeid%>");
+ tree name = get_identifier ("type_info");
+ tree decl = lookup_qualified_name (std_node, name);
+ if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ gcc_rich_location richloc (input_location);
+ maybe_add_include_fixit (&richloc, "<typeinfo>", false);
+ error_at (&richloc,
+ "must %<#include <typeinfo>%> before using"
+ " %<typeid%>");
- return false;
+ return false;
+ }
+ const_type_info_type_node
+ = cp_build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_CONST);
}
tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
@@ -471,19 +493,6 @@ get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
return d;
}
-/* Return a pointer to a type_info object describing TYPE, suitably
- cast to the language defined type. */
-
-static tree
-get_tinfo_ptr (tree type)
-{
- tree decl = get_tinfo_decl (type);
-
- mark_used (decl);
- return build_nop (type_info_ptr_type,
- build_address (decl));
-}
-
/* Return the type_info object for TYPE. */
tree
@@ -1032,7 +1041,7 @@ ptr_initializer (tinfo_s *ti, tree target)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
+ get_void_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
init = build_constructor (init_list_type_node, v);
TREE_CONSTANT (init) = 1;
@@ -1063,8 +1072,8 @@ ptm_initializer (tinfo_s *ti, tree target)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_tinfo_ptr (klass));
+ get_void_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_void_tinfo_ptr (klass));
init = build_constructor (init_list_type_node, v);
TREE_CONSTANT (init) = 1;
@@ -1156,7 +1165,7 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
case TK_SI_CLASS_TYPE:
{
tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0);
- tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
+ tree tinfo = get_void_tinfo_ptr (BINFO_TYPE (base_binfo));
/* get_tinfo_ptr might have reallocated the tinfo_descs vector. */
ti = &(*tinfo_descs)[tk_index];
@@ -1187,7 +1196,7 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
if ((*base_accesses)[ix] == access_public_node)
flags |= 2;
- tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
+ tinfo = get_void_tinfo_ptr (BINFO_TYPE (base_binfo));
if (BINFO_VIRTUAL_P (base_binfo))
{
/* We store the vtable offset at which the virtual
@@ -1360,7 +1369,7 @@ get_tinfo_desc (unsigned ix)
/* Base class internal helper. Pointer to base type, offset to
base, flags. */
tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- NULL_TREE, type_info_ptr_type);
+ NULL_TREE, const_ptr_type_node);
DECL_CHAIN (fld_ptr) = fields;
fields = fld_ptr;
@@ -1396,7 +1405,7 @@ get_tinfo_desc (unsigned ix)
fields = fld_mask;
tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- NULL_TREE, type_info_ptr_type);
+ NULL_TREE, const_ptr_type_node);
DECL_CHAIN (fld_ptr) = fields;
fields = fld_ptr;
@@ -1404,7 +1413,7 @@ get_tinfo_desc (unsigned ix)
{
/* Add a pointer to the class too. */
tree fld_cls = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- NULL_TREE, type_info_ptr_type);
+ NULL_TREE, const_ptr_type_node);
DECL_CHAIN (fld_cls) = fields;
fields = fld_cls;
}
@@ -1421,7 +1430,7 @@ get_tinfo_desc (unsigned ix)
class. This is really a descendant of
__class_type_info. */
tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- NULL_TREE, type_info_ptr_type);
+ NULL_TREE, const_ptr_type_node);
DECL_CHAIN (fld_ptr) = fields;
fields = fld_ptr;
break;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index e191aa3..0d8e5fd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3489,6 +3489,14 @@ finish_member_declaration (tree decl)
if (TREE_CODE (decl) != CONST_DECL)
DECL_CONTEXT (decl) = current_class_type;
+ /* Remember the single FIELD_DECL an anonymous aggregate type is used for. */
+ if (TREE_CODE (decl) == FIELD_DECL
+ && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+ {
+ gcc_assert (!ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))));
+ ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl;
+ }
+
if (TREE_CODE (decl) == USING_DECL)
/* For now, ignore class-scope USING_DECLS, so that debugging
backends do not see them. */
@@ -7334,6 +7342,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"%<device%> id must be integral");
remove = true;
}
+ else if (OMP_CLAUSE_DEVICE_ANCESTOR (c)
+ && TREE_CODE (t) == INTEGER_CST
+ && !integer_onep (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "the %<device%> clause expression must evaluate to "
+ "%<1%>");
+ remove = true;
+ }
else
{
t = mark_rvalue_use (t);
@@ -7510,7 +7527,44 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&aligned_head, DECL_UID (t));
allocate_seen = true;
}
- tree allocator;
+ tree allocator, align;
+ align = OMP_CLAUSE_ALLOCATE_ALIGN (c);
+ if (error_operand_p (align))
+ {
+ remove = true;
+ break;
+ }
+ if (align)
+ {
+ if (!type_dependent_expression_p (align)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (align)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ else
+ {
+ align = mark_rvalue_use (align);
+ if (!processing_template_decl)
+ {
+ align = maybe_constant_value (align);
+ if (TREE_CODE (align) != INTEGER_CST
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ }
+ }
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
if (error_operand_p (allocator))
{
@@ -7535,6 +7589,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"type %qT rather than %<omp_allocator_handle_t%>",
TREE_TYPE (allocator));
remove = true;
+ break;
}
else
{
@@ -9860,14 +9915,15 @@ finish_omp_for_block (tree bind, tree omp_for)
void
finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
- tree lhs, tree rhs, tree v, tree lhs1, tree rhs1,
- tree clauses, enum omp_memory_order mo)
+ tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, tree r,
+ tree clauses, enum omp_memory_order mo, bool weak)
{
tree orig_lhs;
tree orig_rhs;
tree orig_v;
tree orig_lhs1;
tree orig_rhs1;
+ tree orig_r;
bool dependent_p;
tree stmt;
@@ -9876,6 +9932,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
orig_v = v;
orig_lhs1 = lhs1;
orig_rhs1 = rhs1;
+ orig_r = r;
dependent_p = false;
stmt = NULL_TREE;
@@ -9887,7 +9944,10 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
|| (rhs && type_dependent_expression_p (rhs))
|| (v && type_dependent_expression_p (v))
|| (lhs1 && type_dependent_expression_p (lhs1))
- || (rhs1 && type_dependent_expression_p (rhs1)));
+ || (rhs1 && type_dependent_expression_p (rhs1))
+ || (r
+ && r != void_list_node
+ && type_dependent_expression_p (r)));
if (clauses)
{
gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE
@@ -9908,17 +9968,19 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
lhs1 = build_non_dependent_expr (lhs1);
if (rhs1)
rhs1 = build_non_dependent_expr (rhs1);
+ if (r && r != void_list_node)
+ r = build_non_dependent_expr (r);
}
}
if (!dependent_p)
{
bool swapped = false;
- if (rhs1 && cp_tree_equal (lhs, rhs))
+ if (rhs1 && opcode != COND_EXPR && cp_tree_equal (lhs, rhs))
{
std::swap (rhs, rhs1);
swapped = !commutative_tree_code (opcode);
}
- if (rhs1 && !cp_tree_equal (lhs, rhs1))
+ if (rhs1 && opcode != COND_EXPR && !cp_tree_equal (lhs, rhs1))
{
if (code == OMP_ATOMIC)
error ("%<#pragma omp atomic update%> uses two different "
@@ -9939,7 +10001,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
return;
}
stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs,
- v, lhs1, rhs1, swapped, mo,
+ v, lhs1, rhs1, r, swapped, mo, weak,
processing_template_decl != 0);
if (stmt == error_mark_node)
return;
@@ -9956,6 +10018,16 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
{
if (opcode == NOP_EXPR)
stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
+ else if (opcode == COND_EXPR)
+ {
+ stmt = build2 (EQ_EXPR, boolean_type_node, orig_lhs, orig_rhs);
+ if (orig_r)
+ stmt = build2 (MODIFY_EXPR, boolean_type_node, orig_r,
+ stmt);
+ stmt = build3 (COND_EXPR, void_type_node, stmt, orig_rhs1,
+ orig_lhs);
+ orig_rhs1 = NULL_TREE;
+ }
else
stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
if (orig_rhs1)
@@ -9965,12 +10037,14 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
{
stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt);
OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+ OMP_ATOMIC_WEAK (stmt) = weak;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
}
stmt = build2 (OMP_ATOMIC, void_type_node,
clauses ? clauses : integer_zero_node, stmt);
OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+ OMP_ATOMIC_WEAK (stmt) = weak;
SET_EXPR_LOCATION (stmt, loc);
}
@@ -10030,7 +10104,7 @@ finish_omp_flush (int mo)
{
tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
releasing_vec vec;
- if (mo != MEMMODEL_LAST)
+ if (mo != MEMMODEL_LAST && mo != MEMMODEL_SEQ_CST)
{
fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
vec->quick_push (build_int_cst (integer_type_node, mo));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 3c62dd7..32ddf83 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1403,11 +1403,18 @@ cp_build_qualified_type_real (tree type,
/* A reference or method type shall not be cv-qualified.
[dcl.ref], [dcl.fct]. This used to be an error, but as of DR 295
(in CD1) we always ignore extra cv-quals on functions. */
+
+ /* [dcl.ref/1] Cv-qualified references are ill-formed except when
+ the cv-qualifiers are introduced through the use of a typedef-name
+ ([dcl.typedef], [temp.param]) or decltype-specifier
+ ([dcl.type.decltype]),in which case the cv-qualifiers are
+ ignored. */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TYPE_REF_P (type)
|| FUNC_OR_METHOD_TYPE_P (type)))
{
- if (TYPE_REF_P (type))
+ if (TYPE_REF_P (type)
+ && (!typedef_variant_p (type) || FUNC_OR_METHOD_TYPE_P (type)))
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
@@ -1492,9 +1499,9 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
p = &TREE_CHAIN (*p);
}
}
- else if (first_ident)
+ else if (first_ident && first_ident != error_mark_node)
{
- for (tree a2 = first_ident; a2; a2 = TREE_CHAIN (a2))
+ for (tree a2 = first_ident; a2 != a; a2 = TREE_CHAIN (a2))
{
*p = tree_cons (TREE_PURPOSE (a2), TREE_VALUE (a2), NULL_TREE);
p = &TREE_CHAIN (*p);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a46c6d2..ab0f9da 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2618,36 +2618,14 @@ rationalize_conditional_expr (enum tree_code code, tree t,
that are directly reachable. */
tree
-lookup_anon_field (tree t, tree type)
+lookup_anon_field (tree, tree type)
{
tree field;
- t = TYPE_MAIN_VARIANT (t);
-
- for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
- {
- if (TREE_STATIC (field))
- continue;
- if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
- continue;
-
- /* If we find it directly, return the field. */
- if (DECL_NAME (field) == NULL_TREE
- && type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
- {
- return field;
- }
-
- /* Otherwise, it could be nested, search harder. */
- if (DECL_NAME (field) == NULL_TREE
- && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
- {
- tree subfield = lookup_anon_field (TREE_TYPE (field), type);
- if (subfield)
- return subfield;
- }
- }
- return NULL_TREE;
+ type = TYPE_MAIN_VARIANT (type);
+ field = ANON_AGGR_TYPE_FIELD (type);
+ gcc_assert (field);
+ return field;
}
/* Build an expression representing OBJECT.MEMBER. OBJECT is an
@@ -2709,7 +2687,10 @@ build_class_member_access_expr (cp_expr object, tree member,
member_scope = DECL_CLASS_CONTEXT (member);
if (!mark_used (member, complain) && !(complain & tf_error))
return error_mark_node;
- if (TREE_DEPRECATED (member))
+
+ if (TREE_UNAVAILABLE (member))
+ error_unavailable_use (member, NULL_TREE);
+ else if (TREE_DEPRECATED (member))
warn_deprecated_use (member, NULL_TREE);
}
else
@@ -3424,7 +3405,9 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
}
}
- if (TREE_DEPRECATED (member))
+ if (TREE_UNAVAILABLE (member))
+ error_unavailable_use (member, NULL_TREE);
+ else if (TREE_DEPRECATED (member))
warn_deprecated_use (member, NULL_TREE);
if (template_p)
@@ -4620,25 +4603,93 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
|| warning_suppressed_p (op, OPT_Waddress))
return;
+ if (TREE_CODE (op) == NON_DEPENDENT_EXPR)
+ op = TREE_OPERAND (op, 0);
+
tree cop = fold_for_warn (op);
- if (TREE_CODE (cop) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
- && !warning_suppressed_p (cop, OPT_Waddress))
- warning_at (location, OPT_Waddress, "the address of %qD will never "
- "be NULL", TREE_OPERAND (cop, 0));
+ if (TREE_CODE (cop) == NON_LVALUE_EXPR)
+ /* Unwrap the expression for C++ 98. */
+ cop = TREE_OPERAND (cop, 0);
- if (CONVERT_EXPR_P (op)
+ if (TREE_CODE (cop) == PTRMEM_CST)
+ {
+ /* The address of a nonstatic data member is never null. */
+ warning_at (location, OPT_Waddress,
+ "the address %qE will never be NULL",
+ cop);
+ return;
+ }
+
+ if (TREE_CODE (cop) == NOP_EXPR)
+ {
+ /* Allow casts to intptr_t to suppress the warning. */
+ tree type = TREE_TYPE (cop);
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ return;
+
+ STRIP_NOPS (cop);
+ }
+
+ bool warned = false;
+ if (TREE_CODE (cop) == ADDR_EXPR)
+ {
+ cop = TREE_OPERAND (cop, 0);
+
+ /* Set to true in the loop below if OP dereferences its operand.
+ In such a case the ultimate target need not be a decl for
+ the null [in]equality test to be necessarily constant. */
+ bool deref = false;
+
+ /* Get the outermost array or object, or member. */
+ while (handled_component_p (cop))
+ {
+ if (TREE_CODE (cop) == COMPONENT_REF)
+ {
+ /* Get the member (its address is never null). */
+ cop = TREE_OPERAND (cop, 1);
+ break;
+ }
+
+ /* Get the outer array/object to refer to in the warning. */
+ cop = TREE_OPERAND (cop, 0);
+ deref = true;
+ }
+
+ if ((!deref && !decl_with_nonnull_addr_p (cop))
+ || from_macro_expansion_at (location)
+ || warning_suppressed_p (cop, OPT_Waddress))
+ return;
+
+ warned = warning_at (location, OPT_Waddress,
+ "the address of %qD will never be NULL", cop);
+ op = cop;
+ }
+ else if (TREE_CODE (cop) == POINTER_PLUS_EXPR)
+ {
+ /* Adding zero to the null pointer is well-defined in C++. When
+ the offset is unknown (i.e., not a constant) warn anyway since
+ it's less likely that the pointer operand is null than not. */
+ tree off = TREE_OPERAND (cop, 1);
+ if (!integer_zerop (off)
+ && !warning_suppressed_p (cop, OPT_Waddress))
+ warning_at (location, OPT_Waddress, "comparing the result of pointer "
+ "addition %qE and NULL", cop);
+ return;
+ }
+ else if (CONVERT_EXPR_P (op)
&& TYPE_REF_P (TREE_TYPE (TREE_OPERAND (op, 0))))
{
- tree inner_op = op;
- STRIP_NOPS (inner_op);
+ STRIP_NOPS (op);
- if (DECL_P (inner_op))
- warning_at (location, OPT_Waddress,
- "the compiler can assume that the address of "
- "%qD will never be NULL", inner_op);
+ if (DECL_P (op))
+ warned = warning_at (location, OPT_Waddress,
+ "the compiler can assume that the address of "
+ "%qD will never be NULL", op);
}
+
+ if (warned && DECL_P (op))
+ inform (DECL_SOURCE_LOCATION (op), "%qD declared here", op);
}
/* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
@@ -5306,6 +5357,11 @@ cp_build_binary_op (const op_location_t &location,
warning_at (location, OPT_Waddress,
"comparison with string literal results in "
"unspecified behavior");
+ else if (warn_array_compare
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
+ do_warn_array_compare (location, code, stripped_orig_op0,
+ stripped_orig_op1);
}
build_type = boolean_type_node;
@@ -5428,6 +5484,8 @@ cp_build_binary_op (const op_location_t &location,
op1 = cp_convert (TREE_TYPE (op0), op1, complain);
}
result_type = TREE_TYPE (op0);
+
+ warn_for_null_address (location, orig_op0, complain);
}
else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (orig_op0))
return cp_build_binary_op (location, code, op1, op0, complain);
@@ -5576,6 +5634,14 @@ cp_build_binary_op (const op_location_t &location,
"comparison with string literal results "
"in unspecified behavior");
}
+ else if (warn_array_compare
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
+ && code != SPACESHIP_EXPR
+ && (complain & tf_warning))
+ do_warn_array_compare (location, code,
+ tree_strip_any_location_wrapper (orig_op0),
+ tree_strip_any_location_wrapper (orig_op1));
if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
{
@@ -6055,7 +6121,9 @@ cp_build_binary_op (const op_location_t &location,
}
if (sanitize_flags_p ((SANITIZE_SHIFT
- | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
&& current_function_decl != NULL_TREE
&& !processing_template_decl
&& (doing_div_or_mod || doing_shift))
@@ -6067,7 +6135,9 @@ cp_build_binary_op (const op_location_t &location,
op1 = fold_non_dependent_expr (op1, complain);
tree instrument_expr1 = NULL_TREE;
if (doing_div_or_mod
- && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ && sanitize_flags_p (SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE
+ | SANITIZE_SI_OVERFLOW))
{
/* For diagnostics we want to use the promoted types without
shorten_binary_op. So convert the arguments to the
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index dcfdff2..c01f2f8 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -524,7 +524,20 @@ split_nonconstant_init_1 (tree dest, tree init, bool nested)
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
- if (!split_nonconstant_init_1 (sub, value, true))
+ if (!split_nonconstant_init_1 (sub, value, true)
+ /* For flexible array member with initializer we
+ can't remove the initializer, because only the
+ initializer determines how many elements the
+ flexible array member has. */
+ || (!array_type_p
+ && TREE_CODE (inner_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (inner_type) == NULL
+ && TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (value))
+ && !integer_zerop (TYPE_SIZE (TREE_TYPE (value)))
+ && idx == CONSTRUCTOR_NELTS (init) - 1
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR
+ (strip_array_types (inner_type))))
complete_p = false;
else
{
@@ -879,7 +892,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain,
/* Even non-dependent expressions can still have template
codes like CAST_EXPR, so use *_non_dependent_expr to cope. */
- init = fold_non_dependent_expr (init, complain);
+ init = fold_non_dependent_expr (init, complain, /*manifest*/true);
if (init == error_mark_node)
return ok;
@@ -1913,11 +1926,17 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain)
if (processing_template_decl)
{
- if (type && TYPE_PTR_P (type)
- && !dependent_scope_p (TREE_TYPE (type)))
+ tree ttype = NULL_TREE;
+ if (type && TYPE_PTR_P (type))
+ ttype = TREE_TYPE (type);
+ if (ttype && !dependent_scope_p (ttype))
/* Pointer to current instantiation, don't treat as dependent. */;
else if (type_dependent_expression_p (expr))
- return build_min_nt_loc (loc, ARROW_EXPR, expr);
+ {
+ expr = build_min_nt_loc (loc, ARROW_EXPR, expr);
+ TREE_TYPE (expr) = ttype;
+ return expr;
+ }
expr = build_non_dependent_expr (expr);
}
@@ -2157,7 +2176,7 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms,
type = TREE_TYPE (exp);
if (DECL_ARTIFICIAL (exp))
- cp_warn_deprecated_use (type);
+ cp_handle_deprecated_or_unavailable (type);
}
else
type = exp;
diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c
index 2c6bcfa..e112ee8 100644
--- a/gcc/cppbuiltin.c
+++ b/gcc/cppbuiltin.c
@@ -110,6 +110,16 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile)
cpp_define (pfile, "__SUPPORT_SNAN__");
if (!flag_errno_math)
cpp_define (pfile, "__NO_MATH_ERRNO__");
+ if (flag_reciprocal_math)
+ cpp_define (pfile, "__RECIPROCAL_MATH__");
+ if (!flag_signed_zeros)
+ cpp_define (pfile, "__NO_SIGNED_ZEROS__");
+ if (!flag_trapping_math)
+ cpp_define (pfile, "__NO_TRAPPING_MATH__");
+ if (flag_associative_math)
+ cpp_define (pfile, "__ASSOCIATIVE_MATH__");
+ if (flag_rounding_math)
+ cpp_define (pfile, "__ROUNDING_MATH__");
cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d",
flag_finite_math_only);
diff --git a/gcc/cse.c b/gcc/cse.c
index 330c1e9..4c3988e 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -491,14 +491,6 @@ static struct table_elt *table[HASH_SIZE];
static struct table_elt *free_element_chain;
-/* Set to the cost of a constant pool reference if one was found for a
- symbolic constant. If this was found, it means we should try to
- convert constants into constant pool entries if they don't fit in
- the insn. */
-
-static int constant_pool_entries_cost;
-static int constant_pool_entries_regcost;
-
/* Trace a patch through the CFG. */
struct branch_path
@@ -4609,9 +4601,6 @@ cse_insn (rtx_insn *insn)
int src_folded_regcost = MAX_COST;
int src_related_regcost = MAX_COST;
int src_elt_regcost = MAX_COST;
- /* Set nonzero if we need to call force_const_mem on with the
- contents of src_folded before using it. */
- int src_folded_force_flag = 0;
scalar_int_mode int_mode;
dest = SET_DEST (sets[i].rtl);
@@ -5166,15 +5155,7 @@ cse_insn (rtx_insn *insn)
src_related_cost, src_related_regcost) <= 0
&& preferable (src_folded_cost, src_folded_regcost,
src_elt_cost, src_elt_regcost) <= 0)
- {
- trial = src_folded, src_folded_cost = MAX_COST;
- if (src_folded_force_flag)
- {
- rtx forced = force_const_mem (mode, trial);
- if (forced)
- trial = forced;
- }
- }
+ trial = src_folded, src_folded_cost = MAX_COST;
else if (src
&& preferable (src_cost, src_regcost,
src_eqv_cost, src_eqv_regcost) <= 0
@@ -5361,23 +5342,24 @@ cse_insn (rtx_insn *insn)
break;
}
- /* If we previously found constant pool entries for
- constants and this is a constant, try making a
- pool entry. Put it in src_folded unless we already have done
- this since that is where it likely came from. */
+ /* If the current function uses a constant pool and this is a
+ constant, try making a pool entry. Put it in src_folded
+ unless we already have done this since that is where it
+ likely came from. */
- else if (constant_pool_entries_cost
+ else if (crtl->uses_const_pool
&& CONSTANT_P (trial)
- && (src_folded == 0
- || (!MEM_P (src_folded)
- && ! src_folded_force_flag))
+ && !CONST_INT_P (trial)
+ && (src_folded == 0 || !MEM_P (src_folded))
&& GET_MODE_CLASS (mode) != MODE_CC
&& mode != VOIDmode)
{
- src_folded_force_flag = 1;
- src_folded = trial;
- src_folded_cost = constant_pool_entries_cost;
- src_folded_regcost = constant_pool_entries_regcost;
+ src_folded = force_const_mem (mode, trial);
+ if (src_folded)
+ {
+ src_folded_cost = COST (src_folded, mode);
+ src_folded_regcost = approx_reg_cost (src_folded);
+ }
}
}
@@ -6630,8 +6612,6 @@ cse_main (rtx_insn *f ATTRIBUTE_UNUSED, int nregs)
cse_cfg_altered = false;
cse_jumps_altered = false;
recorded_label_ref = false;
- constant_pool_entries_cost = 0;
- constant_pool_entries_regcost = 0;
ebb_data.path_size = 0;
ebb_data.nsets = 0;
rtl_hooks = cse_rtl_hooks;
diff --git a/gcc/ctfc.c b/gcc/ctfc.c
index 1a6ddb8..b76277f 100644
--- a/gcc/ctfc.c
+++ b/gcc/ctfc.c
@@ -132,7 +132,7 @@ ctf_dtd_insert (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
/* Lookup CTF type given a DWARF die for the type. */
-static ctf_dtdef_ref
+ctf_dtdef_ref
ctf_dtd_lookup (const ctf_container_ref ctfc, const dw_die_ref type)
{
ctf_dtdef_t entry;
@@ -791,6 +791,22 @@ ctf_add_sou (ctf_container_ref ctfc, uint32_t flag, const char * name,
return type;
}
+/* Given a TREE_TYPE node, return the CTF type ID for that type. */
+
+ctf_id_t
+ctf_lookup_tree_type (ctf_container_ref ctfc, const tree type)
+{
+ dw_die_ref die = lookup_type_die (type);
+ if (die == NULL)
+ return CTF_NULL_TYPEID;
+
+ ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die);
+ if (dtd == NULL)
+ return CTF_NULL_TYPEID;
+
+ return dtd->dtd_type;
+}
+
/* Check if CTF for TYPE has already been generated. Mainstay for
de-duplication. If CTF type already exists, returns TRUE and updates
the TYPE_ID for the caller. */
@@ -928,11 +944,14 @@ ctfc_delete_strtab (ctf_strtable_t * strtab)
void
ctfc_delete_container (ctf_container_ref ctfc)
{
- /* FIXME - CTF container can be cleaned up now.
- Will the ggc machinery take care of cleaning up the container structure
- including the hash_map members etc. ? */
if (ctfc)
{
+ ctfc->ctfc_types->empty ();
+ ctfc->ctfc_types = NULL;
+
+ ctfc->ctfc_vars->empty ();
+ ctfc->ctfc_types = NULL;
+
ctfc_delete_strtab (&ctfc->ctfc_strtable);
ctfc_delete_strtab (&ctfc->ctfc_aux_strtable);
if (ctfc->ctfc_vars_list)
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index 39c5270..701c7ea 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -212,7 +212,7 @@ enum ctf_dtu_d_union_enum {
CTF_DTU_D_ARRAY,
CTF_DTU_D_ENCODING,
CTF_DTU_D_ARGUMENTS,
- CTF_DTU_D_SLICE,
+ CTF_DTU_D_SLICE
};
enum ctf_dtu_d_union_enum
@@ -388,7 +388,10 @@ extern bool ctf_type_exists (ctf_container_ref, dw_die_ref, ctf_id_t *);
extern void ctf_add_cuname (ctf_container_ref, const char *);
-extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref, dw_die_ref);
+extern ctf_dtdef_ref ctf_dtd_lookup (const ctf_container_ref ctfc,
+ dw_die_ref die);
+extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref ctfc,
+ dw_die_ref die);
extern const char * ctf_add_string (ctf_container_ref, const char *,
uint32_t *, int);
@@ -427,6 +430,9 @@ extern int ctf_add_function_arg (ctf_container_ref, dw_die_ref,
extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t,
dw_die_ref, unsigned int);
+extern ctf_id_t ctf_lookup_tree_type (ctf_container_ref, const tree);
+extern ctf_id_t get_btf_id (ctf_id_t);
+
/* CTF section does not emit location information; at this time, location
information is needed for BTF CO-RE use-cases. */
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index db85ffc..c045cc9 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,96 @@
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * d-lang.cc (d_post_options): Use new macro
+ OPTION_SET_P.
+
+2021-10-05 Iain Sandoe <iain@sandoe.co.uk>
+
+ * d-spec.cc (lang_specific_driver): Push the -static-libstdc++
+ option back onto the command line for targets without support
+ for -Bstatic/dynamic.
+
+2021-10-04 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102574
+ * d-spec.cc (lang_specific_driver): Link libstdc++ statically if
+ -static-libstdc++ was given on command-line.
+
+2021-10-04 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-attribs.cc (d_handle_optimize_attribute): Save target node before
+ calling parse_optimize_options in case it changes.
+
+2021-09-12 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102185
+ * d-builtins.cc (d_eval_constant_expression): Don't include
+ terminating null pointer in string expression conversion.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-codegen.cc: Include dmd/module.h.
+ (build_filename_from_loc): New function.
+ (d_assert_call): Rename to...
+ (build_assert_call): ...this.
+ (build_array_bounds_call): Call arrayboundsp variant of the array
+ bounds failure callback.
+ (build_bounds_condition): Rename to...
+ (build_bounds_index_condition): ...this. Update signature.
+ (build_bounds_slice_condition): New function.
+ (checkaction_trap_p): New function.
+ (d_assert_call): Call assertp variant of assert failure callback.
+ * d-tree.h (class IndexExp): Declare.
+ (class SliceExp): Declare.
+ (build_bounds_condition): Remove.
+ (build_assert_call): Declare.
+ (build_bounds_index_condition): Declare.
+ (build_bounds_slice_condition): Declare.
+ (checkaction_trap_p): Declare.
+ (d_assert_call): Remove.
+ * expr.cc (ExprVisitor::visit(IndexExp *)): Call
+ build_bounds_index_condition.
+ (ExprVisitor::visit(SliceExp *)): Call build_bounds_slice_condition.
+ (ExprVisitor::visit(AssertExp *)): Update setting of libcall.
+ * runtime.cc (enum d_libcall_type): Add LCT_IMMUTABLE_CHARPTR.
+ (get_libcall_type): Handle LCT_IMMUTABLE_CHARPTR.
+ * runtime.def (ASSERT): Rename to...
+ (ASSERTP): ...this. Update signature.
+ (UNITTEST): Rename to...
+ (UNITTESTP): ...this. Update signature.
+ (ARRAY_BOUNDS): Rename to...
+ (ARRAYBOUNDSP): ...this. Updates signature.
+ * toir.cc (IRVisitor::visit(SwitchErrorStatement *)): Update call.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * typeinfo.cc (class TypeInfoVisitor::layout_base): Update comment.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * typeinfo.cc (TypeInfoVisitor::visit(TypeInfoClassDeclaration *)):
+ Use int to store type flags.
+ (TypeInfoVisitor::visit(TypeInfoStructDeclaration *)): Likewise.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * types.cc (TypeVisitor::visit(TypeEnum*)): Get wchar_t type from
+ build_frontend_type.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-convert.cc (convert_for_rvalue): Convert switch statement into if
+ condition.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-builtins.cc (d_init_versions): Use POINTER_SIZE for testing
+ whether to predefine D_LP64.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102094
+ * d-codegen.cc (build_frame_type): Set TYPE_CXX_ODR_P.
+
2021-08-25 Lewis Hyatt <lhyatt@gmail.com>
PR other/93067
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index 0708660..d81b7d1 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -896,6 +896,8 @@ d_handle_optimize_attribute (tree *node, tree name, tree args, int,
/* Save current options. */
cl_optimization_save (&cur_opts, &global_options, &global_options_set);
+ tree prev_target_node = build_target_option_node (&global_options,
+ &global_options_set);
/* If we previously had some optimization options, use them as the
default. */
@@ -914,10 +916,16 @@ d_handle_optimize_attribute (tree *node, tree name, tree args, int,
parse_optimize_options (args);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
= build_optimization_node (&global_options, &global_options_set);
+ tree target_node = build_target_option_node (&global_options,
+ &global_options_set);
+ if (prev_target_node != target_node)
+ DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
/* Restore current options. */
cl_optimization_restore (&global_options, &global_options_set,
&cur_opts);
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (prev_target_node));
if (saved_global_options != NULL)
{
cl_optimization_compare (saved_global_options, &global_options);
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 328711f..33347a1 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -380,7 +380,7 @@ d_eval_constant_expression (const Loc &loc, tree cst)
else if (code == STRING_CST)
{
const void *string = TREE_STRING_POINTER (cst);
- size_t len = TREE_STRING_LENGTH (cst);
+ size_t len = TREE_STRING_LENGTH (cst) - 1;
return StringExp::create (loc, CONST_CAST (void *, string), len);
}
else if (code == VECTOR_CST)
@@ -462,7 +462,7 @@ d_init_versions (void)
VersionCondition::addPredefinedGlobalIdent ("GNU_InlineAsm");
/* LP64 only means 64bit pointers in D. */
- if (global.params.isLP64)
+ if (POINTER_SIZE == 64)
VersionCondition::addPredefinedGlobalIdent ("D_LP64");
/* Setting `global.params.cov' forces module info generation which is
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index fe2ad98..e633650 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/ctfe.h"
#include "dmd/declaration.h"
#include "dmd/identifier.h"
+#include "dmd/module.h"
#include "dmd/target.h"
#include "dmd/template.h"
@@ -1831,50 +1832,149 @@ void_okay_p (tree t)
return t;
}
-/* Builds a CALL_EXPR at location LOC in the source file to execute when an
- array bounds check fails. */
+/* Builds a STRING_CST representing the filename of location LOC. When the
+ location is not valid, the name of the source module is used instead. */
+
+static tree
+build_filename_from_loc (const Loc &loc)
+{
+ const char *filename = loc.filename
+ ? loc.filename : d_function_chain->module->srcfile->toChars ();
+
+ unsigned length = strlen (filename);
+ tree str = build_string (length, filename);
+ TREE_TYPE (str) = make_array_type (Type::tchar, length + 1);
+
+ return build_address (str);
+}
+
+/* Builds a CALL_EXPR at location LOC in the source file to call LIBCALL when
+ an assert check fails. When calling the msg variant functions, MSG is the
+ error message supplied by the user. */
tree
-build_array_bounds_call (const Loc &loc)
+build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
{
- switch (global.params.checkAction)
+ tree file;
+ tree line = size_int (loc.linnum);
+
+ switch (libcall)
{
- case CHECKACTION_D:
- return d_assert_call (loc, LIBCALL_ARRAY_BOUNDS);
+ case LIBCALL_ASSERT_MSG:
+ case LIBCALL_UNITTEST_MSG:
+ case LIBCALL_SWITCH_ERROR:
+ /* File location is passed as a D string. */
+ if (loc.filename)
+ {
+ unsigned len = strlen (loc.filename);
+ tree str = build_string (len, loc.filename);
+ TREE_TYPE (str) = make_array_type (Type::tchar, len);
- case CHECKACTION_C:
- case CHECKACTION_halt:
- return build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
+ size_int (len), build_address (str));
+ }
+ else
+ file = null_array_node;
+ break;
+
+ case LIBCALL_ASSERTP:
+ case LIBCALL_UNITTESTP:
+ file = build_filename_from_loc (loc);
+ break;
default:
gcc_unreachable ();
}
+
+
+ if (msg != NULL_TREE)
+ return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
+ else
+ return build_libcall (libcall, Type::tvoid, 2, file, line);
}
-/* Builds a bounds condition checking that INDEX is between 0 and LEN.
- The condition returns the INDEX if true, or throws a RangeError.
- If INCLUSIVE, we allow INDEX == LEN to return true also. */
+/* Builds a CALL_EXPR at location LOC in the source file to execute when an
+ array bounds check fails. */
tree
-build_bounds_condition (const Loc &loc, tree index, tree len, bool inclusive)
+build_array_bounds_call (const Loc &loc)
{
- if (!array_bounds_check ())
+ /* Terminate the program with a trap if no D runtime present. */
+ if (checkaction_trap_p ())
+ return build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ else
+ {
+ return build_libcall (LIBCALL_ARRAYBOUNDSP, Type::tvoid, 2,
+ build_filename_from_loc (loc),
+ size_int (loc.linnum));
+ }
+}
+
+/* Builds a bounds condition checking that INDEX is between 0 and LENGTH
+ in the index expression IE. The condition returns the INDEX if true, or
+ throws a `RangeError`. */
+
+tree
+build_bounds_index_condition (IndexExp *ie, tree index, tree length)
+{
+ if (ie->indexIsInBounds || !array_bounds_check ())
return index;
/* Prevent multiple evaluations of the index. */
index = d_save_expr (index);
- /* Generate INDEX >= LEN && throw RangeError.
+ /* Generate INDEX >= LENGTH && throw RangeError.
No need to check whether INDEX >= 0 as the front-end should
have already taken care of implicit casts to unsigned. */
- tree condition = fold_build2 (inclusive ? GT_EXPR : GE_EXPR,
- d_bool_type, index, len);
- /* Terminate the program with a trap if no D runtime present. */
- tree boundserr = build_array_bounds_call (loc);
+ tree condition = fold_build2 (GE_EXPR, d_bool_type, index, length);
+ tree boundserr = build_array_bounds_call (ie->e2->loc);
return build_condition (TREE_TYPE (index), condition, boundserr, index);
}
+/* Builds a bounds condition checking that the range LOWER..UPPER do not overlap
+ the slice expression SE of the source array length LENGTH. The condition
+ returns the new array length if true, or throws an `ArraySliceError`. */
+
+tree
+build_bounds_slice_condition (SliceExp *se, tree lower, tree upper, tree length)
+{
+ if (array_bounds_check ())
+ {
+ tree condition = NULL_TREE;
+
+ /* Enforces that `upper <= length`. */
+ if (!se->upperIsInBounds && length != NULL_TREE)
+ condition = fold_build2 (GT_EXPR, d_bool_type, upper, length);
+ else
+ length = integer_zero_node;
+
+ /* Enforces that `lower <= upper`. No need to check `lower <= length` as
+ we've already ensured that `upper <= length`. */
+ if (!se->lowerIsLessThanUpper)
+ {
+ tree lwr_cond = fold_build2 (GT_EXPR, d_bool_type, lower, upper);
+
+ if (condition != NULL_TREE)
+ condition = build_boolop (TRUTH_ORIF_EXPR, condition, lwr_cond);
+ else
+ condition = lwr_cond;
+ }
+
+ if (condition != NULL_TREE)
+ {
+ tree boundserr = build_array_bounds_call (se->loc);
+ upper = build_condition (TREE_TYPE (upper), condition,
+ boundserr, upper);
+ }
+ }
+
+ /* Need to ensure lower always gets evaluated first, as it may be a function
+ call. Generates (lower, upper) - lower. */
+ return fold_build2 (MINUS_EXPR, TREE_TYPE (upper),
+ compound_expr (lower, upper), lower);
+}
+
/* Returns TRUE if array bounds checking code generation is turned on. */
bool
@@ -1905,6 +2005,26 @@ array_bounds_check (void)
}
}
+/* Returns TRUE if we terminate the program with a trap if an array bounds or
+ contract check fails. */
+
+bool
+checkaction_trap_p (void)
+{
+ switch (global.params.checkAction)
+ {
+ case CHECKACTION_D:
+ return false;
+
+ case CHECKACTION_C:
+ case CHECKACTION_halt:
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Returns the TypeFunction class for Type T.
Assumes T is already ->toBasetype(). */
@@ -2093,33 +2213,6 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
return compound_expr (saved_args, result);
}
-/* Builds a call to AssertError or AssertErrorMsg. */
-
-tree
-d_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
-{
- tree file;
- tree line = size_int (loc.linnum);
-
- /* File location is passed as a D string. */
- if (loc.filename)
- {
- unsigned len = strlen (loc.filename);
- tree str = build_string (len, loc.filename);
- TREE_TYPE (str) = make_array_type (Type::tchar, len);
-
- file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
- size_int (len), build_address (str));
- }
- else
- file = null_array_node;
-
- if (msg != NULL)
- return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
- else
- return build_libcall (libcall, Type::tvoid, 2, file, line);
-}
-
/* Build and return the correct call to fmod depending on TYPE.
ARG0 and ARG1 are the arguments pass to the function. */
@@ -2563,6 +2656,7 @@ build_frame_type (tree ffi, FuncDeclaration *fd)
TYPE_FIELDS (frame_rec_type) = fields;
TYPE_READONLY (frame_rec_type) = 1;
+ TYPE_CXX_ODR_P (frame_rec_type) = 1;
layout_type (frame_rec_type);
d_keep (frame_rec_type);
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index d43485d..3b47902 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -613,9 +613,8 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
Type *ebtype = etype->toBasetype ();
Type *tbtype = totype->toBasetype ();
- switch (ebtype->ty)
+ if (ebtype->ty == Tbool)
{
- case Tbool:
/* If casting from bool, the result is either 0 or 1, any other value
violates @safe code, so enforce that it is never invalid. */
if (CONSTANT_CLASS_P (expr))
@@ -633,7 +632,6 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
}
result = convert (build_ctype (tbtype), result);
- break;
}
return result ? result : convert_expr (expr, etype, totype);
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index fa29a46a..be6330f 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -792,13 +792,13 @@ d_post_options (const char ** fn)
if (global.params.betterC)
{
- if (!global_options_set.x_flag_moduleinfo)
+ if (!OPTION_SET_P (flag_moduleinfo))
global.params.useModuleInfo = false;
- if (!global_options_set.x_flag_rtti)
+ if (!OPTION_SET_P (flag_rtti))
global.params.useTypeInfo = false;
- if (!global_options_set.x_flag_exceptions)
+ if (!OPTION_SET_P (flag_exceptions))
global.params.useExceptions = false;
global.params.checkAction = CHECKACTION_C;
@@ -810,7 +810,7 @@ d_post_options (const char ** fn)
/* Turn off partitioning unless it was explicitly requested, as it doesn't
work with D exception chaining, where EH handler uses LSDA to determine
whether two thrown exception are in the same context. */
- if (!global_options_set.x_flag_reorder_blocks_and_partition)
+ if (!OPTION_SET_P (flag_reorder_blocks_and_partition))
global_options.x_flag_reorder_blocks_and_partition = 0;
/* Error about use of deprecated features. */
@@ -819,7 +819,7 @@ d_post_options (const char ** fn)
global.params.useDeprecated = DIAGNOSTICerror;
/* Make -fmax-errors visible to frontend's diagnostic machinery. */
- if (global_options_set.x_flag_max_errors)
+ if (OPTION_SET_P (flag_max_errors))
global.params.errorLimit = flag_max_errors;
if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index 16ff153..b12d28f 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -83,6 +83,9 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
/* "-lstdc++" if it appears on the command line. */
const cl_decoded_option *saw_libcxx = 0;
+ /* True if we saw `-static-libstdc++'. */
+ bool saw_static_libcxx = false;
+
/* Whether we need the C++ STD library. */
bool need_stdcxx = false;
@@ -248,6 +251,11 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
shared_libgcc = false;
break;
+ case OPT_static_libstdc__:
+ saw_static_libcxx = true;
+ args[i] |= SKIPOPT;
+ break;
+
case OPT_static_libphobos:
if (phobos_library != PHOBOS_NOLINK)
phobos_library = PHOBOS_STATIC;
@@ -452,16 +460,39 @@ lang_specific_driver (cl_decoded_option **in_decoded_options,
#endif
}
- if (saw_libcxx)
- new_decoded_options[j++] = *saw_libcxx;
- else if (need_stdcxx)
+ if (saw_libcxx || need_stdcxx)
{
- generate_option (OPT_l,
- (saw_profile_flag
- ? LIBSTDCXX_PROFILE
- : LIBSTDCXX),
- 1, CL_DRIVER, &new_decoded_options[j++]);
- added_libraries++;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (saw_static_libcxx && !static_link)
+ {
+ generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+ }
+#else
+ /* Push the -static-libstdc++ option back onto the command so that
+ a target without LD_STATIC_DYNAMIC can use outfile substitution. */
+ if (saw_static_libcxx && !static_link)
+ generate_option (OPT_static_libstdc__, NULL, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+#endif
+ if (saw_libcxx)
+ new_decoded_options[j++] = *saw_libcxx;
+ else if (need_stdcxx)
+ {
+ generate_option (OPT_l,
+ (saw_profile_flag
+ ? LIBSTDCXX_PROFILE
+ : LIBSTDCXX),
+ 1, CL_DRIVER, &new_decoded_options[j++]);
+ added_libraries++;
+ }
+#ifdef HAVE_LD_STATIC_DYNAMIC
+ if (saw_static_libcxx && !static_link)
+ {
+ generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+ }
+#endif
}
if (shared_libgcc && !static_link)
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index f210b8b..9b90ca5 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -31,6 +31,8 @@ class TypeInfoDeclaration;
class VarDeclaration;
class Expression;
class ClassReferenceExp;
+class IndexExp;
+class SliceExp;
class Module;
class Statement;
class Type;
@@ -575,15 +577,17 @@ extern tree build_array_set (tree, tree, tree);
extern tree build_array_from_val (Type *, tree);
extern tree build_array_from_exprs (Type *, Expressions *, bool);
extern tree void_okay_p (tree);
+extern tree build_assert_call (const Loc &, libcall_fn, tree = NULL_TREE);
extern tree build_array_bounds_call (const Loc &);
-extern tree build_bounds_condition (const Loc &, tree, tree, bool);
+extern tree build_bounds_index_condition (IndexExp *, tree, tree);
+extern tree build_bounds_slice_condition (SliceExp *, tree, tree, tree);
extern bool array_bounds_check (void);
+extern bool checkaction_trap_p (void);
extern tree bind_expr (tree, tree);
extern TypeFunction *get_function_type (Type *);
extern bool call_by_alias_p (FuncDeclaration *, FuncDeclaration *);
extern tree d_build_call_expr (FuncDeclaration *, tree, Expressions *);
extern tree d_build_call (TypeFunction *, tree, tree, Expressions *);
-extern tree d_assert_call (const Loc &, libcall_fn, tree = NULL_TREE);
extern tree build_float_modulus (tree, tree, tree);
extern tree build_vthis_function (tree, tree);
extern tree error_no_frame_access (Dsymbol *);
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index e293cf2..ea21bd5 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1304,8 +1304,8 @@ public:
/* If it's a static array and the index is constant, the front end has
already checked the bounds. */
- if (tb1->ty != Tpointer && !e->indexIsInBounds)
- index = build_bounds_condition (e->e2->loc, index, length, false);
+ if (tb1->ty != Tpointer)
+ index = build_bounds_index_condition (e, index, length);
/* Index the .ptr. */
ptr = void_okay_p (ptr);
@@ -1412,8 +1412,6 @@ public:
ptr = build_array_index (void_okay_p (ptr), lwr_tree);
ptr = build_nop (ptrtype, ptr);
}
- else
- lwr_tree = NULL_TREE;
/* Nothing more to do for static arrays, their bounds checking has been
done at compile-time. */
@@ -1426,46 +1424,8 @@ public:
gcc_assert (tb->ty == Tarray);
/* Generate bounds checking code. */
- tree newlength;
-
- if (!e->upperIsInBounds)
- {
- if (length)
- {
- newlength = build_bounds_condition (e->upr->loc, upr_tree,
- length, true);
- }
- else
- {
- /* Still need to check bounds lwr <= upr for pointers. */
- gcc_assert (tb1->ty == Tpointer);
- newlength = upr_tree;
- }
- }
- else
- newlength = upr_tree;
-
- if (lwr_tree)
- {
- /* Enforces lwr <= upr. No need to check lwr <= length as
- we've already ensured that upr <= length. */
- if (!e->lowerIsLessThanUpper)
- {
- tree cond = build_bounds_condition (e->lwr->loc, lwr_tree,
- upr_tree, true);
-
- /* When bounds checking is off, the index value is
- returned directly. */
- if (cond != lwr_tree)
- newlength = compound_expr (cond, newlength);
- }
-
- /* Need to ensure lwr always gets evaluated first, as it may be a
- function call. Generates (lwr, upr) - lwr. */
- newlength = fold_build2 (MINUS_EXPR, TREE_TYPE (newlength),
- compound_expr (lwr_tree, newlength), lwr_tree);
- }
-
+ tree newlength = build_bounds_slice_condition (e, lwr_tree, upr_tree,
+ length);
tree result = d_array_value (build_ctype (e->type), newlength, ptr);
this->result_ = compound_expr (array, result);
}
@@ -2023,8 +1983,7 @@ public:
tree assert_pass = void_node;
tree assert_fail;
- if (global.params.useAssert == CHECKENABLEon
- && global.params.checkAction == CHECKACTION_D)
+ if (global.params.useAssert == CHECKENABLEon && !checkaction_trap_p ())
{
/* Generate: ((bool) e1 ? (void)0 : _d_assert (...))
or: (e1 != null ? e1._invariant() : _d_assert (...)) */
@@ -2037,10 +1996,10 @@ public:
libcall = unittest_p ? LIBCALL_UNITTEST_MSG : LIBCALL_ASSERT_MSG;
}
else
- libcall = unittest_p ? LIBCALL_UNITTEST : LIBCALL_ASSERT;
+ libcall = unittest_p ? LIBCALL_UNITTESTP : LIBCALL_ASSERTP;
/* Build a call to _d_assert(). */
- assert_fail = d_assert_call (e->loc, libcall, tmsg);
+ assert_fail = build_assert_call (e->loc, libcall, tmsg);
if (global.params.useInvariants == CHECKENABLEon)
{
@@ -2068,8 +2027,7 @@ public:
}
}
}
- else if (global.params.useAssert == CHECKENABLEon
- && global.params.checkAction == CHECKACTION_C)
+ else if (global.params.useAssert == CHECKENABLEon && checkaction_trap_p ())
{
/* Generate: __builtin_trap() */
tree fn = builtin_decl_explicit (BUILT_IN_TRAP);
diff --git a/gcc/d/runtime.cc b/gcc/d/runtime.cc
index d789fca..5206b53 100644
--- a/gcc/d/runtime.cc
+++ b/gcc/d/runtime.cc
@@ -51,6 +51,7 @@ enum d_libcall_type
LCT_ARRAY_VOID, /* void[] */
LCT_ARRAY_SIZE_T, /* size_t[] */
LCT_ARRAY_BYTE, /* byte[] */
+ LCT_IMMUTABLE_CHARPTR, /* immutable(char*) */
LCT_ARRAY_STRING, /* string[] */
LCT_ARRAY_WSTRING, /* wstring[] */
LCT_ARRAY_DSTRING, /* dstring[] */
@@ -200,6 +201,10 @@ get_libcall_type (d_libcall_type type)
libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
break;
+ case LCT_IMMUTABLE_CHARPTR:
+ libcall_types[type] = Type::tchar->pointerTo ()->immutableOf ();
+ break;
+
default:
gcc_unreachable ();
}
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index f872cfc..0296233 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -26,27 +26,31 @@ along with GCC; see the file COPYING3. If not see
extern(C) - for those that are not, ensure to use correct mangling. */
/* Helper macros for parameter building. */
-#define P0() 0
-#define P1(T1) 1, LCT_ ## T1
-#define P2(T1, T2) 2, LCT_ ## T1, LCT_ ## T2
-#define P3(T1, T2, T3) 3, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3
-#define P4(T1, T2, T3, T4) 4, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4
-#define RT(T1) LCT_ ## T1
+#define P0() 0
+#define P1(T1) 1, LCT_ ## T1
+#define P2(T1, T2) \
+ 2, LCT_ ## T1, LCT_ ## T2
+#define P3(T1, T2, T3) \
+ 3, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3
+#define P4(T1, T2, T3, T4) \
+ 4, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4
+#define RT(T1) LCT_ ## T1
/* Used when an assert() contract fails. */
-DEF_D_RUNTIME (ASSERT, "_d_assert", RT(VOID), P2(STRING, UINT), ECF_NORETURN)
+DEF_D_RUNTIME (ASSERTP, "_d_assertp", RT(VOID), P2(IMMUTABLE_CHARPTR, UINT),
+ ECF_NORETURN)
DEF_D_RUNTIME (ASSERT_MSG, "_d_assert_msg", RT(VOID), P3(STRING, STRING, UINT),
ECF_NORETURN)
/* Used when an assert() contract fails in a unittest function. */
-DEF_D_RUNTIME (UNITTEST, "_d_unittest", RT(VOID), P2(STRING, UINT),
+DEF_D_RUNTIME (UNITTESTP, "_d_unittestp", RT(VOID), P2(IMMUTABLE_CHARPTR, UINT),
ECF_NORETURN)
DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(VOID),
P3(STRING, STRING, UINT), ECF_NORETURN)
/* Used when an array index outside the bounds of its range. */
-DEF_D_RUNTIME (ARRAY_BOUNDS, "_d_arraybounds", RT(VOID), P2(STRING, UINT),
- ECF_NORETURN)
+DEF_D_RUNTIME (ARRAYBOUNDSP, "_d_arrayboundsp", RT(VOID),
+ P2(IMMUTABLE_CHARPTR, UINT), ECF_NORETURN)
/* Used when calling new on a class. */
DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index eaee6f7..1c9da10 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -992,7 +992,7 @@ public:
void visit (SwitchErrorStatement *s)
{
- add_stmt (d_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
+ add_stmt (build_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
}
/* A return statement exits the current function and supplies its return
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index 978c73e..fd8c746 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -411,8 +411,7 @@ class TypeInfoVisitor : public Visitor
this->layout_field (value);
}
-
- /* Write out the __vptr and __monitor fields of class CD. */
+ /* Write out the __vptr and optionally __monitor fields of class CD. */
void layout_base (ClassDeclaration *cd)
{
@@ -868,7 +867,7 @@ public:
this->layout_field (inv);
/* ClassFlags m_flags; */
- ClassFlags::Type flags = ClassFlags::hasOffTi;
+ int flags = ClassFlags::hasOffTi;
if (cd->isCOMclass ())
flags |= ClassFlags::isCOMclass;
@@ -962,7 +961,7 @@ public:
this->layout_field (null_pointer_node);
/* ClassFlags m_flags; */
- ClassFlags::Type flags = ClassFlags::hasOffTi;
+ int flags = ClassFlags::hasOffTi;
flags |= ClassFlags::hasTypeInfo;
if (cd->isCOMinterface ())
flags |= ClassFlags::isCOMclass;
@@ -1091,7 +1090,7 @@ public:
this->layout_field (null_pointer_node);
/* StructFlags m_flags; */
- StructFlags::Type m_flags = 0;
+ int m_flags = StructFlags::none;
if (ti->hasPointers ())
m_flags |= StructFlags::hasPointers;
this->layout_field (build_integer_cst (m_flags, d_uint_type));
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 8e67461..fc8a133 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -886,7 +886,8 @@ public:
else if (strcmp (ident, "ulong") == 0)
underlying = build_frontend_type (long_unsigned_type_node);
else if (strcmp (ident, "wchar_t") == 0)
- underlying = target.c.twchar_t;
+ underlying =
+ build_frontend_type (make_unsigned_type (WCHAR_TYPE_SIZE));
else if (strcmp (ident, "longlong") == 0)
underlying = build_frontend_type (long_long_integer_type_node);
else if (strcmp (ident, "ulonglong") == 0)
diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index 934bbe0..458341a 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -98,6 +98,14 @@ dbg_cnt (enum debug_counter index)
return false;
}
+/* Return the counter for INDEX. */
+
+unsigned
+dbg_cnt_counter (enum debug_counter index)
+{
+ return count[index];
+}
+
/* Compare limit_tuple intervals by first item in descending order. */
static int
@@ -200,7 +208,6 @@ void
dbg_cnt_process_opt (const char *arg)
{
char *str = xstrdup (arg);
- unsigned int start = 0;
auto_vec<char *> tokens;
for (char *next = strtok (str, ","); next != NULL; next = strtok (NULL, ","))
@@ -219,7 +226,6 @@ dbg_cnt_process_opt (const char *arg)
if (!dbg_cnt_process_single_pair (name, ranges[j]))
break;
}
- start += strlen (tokens[i]) + 1;
}
}
diff --git a/gcc/dbgcnt.h b/gcc/dbgcnt.h
index 17f2091..3c35dcc 100644
--- a/gcc/dbgcnt.h
+++ b/gcc/dbgcnt.h
@@ -33,6 +33,7 @@ enum debug_counter {
extern bool dbg_cnt_is_enabled (enum debug_counter index);
extern bool dbg_cnt (enum debug_counter index);
+extern unsigned dbg_cnt_counter (enum debug_counter index);
extern void dbg_cnt_process_opt (const char *arg);
extern void dbg_cnt_list_all_counters (void);
diff --git a/gcc/defaults.h b/gcc/defaults.h
index ba79a8e..bb68d0d 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -61,36 +61,35 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
do { \
- FILE *_hide_asm_out_file = (MYFILE); \
+ FILE *_my_file = (MYFILE); \
const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \
int _hide_thissize = (MYLENGTH); \
{ \
- FILE *asm_out_file = _hide_asm_out_file; \
const unsigned char *p = _hide_p; \
int thissize = _hide_thissize; \
int i; \
- fprintf (asm_out_file, "\t.ascii \""); \
+ fprintf (_my_file, "\t.ascii \""); \
\
for (i = 0; i < thissize; i++) \
{ \
int c = p[i]; \
if (c == '\"' || c == '\\') \
- putc ('\\', asm_out_file); \
+ putc ('\\', _my_file); \
if (ISPRINT (c)) \
- putc (c, asm_out_file); \
+ putc (c, _my_file); \
else \
{ \
- fprintf (asm_out_file, "\\%o", c); \
+ fprintf (_my_file, "\\%o", c); \
/* After an octal-escape, if a digit follows, \
terminate one string constant and start another. \
The VAX assembler fails to stop reading the escape \
after three digits, so this is the only way we \
can get it to parse the data properly. */ \
if (i < thissize - 1 && ISDIGIT (p[i + 1])) \
- fprintf (asm_out_file, "\"\n\t.ascii \""); \
+ fprintf (_my_file, "\"\n\t.ascii \""); \
} \
} \
- fprintf (asm_out_file, "\"\n"); \
+ fprintf (_my_file, "\"\n"); \
} \
} \
while (0)
@@ -900,33 +899,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DEFAULT_GDB_EXTENSIONS 1
#endif
-/* If more than one debugging type is supported, you must define
- PREFERRED_DEBUGGING_TYPE to choose the default. */
-
-#if 1 < (defined (DBX_DEBUGGING_INFO) \
- + defined (DWARF2_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO) \
- + defined (VMS_DEBUGGING_INFO))
+/* Default to DWARF2_DEBUGGING_INFO. Legacy targets can choose different
+ by defining PREFERRED_DEBUGGING_TYPE. */
#ifndef PREFERRED_DEBUGGING_TYPE
-#error You must define PREFERRED_DEBUGGING_TYPE
-#endif /* no PREFERRED_DEBUGGING_TYPE */
-
-/* If only one debugging format is supported, define PREFERRED_DEBUGGING_TYPE
- here so other code needn't care. */
-#elif defined DBX_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-#elif defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-#elif defined VMS_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE VMS_AND_DWARF2_DEBUG
-
-#elif defined XCOFF_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE XCOFF_DEBUG
-
#else
-/* No debugging format is supported by this target. */
-#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
+#error You must define PREFERRED_DEBUGGING_TYPE if DWARF is not supported
+#endif
#endif
#ifndef FLOAT_LIB_COMPARE_RETURNS_BOOL
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 5e961e1..85ffb72 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -105,7 +105,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
}
}
-/* Map from location to its no-warning disposition. */
+/* A mapping from a 'location_t' to the warning spec set for it. */
GTY(()) xint_hash_map_t *nowarn_map;
@@ -115,6 +115,8 @@ GTY(()) xint_hash_map_t *nowarn_map;
bool
warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
{
+ gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
if (!nowarn_map)
return false;
@@ -137,6 +139,8 @@ bool
suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
bool supp /* = true */)
{
+ gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
const nowarn_spec_t optspec (supp ? opt : opt_code ());
if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
@@ -173,8 +177,20 @@ copy_warning (location_t to, location_t from)
if (!nowarn_map)
return;
- if (nowarn_spec_t *pspec = nowarn_map->get (from))
- nowarn_map->put (to, *pspec);
+ nowarn_spec_t *from_spec;
+ if (RESERVED_LOCATION_P (from))
+ from_spec = NULL;
+ else
+ from_spec = nowarn_map->get (from);
+ if (RESERVED_LOCATION_P (to))
+ /* We cannot set no-warning dispositions for 'to', so we have no chance but
+ lose those potentially set for 'from'. */
+ ;
else
- nowarn_map->remove (to);
+ {
+ if (from_spec)
+ nowarn_map->put (to, *from_spec);
+ else
+ nowarn_map->remove (to);
+ }
}
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 4e4d260..9b3aaaa 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,12 +130,10 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
return !(lhs == rhs);
}
-typedef location_t key_type_t;
-typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
-/* A mapping from the location of an expression to the warning spec
- set for it. */
+/* A mapping from a 'location_t' to the warning spec set for it. */
extern GTY(()) xint_hash_map_t *nowarn_map;
#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi
index b024998..da4a5b3 100644
--- a/gcc/doc/avr-mmcu.texi
+++ b/gcc/doc/avr-mmcu.texi
@@ -38,7 +38,7 @@
@item avr5
``Enhanced'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{atmega16}, @code{atmega16a}, @code{atmega16hva}, @code{atmega16hva2}, @code{atmega16hvb}, @code{atmega16hvbrevb}, @code{atmega16m1}, @code{atmega16u4}, @code{atmega161}, @code{atmega162}, @code{atmega163}, @code{atmega164a}, @code{atmega164p}, @code{atmega164pa}, @code{atmega165}, @code{atmega165a}, @code{atmega165p}, @code{atmega165pa}, @code{atmega168}, @code{atmega168a}, @code{atmega168p}, @code{atmega168pa}, @code{atmega168pb}, @code{atmega169}, @code{atmega169a}, @code{atmega169p}, @code{atmega169pa}, @code{atmega32}, @code{atmega32a}, @code{atmega32c1}, @code{atmega32hvb}, @code{atmega32hvbrevb}, @code{atmega32m1}, @code{atmega32u4}, @code{atmega32u6}, @code{atmega323}, @code{atmega324a}, @code{atmega324p}, @code{atmega324pa}, @code{atmega325}, @code{atmega325a}, @code{atmega325p}, @code{atmega325pa}, @code{atmega328}, @code{atmega328p}, @code{atmega328pb}, @code{atmega329}, @code{atmega329a}, @code{atmega329p}, @code{atmega329pa}, @code{atmega3250}, @code{atmega3250a}, @code{atmega3250p}, @code{atmega3250pa}, @code{atmega3290}, @code{atmega3290a}, @code{atmega3290p}, @code{atmega3290pa}, @code{atmega406}, @code{atmega64}, @code{atmega64a}, @code{atmega64c1}, @code{atmega64hve}, @code{atmega64hve2}, @code{atmega64m1}, @code{atmega64rfr2}, @code{atmega640}, @code{atmega644}, @code{atmega644a}, @code{atmega644p}, @code{atmega644pa}, @code{atmega644rfr2}, @code{atmega645}, @code{atmega645a}, @code{atmega645p}, @code{atmega649}, @code{atmega649a}, @code{atmega649p}, @code{atmega6450}, @code{atmega6450a}, @code{atmega6450p}, @code{atmega6490}, @code{atmega6490a}, @code{atmega6490p}, @code{ata5795}, @code{ata5790}, @code{ata5790n}, @code{ata5791}, @code{ata6613c}, @code{ata6614q}, @code{ata5782}, @code{ata5831}, @code{ata8210}, @code{ata8510}, @code{ata5702m322}, @code{at90pwm161}, @code{at90pwm216}, @code{at90pwm316}, @code{at90can32}, @code{at90can64}, @code{at90scr100}, @code{at90usb646}, @code{at90usb647}, @code{at94k}, @code{m3000}.
+@*@var{mcu}@tie{}= @code{atmega16}, @code{atmega16a}, @code{atmega16hva}, @code{atmega16hva2}, @code{atmega16hvb}, @code{atmega16hvbrevb}, @code{atmega16m1}, @code{atmega16u4}, @code{atmega161}, @code{atmega162}, @code{atmega163}, @code{atmega164a}, @code{atmega164p}, @code{atmega164pa}, @code{atmega165}, @code{atmega165a}, @code{atmega165p}, @code{atmega165pa}, @code{atmega168}, @code{atmega168a}, @code{atmega168p}, @code{atmega168pa}, @code{atmega168pb}, @code{atmega169}, @code{atmega169a}, @code{atmega169p}, @code{atmega169pa}, @code{atmega32}, @code{atmega32a}, @code{atmega32c1}, @code{atmega32hvb}, @code{atmega32hvbrevb}, @code{atmega32m1}, @code{atmega32u4}, @code{atmega32u6}, @code{atmega323}, @code{atmega324a}, @code{atmega324p}, @code{atmega324pa}, @code{atmega324pb}, @code{atmega325}, @code{atmega325a}, @code{atmega325p}, @code{atmega325pa}, @code{atmega328}, @code{atmega328p}, @code{atmega328pb}, @code{atmega329}, @code{atmega329a}, @code{atmega329p}, @code{atmega329pa}, @code{atmega3250}, @code{atmega3250a}, @code{atmega3250p}, @code{atmega3250pa}, @code{atmega3290}, @code{atmega3290a}, @code{atmega3290p}, @code{atmega3290pa}, @code{atmega406}, @code{atmega64}, @code{atmega64a}, @code{atmega64c1}, @code{atmega64hve}, @code{atmega64hve2}, @code{atmega64m1}, @code{atmega64rfr2}, @code{atmega640}, @code{atmega644}, @code{atmega644a}, @code{atmega644p}, @code{atmega644pa}, @code{atmega644rfr2}, @code{atmega645}, @code{atmega645a}, @code{atmega645p}, @code{atmega649}, @code{atmega649a}, @code{atmega649p}, @code{atmega6450}, @code{atmega6450a}, @code{atmega6450p}, @code{atmega6490}, @code{atmega6490a}, @code{atmega6490p}, @code{ata5795}, @code{ata5790}, @code{ata5790n}, @code{ata5791}, @code{ata6613c}, @code{ata6614q}, @code{ata5782}, @code{ata5831}, @code{ata8210}, @code{ata8510}, @code{ata5702m322}, @code{at90pwm161}, @code{at90pwm216}, @code{at90pwm316}, @code{at90can32}, @code{at90can64}, @code{at90scr100}, @code{at90usb646}, @code{at90usb647}, @code{at94k}, @code{m3000}.
@item avr51
``Enhanced'' devices with 128@tie{}KiB of program memory.
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 6c56988..be05777 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2353,6 +2353,24 @@ features are supported by GCC.
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 __RECIPROCAL_MATH__
+This macro is defined if @option{-freciprocal-math} is used, or enabled
+by another option such as @option{-ffast-math} or by default.
+
+@item __NO_SIGNED_ZEROS__
+This macro is defined if @option{-fno-signed-zeros} is used, or enabled
+by another option such as @option{-ffast-math} or by default.
+
+@item __NO_TRAPPING_MATH__
+This macro is defined if @option{-fno-trapping-math} is used.
+
+@item __ASSOCIATIVE_MATH__
+This macro is defined if @option{-fassociative-math} is used, or enabled
+by another option such as @option{-ffast-math} or by default.
+
+@item __ROUNDING_MATH__
+This macro is defined if @option{-frounding-math} is used.
+
@item __GNUC_EXECUTION_CHARSET_NAME
@itemx __GNUC_WIDE_EXECUTION_CHARSET_NAME
These macros are defined to expand to a narrow string literal of
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f4f6121..2b18155 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1071,9 +1071,10 @@ systems where @code{__float128} is supported. The @code{_Float32}
type is supported on all systems supporting IEEE binary32; the
@code{_Float64} and @code{_Float32x} types are supported on all systems
supporting IEEE binary64. The @code{_Float16} type is supported on AArch64
-systems by default, and on ARM systems when the IEEE format for 16-bit
-floating-point types is selected with @option{-mfp16-format=ieee}.
-GCC does not currently support @code{_Float128x} on any systems.
+systems by default, on ARM systems when the IEEE format for 16-bit
+floating-point types is selected with @option{-mfp16-format=ieee} and,
+for both C and C++, on x86 systems with SSE2 enabled. GCC does not currently
+support @code{_Float128x} on any systems.
On the i386, x86_64, IA-64, and HP-UX targets, you can declare complex
types using the corresponding internal complex type, @code{XCmode} for
@@ -1097,11 +1098,15 @@ typedef _Complex float __attribute__((mode(IC))) _Complex_ibm128;
@section Half-Precision Floating Point
@cindex half-precision floating point
@cindex @code{__fp16} data type
+@cindex @code{__Float16} data type
On ARM and AArch64 targets, GCC supports half-precision (16-bit) floating
point via the @code{__fp16} type defined in the ARM C Language Extensions.
On ARM systems, you must enable this type explicitly with the
@option{-mfp16-format} command-line option in order to use it.
+On x86 targets with SSE2 enabled, GCC supports half-precision (16-bit)
+floating point via the @code{_Float16} type. For C++, x86 provides a builtin
+type named @code{_Float16} which contains same data format as C.
ARM targets support two incompatible representations for half-precision
floating-point values. You must choose one of the representations and
@@ -1145,6 +1150,21 @@ calls.
It is recommended that portable code use the @code{_Float16} type defined
by ISO/IEC TS 18661-3:2015. @xref{Floating Types}.
+On x86 targets with SSE2 enabled, without @option{-mavx512fp16},
+all operations will be emulated by software emulation and the @code{float}
+instructions. The default behavior for @code{FLT_EVAL_METHOD} is to keep the
+intermediate result of the operation as 32-bit precision. This may lead to
+inconsistent behavior between software emulation and AVX512-FP16 instructions.
+Using @option{-fexcess-precision=16} will force round back after each operation.
+
+Using @option{-mavx512fp16} will generate AVX512-FP16 instructions instead of
+software emulation. The default behavior of @code{FLT_EVAL_METHOD} is to round
+after each operation. The same is true with @option{-fexcess-precision=standard}
+and @option{-mfpmath=sse}. If there is no @option{-mfpmath=sse},
+@option{-fexcess-precision=standard} alone does the same thing as before,
+It is useful for code that does not have @code{_Float16} and runs on the x87
+FPU.
+
@node Decimal Float
@section Decimal Floating Types
@cindex decimal floating types
@@ -1380,7 +1400,7 @@ As an extension, GNU C supports named address spaces as
defined in the N1275 draft of ISO/IEC DTR 18037. Support for named
address spaces in GCC will evolve as the draft technical report
changes. Calling conventions for any target might also change. At
-present, only the AVR, M32C, RL78, and x86 targets support
+present, only the AVR, M32C, PRU, RL78, and x86 targets support
address spaces other than the generic address space.
Address space identifiers may be used exactly like any other C type
@@ -1560,6 +1580,23 @@ order to access memory beyond the first 64@tie{}Ki bytes. If
@code{__far} is used with the M32CM or M32C CPU variants, it has no
effect.
+@subsection PRU Named Address Spaces
+@cindex @code{__regio_symbol} PRU Named Address Spaces
+
+On the PRU target, variables qualified with @code{__regio_symbol} are
+aliases used to access the special I/O CPU registers. They must be
+declared as @code{extern} because such variables will not be allocated in
+any data memory. They must also be marked as @code{volatile}, and can
+only be 32-bit integer types. The only names those variables can have
+are @code{__R30} and @code{__R31}, representing respectively the
+@code{R30} and @code{R31} special I/O CPU registers. Hence the following
+example is the only valid usage of @code{__regio_symbol}:
+
+@smallexample
+extern volatile __regio_symbol uint32_t __R30;
+extern volatile __regio_symbol uint32_t __R31;
+@end smallexample
+
@subsection RL78 Named Address Spaces
@cindex @code{__far} RL78 Named Address Spaces
@@ -2860,6 +2897,19 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
The message attached to the attribute is affected by the setting of
the @option{-fmessage-length} option.
+@item unavailable
+@itemx unavailable (@var{msg})
+@cindex @code{unavailable} function attribute
+The @code{unavailable} attribute results in an error if the function
+is used anywhere in the source file. This is useful when identifying
+functions that have been removed from a particular variation of an
+interface. Other than emitting an error rather than a warning, the
+@code{unavailable} attribute behaves in the same manner as
+@code{deprecated}.
+
+The @code{unavailable} attribute can also be used for variables and
+types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
+
@item error ("@var{message}")
@itemx warning ("@var{message}")
@cindex @code{error} function attribute
@@ -3608,7 +3658,10 @@ take function pointer arguments.
@cindex @code{optimize} function attribute
The @code{optimize} attribute is used to specify that a function is to
be compiled with different optimization options than specified on the
-command line. Valid arguments are constant non-negative integers and
+command line. The optimize attribute arguments of a function behave
+behave as if appended to the command-line.
+
+Valid arguments are constant non-negative integers and
strings. Each numeric argument specifies an optimization @var{level}.
Each @var{string} argument consists of one or more comma-separated
substrings. Each substring that begins with the letter @code{O} refers
@@ -3812,7 +3865,8 @@ This attribute prevents stack protection code for the function.
Multiple target back ends implement the @code{target} attribute
to specify that a function is to
be compiled with different target options than specified on the
-command line. One or more strings can be provided as arguments.
+command line. The original target command-line options are ignored.
+One or more strings can be provided as arguments.
Each string consists of one or more comma-separated suffixes to
the @code{-m} prefix jointly forming the name of a machine-dependent
option. @xref{Submodel Options,,Machine-Dependent Options}.
@@ -7300,10 +7354,10 @@ The @code{warn_if_not_aligned} attribute can also be used for types
The @code{alloc_size} variable attribute may be applied to the declaration
of a pointer to a function that returns a pointer and takes at least one
argument of an integer type. It indicates that the returned pointer points
-to an object whose size is given by the function argument at @var{position-1},
+to an object whose size is given by the function argument at @var{position},
or by the product of the arguments at @var{position-1} and @var{position-2}.
Meaningful sizes are positive values less than @code{PTRDIFF_MAX}. Other
-sizes are disagnosed when detected. GCC uses this information to improve
+sizes are diagnosed when detected. GCC uses this information to improve
the results of @code{__builtin_object_size}.
For instance, the following declarations
@@ -7397,6 +7451,22 @@ types (@pxref{Common Function Attributes},
The message attached to the attribute is affected by the setting of
the @option{-fmessage-length} option.
+@item unavailable
+@itemx unavailable (@var{msg})
+@cindex @code{unavailable} variable attribute
+The @code{unavailable} attribute indicates that the variable so marked
+is not available, if it is used anywhere in the source file. It behaves
+in the same manner as the @code{deprecated} attribute except that the
+compiler will emit an error rather than a warning.
+
+It is expected that items marked as @code{deprecated} will eventually be
+withdrawn from interfaces, and then become unavailable. This attribute
+allows for marking them appropriately.
+
+The @code{unavailable} attribute can also be used for functions and
+types (@pxref{Common Function Attributes},
+@pxref{Common Type Attributes}).
+
@item mode (@var{mode})
@cindex @code{mode} variable attribute
This attribute specifies the data type for the declaration---whichever
@@ -7555,6 +7625,22 @@ will be placed in new, unique sections.
This additional functionality requires Binutils version 2.36 or later.
+@item uninitialized
+@cindex @code{uninitialized} variable attribute
+This attribute, attached to a variable with automatic storage, means that
+the variable should not be automatically initialized by the compiler when
+the option @code{-ftrivial-auto-var-init} presents.
+
+With the option @code{-ftrivial-auto-var-init}, all the automatic variables
+that do not have explicit initializers will be initialized by the compiler.
+These additional compiler initializations might incur run-time overhead,
+sometimes dramatically. This attribute can be used to mark some variables
+to be excluded from such automatical initialization in order to reduce runtime
+overhead.
+
+This attribute has no effect when the option @code{-ftrivial-auto-var-init}
+does not present.
+
@item vector_size (@var{bytes})
@cindex @code{vector_size} variable attribute
This attribute specifies the vector size for the type of the declared
@@ -8209,6 +8295,7 @@ attributes.
* Common Type Attributes::
* ARC Type Attributes::
* ARM Type Attributes::
+* BPF Type Attributes::
* MeP Type Attributes::
* PowerPC Type Attributes::
* x86 Type Attributes::
@@ -8456,6 +8543,17 @@ variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.)
The message attached to the attribute is affected by the setting of
the @option{-fmessage-length} option.
+@item unavailable
+@itemx unavailable (@var{msg})
+@cindex @code{unavailable} type attribute
+The @code{unavailable} attribute behaves in the same manner as the
+@code{deprecated} one, but emits an error rather than a warning. It is
+used to indicate that a (perhaps previously @code{deprecated}) type is
+no longer usable.
+
+The @code{unavailable} attribute can also be used for functions and
+variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.)
+
@item designated_init
@cindex @code{designated_init} type attribute
This attribute may only be applied to structure types. It indicates
@@ -8772,6 +8870,17 @@ virtual table for @code{C} is not exported. (You can use
@code{__attribute__} instead of @code{__declspec} if you prefer, but
most Symbian OS code uses @code{__declspec}.)
+@node BPF Type Attributes
+@subsection BPF Type Attributes
+
+@cindex @code{preserve_access_index} type attribute, BPF
+BPF Compile Once - Run Everywhere (CO-RE) support. When attached to a
+@code{struct} or @code{union} type definition, indicates that CO-RE
+relocation information should be generated for any access to a variable
+of that type. The behavior is equivalent to the programmer manually
+wrapping every such access with @code{__builtin_preserve_access_index}.
+
+
@node MeP Type Attributes
@subsection MeP Type Attributes
@@ -8933,6 +9042,12 @@ of the deprecated enumerator, to enable users to easily find further
information about why the enumerator is deprecated, or what they should
do instead. Note that the warnings only occurs for uses.
+@item unavailable
+@cindex @code{unavailable} enumerator attribute
+The @code{unavailable} attribute results in an error if the enumerator
+is used anywhere in the source file. In other respects it behaves in the
+same manner as the @code{deprecated} attribute.
+
@end table
@node Statement Attributes
@@ -15403,6 +15518,10 @@ Load 16-bits from the @code{struct sk_buff} packet data pointed by the register
Load 32-bits from the @code{struct sk_buff} packet data pointed by the register @code{%r6} and return it.
@end deftypefn
+@deftypefn {Built-in Function} void * __builtin_preserve_access_index (@var{expr})
+BPF Compile Once-Run Everywhere (CO-RE) support. Instruct GCC to generate CO-RE relocation records for any accesses to aggregate data structures (struct, union, array types) in @var{expr}. This builtin is otherwise transparent, the return value is whatever @var{expr} evaluates to. It is also overloaded: @var{expr} may be of any type (not necessarily a pointer), the return type is the same. Has no effect if @code{-mco-re} is not in effect (either specified or implied).
+@end deftypefn
+
@node FR-V Built-in Functions
@subsection FR-V Built-in Functions
@@ -21639,6 +21758,18 @@ AMD Family 19h CPU.
@item znver3
AMD Family 19h Zen version 3.
+
+@item x86-64
+Baseline x86-64 microarchitecture level (as defined in x86-64 psABI).
+
+@item x86-64-v2
+x86-64-v2 microarchitecture level.
+
+@item x86-64-v3
+x86-64-v3 microarchitecture level.
+
+@item x86-64-v4
+x86-64-v4 microarchitecture level.
@end table
Here is an example:
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 9b4d7a4..cdfbfdd 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -322,6 +322,9 @@ Necessary in some circumstances, optional in others. See the
host/target specific instructions for your platform for the exact
requirements.
+Note binutils 2.35 or newer is required for LTO to work correctly
+with GNU libtool that includes doing a bootstrap with LTO enabled.
+
@item gzip version 1.2.4 (or later) or
@itemx bzip2 version 1.0.2 (or later)
@@ -1074,11 +1077,6 @@ but for the linker.
Same as @uref{#with-as,,@option{--with-as}}
but for the debug linker (only used on Darwin platforms so far).
-@item --with-stabs
-Specify that stabs debugging
-information should be used instead of whatever format the host normally
-uses. Normally GCC uses the same debug format as the host system.
-
@item --with-tls=@var{dialect}
Specify the default TLS dialect, for systems were there is a choice.
For ARM targets, possible values for @var{dialect} are @code{gnu} or
@@ -3442,8 +3440,8 @@ Microsoft Windows:
@item
The @uref{https://sourceware.org/cygwin/,,Cygwin} project;
@item
-The @uref{http://www.mingw.org/,,MinGW} and
-@uref{http://mingw-w64.org/doku.php,,mingw-w64} projects.
+The @uref{https://osdn.net/projects/mingw/,,MinGW} and
+@uref{http://www.mingw-w64.org/,,mingw-w64} projects.
@end itemize
@item
@@ -5098,6 +5096,10 @@ GCC will build with and support only MinGW runtime 3.12 and later.
Earlier versions of headers are incompatible with the new default semantics
of @code{extern inline} in @code{-std=c99} and @code{-std=gnu99} modes.
+To support emitting DWARF debugging info you need to use GNU binutils
+version 2.16 or above containing support for the @code{.secrel32}
+assembler pseudo-op.
+
@html
<hr />
@end html
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 185b7d2..3663c2b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -212,7 +212,8 @@ in the following sections.
-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
+-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
+-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
@@ -286,7 +287,7 @@ Objective-C and Objective-C++ Dialects}.
-Walloca -Walloca-larger-than=@var{byte-size} @gol
-Wno-aggressive-loop-optimizations @gol
-Warith-conversion @gol
--Warray-bounds -Warray-bounds=@var{n} @gol
+-Warray-bounds -Warray-bounds=@var{n} -Warray-compare @gol
-Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
-Wno-attribute-warning -Wbool-compare -Wbool-operation @gol
-Wno-builtin-declaration-mismatch @gol
@@ -536,9 +537,9 @@ Objective-C and Objective-C++ Dialects}.
-ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol
-ftree-reassoc -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra @gol
-ftree-switch-conversion -ftree-tail-merge @gol
--ftree-ter -ftree-vectorize -ftree-vrp -funconstrained-commons @gol
--funit-at-a-time -funroll-all-loops -funroll-loops @gol
--funsafe-math-optimizations -funswitch-loops @gol
+-ftree-ter -ftree-vectorize -ftree-vrp -ftrivial-auto-var-init @gol
+-funconstrained-commons -funit-at-a-time -funroll-all-loops @gol
+-funroll-loops -funsafe-math-optimizations -funswitch-loops @gol
-fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol
-fweb -fwhole-program -fwpa -fuse-linker-plugin -fzero-call-used-regs @gol
--param @var{name}=@var{value}
@@ -867,7 +868,8 @@ Objective-C and Objective-C++ Dialects}.
@emph{eBPF Options}
@gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
--mframe-limit=@var{bytes} -mxbpf}
+-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
+-mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
@emph{FR30 Options}
@gccoptlist{-msmall-model -mno-lsim}
@@ -1358,6 +1360,7 @@ See RS/6000 and PowerPC Options.
-mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid @gol
-mrdseed -msgx -mavx512vp2intersect -mserialize -mtsxldtrk@gol
-mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset -mavxvnni@gol
+-mavx512fp16 @gol
-mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
-mkl -mwidekl @gol
@@ -2614,7 +2617,7 @@ under @code{OFFLOAD_TARGET_NAMES}.
@item -foffload-options=@var{options}
@itemx -foffload-options=@var{target-triplet-list}=@var{options}
-@opindex foffload
+@opindex foffload-options
@cindex Offloading options
@cindex OpenACC offloading options
@cindex OpenMP offloading options
@@ -3086,7 +3089,7 @@ errors if these functions are not inlined everywhere they are called.
@itemx -fno-modules-ts
@opindex fmodules-ts
@opindex fno-modules-ts
-Enable support for C++20 modules (@xref{C++ Modules}). The
+Enable support for C++20 modules (@pxref{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.
@@ -5523,6 +5526,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
@gccoptlist{-Waddress @gol
-Warray-bounds=1 @r{(only with} @option{-O2}@r{)} @gol
+-Warray-compare @gol
-Warray-parameter=2 @r{(C and Objective-C only)} @gol
-Wbool-compare @gol
-Wbool-operation @gol
@@ -6420,10 +6424,12 @@ int b[2][2] = @{ @{ 0, 1 @}, @{ 2, 3 @} @};
This warning is enabled by @option{-Wall}.
-@item -Wmissing-include-dirs @r{(C, C++, Objective-C and Objective-C++ only)}
+@item -Wmissing-include-dirs @r{(C, C++, Objective-C, Objective-C++ and Fortran only)}
@opindex Wmissing-include-dirs
@opindex Wno-missing-include-dirs
-Warn if a user-supplied include directory does not exist.
+Warn if a user-supplied include directory does not exist. This opions is disabled
+by default for C, C++, Objective-C and Objective-C++. For Fortran, it is partially
+enabled by default by warning for -I and -J, only.
@item -Wno-missing-profile
@opindex Wmissing-profile
@@ -7492,6 +7498,20 @@ pointers. This warning level may give a larger number of
false positives and is deactivated by default.
@end table
+@item -Warray-compare
+@opindex Warray-compare
+@opindex Wno-array-compare
+Warn about equality and relational comparisons between two operands of array
+type. This comparison was deprecated in C++20. For example:
+
+@smallexample
+int arr1[5];
+int arr2[5];
+bool same = arr1 == arr2;
+@end smallexample
+
+@option{-Warray-compare} is enabled by @option{-Wall}.
+
@item -Warray-parameter
@itemx -Warray-parameter=@var{n}
@opindex Wno-array-parameter
@@ -8510,17 +8530,43 @@ by @option{-Wall}.
@item -Waddress
@opindex Waddress
@opindex Wno-address
-Warn about suspicious uses of memory addresses. These include using
-the address of a function in a conditional expression, such as
-@code{void func(void); if (func)}, and comparisons against the memory
-address of a string literal, such as @code{if (x == "abc")}. Such
-uses typically indicate a programmer error: the address of a function
-always evaluates to true, so their use in a conditional usually
-indicate that the programmer forgot the parentheses in a function
-call; and comparisons against string literals result in unspecified
-behavior and are not portable in C, so they usually indicate that the
-programmer intended to use @code{strcmp}. This warning is enabled by
-@option{-Wall}.
+Warn about suspicious uses of address expressions. These include comparing
+the address of a function or a declared object to the null pointer constant
+such as in
+@smallexample
+void f (void);
+void g (void)
+@{
+ if (!func) // warning: expression evaluates to false
+ abort ();
+@}
+@end smallexample
+comparisons of a pointer to a string literal, such as in
+@smallexample
+void f (const char *x)
+@{
+ if (x == "abc") // warning: expression evaluates to false
+ puts ("equal");
+@}
+@end smallexample
+and tests of the results of pointer addition or subtraction for equality
+to null, such as in
+@smallexample
+void f (const int *p, int i)
+@{
+ return p + i == NULL;
+@}
+@end smallexample
+Such uses typically indicate a programmer error: the address of most
+functions and objects necessarily evaluates to true (the exception are
+weak symbols), so their use in a conditional might indicate missing
+parentheses in a function call or a missing dereference in an array
+expression. The subset of the warning for object pointers can be
+suppressed by casting the pointer operand to an integer type such
+as @code{inptr_t} or @code{uinptr_t}.
+Comparisons against string literals result in unspecified behavior
+and are not portable, and suggest the intent was to call @code{strcmp}.
+@option{-Waddress} warning is enabled by @option{-Wall}.
@item -Wno-address-of-packed-member
@opindex Waddress-of-packed-member
@@ -8715,6 +8761,28 @@ s x = @{ @};
This warning is included in @option{-Wextra}. To get other @option{-Wextra}
warnings without this one, use @option{-Wextra -Wno-missing-field-initializers}.
+@item -Wno-missing-requires
+@opindex Wmissing-requires
+@opindex Wno-missing-requires
+
+By default, the compiler warns about a concept-id appearing as a C++20 simple-requirement:
+
+@smallexample
+bool satisfied = requires @{ C<T> @};
+@end smallexample
+
+Here @samp{satisfied} will be true if @samp{C<T>} is a valid
+expression, which it is for all T. Presumably the user meant to write
+
+@smallexample
+bool satisfied = requires @{ requires C<T> @};
+@end smallexample
+
+so @samp{satisfied} is only true if concept @samp{C} is satisfied for
+type @samp{T}.
+
+This warning can be disabled with @option{-Wno-missing-requires}.
+
@item -Wno-multichar
@opindex Wno-multichar
@opindex Wmultichar
@@ -8957,6 +9025,43 @@ that has already been done in the current function. Therefore,
seemingly insignificant changes in the source program can cause the
warnings produced by @option{-Winline} to appear or disappear.
+@item -Winterference-size
+@opindex Winterference-size
+Warn about use of C++17 @code{std::hardware_destructive_interference_size}
+without specifying its value with @option{--param destructive-interference-size}.
+Also warn about questionable values for that option.
+
+This variable is intended to be used for controlling class layout, to
+avoid false sharing in concurrent code:
+
+@smallexample
+struct independent_fields @{
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
+@};
+@end smallexample
+
+Here @samp{one} and @samp{two} are intended to be far enough apart
+that stores to one won't require accesses to the other to reload the
+cache line.
+
+By default, @option{--param destructive-interference-size} and
+@option{--param constructive-interference-size} are set based on the
+current @option{-mtune} option, typically to the L1 cache line size
+for the particular target CPU, sometimes to a range if tuning for a
+generic target. So all translation units that depend on ABI
+compatibility for the use of these variables must be compiled with
+the same @option{-mtune} (or @option{-mcpu}).
+
+If ABI stability is important, such as if the use is in a header for a
+library, you should probably not use the hardware interference size
+variables at all. Alternatively, you can force a particular value
+with @option{--param}.
+
+If you are confident that your use of the variable does not affect ABI
+outside a single build of your project, you can turn off the warning
+with @option{-Wno-interference-size}.
+
@item -Wint-in-bool-context
@opindex Wint-in-bool-context
@opindex Wno-int-in-bool-context
@@ -10311,9 +10416,12 @@ also turns on the following optimization flags:
-fstrict-aliasing @gol
-fthread-jumps @gol
-ftree-builtin-call-dce @gol
+-ftree-loop-vectorize @gol
-ftree-pre @gol
+-ftree-slp-vectorize @gol
-ftree-switch-conversion -ftree-tail-merge @gol
--ftree-vrp}
+-ftree-vrp @gol
+-fvect-cost-model=very-cheap}
Please note the warning under @option{-fgcse} about
invoking @option{-O2} on programs that use computed gotos.
@@ -10333,11 +10441,8 @@ by @option{-O2} and also turns on the following optimization flags:
-fsplit-loops @gol
-fsplit-paths @gol
-ftree-loop-distribution @gol
--ftree-loop-vectorize @gol
-ftree-partial-pre @gol
--ftree-slp-vectorize @gol
-funswitch-loops @gol
--fvect-cost-model @gol
-fvect-cost-model=dynamic @gol
-fversion-loops-for-strides}
@@ -10681,7 +10786,7 @@ so, the first branch is redirected to either the destination of the
second branch or a point immediately following it, depending on whether
the condition is known to be true or false.
-Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+Enabled at levels @option{-O1}, @option{-O2}, @option{-O3}, @option{-Os}.
@item -fsplit-wide-types
@opindex fsplit-wide-types
@@ -11783,6 +11888,41 @@ Perform basic block vectorization on trees. This flag is enabled by default at
@option{-O3} and by @option{-ftree-vectorize}, @option{-fprofile-use},
and @option{-fauto-profile}.
+@item -ftrivial-auto-var-init=@var{choice}
+@opindex ftrivial-auto-var-init
+Initialize automatic variables with either a pattern or with zeroes to increase
+the security and predictability of a program by preventing uninitialized memory
+disclosure and use.
+GCC still considers an automatic variable that doesn't have an explicit
+initializer as uninitialized, -Wuninitialized will still report warning messages
+on such automatic variables.
+With this option, GCC will also initialize any padding of automatic variables
+that have structure or union types to zeroes.
+
+The three values of @var{choice} are:
+
+@itemize @bullet
+@item
+@samp{uninitialized} doesn't initialize any automatic variables.
+This is C and C++'s default.
+
+@item
+@samp{pattern} Initialize automatic variables with values which will likely
+transform logic bugs into crashes down the line, are easily recognized in a
+crash dump and without being values that programmers can rely on for useful
+program semantics.
+The current value is byte-repeatable pattern with byte "0xFE".
+The values used for pattern initialization might be changed in the future.
+
+@item
+@samp{zero} Initialize automatic variables with zeroes.
+@end itemize
+
+The default is @samp{uninitialized}.
+
+You can control this behavior for a specific variable by using the variable
+attribute @code{uninitialized} (@pxref{Variable Attributes}).
+
@item -fvect-cost-model=@var{model}
@opindex fvect-cost-model
Alter the cost model used for vectorization. The @var{model} argument
@@ -13842,6 +13982,34 @@ prefetch hints can be issued for any constant stride.
This setting is only useful for strides that are known and constant.
+@item destructive-interference-size
+@item constructive-interference-size
+The values for the C++17 variables
+@code{std::hardware_destructive_interference_size} and
+@code{std::hardware_constructive_interference_size}. The destructive
+interference size is the minimum recommended offset between two
+independent concurrently-accessed objects; the constructive
+interference size is the maximum recommended size of contiguous memory
+accessed together. Typically both will be the size of an L1 cache
+line for the target, in bytes. For a generic target covering a range of L1
+cache line sizes, typically the constructive interference size will be
+the small end of the range and the destructive size will be the large
+end.
+
+The destructive interference size is intended to be used for layout,
+and thus has ABI impact. The default value is not expected to be
+stable, and on some targets varies with @option{-mtune}, so use of
+this variable in a context where ABI stability is important, such as
+the public interface of a library, is strongly discouraged; if it is
+used in that context, users can stabilize the value using this
+option.
+
+The constructive interference size is less sensitive, as it is
+typically only used in a @samp{static_assert} to make sure that a type
+fits within a cache line.
+
+See also @option{-Winterference-size}.
+
@item loop-interchange-max-num-stmts
The maximum number of stmts in a loop to be interchanged.
@@ -14041,6 +14209,10 @@ Maximum depth of recursive cloning for self-recursive function.
Recursive cloning only when the probability of call being executed exceeds
the parameter.
+@item ipa-cp-recursive-freq-factor
+The number of times interprocedural copy propagation expects recursive
+functions to call themselves.
+
@item ipa-cp-recursion-penalty
Percentage penalty the recursive functions will receive when they
are evaluated for cloning.
@@ -14259,14 +14431,6 @@ Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit().
Maximum number of instructions to copy when duplicating blocks on a
finite state automaton jump thread path.
-@item max-fsm-thread-length
-Maximum number of basic blocks on a finite state automaton jump thread
-path.
-
-@item max-fsm-thread-paths
-Maximum number of new jump thread paths to create for a finite state
-automaton.
-
@item parloops-chunk-size
Chunk size of omp schedule for loops parallelized by parloops.
@@ -14300,6 +14464,9 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
@item evrp-mode
Specifies the mode Early VRP should operate in.
+@item evrp-switch-limit
+Specifies the maximum number of switch cases before EVRP ignores a switch.
+
@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.
@@ -14418,10 +14585,6 @@ The maximum depth of recursive inlining for non-inline functions.
Scale factor to apply to the number of statements in a threading path
when comparing to the number of (scaled) blocks.
-@item fsm-maximum-phi-arguments
-Maximum number of arguments a PHI may have before the FSM threader
-will not try to thread through its block.
-
@item uninit-control-dep-attempts
Maximum number of nested calls to search for control dependencies
during uninitialized variable analysis.
@@ -14674,6 +14837,10 @@ supports locking, the data files will be correctly updated. Unless
a strict ISO C dialect option is in effect, @code{fork} calls are
detected and correctly handled without double counting.
+Moreover, an object file can be recompiled multiple times
+and the corresponding @file{.gcda} file merges as long as
+the source file and the compiler options are unchanged.
+
@item
For profile-directed optimizations, compile the source files again with
the same optimization and code generation options plus
@@ -15039,7 +15206,8 @@ The option cannot be combined with @option{-fsanitize=thread}.
@opindex fsanitize=undefined
Enable UndefinedBehaviorSanitizer, a fast undefined behavior detector.
Various computations are instrumented to detect undefined behavior
-at runtime. Current suboptions are:
+at runtime. See @uref{https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html} for more details. The run-time behavior can be influenced using the
+@env{UBSAN_OPTIONS} environment variable. Current suboptions are:
@table @gcctabopt
@@ -15066,7 +15234,7 @@ ISO C90 and C99, etc.
@item -fsanitize=integer-divide-by-zero
@opindex fsanitize=integer-divide-by-zero
-Detect integer division by zero as well as @code{INT_MIN / -1} division.
+Detect integer division by zero.
@item -fsanitize=unreachable
@opindex fsanitize=unreachable
@@ -15098,7 +15266,8 @@ returning a value. This option works in C++ only.
@opindex fsanitize=signed-integer-overflow
This option enables signed integer overflow checking. We check that
the result of @code{+}, @code{*}, and both unary and binary @code{-}
-does not overflow in the signed arithmetics. Note, integer promotion
+does not overflow in the signed arithmetics. This also detects
+@code{INT_MIN / -1} signed division. Note, integer promotion
rules must be taken into account. That is, the following is not an
overflow:
@smallexample
@@ -16373,7 +16542,8 @@ Note that this requires platform-specific runtime support that does
not exist everywhere. Moreover, it only allows @emph{trapping}
instructions to throw exceptions, i.e.@: memory references or floating-point
instructions. It does not allow exceptions to be thrown from
-arbitrary signal handlers such as @code{SIGALRM}.
+arbitrary signal handlers such as @code{SIGALRM}. This enables
+@option{-fexceptions}.
@item -fdelete-dead-exceptions
@opindex fdelete-dead-exceptions
@@ -18406,6 +18576,8 @@ and the features that they enable by default:
@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.7-a} @tab Armv8.7-A @tab @samp{armv8.6-a}, @samp{+ls64}
+@item @samp{armv9-a} @tab Armv9-A @tab @samp{armv8.5-a}, @samp{+sve}, @samp{+sve2}
@item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r}
@end multitable
@@ -18449,7 +18621,8 @@ performance of the code. Permissible values for this option are:
@samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53},
@samp{cortex-a75.cortex-a55}, @samp{cortex-a76.cortex-a55},
-@samp{cortex-r82}, @samp{cortex-x1}, @samp{native}.
+@samp{cortex-r82}, @samp{cortex-x1}, @samp{cortex-x2},
+@samp{cortex-a510}, @samp{cortex-a710}, @samp{native}.
The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53},
@@ -18692,6 +18865,9 @@ 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 ls64
+Enable the 64-byte atomic load and store instructions for accelerators.
+This option is enabled by default for @option{-march=armv8.7-a}.
@item flagm
Enable the Flag Manipulation instructions Extension.
@item pauth
@@ -19817,6 +19993,7 @@ Permissible names are:
@samp{armv8.4-a},
@samp{armv8.5-a},
@samp{armv8.6-a},
+@samp{armv9-a},
@samp{armv7-r},
@samp{armv8-r},
@samp{armv6-m}, @samp{armv6s-m},
@@ -20306,8 +20483,8 @@ Permissible names are: @samp{arm7tdmi}, @samp{arm7tdmi-s}, @samp{arm710t},
@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-a78c},
-@samp{ares}, @samp{cortex-r4}, @samp{cortex-r4f},
-@samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52},
+@samp{ares}, @samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-r5},
+@samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52}, @samp{cortex-r52plus},
@samp{cortex-m0}, @samp{cortex-m0plus}, @samp{cortex-m1}, @samp{cortex-m3},
@samp{cortex-m4}, @samp{cortex-m7}, @samp{cortex-m23}, @samp{cortex-m33},
@samp{cortex-m35p}, @samp{cortex-m55}, @samp{cortex-x1},
@@ -20391,8 +20568,8 @@ Disables the floating-point and SIMD instructions on
@item +nofp.dp
Disables the double-precision component of the floating-point instructions
-on @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52} and
-@samp{cortex-m7}.
+on @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52},
+@samp{cortex-r52plus} and @samp{cortex-m7}.
@item +nosimd
Disables the SIMD (but not floating-point) instructions on
@@ -22571,6 +22748,53 @@ Generate code for a big-endian target.
@opindex mlittle-endian
Generate code for a little-endian target. This is the default.
+@item -mjmpext
+@opindex mjmpext
+Enable generation of extra conditional-branch instructions.
+Enabled for CPU v2 and above.
+
+@item -mjmp32
+@opindex mjmp32
+Enable 32-bit jump instructions. Enabled for CPU v3 and above.
+
+@item -malu32
+@opindex malu32
+Enable 32-bit ALU instructions. Enabled for CPU v3 and above.
+
+@item -mcpu=@var{version}
+@opindex mcpu
+This specifies which version of the eBPF ISA to target. Newer versions
+may not be supported by all kernels. The default is @samp{v3}.
+
+Supported values for @var{version} are:
+
+@table @samp
+@item v1
+The first stable eBPF ISA with no special features or extensions.
+
+@item v2
+Supports the jump extensions, as in @option{-mjmpext}.
+
+@item v3
+All features of v2, plus:
+@itemize @minus
+@item 32-bit jump operations, as in @option{-mjmp32}
+@item 32-bit ALU operations, as in @option{-malu32}
+@end itemize
+
+@end table
+
+@item -mco-re
+@opindex mco-re
+Enable BPF Compile Once - Run Everywhere (CO-RE) support. Requires and
+is implied by @option{-gbtf}.
+
+@item -mno-co-re
+@opindex mno-co-re
+Disable BPF Compile Once - Run Everywhere (CO-RE) support. BPF CO-RE
+support is enabled by default when generating BTF debug information for
+the BPF target.
+
@item -mxbpf
Generate code for an expanded version of BPF, which relaxes some of
the restrictions imposed by the BPF architecture:
@@ -29449,10 +29673,11 @@ so @option{-mno-lra} needs to be passed to get old Reload.
Set the instruction set, register set, and instruction scheduling parameters
for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{hypersparc},
-@samp{leon}, @samp{leon3}, @samp{leon3v7}, @samp{sparclite}, @samp{f930},
-@samp{f934}, @samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9},
-@samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2},
-@samp{niagara3}, @samp{niagara4}, @samp{niagara7} and @samp{m8}.
+@samp{leon}, @samp{leon3}, @samp{leon3v7}, @samp{leon5}, @samp{sparclite},
+@samp{f930}, @samp{f934}, @samp{sparclite86x}, @samp{sparclet}, @samp{tsc701},
+@samp{v9}, @samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara},
+@samp{niagara2}, @samp{niagara3}, @samp{niagara4}, @samp{niagara7} and
+@samp{m8}.
Native Solaris and GNU/Linux toolchains also support the value @samp{native},
which selects the best architecture option for the host processor.
@@ -29471,7 +29696,7 @@ implementations.
cypress, leon3v7
@item v8
-supersparc, hypersparc, leon, leon3
+supersparc, hypersparc, leon, leon3, leon5
@item sparclite
f930, f934, sparclite86x
@@ -29538,7 +29763,7 @@ The same values for @option{-mcpu=@var{cpu_type}} can be used for
@option{-mtune=@var{cpu_type}}, but the only useful values are those
that select a particular CPU implementation. Those are
@samp{cypress}, @samp{supersparc}, @samp{hypersparc}, @samp{leon},
-@samp{leon3}, @samp{leon3v7}, @samp{f930}, @samp{f934},
+@samp{leon3}, @samp{leon3v7}, @samp{leon5}, @samp{f930}, @samp{f934},
@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc},
@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3},
@samp{niagara4}, @samp{niagara7} and @samp{m8}. With native Solaris
@@ -31214,6 +31439,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mavx512bf16
@opindex mavx512bf16
@need 200
+@itemx -mavx512fp16
+@opindex mavx512fp16
+@need 200
@itemx -mgfni
@opindex mgfni
@need 200
@@ -31292,9 +31520,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, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI 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, AVX512FP16
+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
@@ -33333,7 +33561,7 @@ 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
+use a non-standard suffix (@pxref{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
@@ -33395,8 +33623,8 @@ 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.
+For details of the @option{-fmodule-mapper} family of options,
+@pxref{C++ Module Mapper}.
@menu
* C++ Module Mapper:: Module Mapper
@@ -33613,8 +33841,8 @@ 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.
+@code{SOURCE_DATE_EPOCH}. For further details
+@pxref{Environment Variables}.
A set of related CMIs may be copied, provided the relative pathnames
are preserved.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index f8047ae..41f1850 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5776,11 +5776,13 @@ multiplication.
@item @samp{smul@var{m}3_highpart}
Perform a signed multiplication of operands 1 and 2, which have mode
@var{m}, and store the most significant half of the product in operand 0.
-The least significant half of the product is discarded.
+The least significant half of the product is discarded. This may be
+represented in RTL using a @code{smul_highpart} RTX expression.
@cindex @code{umul@var{m}3_highpart} instruction pattern
@item @samp{umul@var{m}3_highpart}
-Similar, but the multiplication is unsigned.
+Similar, but the multiplication is unsigned. This may be represented
+in RTL using an @code{umul_highpart} RTX expression.
@cindex @code{madd@var{m}@var{n}4} instruction pattern
@item @samp{madd@var{m}@var{n}4}
@@ -6695,6 +6697,13 @@ operand 2 is the character to search for (normally zero),
and operand 3 is a constant describing the known alignment
of the beginning of the string.
+@cindex @code{rawmemchr@var{m}} instruction pattern
+@item @samp{rawmemchr@var{m}}
+Scan memory referred to by operand 1 for the first occurrence of operand 2.
+Operand 1 is a @code{mem} and operand 2 a @code{const_int} of mode @var{m}.
+Operand 0 is the result, i.e., a pointer to the first occurrence of operand 2
+in the memory block given by operand 1.
+
@cindex @code{float@var{m}@var{n}2} instruction pattern
@item @samp{float@var{m}@var{n}2}
Convert signed integer operand 1 (valid for fixed point mode @var{m}) to
@@ -11074,6 +11083,8 @@ The syntax is as follows:
(define_c_enum "@var{name}" [
@var{value0}
@var{value1}
+ (@var{value32} 32)
+ @var{value33}
@dots{}
@var{valuen}
])
@@ -11086,6 +11097,8 @@ in @file{insn-constants.h}:
enum @var{name} @{
@var{value0} = 0,
@var{value1} = 1,
+ @var{value32} = 32,
+ @var{value33} = 33,
@dots{}
@var{valuen} = @var{n}
@};
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index e1e76a9..2058997 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -2524,7 +2524,19 @@ not be the same.
For unsigned widening multiplication, use the same idiom, but with
@code{zero_extend} instead of @code{sign_extend}.
+@findex smul_highpart
+@findex umul_highpart
+@cindex high-part multiplication
+@cindex multiplication high part
+@item (smul_highpart:@var{m} @var{x} @var{y})
+@itemx (umul_highpart:@var{m} @var{x} @var{y})
+Represents the high-part multiplication of @var{x} and @var{y} carried
+out in machine mode @var{m}. @code{smul_highpart} returns the high part
+of a signed multiplication, @code{umul_highpart} returns the high part
+of an unsigned multiplication.
+
@findex fma
+@cindex fused multiply-add
@item (fma:@var{m} @var{x} @var{y} @var{z})
Represents the @code{fma}, @code{fmaf}, and @code{fmal} builtin
functions, which compute @samp{@var{x} * @var{y} + @var{z}}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index bbdbf5f..9649695 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1009,20 +1009,26 @@ Do not define this macro if it would never modify @var{m}.
Return a value, with the same meaning as the C99 macro
@code{FLT_EVAL_METHOD} that describes which excess precision should be
applied. @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT},
-@code{EXCESS_PRECISION_TYPE_FAST}, or
-@code{EXCESS_PRECISION_TYPE_STANDARD}. For
+@code{EXCESS_PRECISION_TYPE_FAST},
+@code{EXCESS_PRECISION_TYPE_STANDARD}, or
+@code{EXCESS_PRECISION_TYPE_FLOAT16}. For
@code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which
precision and range operations will be implictly evaluated in regardless
of the excess precision explicitly added. For
-@code{EXCESS_PRECISION_TYPE_STANDARD} and
+@code{EXCESS_PRECISION_TYPE_STANDARD},
+@code{EXCESS_PRECISION_TYPE_FLOAT16}, and
@code{EXCESS_PRECISION_TYPE_FAST}, the target should return the
explicit excess precision that should be added depending on the
value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.
Note that unpredictable explicit excess precision does not make sense,
so a target should never return @code{FLT_EVAL_METHOD_UNPREDICTABLE}
-when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD} or
+when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD},
+@code{EXCESS_PRECISION_TYPE_FLOAT16} or
@code{EXCESS_PRECISION_TYPE_FAST}.
@end deftypefn
+Return a value, with the same meaning as the C99 macro
+@code{FLT_EVAL_METHOD} that describes which excess precision should be
+applied.
@c hook-end
@deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
@@ -6815,7 +6821,7 @@ private variables at OpenACC device-lowering time using the
@end deftypefn
@c hook-end
-@deftypefn {Target Hook} tree TARGET_GOACC_CREATE_WORKER_BROADCAST_RECORD (tree @var{rec}, bool @var{sender}, const char *@var{name})
+@deftypefn {Target Hook} tree TARGET_GOACC_CREATE_WORKER_BROADCAST_RECORD (tree @var{rec}, bool @var{sender}, const char *@var{name}, unsigned HOST_WIDE_INT @var{offset})
Create a record used to propagate local-variable state from an active
worker to other workers. A possible implementation might adjust the type
of REC to place the new variable in shared GPU memory.
@@ -6824,6 +6830,13 @@ Presence of this target hook indicates that middle end neutering/broadcasting
be used.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_GOACC_SHARED_MEM_LAYOUT (unsigned HOST_WIDE_INT *@var{}, unsigned HOST_WIDE_INT *@var{}, @var{int[]}, unsigned @var{HOST_WIDE_INT[]}, unsigned @var{HOST_WIDE_INT[]})
+Lay out a fixed shared-memory region on the target. The LO and HI
+arguments should be set to a range of addresses that can be used for worker
+broadcasting. The dimensions, reduction size and gang-private size
+arguments are for the current offload region.
+@end deftypefn
+
@node Anchored Addresses
@section Anchored Addresses
@cindex anchored addresses
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index fdf16b9..86352dc 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -929,6 +929,9 @@ Do not define this macro if it would never modify @var{m}.
@end defmac
@hook TARGET_C_EXCESS_PRECISION
+Return a value, with the same meaning as the C99 macro
+@code{FLT_EVAL_METHOD} that describes which excess precision should be
+applied.
@hook TARGET_PROMOTE_FUNCTION_MODE
@@ -4225,6 +4228,8 @@ address; but often a machine-dependent strategy can generate better code.
@hook TARGET_GOACC_CREATE_WORKER_BROADCAST_RECORD
+@hook TARGET_GOACC_SHARED_MEM_LAYOUT
+
@node Anchored Addresses
@section Anchored Addresses
@cindex anchored addresses
diff --git a/gcc/doc/trouble.texi b/gcc/doc/trouble.texi
index 40c51ae..8b34be4 100644
--- a/gcc/doc/trouble.texi
+++ b/gcc/doc/trouble.texi
@@ -865,10 +865,11 @@ objects behave unspecified when being assigned. For example:
@smallexample
struct Base@{
char *name;
- Base(char *n) : name(strdup(n))@{@}
+ Base(const char *n) : name(strdup(n))@{@}
Base& operator= (const Base& other)@{
free (name);
name = strdup (other.name);
+ return *this;
@}
@};
@@ -901,8 +902,8 @@ inside @samp{func} in the example).
G++ implements the ``intuitive'' algorithm for copy-assignment: assign all
direct bases, then assign all members. In that algorithm, the virtual
base subobject can be encountered more than once. In the example, copying
-proceeds in the following order: @samp{val}, @samp{name} (via
-@code{strdup}), @samp{bval}, and @samp{name} again.
+proceeds in the following order: @samp{name} (via @code{strdup}),
+@samp{val}, @samp{name} again, and @samp{bval}.
If application code relies on copy-assignment, a user-defined
copy-assignment operator removes any uncertainties. With such an
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 8169daf..e6ead5d 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -145,6 +145,7 @@ static const kv_pair<dump_flags_t> dump_options[] =
{"missed", MSG_MISSED_OPTIMIZATION},
{"note", MSG_NOTE},
{"optall", MSG_ALL_KINDS},
+ {"threading", TDF_THREADING},
{"all", dump_flags_t (TDF_ALL_VALUES
& ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
| TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 892bfc9..7622675 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -74,7 +74,7 @@ enum dump_kind
the DUMP_OPTIONS array in dumpfile.c. The TDF_* flags coexist with
MSG_* flags (for -fopt-info) and the bit values must be chosen to
allow that. */
-enum dump_flag
+enum dump_flag : uint32_t
{
/* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK. */
TDF_NONE = 0,
@@ -140,23 +140,26 @@ enum dump_flag
/* Dump SCEV details. */
TDF_SCEV = (1 << 19),
- /* Dump in GIMPLE FE syntax */
+ /* Dump in GIMPLE FE syntax. */
TDF_GIMPLE = (1 << 20),
/* Dump folding details. */
TDF_FOLDING = (1 << 21),
+ /* Dumping for range path solver. */
+ TDF_THREADING = (1 << 22),
+
/* MSG_* flags for expressing the kinds of message to
be emitted by -fopt-info. */
/* -fopt-info optimized sources. */
- MSG_OPTIMIZED_LOCATIONS = (1 << 22),
+ MSG_OPTIMIZED_LOCATIONS = (1 << 23),
/* Missed opportunities. */
- MSG_MISSED_OPTIMIZATION = (1 << 23),
+ MSG_MISSED_OPTIMIZATION = (1 << 24),
/* General optimization info. */
- MSG_NOTE = (1 << 24),
+ MSG_NOTE = (1 << 25),
/* Mask for selecting MSG_-kind flags. */
MSG_ALL_KINDS = (MSG_OPTIMIZED_LOCATIONS
@@ -175,30 +178,33 @@ enum dump_flag
sub-option of -fopt-info to show the internal messages. */
/* Implicitly supplied for messages at the top-level dump scope. */
- MSG_PRIORITY_USER_FACING = (1 << 25),
+ MSG_PRIORITY_USER_FACING = (1 << 26),
/* Implicitly supplied for messages within nested dump scopes. */
- MSG_PRIORITY_INTERNALS = (1 << 26),
+ MSG_PRIORITY_INTERNALS = (1 << 27),
/* Supplied when an opt_problem generated in a nested scope is re-emitted
at the top-level. We want to default to showing these in -fopt-info
output, but to *not* show them in dump files, as the message would be
shown twice, messing up "scan-tree-dump-times" in DejaGnu tests. */
- MSG_PRIORITY_REEMITTED = (1 << 27),
+ MSG_PRIORITY_REEMITTED = (1 << 28),
/* Mask for selecting MSG_PRIORITY_* flags. */
MSG_ALL_PRIORITIES = (MSG_PRIORITY_USER_FACING
| MSG_PRIORITY_INTERNALS
| MSG_PRIORITY_REEMITTED),
+ /* All -fdump- flags. */
+ TDF_ALL_VALUES = (1 << 29) - 1,
+
/* Dumping for -fcompare-debug. */
- TDF_COMPARE_DEBUG = (1 << 28),
+ TDF_COMPARE_DEBUG = (1 << 29),
- /* For error. */
- TDF_ERROR = (1 << 26),
+ /* Dump a GIMPLE value which means wrapping certain things with _Literal. */
+ TDF_GIMPLE_VAL = (1 << 30),
- /* All values. */
- TDF_ALL_VALUES = (1 << 29) - 1
+ /* For error. */
+ TDF_ERROR = ((uint32_t)1 << 31),
};
/* Dump flags type. */
@@ -208,32 +214,36 @@ typedef enum dump_flag dump_flags_t;
static inline dump_flags_t
operator| (dump_flags_t lhs, dump_flags_t rhs)
{
- return (dump_flags_t)((int)lhs | (int)rhs);
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline dump_flags_t
operator& (dump_flags_t lhs, dump_flags_t rhs)
{
- return (dump_flags_t)((int)lhs & (int)rhs);
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline dump_flags_t
operator~ (dump_flags_t flags)
{
- return (dump_flags_t)~((int)flags);
+ return (dump_flags_t)~((std::underlying_type<dump_flags_t>::type)flags);
}
static inline dump_flags_t &
operator|= (dump_flags_t &lhs, dump_flags_t rhs)
{
- lhs = (dump_flags_t)((int)lhs | (int)rhs);
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
static inline dump_flags_t &
operator&= (dump_flags_t &lhs, dump_flags_t rhs)
{
- lhs = (dump_flags_t)((int)lhs & (int)rhs);
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
@@ -272,13 +282,15 @@ typedef enum optgroup_flag optgroup_flags_t;
static inline optgroup_flags_t
operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
{
- return (optgroup_flags_t)((int)lhs | (int)rhs);
+ return (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
}
static inline optgroup_flags_t &
operator|= (optgroup_flags_t &lhs, optgroup_flags_t rhs)
{
- lhs = (optgroup_flags_t)((int)lhs | (int)rhs);
+ lhs = (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
return lhs;
}
diff --git a/gcc/dwarf2ctf.c b/gcc/dwarf2ctf.c
index 5e8a725..edd3281 100644
--- a/gcc/dwarf2ctf.c
+++ b/gcc/dwarf2ctf.c
@@ -33,7 +33,7 @@ static ctf_id_t
gen_ctf_type (ctf_container_ref, dw_die_ref);
/* All the DIE structures we handle come from the DWARF information
- generated by GCC. However, there are two situations where we need
+ generated by GCC. However, there are three situations where we need
to create our own created DIE structures because GCC doesn't
provide them.
@@ -368,7 +368,7 @@ gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type)
/* DWARF array types pretend C supports multi-dimensional arrays.
So for the type int[N][M], the array type DIE contains two
- subrange_type children, the first iwth upper bound N-1 and the
+ subrange_type children, the first with upper bound N-1 and the
second with upper bound M-1.
CTF, on the other hand, just encodes each array type in its own
@@ -917,6 +917,27 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
return type_id;
}
+/* Prepare for output and write out the CTF debug information. */
+
+static void
+ctf_debug_finalize (const char *filename, bool btf)
+{
+ if (btf)
+ {
+ btf_output (filename);
+ btf_finalize ();
+ }
+
+ else
+ {
+ /* Emit the collected CTF information. */
+ ctf_output (filename);
+
+ /* Reset the CTF state. */
+ ctf_finalize ();
+ }
+}
+
bool
ctf_do_die (dw_die_ref die)
{
@@ -966,24 +987,31 @@ ctf_debug_init_postprocess (bool btf)
btf_init_postprocess ();
}
-/* Prepare for output and write out the CTF debug information. */
+/* Early finish CTF/BTF debug info. */
void
-ctf_debug_finalize (const char *filename, bool btf)
+ctf_debug_early_finish (const char * filename)
{
- if (btf)
- {
- btf_output (filename);
- btf_finalize ();
- }
+ /* Emit CTF debug info early always. */
+ if (ctf_debug_info_level > CTFINFO_LEVEL_NONE
+ /* Emit BTF debug info early if CO-RE relocations are not
+ required. */
+ || (btf_debuginfo_p () && !btf_with_core_debuginfo_p ()))
+ ctf_debug_finalize (filename, btf_debuginfo_p ());
+}
- else
- {
- /* Emit the collected CTF information. */
- ctf_output (filename);
+/* Finish CTF/BTF debug info emission. */
- /* Reset the CTF state. */
- ctf_finalize ();
+void
+ctf_debug_finish (const char * filename)
+{
+ /* Emit BTF debug info here when CO-RE relocations need to be generated.
+ BTF with CO-RE relocations needs to be generated when CO-RE is in effect
+ for the BPF target. */
+ if (btf_with_core_debuginfo_p ())
+ {
+ gcc_assert (btf_debuginfo_p ());
+ ctf_debug_finalize (filename, btf_debuginfo_p ());
}
}
diff --git a/gcc/dwarf2ctf.h b/gcc/dwarf2ctf.h
index a3cf567..9edbde0 100644
--- a/gcc/dwarf2ctf.h
+++ b/gcc/dwarf2ctf.h
@@ -24,13 +24,15 @@ along with GCC; see the file COPYING3. If not see
#define GCC_DWARF2CTF_H 1
#include "dwarf2out.h"
+#include "flags.h"
/* Debug Format Interface. Used in dwarf2out.c. */
extern void ctf_debug_init (void);
extern void ctf_debug_init_postprocess (bool);
extern bool ctf_do_die (dw_die_ref);
-extern void ctf_debug_finalize (const char *, bool);
+extern void ctf_debug_early_finish (const char *);
+extern void ctf_debug_finish (const char *);
/* Wrappers for CTF/BTF to fetch information from GCC DWARF DIE. Used in
ctfc.c.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 07a479f..20f2c5d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3740,7 +3740,6 @@ static bool remove_AT (dw_die_ref, enum dwarf_attribute);
static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
static void add_child_die (dw_die_ref, dw_die_ref);
static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
-static dw_die_ref lookup_type_die (tree);
static dw_die_ref strip_naming_typedef (tree, dw_die_ref);
static dw_die_ref lookup_type_die_strip_naming_typedef (tree);
static void equate_type_number_to_die (tree, dw_die_ref);
@@ -5838,7 +5837,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
/* Return the DIE associated with the given type specifier. */
-static inline dw_die_ref
+dw_die_ref
lookup_type_die (tree type)
{
dw_die_ref die = TYPE_SYMTAB_DIE (type);
@@ -13542,6 +13541,7 @@ modified_type_die (tree type, int cv_quals, bool reverse,
tree qualified_type;
tree name, low, high;
dw_die_ref mod_scope;
+ struct array_descr_info info;
/* Only these cv-qualifiers are currently handled. */
const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC |
@@ -13786,6 +13786,13 @@ modified_type_die (tree type, int cv_quals, bool reverse,
}
}
}
+ else if (code == ARRAY_TYPE
+ || (lang_hooks.types.get_array_descr_info
+ && lang_hooks.types.get_array_descr_info (type, &info)))
+ {
+ gen_type_die (type, context_die);
+ return lookup_type_die (type);
+ }
else if (code == INTEGER_TYPE
&& TREE_TYPE (type) != NULL_TREE
&& subrange_type_for_debug_p (type, &low, &high))
@@ -13822,8 +13829,7 @@ modified_type_die (tree type, int cv_quals, bool reverse,
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (code == FUNCTION_TYPE || code == METHOD_TYPE)
{
/* For function/method types, can't just use type_main_variant here,
because that can have different ref-qualifiers for C++,
@@ -13836,13 +13842,12 @@ modified_type_die (tree type, int cv_quals, bool reverse,
return lookup_type_die (t);
return lookup_type_die (type);
}
- else if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
- return lookup_type_die (type_main_variant (type));
- else
- /* Vectors have the debugging information in the type,
- not the main variant. */
+ /* Vectors have the debugging information in the type,
+ not the main variant. */
+ else if (code == VECTOR_TYPE)
return lookup_type_die (type);
+ else
+ return lookup_type_die (type_main_variant (type));
}
/* Builtin types don't have a DECL_ORIGINAL_TYPE. For those,
@@ -16804,6 +16809,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
case CONST_FIXED:
case CLRSB:
case CLOBBER:
+ case SMUL_HIGHPART:
+ case UMUL_HIGHPART:
break;
case CONST_STRING:
@@ -30289,6 +30296,40 @@ mark_base_types (dw_loc_descr_ref loc)
}
}
+/* Stripped-down variant of resolve_addr, mark DW_TAG_base_type nodes
+ referenced from typed stack ops and count how often they are used. */
+
+static void
+mark_base_types (dw_die_ref die)
+{
+ dw_die_ref c;
+ dw_attr_node *a;
+ dw_loc_list_ref *curr;
+ unsigned ix;
+
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ switch (AT_class (a))
+ {
+ case dw_val_class_loc_list:
+ curr = AT_loc_list_ptr (a);
+ while (*curr)
+ {
+ mark_base_types ((*curr)->expr);
+ curr = &(*curr)->dw_loc_next;
+ }
+ break;
+
+ case dw_val_class_loc:
+ mark_base_types (AT_loc (a));
+ break;
+
+ default:
+ break;
+ }
+
+ FOR_EACH_CHILD (die, c, mark_base_types (c));
+}
+
/* Comparison function for sorting marked base types. */
static int
@@ -31913,6 +31954,11 @@ dwarf2out_finish (const char *filename)
unsigned char checksum[16];
char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES];
+ /* Generate CTF/BTF debug info. */
+ if ((ctf_debug_info_level > CTFINFO_LEVEL_NONE
+ || btf_debuginfo_p ()) && lang_GNU_C ())
+ ctf_debug_finish (filename);
+
/* Skip emitting DWARF if not required. */
if (!dwarf_debuginfo_p ())
return;
@@ -32691,6 +32737,7 @@ ctf_debug_do_cu (dw_die_ref die)
static void
dwarf2out_early_finish (const char *filename)
{
+ comdat_type_node *ctnode;
set_early_dwarf s;
char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -32770,8 +32817,7 @@ dwarf2out_early_finish (const char *filename)
/* For each new comdat type unit, copy declarations for incomplete
types to make the new unit self-contained (i.e., no direct
references to the main compile unit). */
- for (comdat_type_node *ctnode = comdat_type_list;
- ctnode != NULL; ctnode = ctnode->next)
+ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
copy_decls_for_unworthy_types (ctnode->root_die);
copy_decls_for_unworthy_types (comp_unit_die ());
@@ -32786,8 +32832,7 @@ dwarf2out_early_finish (const char *filename)
note_variable_value (comp_unit_die ());
for (limbo_die_node *node = cu_die_list; node; node = node->next)
note_variable_value (node->die);
- for (comdat_type_node *ctnode = comdat_type_list; ctnode != NULL;
- ctnode = ctnode->next)
+ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
note_variable_value (ctnode->root_die);
for (limbo_die_node *node = limbo_die_list; node; node = node->next)
note_variable_value (node->die);
@@ -32817,8 +32862,8 @@ dwarf2out_early_finish (const char *filename)
ctf_debug_do_cu (node->die);
/* Post process the debug data in the CTF container if necessary. */
ctf_debug_init_postprocess (btf_debuginfo_p ());
- /* Emit CTF/BTF debug info. */
- ctf_debug_finalize (filename, btf_debuginfo_p ());
+
+ ctf_debug_early_finish (filename);
}
/* Do not generate DWARF assembler now when not producing LTO bytecode. */
@@ -32839,13 +32884,17 @@ dwarf2out_early_finish (const char *filename)
location related output removed and some LTO specific changes.
Some refactoring might make both smaller and easier to match up. */
+ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
+ mark_base_types (ctnode->root_die);
+ mark_base_types (comp_unit_die ());
+ move_marked_base_types ();
+
/* Traverse the DIE's and add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die ());
for (limbo_die_node *node = limbo_die_list; node; node = node->next)
add_sibling_attributes (node->die);
- for (comdat_type_node *ctnode = comdat_type_list;
- ctnode != NULL; ctnode = ctnode->next)
+ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
add_sibling_attributes (ctnode->root_die);
/* AIX Assembler inserts the length, so adjust the reference to match the
@@ -32875,8 +32924,7 @@ dwarf2out_early_finish (const char *filename)
output_comp_unit (node->die, 0, NULL);
hash_table<comdat_type_hasher> comdat_type_table (100);
- for (comdat_type_node *ctnode = comdat_type_list;
- ctnode != NULL; ctnode = ctnode->next)
+ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
{
comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index b2152a5..312a990 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -417,6 +417,7 @@ extern dw_die_ref new_die_raw (enum dwarf_tag);
extern dw_die_ref base_type_die (tree, bool);
extern dw_die_ref lookup_decl_die (tree);
+extern dw_die_ref lookup_type_die (tree);
extern dw_die_ref dw_get_die_child (dw_die_ref);
extern dw_die_ref dw_get_die_sib (dw_die_ref);
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index ff3b444..e6158f2 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1625,19 +1625,22 @@ gen_highpart (machine_mode mode, rtx x)
gcc_assert (known_le (msize, (unsigned int) UNITS_PER_WORD)
|| known_eq (msize, GET_MODE_UNIT_SIZE (GET_MODE (x))));
- result = simplify_gen_subreg (mode, x, GET_MODE (x),
- subreg_highpart_offset (mode, GET_MODE (x)));
- gcc_assert (result);
-
- /* simplify_gen_subreg is not guaranteed to return a valid operand for
- the target if we have a MEM. gen_highpart must return a valid operand,
- emitting code if necessary to do so. */
- if (MEM_P (result))
+ /* gen_lowpart_common handles a lot of special cases due to needing to handle
+ paradoxical subregs; it only calls simplify_gen_subreg when certain that
+ it will produce something meaningful. The only case we need to handle
+ specially here is MEM. */
+ if (MEM_P (x))
{
- result = validize_mem (result);
- gcc_assert (result);
+ poly_int64 offset = subreg_highpart_offset (mode, GET_MODE (x));
+ return adjust_address (x, mode, offset);
}
+ result = simplify_gen_subreg (mode, x, GET_MODE (x),
+ subreg_highpart_offset (mode, GET_MODE (x)));
+ /* Since we handle MEM directly above, we should never get a MEM back
+ from simplify_gen_subreg. */
+ gcc_assert (result && !MEM_P (result));
+
return result;
}
diff --git a/gcc/explow.c b/gcc/explow.c
index b6da277..a35423f 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "diagnostic-core.h"
#include "stor-layout.h"
+#include "langhooks.h"
#include "except.h"
#include "dojump.h"
#include "explow.h"
@@ -1641,8 +1642,14 @@ set_stack_check_libfunc (const char *libfunc_name)
{
gcc_assert (stack_check_libfunc == NULL_RTX);
stack_check_libfunc = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
+ tree ptype
+ = Pmode == ptr_mode
+ ? ptr_type_node
+ : lang_hooks.types.type_for_mode (Pmode, 1);
+ tree ftype
+ = build_function_type_list (void_type_node, ptype, NULL_TREE);
tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier (libfunc_name), void_type_node);
+ get_identifier (libfunc_name), ftype);
DECL_EXTERNAL (decl) = 1;
SET_SYMBOL_REF_DECL (stack_check_libfunc, decl);
}
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3143f38..bbdd0e7 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -806,7 +806,8 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
}
}
else if (constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, &regnum)
- && multiple_p (bitsize, regsize * BITS_PER_UNIT))
+ && multiple_p (bitsize, regsize * BITS_PER_UNIT)
+ && known_ge (GET_MODE_BITSIZE (GET_MODE (op0)), bitsize))
{
sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
regnum * regsize);
@@ -1571,14 +1572,16 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
if (GET_MODE (target) != ext_mode)
{
+ rtx temp;
/* Don't use LHS paradoxical subreg if explicit truncation is needed
between the mode of the extraction (word_mode) and the target
mode. Instead, create a temporary and use convert_move to set
the target. */
if (REG_P (target)
- && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode))
+ && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode)
+ && (temp = gen_lowpart_if_possible (ext_mode, target)))
{
- target = gen_lowpart (ext_mode, target);
+ target = temp;
if (partial_subreg_p (GET_MODE (spec_target), ext_mode))
spec_target_subreg = target;
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 096c031..eb33643 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -236,8 +236,27 @@ convert_move (rtx to, rtx from, int unsignedp)
>= GET_MODE_PRECISION (to_int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp))
{
+ scalar_int_mode int_orig_mode;
+ scalar_int_mode int_inner_mode;
+ machine_mode orig_mode = GET_MODE (from);
+
from = gen_lowpart (to_int_mode, SUBREG_REG (from));
from_mode = to_int_mode;
+
+ /* Preserve SUBREG_PROMOTED_VAR_P if the new mode is wider than
+ the original mode, but narrower than the inner mode. */
+ if (GET_CODE (from) == SUBREG
+ && is_a <scalar_int_mode> (orig_mode, &int_orig_mode)
+ && GET_MODE_PRECISION (to_int_mode)
+ > GET_MODE_PRECISION (int_orig_mode)
+ && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (from)),
+ &int_inner_mode)
+ && GET_MODE_PRECISION (int_inner_mode)
+ > GET_MODE_PRECISION (to_int_mode))
+ {
+ SUBREG_PROMOTED_VAR_P (from) = 1;
+ SUBREG_PROMOTED_SET (from, unsignedp);
+ }
}
gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to));
@@ -688,7 +707,27 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
&& (GET_MODE_PRECISION (subreg_promoted_mode (x))
>= GET_MODE_PRECISION (int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
- x = gen_lowpart (int_mode, SUBREG_REG (x));
+ {
+ scalar_int_mode int_orig_mode;
+ scalar_int_mode int_inner_mode;
+ machine_mode orig_mode = GET_MODE (x);
+ x = gen_lowpart (int_mode, SUBREG_REG (x));
+
+ /* Preserve SUBREG_PROMOTED_VAR_P if the new mode is wider than
+ the original mode, but narrower than the inner mode. */
+ if (GET_CODE (x) == SUBREG
+ && is_a <scalar_int_mode> (orig_mode, &int_orig_mode)
+ && GET_MODE_PRECISION (int_mode)
+ > GET_MODE_PRECISION (int_orig_mode)
+ && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)),
+ &int_inner_mode)
+ && GET_MODE_PRECISION (int_inner_mode)
+ > GET_MODE_PRECISION (int_mode))
+ {
+ SUBREG_PROMOTED_VAR_P (x) = 1;
+ SUBREG_PROMOTED_SET (x, unsignedp);
+ }
+ }
if (GET_MODE (x) != VOIDmode)
oldmode = GET_MODE (x);
@@ -5266,7 +5305,7 @@ get_bit_range (poly_uint64_pod *bitstart, poly_uint64_pod *bitend, tree exp,
has non-BLKmode. DECL_RTL must not be a MEM; if
DECL_RTL was not set yet, return false. */
-static inline bool
+bool
non_mem_decl_p (tree base)
{
if (!DECL_P (base)
@@ -5283,7 +5322,7 @@ non_mem_decl_p (tree base)
/* Returns true if REF refers to an object that does not
reside in memory and has non-BLKmode. */
-static inline bool
+bool
mem_ref_refers_to_non_mem_p (tree ref)
{
tree base;
diff --git a/gcc/expr.h b/gcc/expr.h
index 94a85b4..890ec19 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -346,4 +346,7 @@ extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
/* Return an rtx for the size in bytes of the value of an expr. */
extern rtx expr_size (tree);
+extern bool mem_ref_refers_to_non_mem_p (tree);
+extern bool non_mem_decl_p (tree);
+
#endif /* GCC_EXPR_H */
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 4fb1cb4..ae0b216 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -31,7 +31,8 @@ enum debug_info_type
DINFO_TYPE_VMS = 4, /* VMS debug info. */
DINFO_TYPE_CTF = 5, /* CTF debug info. */
DINFO_TYPE_BTF = 6, /* BTF debug info. */
- DINFO_TYPE_MAX = DINFO_TYPE_BTF /* Marker only. */
+ DINFO_TYPE_BTF_WITH_CORE = 7, /* BTF debug info with CO-RE relocations. */
+ DINFO_TYPE_MAX = DINFO_TYPE_BTF_WITH_CORE /* Marker only. */
};
#define NO_DEBUG (0U)
@@ -47,6 +48,9 @@ enum debug_info_type
#define CTF_DEBUG (1U << DINFO_TYPE_CTF)
/* Write BTF debug info (using btfout.c). */
#define BTF_DEBUG (1U << DINFO_TYPE_BTF)
+/* Write BTF debug info for BPF CO-RE usecase (using btfout.c). */
+#define BTF_WITH_CORE_DEBUG (1U << DINFO_TYPE_BTF_WITH_CORE)
+
/* Note: Adding new definitions to handle -combination- of debug formats,
like VMS_AND_DWARF2_DEBUG is not recommended. This definition remains
here for historical reasons. */
@@ -187,10 +191,6 @@ enum ira_region
IRA_REGION_ONE,
IRA_REGION_ALL,
IRA_REGION_MIXED,
- /* This value means that there were no options -fira-region on the
- command line and that we should choose a value depending on the
- used -O option. */
- IRA_REGION_AUTODETECT
};
/* The options for excess precision. */
@@ -198,7 +198,8 @@ enum excess_precision
{
EXCESS_PRECISION_DEFAULT,
EXCESS_PRECISION_FAST,
- EXCESS_PRECISION_STANDARD
+ EXCESS_PRECISION_STANDARD,
+ EXCESS_PRECISION_FLOAT16
};
/* The options for which values of FLT_EVAL_METHOD are permissible. */
@@ -276,6 +277,13 @@ enum vect_cost_model {
VECT_COST_MODEL_DEFAULT = 1
};
+/* Automatic variable initialization type. */
+enum auto_init_type {
+ AUTO_INIT_UNINITIALIZED = 0,
+ AUTO_INIT_PATTERN = 1,
+ AUTO_INIT_ZERO = 2
+};
+
/* Different instrumentation modes. */
enum sanitize_code {
/* AddressSanitizer. */
diff --git a/gcc/flags.h b/gcc/flags.h
index afedef0..af61bcd 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -44,6 +44,10 @@ const char * debug_set_names (uint32_t w_symbols);
extern bool btf_debuginfo_p ();
+/* Return true iff BTF with CO-RE debug info is enabled. */
+
+extern bool btf_with_core_debuginfo_p ();
+
/* Return true iff CTF debug info is enabled. */
extern bool ctf_debuginfo_p ();
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9679f35..2d3d33a 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,419 @@
+2021-10-15 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102685
+ * decl.c (match_clist_expr): Set rank/shape of clist initializer
+ to match LHS.
+ * resolve.c (resolve_structure_cons): In a structure constructor,
+ compare shapes of array components against declared shape.
+
+2021-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102717
+ * simplify.c (gfc_simplify_reshape): Replace assert by error
+ message for negative elements in SHAPE array.
+
+2021-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102716
+ * check.c (gfc_check_shape): Reorder checks so that invalid KIND
+ arguments can be detected.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * gfortran.h (enum gfc_statement): Add ST_OMP_DECLARE_VARIANT.
+ (enum gfc_omp_trait_property_kind): New.
+ (struct gfc_omp_trait_property): New.
+ (gfc_get_omp_trait_property): New macro.
+ (struct gfc_omp_selector): New.
+ (gfc_get_omp_selector): New macro.
+ (struct gfc_omp_set_selector): New.
+ (gfc_get_omp_set_selector): New macro.
+ (struct gfc_omp_declare_variant): New.
+ (gfc_get_omp_declare_variant): New macro.
+ (struct gfc_namespace): Add omp_declare_variant field.
+ (gfc_free_omp_declare_variant_list): New prototype.
+ * match.h (gfc_match_omp_declare_variant): New prototype.
+ * openmp.c (gfc_free_omp_trait_property_list): New.
+ (gfc_free_omp_selector_list): New.
+ (gfc_free_omp_set_selector_list): New.
+ (gfc_free_omp_declare_variant_list): New.
+ (gfc_match_omp_clauses): Add extra optional argument. Handle end of
+ clauses for context selectors.
+ (omp_construct_selectors, omp_device_selectors,
+ omp_implementation_selectors, omp_user_selectors): New.
+ (gfc_match_omp_context_selector): New.
+ (gfc_match_omp_context_selector_specification): New.
+ (gfc_match_omp_declare_variant): New.
+ * parse.c: Include tree-core.h and omp-general.h.
+ (decode_omp_directive): Handle 'declare variant'.
+ (case_omp_decl): Include ST_OMP_DECLARE_VARIANT.
+ (gfc_ascii_statement): Handle ST_OMP_DECLARE_VARIANT.
+ (gfc_parse_file): Initialize omp_requires_mask.
+ * symbol.c (gfc_free_namespace): Call
+ gfc_free_omp_declare_variant_list.
+ * trans-decl.c (gfc_get_extern_function_decl): Call
+ gfc_trans_omp_declare_variant.
+ (gfc_create_function_decl): Call gfc_trans_omp_declare_variant.
+ * trans-openmp.c (gfc_trans_omp_declare_variant): New.
+ * trans-stmt.h (gfc_trans_omp_declare_variant): New prototype.
+
+2021-10-13 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Handle ancestor modifier,
+ avoid ICE for GFC_OMP_ATOMIC_SWAP.
+ * gfortran.h (gfc_omp_clauses): Change 'anecestor' into a bitfield.
+
+2021-10-12 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102541
+ * check.c (gfc_check_present): Handle optional CLASS.
+ * interface.c (gfc_compare_actual_formal): Likewise.
+ * trans-array.c (gfc_trans_g77_array): Likewise.
+ * trans-decl.c (gfc_build_dummy_array_decl): Likewise.
+ * trans-types.c (gfc_sym_type): Likewise.
+ * primary.c (gfc_variable_attr): Fixes for dummy and
+ pointer when 'class%_data' is passed.
+ * trans-expr.c (set_dtype_for_unallocated, gfc_conv_procedure_call):
+ For assumed-rank dummy, fix setting rank for dealloc/notassoc actual
+ and setting ubound to -1 for assumed-size actuals.
+
+2021-10-10 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/99348
+ PR fortran/102521
+ * decl.c (add_init_expr_to_sym): Extend initialization of
+ parameter arrays from scalars to handle derived types.
+
+2021-10-09 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/65454
+ * module.c (read_module): Handle old and new-style relational
+ operators when used in USE module, ONLY: OPERATOR(op).
+
+2021-10-08 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/54753
+ * interface.c (gfc_compare_actual_formal): Add diagnostic
+ for F2018:C839. Refactor shared code and fix bugs with class
+ array info lookup, and extend similar diagnostic from PR94110
+ to also cover class types.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * options.c (gfc_post_options): Use new macro
+ OPTION_SET_P.
+
+2021-10-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * resolve.c (resolve_values): Only show
+ deprecated warning if attr.referenced.
+
+2021-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/54753
+ * resolve.c (can_generate_init, resolve_fl_variable_derived,
+ resolve_symbol): Only do initialization with intent(out) if not
+ inside of an interface block.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * array.c: Remove an unnecessary test.
+ * trans-array.c: Same.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.h (gfc_omp_clauses): Add order_reproducible bitfield.
+ * dump-parse-tree.c (show_omp_clauses): Print REPRODUCIBLE: for it.
+ * openmp.c (gfc_match_omp_clauses): Set order_reproducible for
+ explicit reproducible: modifier.
+ * trans-openmp.c (gfc_trans_omp_clauses): Set
+ OMP_CLAUSE_ORDER_REPRODUCIBLE for order_reproducible.
+ (gfc_split_omp_clauses): Also copy order_reproducible.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * simplify.c (simplify_size): Resolve expressions used in array
+ specifications so that SIZE can be simplified.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ * expr.c: The correct reference to Fortran standard is: F2018:10.1.12.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/71703
+ PR fortran/84007
+ * trans-intrinsic.c (gfc_conv_same_type_as): Fix handling
+ of UNLIMITED_POLY.
+ * trans.h (gfc_vtpr_hash_get): Renamed prototype to ...
+ (gfc_vptr_hash_get): ... this to match function name.
+
+2021-09-29 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102520
+ * array.c (expand_constructor): Do not dereference NULL pointer.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * trans-array.c (gfc_tree_array_size): New function to
+ find size inline (whole array or one dimension).
+ (array_parameter_size): Use it, take stmt_block as arg.
+ (gfc_conv_array_parameter): Update call.
+ * trans-array.h (gfc_tree_array_size): Add prototype.
+ * trans-decl.c (gfor_fndecl_size0, gfor_fndecl_size1): Remove
+ these global vars.
+ (gfc_build_intrinsic_function_decls): Remove their initialization.
+ * trans-expr.c (gfc_conv_procedure_call): Update
+ bounds of pointer/allocatable actual args to nonallocatable/nonpointer
+ dummies to be one based.
+ * trans-intrinsic.c (gfc_conv_intrinsic_shape): Fix case for
+ assumed rank with allocatable/pointer dummy.
+ (gfc_conv_intrinsic_size): Update to use inline function.
+ * trans.h (gfor_fndecl_size0, gfor_fndecl_size1): Remove var decl.
+
+2021-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/101334
+ * trans-intrinsic.c (gfc_conv_associated): Support assumed-rank
+ 'pointer' with scalar/array 'target' argument.
+
+2021-09-24 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * expr.c (is_non_constant_intrinsic): Check for intrinsics
+ excluded in constant expressions (F2018:10.1.2).
+ (gfc_is_constant_expr): Use that check.
+
+2021-09-24 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101333
+ * interface.c (compare_parameter): Enforce F2018 C711.
+
+2021-09-24 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * scanner.c (load_file): Return void, call (gfc_)fatal_error for
+ all errors.
+ (include_line, include_stmt, gfc_new_file): Remove exit call
+ for failed load_file run.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101320
+ * decl.c (gfc_verify_c_interop_param): Handle F2018 C1557,
+ aka TS29113 C516.
+
+2021-09-23 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/93834
+ * trans-intrinsic.c (gfc_conv_allocated): Cleanup. Handle
+ coindexed scalar coarrays.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101319
+ * interface.c (gfc_compare_actual_formal): Extend existing
+ assumed-type diagnostic to also check for argument with type
+ parameters.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101334
+ * check.c (gfc_check_associated): Allow an assumed-rank
+ array for the pointer argument.
+ * interface.c (compare_parameter): Also give rank mismatch
+ error on assumed-rank array.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ * trans-stmt.c (trans_associate_var): Check that result of
+ GFC_DECL_SAVED_DESCRIPTOR is not null before using it.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * cpp.c (gfc_cpp_register_include_paths, gfc_cpp_post_options):
+ Add new bool verbose_missing_dir_warn argument.
+ * cpp.h (gfc_cpp_post_options): Update prototype.
+ * f95-lang.c (gfc_init): Remove duplicated file-not found diag.
+ * gfortran.h (gfc_check_include_dirs): Takes bool
+ verbose_missing_dir_warn arg.
+ (gfc_new_file): Returns now void.
+ * options.c (gfc_post_options): Update to warn for -I and -J,
+ only, by default but for all when user requested.
+ * scanner.c (gfc_do_check_include_dir):
+ (gfc_do_check_include_dirs, gfc_check_include_dirs): Take bool
+ verbose warn arg and update to avoid printing the same message
+ twice or never.
+ (load_file): Fix indent.
+ (gfc_new_file): Return void and exit when load_file failed
+ as all other load_file users do.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ * trans-expr.c (gfc_simple_for_loop): New.
+ * trans.h (gfc_simple_for_loop): New prototype.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * cpp.c: Define GCC_C_COMMON_C for #include "options.h" to make
+ cpp_reason_option_codes available.
+ (gfc_cpp_register_include_paths): Make static, set pfile's
+ warn_missing_include_dirs and move before caller.
+ (gfc_cpp_init_cb): New, cb code moved from ...
+ (gfc_cpp_init_0): ... here.
+ (gfc_cpp_post_options): Call gfc_cpp_init_cb.
+ (cb_cpp_diagnostic_cpp_option): New. As implemented in c-family
+ to match CppReason flags to -W... names.
+ (cb_cpp_diagnostic): Use it to replace single special case.
+ * cpp.h (gfc_cpp_register_include_paths): Remove as now static.
+ * gfortran.h (gfc_check_include_dirs): New prototype.
+ (gfc_add_include_path): Add new bool arg.
+ * options.c (gfc_init_options): Don't set -Wmissing-include-dirs.
+ (gfc_post_options): Set it here after commandline processing. Call
+ gfc_add_include_path with defer_warn=false.
+ (gfc_handle_option): Call it with defer_warn=true.
+ * scanner.c (gfc_do_check_include_dir, gfc_do_check_include_dirs,
+ gfc_check_include_dirs): New. Diagnostic moved from ...
+ (add_path_to_list): ... here, which came before cmdline processing.
+ Take additional bool defer_warn argument.
+ (gfc_add_include_path): Take additional defer_warn arg.
+ * scanner.h (struct gfc_directorylist): Reorder for alignment issues,
+ add new 'bool warn'.
+
+2021-09-20 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.h (gfc_omp_clauses): Add order_unconstrained.
+ * dump-parse-tree.c (show_omp_clauses): Dump it.
+ * openmp.c (gfc_match_omp_clauses): Match unconstrained/reproducible
+ modifiers to ordered(concurrent).
+ (OMP_DISTRIBUTE_CLAUSES): Accept ordered clause.
+ (resolve_omp_clauses): Reject ordered + order on same directive.
+ * trans-openmp.c (gfc_trans_omp_clauses, gfc_split_omp_clauses): Pass
+ on unconstrained modifier of ordered(concurrent).
+
+2021-09-17 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102366
+ * trans-decl.c (gfc_finish_var_decl): Disable the warning message
+ for variables moved from stack to static storange if they are
+ declared in the main, but allow the move to happen.
+
+2021-09-17 Sandra Loosemore <sandra@codesourcery.com>
+
+ * intrinsic.texi (ISO_C_BINDING): Change C_FLOAT128 to correspond
+ to _Float128 rather than __float128.
+ * iso-c-binding.def (c_float128): Update comments.
+ * trans-intrinsic.c (gfc_builtin_decl_for_float_kind): Likewise.
+ (build_round_expr): Likewise.
+ (gfc_build_intrinsic_lib_fndcecls): Likewise.
+ * trans-types.h (gfc_real16_is_float128): Likewise.
+
+2021-09-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102287
+ * trans-expr.c (gfc_conv_procedure_call): Wrap deallocation of
+ allocatable components of optional allocatable derived type
+ procedure arguments with INTENT(OUT) into a presence check.
+
+2021-09-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102311
+ * resolve.c (resolve_entries): Attempt to recover cleanly after
+ rejecting mismatched function entries.
+
+2021-09-14 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102313
+ * parse.c (gfc_ascii_statement): Add missing ST_OMP_END_SCOPE.
+
+2021-09-13 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/82314
+ * decl.c (add_init_expr_to_sym): For proper initialization of
+ array-valued named constants the array bounds need to be
+ simplified before adding the initializer.
+
+2021-09-13 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/85130
+ * expr.c (find_substring_ref): Handle given substring start and
+ end indices as signed integers, not unsigned.
+
+2021-09-09 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98490
+ * trans-expr.c (gfc_conv_substring): Do not generate substring
+ bounds check for implied do loop index variable before it actually
+ becomes defined.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * options.c (gfc_post_options): Issue an error for
+ -fexcess-precision=16.
+
+2021-09-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/101327
+ * expr.c (find_array_element): When bounds cannot be determined as
+ constant, return error instead of aborting.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * openmp.c (gfc_match_omp_flush): Parse 'seq_cst' clause on 'flush'
+ directive.
+ * trans-openmp.c (gfc_trans_omp_flush): Handle OMP_MEMORDER_SEQ_CST.
+
+2021-09-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * decl.c (gfc_verify_c_interop_param): Reject pointer with
+ CONTIGUOUS attributes as dummy arg. Reject character len > 1
+ when passed as byte stream.
+
+2021-09-01 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/56985
+ * resolve.c (resolve_common_vars): Fix grammar and improve wording
+ of error message rejecting an unlimited polymorphic in COMMON.
+
+2021-08-31 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/100950
+ * simplify.c (substring_has_constant_len): Minimize checks for
+ substring expressions being allowed.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * gfortran.h: Add variable for 'ancestor' in struct gfc_omp_clauses.
+ * openmp.c (gfc_match_omp_clauses): Parse device-modifiers 'device_num'
+ and 'ancestor' in 'target device' clauses.
+ * trans-openmp.c (gfc_trans_omp_clauses): Set OMP_CLAUSE_DEVICE_ANCESTOR.
+
+2021-08-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102113
+ * match.c (gfc_match_goto): Allow for whitespace in parsing list
+ of labels.
+
+2021-08-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/101349
+ * resolve.c (resolve_allocate_expr): An unlimited polymorphic
+ argument to ALLOCATE must be ALLOCATABLE or a POINTER. Fix the
+ corresponding check.
+
+2021-08-28 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/87737
+ * resolve.c (resolve_entries): For functions of type CHARACTER
+ tighten the checks for matching characteristics.
+
2021-08-25 Lewis Hyatt <lhyatt@gmail.com>
PR other/93067
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index b858bad..6552eaf 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -1798,6 +1798,9 @@ expand_constructor (gfc_constructor_base base)
e = c->expr;
+ if (e == NULL)
+ return false;
+
if (empty_constructor)
empty_ts = e->ts;
@@ -2578,7 +2581,7 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
}
}
- if (array->shape && array->shape[dimen])
+ if (array->shape)
{
mpz_init_set (*result, array->shape[dimen]);
return true;
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 851af1b..cfaf9d2 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -1520,7 +1520,9 @@ gfc_check_associated (gfc_expr *pointer, gfc_expr *target)
t = true;
if (!same_type_check (pointer, 0, target, 1, true))
t = false;
- if (!rank_check (target, 0, pointer->rank))
+ /* F2018 C838 explicitly allows an assumed-rank variable as the first
+ argument of intrinsic inquiry functions. */
+ if (pointer->rank != -1 && !rank_check (target, 0, pointer->rank))
t = false;
if (target->rank > 0)
{
@@ -4528,7 +4530,9 @@ gfc_check_present (gfc_expr *a)
return false;
}
- if (!sym->attr.optional)
+ /* For CLASS, the optional attribute might be set at either location. */
+ if ((sym->ts.type != BT_CLASS || !CLASS_DATA (sym)->attr.optional)
+ && !sym->attr.optional)
{
gfc_error ("%qs argument of %qs intrinsic at %L must be of "
"an OPTIONAL dummy variable",
@@ -5082,6 +5086,13 @@ gfc_check_shape (gfc_expr *source, gfc_expr *kind)
if (gfc_invalid_null_arg (source))
return false;
+ if (!kind_check (kind, 1, BT_INTEGER))
+ return false;
+ if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
+ "with KIND argument at %L",
+ gfc_current_intrinsic, &kind->where))
+ return false;
+
if (source->rank == 0 || source->expr_type != EXPR_VARIABLE)
return true;
@@ -5094,13 +5105,6 @@ gfc_check_shape (gfc_expr *source, gfc_expr *kind)
return false;
}
- if (!kind_check (kind, 1, BT_INTEGER))
- return false;
- if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
- gfc_current_intrinsic, &kind->where))
- return false;
-
return true;
}
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 83c4517..e86386c 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -19,11 +19,15 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+
+#define GCC_C_COMMON_C
+#include "options.h" /* For cpp_reason_option_codes. */
+#undef GCC_C_COMMON_C
+
#include "target.h"
#include "gfortran.h"
#include "diagnostic.h"
-
#include "toplev.h"
#include "../../libcpp/internal.h"
@@ -240,6 +244,19 @@ gfc_cpp_temporary_file (void)
return gfc_cpp_option.temporary_filename;
}
+static void
+gfc_cpp_register_include_paths (bool verbose_missing_dir_warn)
+{
+ int cxx_stdinc = 0;
+ cpp_get_options (cpp_in)->warn_missing_include_dirs
+ = (global_options.x_cpp_warn_missing_include_dirs
+ && verbose_missing_dir_warn);
+ register_include_chains (cpp_in, gfc_cpp_option.sysroot,
+ gfc_cpp_option.prefix, gfc_cpp_option.multilib,
+ gfc_cpp_option.standard_include_paths, cxx_stdinc,
+ gfc_cpp_option.verbose);
+}
+
void
gfc_cpp_init_options (unsigned int decoded_options_count,
struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
@@ -435,9 +452,40 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
return result;
}
+/* This function needs to be called before gfc_cpp_register_include_paths
+ as the latter may diagnose missing include directories. */
+static void
+gfc_cpp_init_cb (void)
+{
+ struct cpp_callbacks *cb;
+
+ cb = cpp_get_callbacks (cpp_in);
+ cb->file_change = cb_file_change;
+ cb->line_change = cb_line_change;
+ cb->ident = cb_ident;
+ cb->def_pragma = cb_def_pragma;
+ cb->diagnostic = cb_cpp_diagnostic;
+
+ if (gfc_cpp_option.dump_includes)
+ cb->include = cb_include;
+
+ if ((gfc_cpp_option.dump_macros == 'D')
+ || (gfc_cpp_option.dump_macros == 'N'))
+ {
+ cb->define = cb_define;
+ cb->undef = cb_undef;
+ }
+
+ if (gfc_cpp_option.dump_macros == 'U')
+ {
+ cb->before_define = dump_queued_macros;
+ cb->used_define = cb_used_define;
+ cb->used_undef = cb_used_undef;
+ }
+}
void
-gfc_cpp_post_options (void)
+gfc_cpp_post_options (bool verbose_missing_dir_warn)
{
/* Any preprocessing-related option without '-cpp' is considered
an error. */
@@ -498,40 +546,15 @@ gfc_cpp_post_options (void)
way libcpp will do it, namely, with no charset conversion but with
skipping of a UTF-8 BOM if present. */
diagnostic_initialize_input_context (global_dc, nullptr, true);
+ gfc_cpp_init_cb ();
- gfc_cpp_register_include_paths ();
+ gfc_cpp_register_include_paths (verbose_missing_dir_warn);
}
void
gfc_cpp_init_0 (void)
{
- struct cpp_callbacks *cb;
-
- cb = cpp_get_callbacks (cpp_in);
- cb->file_change = cb_file_change;
- cb->line_change = cb_line_change;
- cb->ident = cb_ident;
- cb->def_pragma = cb_def_pragma;
- cb->diagnostic = cb_cpp_diagnostic;
-
- if (gfc_cpp_option.dump_includes)
- cb->include = cb_include;
-
- if ((gfc_cpp_option.dump_macros == 'D')
- || (gfc_cpp_option.dump_macros == 'N'))
- {
- cb->define = cb_define;
- cb->undef = cb_undef;
- }
-
- if (gfc_cpp_option.dump_macros == 'U')
- {
- cb->before_define = dump_queued_macros;
- cb->used_define = cb_used_define;
- cb->used_undef = cb_used_undef;
- }
-
/* Initialize the print structure. Setting print.src_line to -1 here is
a trick to guarantee that the first token of the file will cause
a linemarker to be output by maybe_print_line. */
@@ -723,17 +746,6 @@ gfc_cpp_add_include_path_after (char *path, bool user_supplied)
add_path (path, INC_AFTER, cxx_aware, user_supplied);
}
-void
-gfc_cpp_register_include_paths (void)
-{
- int cxx_stdinc = 0;
- register_include_chains (cpp_in, gfc_cpp_option.sysroot,
- gfc_cpp_option.prefix, gfc_cpp_option.multilib,
- gfc_cpp_option.standard_include_paths, cxx_stdinc,
- gfc_cpp_option.verbose);
-}
-
-
static void scan_translation_unit_trad (cpp_reader *);
static void account_for_newlines (const unsigned char *, size_t);
@@ -1043,6 +1055,21 @@ cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
cpp_define_queue = q;
}
+/* Return the gcc option code associated with the reason for a cpp
+ message, or 0 if none. */
+
+static int
+cb_cpp_diagnostic_cpp_option (enum cpp_warning_reason reason)
+{
+ const struct cpp_reason_option_codes_t *entry;
+
+ for (entry = cpp_reason_option_codes; entry->reason != CPP_W_NONE; entry++)
+ if (entry->reason == reason)
+ return entry->option_code;
+ return 0;
+}
+
+
/* Callback from cpp_error for PFILE to print diagnostics from the
preprocessor. The diagnostic is of type LEVEL, with REASON set
to the reason code if LEVEL is represents a warning, at location
@@ -1089,8 +1116,8 @@ cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
}
diagnostic_set_info_translated (&diagnostic, msg, ap,
richloc, dlevel);
- if (reason == CPP_W_WARNING_DIRECTIVE)
- diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
+ diagnostic_override_option_index (&diagnostic,
+ cb_cpp_diagnostic_cpp_option (reason));
ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
if (level == CPP_DL_WARNING_SYSHDR)
global_dc->dc_warn_system_headers = save_warn_system_headers;
diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h
index f642c77..44644a2 100644
--- a/gcc/fortran/cpp.h
+++ b/gcc/fortran/cpp.h
@@ -41,7 +41,7 @@ void gfc_cpp_init_options (unsigned int decoded_options_count,
int gfc_cpp_handle_option(size_t scode, const char *arg, int value);
-void gfc_cpp_post_options (void);
+void gfc_cpp_post_options (bool);
bool gfc_cpp_preprocess (const char *source_file);
@@ -50,6 +50,4 @@ void gfc_cpp_done (void);
void gfc_cpp_add_include_path (char *path, bool user_supplied);
void gfc_cpp_add_include_path_after (char *path, bool user_supplied);
-void gfc_cpp_register_include_paths (void);
-
#endif /* GFC_CPP_H */
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 05081c4..6784b07 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -896,9 +896,6 @@ match_clist_expr (gfc_expr **result, gfc_typespec *ts, gfc_array_spec *as)
expr->ts = *ts;
expr->value.constructor = array_head;
- expr->rank = as->rank;
- expr->shape = gfc_get_shape (expr->rank);
-
/* Validate sizes. We built expr ourselves, so cons_size will be
constant (we fail above for non-constant expressions).
We still need to verify that the sizes match. */
@@ -911,6 +908,12 @@ match_clist_expr (gfc_expr **result, gfc_typespec *ts, gfc_array_spec *as)
mpz_clear (cons_size);
if (cmp)
goto cleanup;
+
+ /* Set the rank/shape to match the LHS as auto-reshape is implied. */
+ expr->rank = as->rank;
+ expr->shape = gfc_get_shape (as->rank);
+ for (int i = 0; i < as->rank; ++i)
+ spec_dimen_size (as, i, &expr->shape[i]);
}
/* Make sure scalar types match. */
@@ -1551,11 +1554,29 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
sym->ns->proc_name->name);
}
+ /* Per F2018, 18.3.6 (5), pointer + contiguous is not permitted. */
+ if (sym->attr.pointer && sym->attr.contiguous)
+ gfc_error ("Dummy argument %qs at %L may not be a pointer with "
+ "CONTIGUOUS attribute as procedure %qs is BIND(C)",
+ sym->name, &sym->declared_at, sym->ns->proc_name->name);
+
+ /* Per F2018, C1557, pointer/allocatable dummies to a bind(c)
+ procedure that are default-initialized are not permitted. */
+ if ((sym->attr.pointer || sym->attr.allocatable)
+ && sym->ts.type == BT_DERIVED
+ && gfc_has_default_initializer (sym->ts.u.derived))
+ {
+ gfc_error ("Default-initialized %s dummy argument %qs "
+ "at %L is not permitted in BIND(C) procedure %qs",
+ (sym->attr.pointer ? "pointer" : "allocatable"),
+ sym->name, &sym->declared_at,
+ sym->ns->proc_name->name);
+ retval = false;
+ }
+
/* Character strings are only C interoperable if they have a
- length of 1. However, as argument they are either iteroperable
- when passed as descriptor (which requires len=: or len=*) or
- when having a constant length or are always passed by
- descriptor. */
+ length of 1. However, as an argument they are also iteroperable
+ when passed as descriptor (which requires len=: or len=*). */
if (sym->ts.type == BT_CHARACTER)
{
gfc_charlen *cl = sym->ts.u.cl;
@@ -1584,15 +1605,6 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
sym->name, &sym->declared_at,
sym->ns->proc_name->name))
retval = false;
- else if (!sym->attr.dimension)
- {
- /* FIXME: Use CFI array descriptor for scalars. */
- gfc_error ("Sorry, deferred-length scalar character dummy "
- "argument %qs at %L of procedure %qs with "
- "BIND(C) not yet supported", sym->name,
- &sym->declared_at, sym->ns->proc_name->name);
- retval = false;
- }
}
else if (sym->attr.value
&& (!cl || !cl->length
@@ -1607,29 +1619,17 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
else if (!cl || !cl->length)
{
/* Assumed length; F2018, 18.3.6 (5)(2).
- Uses the CFI array descriptor. */
+ Uses the CFI array descriptor - also for scalars and
+ explicit-size/assumed-size arrays. */
if (!gfc_notify_std (GFC_STD_F2018,
"Assumed-length character dummy argument "
"%qs at %L of procedure %qs with BIND(C) "
"attribute", sym->name, &sym->declared_at,
sym->ns->proc_name->name))
retval = false;
- else if (!sym->attr.dimension
- || sym->as->type == AS_ASSUMED_SIZE
- || sym->as->type == AS_EXPLICIT)
- {
- /* FIXME: Valid - should use the CFI array descriptor, but
- not yet handled for scalars and assumed-/explicit-size
- arrays. */
- gfc_error ("Sorry, character dummy argument %qs at %L "
- "with assumed length is not yet supported for "
- "procedure %qs with BIND(C) attribute",
- sym->name, &sym->declared_at,
- sym->ns->proc_name->name);
- retval = false;
- }
}
- else if (cl->length->expr_type != EXPR_CONSTANT)
+ else if (cl->length->expr_type != EXPR_CONSTANT
+ || mpz_cmp_si (cl->length->value.integer, 1) != 0)
{
/* F2018, 18.3.6, (5), item 4. */
if (!sym->attr.dimension
@@ -1637,30 +1637,17 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
|| sym->as->type == AS_EXPLICIT)
{
gfc_error ("Character dummy argument %qs at %L must be "
- "of constant length or assumed length, "
+ "of constant length of one or assumed length, "
"unless it has assumed shape or assumed rank, "
"as procedure %qs has the BIND(C) attribute",
sym->name, &sym->declared_at,
sym->ns->proc_name->name);
retval = false;
}
- else if (!gfc_notify_std (GFC_STD_F2018,
- "Character dummy argument %qs at "
- "%L with nonconstant length as "
- "procedure %qs is BIND(C)",
- sym->name, &sym->declared_at,
- sym->ns->proc_name->name))
- retval = false;
+ /* else: valid only since F2018 - and an assumed-shape/rank
+ array; however, gfc_notify_std is already called when
+ those array types are used. Thus, silently accept F200x. */
}
- else if (mpz_cmp_si (cl->length->value.integer, 1) != 0
- && !gfc_notify_std (GFC_STD_F2008,
- "Character dummy argument %qs at %L "
- "with length greater than 1 for "
- "procedure %qs with BIND(C) "
- "attribute",
- sym->name, &sym->declared_at,
- sym->ns->proc_name->name))
- retval = false;
}
/* We have to make sure that any param to a bind(c) routine does
@@ -2176,6 +2163,24 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
sym->as->type = AS_EXPLICIT;
}
+ /* Ensure that explicit bounds are simplified. */
+ if (sym->attr.flavor == FL_PARAMETER && sym->attr.dimension
+ && sym->as->type == AS_EXPLICIT)
+ {
+ for (int dim = 0; dim < sym->as->rank; ++dim)
+ {
+ gfc_expr *e;
+
+ e = sym->as->lower[dim];
+ if (e->expr_type != EXPR_CONSTANT)
+ gfc_reduce_init_expr (e);
+
+ e = sym->as->upper[dim];
+ if (e->expr_type != EXPR_CONSTANT)
+ gfc_reduce_init_expr (e);
+ }
+ }
+
/* Need to check if the expression we initialized this
to was one of the iso_c_binding named constants. If so,
and we're a parameter (constant), let it be iso_c.
@@ -2203,12 +2208,16 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
gfc_expr *array;
int n;
if (sym->attr.flavor == FL_PARAMETER
- && init->expr_type == EXPR_CONSTANT
- && spec_size (sym->as, &size)
- && mpz_cmp_si (size, 0) > 0)
+ && gfc_is_constant_expr (init)
+ && (init->expr_type == EXPR_CONSTANT
+ || init->expr_type == EXPR_STRUCTURE)
+ && spec_size (sym->as, &size)
+ && mpz_cmp_si (size, 0) > 0)
{
array = gfc_get_array_expr (init->ts.type, init->ts.kind,
&init->where);
+ if (init->ts.type == BT_DERIVED)
+ array->ts.u.derived = init->ts.u.derived;
for (n = 0; n < (int)mpz_get_si (size); n++)
gfc_constructor_append_expr (&array->value.constructor,
n == 0
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index a1df47c..14a3078 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1630,7 +1630,14 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
if (omp_clauses->independent)
fputs (" INDEPENDENT", dumpfile);
if (omp_clauses->order_concurrent)
- fputs (" ORDER(CONCURRENT)", dumpfile);
+ {
+ fputs (" ORDER(", dumpfile);
+ if (omp_clauses->order_unconstrained)
+ fputs ("UNCONSTRAINED:", dumpfile);
+ else if (omp_clauses->order_reproducible)
+ fputs ("REPRODUCIBLE:", dumpfile);
+ fputs ("CONCURRENT)", dumpfile);
+ }
if (omp_clauses->ordered)
{
if (omp_clauses->orderedc)
@@ -1743,6 +1750,8 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
if (omp_clauses->device)
{
fputs (" DEVICE(", dumpfile);
+ if (omp_clauses->ancestor)
+ fputs ("ANCESTOR:", dumpfile);
show_expr (omp_clauses->device);
fputc (')', dumpfile);
}
@@ -1887,7 +1896,7 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
if (omp_clauses->atomic_op != GFC_OMP_ATOMIC_UNSET)
{
const char *atomic_op;
- switch (omp_clauses->atomic_op)
+ switch (omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
{
case GFC_OMP_ATOMIC_READ: atomic_op = "READ"; break;
case GFC_OMP_ATOMIC_WRITE: atomic_op = "WRITE"; break;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 35563a7..66f24c6 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -990,6 +990,34 @@ done:
}
+/* Standard intrinsics listed under F2018:10.1.12 (6), which are excluded in
+ constant expressions, except TRANSFER (c.f. item (8)), which would need
+ separate treatment. */
+
+static bool
+is_non_constant_intrinsic (gfc_expr *e)
+{
+ if (e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym)
+ {
+ switch (e->value.function.isym->id)
+ {
+ case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
+ case GFC_ISYM_GET_TEAM:
+ case GFC_ISYM_NULL:
+ case GFC_ISYM_NUM_IMAGES:
+ case GFC_ISYM_TEAM_NUMBER:
+ case GFC_ISYM_THIS_IMAGE:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+
/* Determine if an expression is constant in the sense of F08:7.1.12.
* This function expects that the expression has already been simplified. */
@@ -1023,6 +1051,10 @@ gfc_is_constant_expr (gfc_expr *e)
gcc_assert (e->symtree || e->value.function.esym
|| e->value.function.isym);
+ /* Check for intrinsics excluded in constant expressions. */
+ if (e->value.function.isym && is_non_constant_intrinsic (e))
+ return false;
+
/* Call to intrinsic with at least one argument. */
if (e->value.function.isym && e->value.function.actual)
{
@@ -1078,11 +1110,13 @@ is_CFI_desc (gfc_symbol *sym, gfc_expr *e)
if (sym && sym->attr.dummy
&& sym->ns->proc_name->attr.is_bind_c
- && sym->attr.dimension
&& (sym->attr.pointer
|| sym->attr.allocatable
- || sym->as->type == AS_ASSUMED_SHAPE
- || sym->as->type == AS_ASSUMED_RANK))
+ || (sym->attr.dimension
+ && (sym->as->type == AS_ASSUMED_SHAPE
+ || sym->as->type == AS_ASSUMED_RANK))
+ || (sym->ts.type == BT_CHARACTER
+ && (!sym->ts.u.cl || !sym->ts.u.cl->length))))
return true;
return false;
@@ -1337,7 +1371,9 @@ find_array_element (gfc_constructor_base base, gfc_array_ref *ar,
for (i = 0; i < ar->dimen; i++)
{
if (!gfc_reduce_init_expr (ar->as->lower[i])
- || !gfc_reduce_init_expr (ar->as->upper[i]))
+ || !gfc_reduce_init_expr (ar->as->upper[i])
+ || ar->as->upper[i]->expr_type != EXPR_CONSTANT
+ || ar->as->lower[i]->expr_type != EXPR_CONSTANT)
{
t = false;
cons = NULL;
@@ -1351,9 +1387,6 @@ find_array_element (gfc_constructor_base base, gfc_array_ref *ar,
goto depart;
}
- gcc_assert (ar->as->upper[i]->expr_type == EXPR_CONSTANT
- && ar->as->lower[i]->expr_type == EXPR_CONSTANT);
-
/* Check the bounds. */
if ((ar->as->upper[i]
&& mpz_cmp (e->value.integer,
@@ -1725,8 +1758,8 @@ find_substring_ref (gfc_expr *p, gfc_expr **newp)
*newp = gfc_copy_expr (p);
free ((*newp)->value.character.string);
- end = (gfc_charlen_t) mpz_get_ui (p->ref->u.ss.end->value.integer);
- start = (gfc_charlen_t) mpz_get_ui (p->ref->u.ss.start->value.integer);
+ end = (gfc_charlen_t) mpz_get_si (p->ref->u.ss.end->value.integer);
+ start = (gfc_charlen_t) mpz_get_si (p->ref->u.ss.start->value.integer);
if (end >= start)
length = end - start + 1;
else
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 026228d..58dcaf0 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -259,8 +259,8 @@ gfc_init (void)
gfc_init_1 ();
- if (!gfc_new_file ())
- fatal_error (input_location, "cannot open input file: %s", gfc_source_file);
+ /* Calls exit in case of a fail. */
+ gfc_new_file ();
if (flag_preprocess_only)
return false;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 48cdcdf..66192c0 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -105,6 +105,40 @@ typedef struct
}
mstring;
+/* ISO_Fortran_binding.h
+ CAUTION: This has to be kept in sync with libgfortran. */
+
+#define CFI_type_kind_shift 8
+#define CFI_type_mask 0xFF
+#define CFI_type_from_type_kind(t, k) (t + (k << CFI_type_kind_shift))
+
+/* Constants, defined as macros. */
+#define CFI_VERSION 1
+#define CFI_MAX_RANK 15
+
+/* Attributes. */
+#define CFI_attribute_pointer 0
+#define CFI_attribute_allocatable 1
+#define CFI_attribute_other 2
+
+#define CFI_type_mask 0xFF
+#define CFI_type_kind_shift 8
+
+/* Intrinsic types. Their kind number defines their storage size. */
+#define CFI_type_Integer 1
+#define CFI_type_Logical 2
+#define CFI_type_Real 3
+#define CFI_type_Complex 4
+#define CFI_type_Character 5
+
+/* Combined type (for more, see ISO_Fortran_binding.h). */
+#define CFI_type_ucs4_char (CFI_type_Character + (4 << CFI_type_kind_shift))
+
+/* Types with no kind. */
+#define CFI_type_struct 6
+#define CFI_type_cptr 7
+#define CFI_type_cfunptr 8
+#define CFI_type_other -1
/*************************** Enums *****************************/
@@ -239,7 +273,7 @@ enum gfc_statement
ST_OMP_DO_SIMD, ST_OMP_END_DO_SIMD, ST_OMP_PARALLEL_DO_SIMD,
ST_OMP_END_PARALLEL_DO_SIMD, ST_OMP_DECLARE_SIMD, ST_OMP_DECLARE_REDUCTION,
ST_OMP_TARGET, ST_OMP_END_TARGET, ST_OMP_TARGET_DATA, ST_OMP_END_TARGET_DATA,
- ST_OMP_TARGET_UPDATE, ST_OMP_DECLARE_TARGET,
+ ST_OMP_TARGET_UPDATE, ST_OMP_DECLARE_TARGET, ST_OMP_DECLARE_VARIANT,
ST_OMP_TEAMS, ST_OMP_END_TEAMS, ST_OMP_DISTRIBUTE, ST_OMP_END_DISTRIBUTE,
ST_OMP_DISTRIBUTE_SIMD, ST_OMP_END_DISTRIBUTE_SIMD,
ST_OMP_DISTRIBUTE_PARALLEL_DO, ST_OMP_END_DISTRIBUTE_PARALLEL_DO,
@@ -1486,11 +1520,12 @@ typedef struct gfc_omp_clauses
enum gfc_omp_atomic_op atomic_op;
enum gfc_omp_defaultmap defaultmap[OMP_DEFAULTMAP_CAT_NUM];
int collapse, orderedc;
- unsigned nowait:1, ordered:1, untied:1, mergeable:1;
+ unsigned nowait:1, ordered:1, untied:1, mergeable:1, ancestor:1;
unsigned inbranch:1, notinbranch:1, nogroup:1;
unsigned sched_simd:1, sched_monotonic:1, sched_nonmonotonic:1;
unsigned simd:1, threads:1, depend_source:1, destroy:1, order_concurrent:1;
- unsigned capture:1, grainsize_strict:1, num_tasks_strict:1;
+ unsigned order_unconstrained:1, order_reproducible:1, capture:1;
+ unsigned grainsize_strict:1, num_tasks_strict:1;
ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
@@ -1552,6 +1587,73 @@ typedef struct gfc_omp_declare_simd
gfc_omp_declare_simd;
#define gfc_get_omp_declare_simd() XCNEW (gfc_omp_declare_simd)
+
+enum gfc_omp_trait_property_kind
+{
+ CTX_PROPERTY_NONE,
+ CTX_PROPERTY_USER,
+ CTX_PROPERTY_NAME_LIST,
+ CTX_PROPERTY_ID,
+ CTX_PROPERTY_EXPR,
+ CTX_PROPERTY_SIMD
+};
+
+typedef struct gfc_omp_trait_property
+{
+ struct gfc_omp_trait_property *next;
+ enum gfc_omp_trait_property_kind property_kind;
+ bool is_name : 1;
+
+ union
+ {
+ gfc_expr *expr;
+ gfc_symbol *sym;
+ gfc_omp_clauses *clauses;
+ char *name;
+ };
+} gfc_omp_trait_property;
+#define gfc_get_omp_trait_property() XCNEW (gfc_omp_trait_property)
+
+typedef struct gfc_omp_selector
+{
+ struct gfc_omp_selector *next;
+
+ char *trait_selector_name;
+ gfc_expr *score;
+ struct gfc_omp_trait_property *properties;
+} gfc_omp_selector;
+#define gfc_get_omp_selector() XCNEW (gfc_omp_selector)
+
+typedef struct gfc_omp_set_selector
+{
+ struct gfc_omp_set_selector *next;
+
+ const char *trait_set_selector_name;
+ struct gfc_omp_selector *trait_selectors;
+} gfc_omp_set_selector;
+#define gfc_get_omp_set_selector() XCNEW (gfc_omp_set_selector)
+
+
+/* Node in the linked list used for storing !$omp declare variant
+ constructs. */
+
+typedef struct gfc_omp_declare_variant
+{
+ struct gfc_omp_declare_variant *next;
+ locus where; /* Where the !$omp declare variant construct occurred. */
+
+ struct gfc_symtree *base_proc_symtree;
+ struct gfc_symtree *variant_proc_symtree;
+
+ gfc_omp_set_selector *set_selectors;
+
+ bool checked_p : 1; /* Set if previously checked for errors. */
+ bool error_p : 1; /* Set if error found in directive. */
+}
+gfc_omp_declare_variant;
+#define gfc_get_omp_declare_variant() XCNEW (gfc_omp_declare_variant)
+
+
typedef struct gfc_omp_udr
{
struct gfc_omp_udr *next;
@@ -2021,6 +2123,9 @@ typedef struct gfc_namespace
/* Linked list of !$omp declare simd constructs. */
struct gfc_omp_declare_simd *omp_declare_simd;
+ /* Linked list of !$omp declare variant constructs. */
+ struct gfc_omp_declare_variant *omp_declare_variant;
+
/* A hash set for the the gfc expressions that have already
been finalized in this namespace. */
@@ -3027,9 +3132,10 @@ match gfc_get_pdt_instance (gfc_actual_arglist *, gfc_symbol **,
void gfc_scanner_done_1 (void);
void gfc_scanner_init_1 (void);
-void gfc_add_include_path (const char *, bool, bool, bool);
+void gfc_add_include_path (const char *, bool, bool, bool, bool);
void gfc_add_intrinsic_modules_path (const char *);
void gfc_release_include_path (void);
+void gfc_check_include_dirs (bool);
FILE *gfc_open_included_file (const char *, bool, bool);
int gfc_at_end (void);
@@ -3061,7 +3167,7 @@ gfc_char_t gfc_peek_char (void);
char gfc_peek_ascii_char (void);
void gfc_error_recovery (void);
void gfc_gobble_whitespace (void);
-bool gfc_new_file (void);
+void gfc_new_file (void);
const char * gfc_read_orig_filename (const char *, const char **);
extern gfc_source_form gfc_current_form;
@@ -3420,6 +3526,7 @@ bool gfc_omp_requires_add_clause (gfc_omp_requires_kind, const char *,
void gfc_check_omp_requires (gfc_namespace *, int);
void gfc_free_omp_clauses (gfc_omp_clauses *);
void gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *);
+void gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list);
void gfc_free_omp_declare_simd (gfc_omp_declare_simd *);
void gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *);
void gfc_free_omp_udr (gfc_omp_udr *);
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 9e3e8aa..24698be 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -2448,6 +2448,21 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
return false;
}
+ /* TS29113 C407c; F2018 C711. */
+ if (actual->ts.type == BT_ASSUMED
+ && symbol_rank (formal) == -1
+ && actual->rank != -1
+ && !(actual->symtree->n.sym->as
+ && actual->symtree->n.sym->as->type == AS_ASSUMED_SHAPE))
+ {
+ if (where)
+ gfc_error ("Assumed-type actual argument at %L corresponding to "
+ "assumed-rank dummy argument %qs must be "
+ "assumed-shape or assumed-rank",
+ &actual->where, formal->name);
+ return false;
+ }
+
/* F2008, 12.5.2.5; IR F08/0073. */
if (formal->ts.type == BT_CLASS && formal->attr.class_ok
&& actual->expr_type != EXPR_NULL
@@ -2634,7 +2649,9 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
&& formal->as->type == AS_ASSUMED_SHAPE))
&& actual->expr_type != EXPR_NULL)
|| (actual->rank == 0 && formal->attr.dimension
- && gfc_is_coindexed (actual)))
+ && gfc_is_coindexed (actual))
+ /* Assumed-rank actual argument; F2018 C838. */
+ || actual->rank == -1)
{
if (where
&& (!formal->attr.artificial || (!formal->maybe_array
@@ -3044,6 +3061,8 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
unsigned long actual_size, formal_size;
bool full_array = false;
gfc_array_ref *actual_arr_ref;
+ gfc_array_spec *fas, *aas;
+ bool pointer_dummy, pointer_arg, allocatable_arg;
actual = *ap;
@@ -3181,21 +3200,21 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
is_elemental, where))
return false;
- /* TS 29113, 6.3p2. */
+ /* TS 29113, 6.3p2; F2018 15.5.2.4. */
if (f->sym->ts.type == BT_ASSUMED
&& (a->expr->ts.type == BT_DERIVED
|| (a->expr->ts.type == BT_CLASS && CLASS_DATA (a->expr))))
{
- gfc_namespace *f2k_derived;
-
- f2k_derived = a->expr->ts.type == BT_DERIVED
- ? a->expr->ts.u.derived->f2k_derived
- : CLASS_DATA (a->expr)->ts.u.derived->f2k_derived;
-
- if (f2k_derived
- && (f2k_derived->finalizers || f2k_derived->tb_sym_root))
+ gfc_symbol *derived = (a->expr->ts.type == BT_DERIVED
+ ? a->expr->ts.u.derived
+ : CLASS_DATA (a->expr)->ts.u.derived);
+ gfc_namespace *f2k_derived = derived->f2k_derived;
+ if (derived->attr.pdt_type
+ || (f2k_derived
+ && (f2k_derived->finalizers || f2k_derived->tb_sym_root)))
{
- gfc_error ("Actual argument at %L to assumed-type dummy is of "
+ gfc_error ("Actual argument at %L to assumed-type dummy "
+ "has type parameters or is of "
"derived type with type-bound or FINAL procedures",
&a->expr->where);
return false;
@@ -3312,13 +3331,60 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
return false;
}
- if (f->sym->as
- && (f->sym->as->type == AS_ASSUMED_SHAPE
- || f->sym->as->type == AS_DEFERRED
- || (f->sym->as->type == AS_ASSUMED_RANK && f->sym->attr.pointer))
- && a->expr->expr_type == EXPR_VARIABLE
- && a->expr->symtree->n.sym->as
- && a->expr->symtree->n.sym->as->type == AS_ASSUMED_SIZE
+ /* Class array variables and expressions store array info in a
+ different place from non-class objects; consolidate the logic
+ to access it here instead of repeating it below. Note that
+ pointer_arg and allocatable_arg are not fully general and are
+ only used in a specific situation below with an assumed-rank
+ argument. */
+ if (f->sym->ts.type == BT_CLASS && CLASS_DATA (f->sym))
+ {
+ gfc_component *classdata = CLASS_DATA (f->sym);
+ fas = classdata->as;
+ pointer_dummy = classdata->attr.class_pointer;
+ }
+ else
+ {
+ fas = f->sym->as;
+ pointer_dummy = f->sym->attr.pointer;
+ }
+
+ if (a->expr->expr_type != EXPR_VARIABLE)
+ {
+ aas = NULL;
+ pointer_arg = false;
+ allocatable_arg = false;
+ }
+ else if (a->expr->ts.type == BT_CLASS
+ && a->expr->symtree->n.sym
+ && CLASS_DATA (a->expr->symtree->n.sym))
+ {
+ gfc_component *classdata = CLASS_DATA (a->expr->symtree->n.sym);
+ aas = classdata->as;
+ pointer_arg = classdata->attr.class_pointer;
+ allocatable_arg = classdata->attr.allocatable;
+ }
+ else
+ {
+ aas = a->expr->symtree->n.sym->as;
+ pointer_arg = a->expr->symtree->n.sym->attr.pointer;
+ allocatable_arg = a->expr->symtree->n.sym->attr.allocatable;
+ }
+
+ /* F2018:9.5.2(2) permits assumed-size whole array expressions as
+ actual arguments only if the shape is not required; thus it
+ cannot be passed to an assumed-shape array dummy.
+ F2018:15.5.2.(2) permits passing a nonpointer actual to an
+ intent(in) pointer dummy argument and this is accepted by
+ the compare_pointer check below, but this also requires shape
+ information.
+ There's more discussion of this in PR94110. */
+ if (fas
+ && (fas->type == AS_ASSUMED_SHAPE
+ || fas->type == AS_DEFERRED
+ || (fas->type == AS_ASSUMED_RANK && pointer_dummy))
+ && aas
+ && aas->type == AS_ASSUMED_SIZE
&& (a->expr->ref == NULL
|| (a->expr->ref->type == REF_ARRAY
&& a->expr->ref->u.ar.type == AR_FULL)))
@@ -3329,6 +3395,35 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
return false;
}
+ /* Diagnose F2018 C839 (TS29113 C535c). Here the problem is
+ passing an assumed-size array to an INTENT(OUT) assumed-rank
+ dummy when it doesn't have the size information needed to run
+ initializers and finalizers. */
+ if (f->sym->attr.intent == INTENT_OUT
+ && fas
+ && fas->type == AS_ASSUMED_RANK
+ && aas
+ && ((aas->type == AS_ASSUMED_SIZE
+ && (a->expr->ref == NULL
+ || (a->expr->ref->type == REF_ARRAY
+ && a->expr->ref->u.ar.type == AR_FULL)))
+ || (aas->type == AS_ASSUMED_RANK
+ && !pointer_arg
+ && !allocatable_arg))
+ && (a->expr->ts.type == BT_CLASS
+ || (a->expr->ts.type == BT_DERIVED
+ && (gfc_is_finalizable (a->expr->ts.u.derived, NULL)
+ || gfc_has_ultimate_allocatable (a->expr)
+ || gfc_has_default_initializer
+ (a->expr->ts.u.derived)))))
+ {
+ if (where)
+ gfc_error ("Actual argument to assumed-rank INTENT(OUT) "
+ "dummy %qs at %L cannot be of unknown size",
+ f->sym->name, where);
+ return false;
+ }
+
if (a->expr->expr_type != EXPR_NULL
&& compare_pointer (f->sym, a->expr) == 0)
{
@@ -3462,7 +3557,7 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
&& a->expr->expr_type == EXPR_VARIABLE
&& a->expr->symtree->n.sym->as
&& a->expr->symtree->n.sym->as->type == AS_ASSUMED_SHAPE
- && !(f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE))
+ && !(fas && fas->type == AS_ASSUMED_SHAPE))
{
if (where)
gfc_error ("Assumed-shape actual argument at %L is "
@@ -3479,7 +3574,7 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
if (f->sym->attr.volatile_
&& actual_arr_ref && actual_arr_ref->type == AR_SECTION
- && !(f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE))
+ && !(fas && fas->type == AS_ASSUMED_SHAPE))
{
if (where)
gfc_error ("Array-section actual argument at %L is "
@@ -3497,8 +3592,8 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
&& a->expr->expr_type == EXPR_VARIABLE
&& a->expr->symtree->n.sym->attr.pointer
&& a->expr->symtree->n.sym->as
- && !(f->sym->as
- && (f->sym->as->type == AS_ASSUMED_SHAPE
+ && !(fas
+ && (fas->type == AS_ASSUMED_SHAPE
|| f->sym->attr.pointer)))
{
if (where)
@@ -3529,8 +3624,13 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
"at %L", where);
return false;
}
- if (!f->sym->attr.optional
- || (in_statement_function && f->sym->attr.optional))
+ /* For CLASS, the optional attribute might be set at either location. */
+ if (((f->sym->ts.type != BT_CLASS || !CLASS_DATA (f->sym)->attr.optional)
+ && !f->sym->attr.optional)
+ || (in_statement_function
+ && (f->sym->attr.optional
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->attr.optional))))
{
if (where)
gfc_error ("Missing actual argument for argument %qs at %L",
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 219f04f..f5c88d9 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -5237,12 +5237,13 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag,
/* In building an array constructor, gfortran can end up here when no
conversion is required for an intrinsic type. We need to let derived
types drop through. */
- if (from_ts.type != BT_DERIVED
+ if (from_ts.type != BT_DERIVED && from_ts.type != BT_CLASS
&& (from_ts.type == ts->type && from_ts.kind == ts->kind))
return true;
- if (expr->ts.type == BT_DERIVED && ts->type == BT_DERIVED
- && gfc_compare_types (&expr->ts, ts))
+ if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
+ && (ts->type == BT_DERIVED || ts->type == BT_CLASS)
+ && gfc_compare_types (ts, &expr->ts))
return true;
/* If array is true then conversion is in an array constructor where
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 81c5298..e3916ba 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -15177,8 +15177,8 @@ In addition to the integer named constants required by the Fortran 2003
standard and @code{C_PTRDIFF_T} of TS 29113, GNU Fortran provides as an
extension named constants for the 128-bit integer types supported by the
C compiler: @code{C_INT128_T, C_INT_LEAST128_T, C_INT_FAST128_T}.
-Furthermore, if @code{__float128} is supported in C, the named constants
-@code{C_FLOAT128, C_FLOAT128_COMPLEX} are defined.
+Furthermore, if @code{_Float128} is supported in C, the named constants
+@code{C_FLOAT128} and @code{C_FLOAT128_COMPLEX} are defined.
@multitable @columnfractions .15 .35 .35 .35
@headitem Fortran Type @tab Named constant @tab C type @tab Extension
@@ -15209,11 +15209,11 @@ Furthermore, if @code{__float128} is supported in C, the named constants
@item @code{REAL} @tab @code{C_FLOAT} @tab @code{float}
@item @code{REAL} @tab @code{C_DOUBLE} @tab @code{double}
@item @code{REAL} @tab @code{C_LONG_DOUBLE} @tab @code{long double}
-@item @code{REAL} @tab @code{C_FLOAT128} @tab @code{__float128} @tab Ext.
+@item @code{REAL} @tab @code{C_FLOAT128} @tab @code{_Float128} @tab Ext.
@item @code{COMPLEX}@tab @code{C_FLOAT_COMPLEX} @tab @code{float _Complex}
@item @code{COMPLEX}@tab @code{C_DOUBLE_COMPLEX}@tab @code{double _Complex}
@item @code{COMPLEX}@tab @code{C_LONG_DOUBLE_COMPLEX}@tab @code{long double _Complex}
-@item @code{REAL} @tab @code{C_FLOAT128_COMPLEX} @tab @code{__float128 _Complex} @tab Ext.
+@item @code{COMPLEX}@tab @code{C_FLOAT128_COMPLEX} @tab @code{_Float128 _Complex} @tab Ext.
@item @code{LOGICAL}@tab @code{C_BOOL} @tab @code{_Bool}
@item @code{CHARACTER}@tab @code{C_CHAR} @tab @code{char}
@end multitable
diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def
index e65c750..50256fe 100644
--- a/gcc/fortran/iso-c-binding.def
+++ b/gcc/fortran/iso-c-binding.def
@@ -116,7 +116,7 @@ NAMED_REALCST (ISOCBINDING_LONG_DOUBLE, "c_long_double", \
get_real_kind_from_node (long_double_type_node), GFC_STD_F2003)
/* GNU Extension. Note that the equivalence here is specifically to
- the IEEE 128-bit type __float128; if that does not map onto a type
+ the IEEE 128-bit type _Float128; if that does not map onto a type
otherwise supported by the Fortran front end, get_real_kind_from_node
will reject it as unsupported. */
NAMED_REALCST (ISOCBINDING_FLOAT128, "c_float128", \
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 16502da..53a575e 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -4079,7 +4079,7 @@ gfc_match_goto (void)
}
while (gfc_match_char (',') == MATCH_YES);
- if (gfc_match (")%t") != MATCH_YES)
+ if (gfc_match (" )%t") != MATCH_YES)
goto syntax;
if (head == NULL)
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 92fd127..21e94f7 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -160,6 +160,7 @@ match gfc_match_omp_critical (void);
match gfc_match_omp_declare_reduction (void);
match gfc_match_omp_declare_simd (void);
match gfc_match_omp_declare_target (void);
+match gfc_match_omp_declare_variant (void);
match gfc_match_omp_depobj (void);
match gfc_match_omp_distribute (void);
match gfc_match_omp_distribute_parallel_do (void);
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index 3d449ae1..e6402e8 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -130,7 +130,6 @@ gfc_typename (gfc_typespec *ts, bool for_hash)
static char buffer2[GFC_MAX_SYMBOL_LEN + 8];
static int flag = 0;
char *buffer;
- gfc_typespec *ts1;
gfc_charlen_t length = 0;
buffer = flag ? buffer1 : buffer2;
@@ -180,16 +179,17 @@ gfc_typename (gfc_typespec *ts, bool for_hash)
sprintf (buffer, "TYPE(%s)", ts->u.derived->name);
break;
case BT_CLASS:
- if (ts->u.derived == NULL)
+ if (!ts->u.derived || !ts->u.derived->components
+ || !ts->u.derived->components->ts.u.derived)
{
sprintf (buffer, "invalid class");
break;
}
- ts1 = ts->u.derived->components ? &ts->u.derived->components->ts : NULL;
- if (ts1 && ts1->u.derived && ts1->u.derived->attr.unlimited_polymorphic)
+ if (ts->u.derived->components->ts.u.derived->attr.unlimited_polymorphic)
sprintf (buffer, "CLASS(*)");
else
- sprintf (buffer, "CLASS(%s)", ts->u.derived->name);
+ sprintf (buffer, "CLASS(%s)",
+ ts->u.derived->components->ts.u.derived->name);
break;
case BT_ASSUMED:
sprintf (buffer, "TYPE(*)");
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 1804066..7b98ba5 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -5592,6 +5592,9 @@ read_module (void)
for (i = GFC_INTRINSIC_BEGIN; i != GFC_INTRINSIC_END; i++)
{
+ gfc_use_rename *u = NULL, *v = NULL;
+ int j = i;
+
if (i == INTRINSIC_USER)
continue;
@@ -5599,18 +5602,73 @@ read_module (void)
{
u = find_use_operator ((gfc_intrinsic_op) i);
- if (u == NULL)
+ /* F2018:10.1.5.5.1 requires same interpretation of old and new-style
+ relational operators. Special handling for USE, ONLY. */
+ switch (i)
+ {
+ case INTRINSIC_EQ:
+ j = INTRINSIC_EQ_OS;
+ break;
+ case INTRINSIC_EQ_OS:
+ j = INTRINSIC_EQ;
+ break;
+ case INTRINSIC_NE:
+ j = INTRINSIC_NE_OS;
+ break;
+ case INTRINSIC_NE_OS:
+ j = INTRINSIC_NE;
+ break;
+ case INTRINSIC_GT:
+ j = INTRINSIC_GT_OS;
+ break;
+ case INTRINSIC_GT_OS:
+ j = INTRINSIC_GT;
+ break;
+ case INTRINSIC_GE:
+ j = INTRINSIC_GE_OS;
+ break;
+ case INTRINSIC_GE_OS:
+ j = INTRINSIC_GE;
+ break;
+ case INTRINSIC_LT:
+ j = INTRINSIC_LT_OS;
+ break;
+ case INTRINSIC_LT_OS:
+ j = INTRINSIC_LT;
+ break;
+ case INTRINSIC_LE:
+ j = INTRINSIC_LE_OS;
+ break;
+ case INTRINSIC_LE_OS:
+ j = INTRINSIC_LE;
+ break;
+ default:
+ break;
+ }
+
+ if (j != i)
+ v = find_use_operator ((gfc_intrinsic_op) j);
+
+ if (u == NULL && v == NULL)
{
skip_list ();
continue;
}
- u->found = 1;
+ if (u)
+ u->found = 1;
+ if (v)
+ v->found = 1;
}
mio_interface (&gfc_current_ns->op[i]);
- if (u && !gfc_current_ns->op[i])
- u->found = 0;
+ if (!gfc_current_ns->op[i] && !gfc_current_ns->op[j])
+ {
+ if (u)
+ u->found = 0;
+ if (v)
+ v->found = 0;
+ }
}
mio_rparen ();
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 715fd32..2a161f3 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -168,6 +168,70 @@ gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
}
}
+static void
+gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
+{
+ while (list)
+ {
+ gfc_omp_trait_property *current = list;
+ list = list->next;
+ switch (current->property_kind)
+ {
+ case CTX_PROPERTY_ID:
+ free (current->name);
+ break;
+ case CTX_PROPERTY_NAME_LIST:
+ if (current->is_name)
+ free (current->name);
+ break;
+ case CTX_PROPERTY_SIMD:
+ gfc_free_omp_clauses (current->clauses);
+ break;
+ default:
+ break;
+ }
+ free (current);
+ }
+}
+
+static void
+gfc_free_omp_selector_list (gfc_omp_selector *list)
+{
+ while (list)
+ {
+ gfc_omp_selector *current = list;
+ list = list->next;
+ gfc_free_omp_trait_property_list (current->properties);
+ free (current);
+ }
+}
+
+static void
+gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
+{
+ while (list)
+ {
+ gfc_omp_set_selector *current = list;
+ list = list->next;
+ gfc_free_omp_selector_list (current->trait_selectors);
+ free (current);
+ }
+}
+
+/* Free an !$omp declare variant construct list. */
+
+void
+gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
+{
+ while (list)
+ {
+ gfc_omp_declare_variant *current = list;
+ list = list->next;
+ gfc_free_omp_set_selector_list (current->set_selectors);
+ free (current);
+ }
+}
+
/* Free an !$omp declare reduction. */
void
@@ -1353,7 +1417,7 @@ gfc_match_dupl_atomic (bool not_dupl, const char *name)
static match
gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
bool first = true, bool needs_space = true,
- bool openacc = false)
+ bool openacc = false, bool context_selector = false)
{
bool error = false;
gfc_omp_clauses *c = gfc_get_omp_clauses ();
@@ -1825,11 +1889,54 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
continue;
if ((mask & OMP_CLAUSE_DEVICE)
&& !openacc
- && (m = gfc_match_dupl_check (!c->device, "device", true,
- &c->device)) != MATCH_NO)
+ && ((m = gfc_match_dupl_check (!c->device, "device", true))
+ != MATCH_NO))
{
if (m == MATCH_ERROR)
goto error;
+ c->ancestor = false;
+ if (gfc_match ("device_num : ") == MATCH_YES)
+ {
+ if (gfc_match ("%e )", &c->device) != MATCH_YES)
+ {
+ gfc_error ("Expected integer expression at %C");
+ break;
+ }
+ }
+ else if (gfc_match ("ancestor : ") == MATCH_YES)
+ {
+ c->ancestor = true;
+ if (!(gfc_current_ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
+ {
+ gfc_error ("%<ancestor%> device modifier not "
+ "preceded by %<requires%> directive "
+ "with %<reverse_offload%> clause at %C");
+ break;
+ }
+ locus old_loc2 = gfc_current_locus;
+ if (gfc_match ("%e )", &c->device) == MATCH_YES)
+ {
+ int device = 0;
+ if (!gfc_extract_int (c->device, &device) && device != 1)
+ {
+ gfc_current_locus = old_loc2;
+ gfc_error ("the %<device%> clause expression must "
+ "evaluate to %<1%> at %C");
+ break;
+ }
+ }
+ else
+ {
+ gfc_error ("Expected integer expression at %C");
+ break;
+ }
+ }
+ else if (gfc_match ("%e )", &c->device) != MATCH_YES)
+ {
+ gfc_error ("Expected integer expression or a single device-"
+ "modifier %<device_num%> or %<ancestor%> at %C");
+ break;
+ }
continue;
}
if ((mask & OMP_CLAUSE_DEVICE)
@@ -2326,9 +2433,24 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
break;
case 'o':
if ((mask & OMP_CLAUSE_ORDER)
- && !c->order_concurrent
- && gfc_match ("order ( concurrent )") == MATCH_YES)
+ && (m = gfc_match_dupl_check (!c->order_concurrent, "order ("))
+ != MATCH_NO)
{
+ if (m == MATCH_ERROR)
+ goto error;
+ if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
+ c->order_reproducible = true;
+ else if (gfc_match (" concurrent )") == MATCH_YES)
+ ;
+ else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
+ c->order_unconstrained = true;
+ else
+ {
+ gfc_error ("Expected ORDER(CONCURRENT) at %C "
+ "with optional %<reproducible%> or "
+ "%<unconstrained%> modifier");
+ goto error;
+ }
c->order_concurrent = true;
continue;
}
@@ -2785,7 +2907,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
end:
- if (error || gfc_match_omp_eos () != MATCH_YES)
+ if (error
+ || (context_selector && gfc_peek_ascii_char () != ')')
+ || (!context_selector && gfc_match_omp_eos () != MATCH_YES))
{
if (!gfc_error_flag_test ())
gfc_error ("Failed to match clause at %C");
@@ -3432,7 +3556,8 @@ cleanup:
| OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION)
#define OMP_DISTRIBUTE_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
- | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE)
+ | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
+ | OMP_CLAUSE_ORDER)
#define OMP_SINGLE_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE)
#define OMP_ORDERED_CLAUSES \
@@ -3739,7 +3864,9 @@ gfc_match_omp_flush (void)
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)
+ if (gfc_match ("seq_cst") == MATCH_YES)
+ mo = OMP_MEMORDER_SEQ_CST;
+ else if (gfc_match ("acq_rel") == MATCH_YES)
mo = OMP_MEMORDER_ACQ_REL;
else if (gfc_match ("release") == MATCH_YES)
mo = OMP_MEMORDER_RELEASE;
@@ -3747,7 +3874,7 @@ gfc_match_omp_flush (void)
mo = OMP_MEMORDER_ACQUIRE;
else
{
- gfc_error ("Expected AQC_REL, RELEASE, or ACQUIRE at %C");
+ gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
return MATCH_ERROR;
}
c = gfc_get_omp_clauses ();
@@ -4368,6 +4495,449 @@ cleanup:
}
+static const char *const omp_construct_selectors[] = {
+ "simd", "target", "teams", "parallel", "do", NULL };
+static const char *const omp_device_selectors[] = {
+ "kind", "isa", "arch", NULL };
+static const char *const omp_implementation_selectors[] = {
+ "vendor", "extension", "atomic_default_mem_order", "unified_address",
+ "unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
+static const char *const omp_user_selectors[] = {
+ "condition", NULL };
+
+
+/* OpenMP 5.0:
+
+ trait-selector:
+ trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
+
+ trait-score:
+ score(score-expression) */
+
+match
+gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
+{
+ do
+ {
+ char selector[GFC_MAX_SYMBOL_LEN + 1];
+
+ if (gfc_match_name (selector) != MATCH_YES)
+ {
+ gfc_error ("expected trait selector name at %C");
+ return MATCH_ERROR;
+ }
+
+ gfc_omp_selector *os = gfc_get_omp_selector ();
+ os->trait_selector_name = XNEWVEC (char, strlen (selector) + 1);
+ strcpy (os->trait_selector_name, selector);
+ os->next = oss->trait_selectors;
+ oss->trait_selectors = os;
+
+ const char *const *selectors = NULL;
+ bool allow_score = true;
+ bool allow_user = false;
+ int property_limit = 0;
+ enum gfc_omp_trait_property_kind property_kind = CTX_PROPERTY_NONE;
+ switch (oss->trait_set_selector_name[0])
+ {
+ case 'c': /* construct */
+ selectors = omp_construct_selectors;
+ allow_score = false;
+ property_limit = 1;
+ property_kind = CTX_PROPERTY_SIMD;
+ break;
+ case 'd': /* device */
+ selectors = omp_device_selectors;
+ allow_score = false;
+ allow_user = true;
+ property_limit = 3;
+ property_kind = CTX_PROPERTY_NAME_LIST;
+ break;
+ case 'i': /* implementation */
+ selectors = omp_implementation_selectors;
+ allow_user = true;
+ property_limit = 3;
+ property_kind = CTX_PROPERTY_NAME_LIST;
+ break;
+ case 'u': /* user */
+ selectors = omp_user_selectors;
+ property_limit = 1;
+ property_kind = CTX_PROPERTY_EXPR;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ for (int i = 0; ; i++)
+ {
+ if (selectors[i] == NULL)
+ {
+ if (allow_user)
+ {
+ property_kind = CTX_PROPERTY_USER;
+ break;
+ }
+ else
+ {
+ gfc_error ("selector '%s' not allowed for context selector "
+ "set '%s' at %C",
+ selector, oss->trait_set_selector_name);
+ return MATCH_ERROR;
+ }
+ }
+ if (i == property_limit)
+ property_kind = CTX_PROPERTY_NONE;
+ if (strcmp (selectors[i], selector) == 0)
+ break;
+ }
+ if (property_kind == CTX_PROPERTY_NAME_LIST
+ && oss->trait_set_selector_name[0] == 'i'
+ && strcmp (selector, "atomic_default_mem_order") == 0)
+ property_kind = CTX_PROPERTY_ID;
+
+ if (gfc_match (" (") == MATCH_YES)
+ {
+ if (property_kind == CTX_PROPERTY_NONE)
+ {
+ gfc_error ("selector '%s' does not accept any properties at %C",
+ selector);
+ return MATCH_ERROR;
+ }
+
+ if (allow_score && gfc_match (" score") == MATCH_YES)
+ {
+ if (gfc_match (" (") != MATCH_YES)
+ {
+ gfc_error ("expected '(' at %C");
+ return MATCH_ERROR;
+ }
+ if (gfc_match_expr (&os->score) != MATCH_YES
+ || !gfc_resolve_expr (os->score)
+ || os->score->ts.type != BT_INTEGER
+ || os->score->rank != 0)
+ {
+ gfc_error ("score argument must be constant integer "
+ "expression at %C");
+ return MATCH_ERROR;
+ }
+
+ if (os->score->expr_type == EXPR_CONSTANT
+ && mpz_sgn (os->score->value.integer) < 0)
+ {
+ gfc_error ("score argument must be non-negative at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_match (" )") != MATCH_YES)
+ {
+ gfc_error ("expected ')' at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_match (" :") != MATCH_YES)
+ {
+ gfc_error ("expected : at %C");
+ return MATCH_ERROR;
+ }
+ }
+
+ gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
+ otp->property_kind = property_kind;
+ otp->next = os->properties;
+ os->properties = otp;
+
+ switch (property_kind)
+ {
+ case CTX_PROPERTY_USER:
+ do
+ {
+ if (gfc_match_expr (&otp->expr) != MATCH_YES)
+ {
+ gfc_error ("property must be constant integer "
+ "expression or string literal at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_match (" ,") != MATCH_YES)
+ break;
+ }
+ while (1);
+ break;
+ case CTX_PROPERTY_ID:
+ {
+ char buf[GFC_MAX_SYMBOL_LEN + 1];
+ if (gfc_match_name (buf) == MATCH_YES)
+ {
+ otp->name = XNEWVEC (char, strlen (buf) + 1);
+ strcpy (otp->name, buf);
+ }
+ else
+ {
+ gfc_error ("expected identifier at %C");
+ return MATCH_ERROR;
+ }
+ }
+ break;
+ case CTX_PROPERTY_NAME_LIST:
+ do
+ {
+ char buf[GFC_MAX_SYMBOL_LEN + 1];
+ if (gfc_match_name (buf) == MATCH_YES)
+ {
+ otp->name = XNEWVEC (char, strlen (buf) + 1);
+ strcpy (otp->name, buf);
+ otp->is_name = true;
+ }
+ else if (gfc_match_literal_constant (&otp->expr, 0)
+ != MATCH_YES
+ || otp->expr->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("expected identifier or string literal "
+ "at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_match (" ,") == MATCH_YES)
+ {
+ otp = gfc_get_omp_trait_property ();
+ otp->property_kind = property_kind;
+ otp->next = os->properties;
+ os->properties = otp;
+ }
+ else
+ break;
+ }
+ while (1);
+ break;
+ case CTX_PROPERTY_EXPR:
+ if (gfc_match_expr (&otp->expr) != MATCH_YES)
+ {
+ gfc_error ("expected expression at %C");
+ return MATCH_ERROR;
+ }
+ if (!gfc_resolve_expr (otp->expr)
+ || (otp->expr->ts.type != BT_LOGICAL
+ && otp->expr->ts.type != BT_INTEGER)
+ || otp->expr->rank != 0)
+ {
+ gfc_error ("property must be constant integer or logical "
+ "expression at %C");
+ return MATCH_ERROR;
+ }
+ break;
+ case CTX_PROPERTY_SIMD:
+ {
+ if (gfc_match_omp_clauses (&otp->clauses,
+ OMP_DECLARE_SIMD_CLAUSES,
+ true, false, false, true)
+ != MATCH_YES)
+ {
+ gfc_error ("expected simd clause at %C");
+ return MATCH_ERROR;
+ }
+ break;
+ }
+ default:
+ gcc_unreachable ();
+ }
+
+ if (gfc_match (" )") != MATCH_YES)
+ {
+ gfc_error ("expected ')' at %C");
+ return MATCH_ERROR;
+ }
+ }
+ else if (property_kind == CTX_PROPERTY_NAME_LIST
+ || property_kind == CTX_PROPERTY_ID
+ || property_kind == CTX_PROPERTY_EXPR)
+ {
+ if (gfc_match (" (") != MATCH_YES)
+ {
+ gfc_error ("expected '(' at %C");
+ return MATCH_ERROR;
+ }
+ }
+
+ if (gfc_match (" ,") != MATCH_YES)
+ break;
+ }
+ while (1);
+
+ return MATCH_YES;
+}
+
+/* OpenMP 5.0:
+
+ trait-set-selector[,trait-set-selector[,...]]
+
+ trait-set-selector:
+ trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
+
+ trait-set-selector-name:
+ constructor
+ device
+ implementation
+ user */
+
+match
+gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv)
+{
+ do
+ {
+ match m;
+ const char *selector_sets[] = { "construct", "device",
+ "implementation", "user" };
+ const int selector_set_count
+ = sizeof (selector_sets) / sizeof (*selector_sets);
+ int i;
+ char buf[GFC_MAX_SYMBOL_LEN + 1];
+
+ m = gfc_match_name (buf);
+ if (m == MATCH_YES)
+ for (i = 0; i < selector_set_count; i++)
+ if (strcmp (buf, selector_sets[i]) == 0)
+ break;
+
+ if (m != MATCH_YES || i == selector_set_count)
+ {
+ gfc_error ("expected 'construct', 'device', 'implementation' or "
+ "'user' at %C");
+ return MATCH_ERROR;
+ }
+
+ m = gfc_match (" =");
+ if (m != MATCH_YES)
+ {
+ gfc_error ("expected '=' at %C");
+ return MATCH_ERROR;
+ }
+
+ m = gfc_match (" {");
+ if (m != MATCH_YES)
+ {
+ gfc_error ("expected '{' at %C");
+ return MATCH_ERROR;
+ }
+
+ gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
+ oss->next = odv->set_selectors;
+ oss->trait_set_selector_name = selector_sets[i];
+ odv->set_selectors = oss;
+
+ if (gfc_match_omp_context_selector (oss) != MATCH_YES)
+ return MATCH_ERROR;
+
+ m = gfc_match (" }");
+ if (m != MATCH_YES)
+ {
+ gfc_error ("expected '}' at %C");
+ return MATCH_ERROR;
+ }
+
+ m = gfc_match (" ,");
+ if (m != MATCH_YES)
+ break;
+ }
+ while (1);
+
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_declare_variant (void)
+{
+ bool first_p = true;
+ char buf[GFC_MAX_SYMBOL_LEN + 1];
+
+ if (gfc_match (" (") != MATCH_YES)
+ {
+ gfc_error ("expected '(' at %C");
+ return MATCH_ERROR;
+ }
+
+ gfc_symtree *base_proc_st, *variant_proc_st;
+ if (gfc_match_name (buf) != MATCH_YES)
+ {
+ gfc_error ("expected name at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_get_ha_sym_tree (buf, &base_proc_st))
+ return MATCH_ERROR;
+
+ if (gfc_match (" :") == MATCH_YES)
+ {
+ if (gfc_match_name (buf) != MATCH_YES)
+ {
+ gfc_error ("expected variant name at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
+ return MATCH_ERROR;
+ }
+ else
+ {
+ /* Base procedure not specified. */
+ variant_proc_st = base_proc_st;
+ base_proc_st = NULL;
+ }
+
+ gfc_omp_declare_variant *odv;
+ odv = gfc_get_omp_declare_variant ();
+ odv->where = gfc_current_locus;
+ odv->variant_proc_symtree = variant_proc_st;
+ odv->base_proc_symtree = base_proc_st;
+ odv->next = NULL;
+ odv->error_p = false;
+
+ /* Add the new declare variant to the end of the list. */
+ gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
+ while (*prev_next)
+ prev_next = &((*prev_next)->next);
+ *prev_next = odv;
+
+ if (gfc_match (" )") != MATCH_YES)
+ {
+ gfc_error ("expected ')' at %C");
+ return MATCH_ERROR;
+ }
+
+ for (;;)
+ {
+ if (gfc_match (" match") != MATCH_YES)
+ {
+ if (first_p)
+ {
+ gfc_error ("expected 'match' at %C");
+ return MATCH_ERROR;
+ }
+ else
+ break;
+ }
+
+ if (gfc_match (" (") != MATCH_YES)
+ {
+ gfc_error ("expected '(' at %C");
+ return MATCH_ERROR;
+ }
+
+ if (gfc_match_omp_context_selector_specification (odv) != MATCH_YES)
+ return MATCH_ERROR;
+
+ if (gfc_match (" )") != MATCH_YES)
+ {
+ gfc_error ("expected ')' at %C");
+ return MATCH_ERROR;
+ }
+
+ first_p = false;
+ }
+
+ return MATCH_YES;
+}
+
+
match
gfc_match_omp_threadprivate (void)
{
@@ -5598,7 +6168,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
&code->loc);
-
+ if (omp_clauses->order_concurrent && omp_clauses->ordered)
+ gfc_error ("ORDER clause must not be used together ORDERED at %L",
+ &code->loc);
if (omp_clauses->if_expr)
{
gfc_expr *expr = omp_clauses->if_expr;
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 1723f68..3499a1c 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -159,14 +159,7 @@ gfc_init_options (unsigned int decoded_options_count,
| GFC_FPE_UNDERFLOW;
gfc_option.rtcheck = 0;
- /* ??? Wmissing-include-dirs is disabled by default in C/C++ but
- enabled by default in Fortran. Ideally, we should express this
- in .opt, but that is not supported yet. */
- SET_OPTION_IF_UNSET (&global_options, &global_options_set,
- cpp_warn_missing_include_dirs, 1);
-
set_dec_flags (0);
-
set_default_std_flags ();
/* Initialize cpp-related options. */
@@ -258,8 +251,21 @@ gfc_post_options (const char **pfilename)
{
const char *filename = *pfilename, *canon_source_file = NULL;
char *source_path;
+ bool verbose_missing_dir_warn;
int i;
+ /* This needs to be after the commandline has been processed.
+ In Fortran, the options is by default enabled, in C/C++
+ by default disabled.
+ If not enabled explicitly by the user, only warn for -I
+ and -J, otherwise warn for all include paths. */
+ verbose_missing_dir_warn
+ = (OPTION_SET_P (cpp_warn_missing_include_dirs)
+ && global_options.x_cpp_warn_missing_include_dirs);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ cpp_warn_missing_include_dirs, 1);
+ gfc_check_include_dirs (verbose_missing_dir_warn);
+
/* Finalize DEC flags. */
post_dec_flags (flag_dec);
@@ -267,6 +273,9 @@ gfc_post_options (const char **pfilename)
support. */
if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
sorry ("%<-fexcess-precision=standard%> for Fortran");
+ else if (flag_excess_precision == EXCESS_PRECISION_FLOAT16)
+ sorry ("%<-fexcess-precision=16%> for Fortran");
+
flag_excess_precision = EXCESS_PRECISION_FAST;
/* Fortran allows associative math - but we cannot reassociate if
@@ -300,7 +309,7 @@ gfc_post_options (const char **pfilename)
flag_dump_fortran_original = 0;
/* Make -fmax-errors visible to gfortran's diagnostic machinery. */
- if (global_options_set.x_flag_max_errors)
+ if (OPTION_SET_P (flag_max_errors))
gfc_option.max_errors = flag_max_errors;
/* Verify the input file name. */
@@ -336,10 +345,13 @@ gfc_post_options (const char **pfilename)
source_path = (char *) alloca (i + 1);
memcpy (source_path, canon_source_file, i);
source_path[i] = 0;
- gfc_add_include_path (source_path, true, true, true);
+ /* Only warn if the directory is different from the input file as
+ if that one is not found, already an error is shown. */
+ bool warn = gfc_option.flag_preprocessed && gfc_source_file != filename;
+ gfc_add_include_path (source_path, true, true, warn, false);
}
else
- gfc_add_include_path (".", true, true, true);
+ gfc_add_include_path (".", true, true, false, false);
if (canon_source_file != gfc_source_file)
free (CONST_CAST (char *, canon_source_file));
@@ -376,7 +388,7 @@ gfc_post_options (const char **pfilename)
/* Enable -Werror=line-truncation when -Werror and -Wno-error have
not been set. */
- if (warn_line_truncation && !global_options_set.x_warnings_are_errors
+ if (warn_line_truncation && !OPTION_SET_P (warnings_are_errors)
&& (global_dc->classify_diagnostic[OPT_Wline_truncation] ==
DK_UNSPECIFIED))
diagnostic_classify_diagnostic (global_dc, OPT_Wline_truncation,
@@ -487,7 +499,7 @@ gfc_post_options (const char **pfilename)
gfc_fatal_error ("Maximum subrecord length cannot exceed %d",
MAX_SUBRECORD_LENGTH);
- gfc_cpp_post_options ();
+ gfc_cpp_post_options (verbose_missing_dir_warn);
if (gfc_option.allow_std & GFC_STD_F2008)
lang_hooks.name = "GNU Fortran2008";
@@ -508,7 +520,7 @@ gfc_handle_module_path_options (const char *arg)
gfc_option.module_dir = XCNEWVEC (char, strlen (arg) + 2);
strcpy (gfc_option.module_dir, arg);
- gfc_add_include_path (gfc_option.module_dir, true, false, true);
+ gfc_add_include_path (gfc_option.module_dir, true, false, true, true);
strcat (gfc_option.module_dir, "/");
}
@@ -687,7 +699,7 @@ gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
with intrinsic modules. Do no warn because during testing
without an installed compiler, we would get lots of bogus
warnings for a missing include directory. */
- gfc_add_include_path (arg, false, false, false);
+ gfc_add_include_path (arg, false, false, false, true);
gfc_add_intrinsic_modules_path (arg);
break;
@@ -734,7 +746,7 @@ gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_I:
- gfc_add_include_path (arg, true, false, true);
+ gfc_add_include_path (arg, true, false, true, true);
break;
case OPT_J:
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index d37a0b5..2a454be 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3. If not see
#include <setjmp.h>
#include "match.h"
#include "parse.h"
+#include "tree-core.h"
+#include "omp-general.h"
/* Current statement label. Zero means no statement label. Because new_st
can get wiped during statement matching, we have to keep it separate. */
@@ -860,6 +862,8 @@ decode_omp_directive (void)
ST_OMP_DECLARE_SIMD);
matchdo ("declare target", gfc_match_omp_declare_target,
ST_OMP_DECLARE_TARGET);
+ matchdo ("declare variant", gfc_match_omp_declare_variant,
+ ST_OMP_DECLARE_VARIANT);
break;
case 's':
matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
@@ -1718,6 +1722,7 @@ next_statement (void)
#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_DECLARE_VARIANT: \
case ST_OMP_REQUIRES: case ST_OACC_ROUTINE: case ST_OACC_DECLARE
/* Block end statements. Errors associated with interchanging these
@@ -2361,6 +2366,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_DECLARE_TARGET:
p = "!$OMP DECLARE TARGET";
break;
+ case ST_OMP_DECLARE_VARIANT:
+ p = "!$OMP DECLARE VARIANT";
+ break;
case ST_OMP_DEPOBJ:
p = "!$OMP DEPOBJ";
break;
@@ -2406,6 +2414,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_END_DO_SIMD:
p = "!$OMP END DO SIMD";
break;
+ case ST_OMP_END_SCOPE:
+ p = "!$OMP END SCOPE";
+ break;
case ST_OMP_END_SIMD:
p = "!$OMP END SIMD";
break;
@@ -6790,6 +6801,24 @@ done:
gfc_current_ns = gfc_current_ns->sibling)
gfc_check_omp_requires (gfc_current_ns, omp_requires);
+ /* Populate omp_requires_mask (needed for resolving OpenMP
+ metadirectives and declare variant). */
+ switch (omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
+ {
+ case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_SEQ_CST);
+ break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_ACQ_REL);
+ break;
+ case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_RELAXED);
+ break;
+ }
+
/* Do the parse tree dump. */
gfc_current_ns = flag_dump_fortran_original ? gfc_global_ns_list : NULL;
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 56a78d6..d873264 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2627,7 +2627,7 @@ check_substring:
symbol_attribute
gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
{
- int dimension, codimension, pointer, allocatable, target;
+ int dimension, codimension, pointer, allocatable, target, optional;
symbol_attribute attr;
gfc_ref *ref;
gfc_symbol *sym;
@@ -2640,12 +2640,14 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
sym = expr->symtree->n.sym;
attr = sym->attr;
+ optional = attr.optional;
if (sym->ts.type == BT_CLASS && sym->attr.class_ok && sym->ts.u.derived)
{
dimension = CLASS_DATA (sym)->attr.dimension;
codimension = CLASS_DATA (sym)->attr.codimension;
pointer = CLASS_DATA (sym)->attr.class_pointer;
allocatable = CLASS_DATA (sym)->attr.allocatable;
+ optional |= CLASS_DATA (sym)->attr.optional;
}
else
{
@@ -2667,6 +2669,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
if (ref->type == REF_INQUIRY)
{
has_inquiry_part = true;
+ optional = false;
break;
}
@@ -2684,12 +2687,13 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
case AR_SECTION:
allocatable = pointer = 0;
dimension = 1;
+ optional = false;
break;
case AR_ELEMENT:
/* Handle coarrays. */
if (ref->u.ar.dimen > 0)
- allocatable = pointer = 0;
+ allocatable = pointer = optional = false;
break;
case AR_UNKNOWN:
@@ -2702,6 +2706,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
break;
case REF_COMPONENT:
+ optional = false;
comp = ref->u.c.component;
attr = comp->attr;
if (ts != NULL && !has_inquiry_part)
@@ -2723,7 +2728,10 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
else
{
codimension = comp->attr.codimension;
- pointer = comp->attr.pointer;
+ if (expr->ts.type == BT_CLASS && strcmp (comp->name, "_data") == 0)
+ pointer = comp->attr.class_pointer;
+ else
+ pointer = comp->attr.pointer;
allocatable = comp->attr.allocatable;
}
if (pointer || attr.proc_pointer)
@@ -2733,7 +2741,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
case REF_INQUIRY:
case REF_SUBSTRING:
- allocatable = pointer = 0;
+ allocatable = pointer = optional = false;
break;
}
@@ -2743,6 +2751,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
attr.allocatable = allocatable;
attr.target = target;
attr.save = sym->attr.save;
+ attr.optional = optional;
return attr;
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 5b9ba43..5ccd907 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -804,6 +804,15 @@ resolve_entries (gfc_namespace *ns)
the same string length, i.e. both len=*, or both len=4.
Having both len=<variable> is also possible, but difficult to
check at compile time. */
+ else if (ts->type == BT_CHARACTER
+ && (el->sym->result->attr.allocatable
+ != ns->entries->sym->result->attr.allocatable))
+ {
+ gfc_error ("Function %s at %L has entry %s with mismatched "
+ "characteristics", ns->entries->sym->name,
+ &ns->entries->sym->declared_at, el->sym->name);
+ goto cleanup;
+ }
else if (ts->type == BT_CHARACTER && ts->u.cl && fts->u.cl
&& (((ts->u.cl->length && !fts->u.cl->length)
||(!ts->u.cl->length && fts->u.cl->length))
@@ -908,6 +917,8 @@ resolve_entries (gfc_namespace *ns)
}
}
}
+
+cleanup:
proc->attr.access = ACCESS_PRIVATE;
proc->attr.entry_master = 1;
@@ -970,7 +981,7 @@ resolve_common_vars (gfc_common_head *common_block, bool named_common)
}
if (UNLIMITED_POLY (csym))
- gfc_error_now ("%qs in cannot appear in COMMON at %L "
+ gfc_error_now ("%qs at %L cannot appear in COMMON "
"[F2008:C5100]", csym->name, &csym->declared_at);
if (csym->ts.type != BT_DERIVED)
@@ -1443,6 +1454,34 @@ resolve_structure_cons (gfc_expr *expr, int init)
}
}
+ /* Validate shape, except for dynamic or PDT arrays. */
+ if (cons->expr->expr_type == EXPR_ARRAY && rank == cons->expr->rank
+ && comp->as && !comp->attr.allocatable && !comp->attr.pointer
+ && !comp->attr.pdt_array)
+ {
+ mpz_t len;
+ mpz_init (len);
+ for (int n = 0; n < rank; n++)
+ {
+ gcc_assert (comp->as->upper[n]->expr_type == EXPR_CONSTANT
+ && comp->as->lower[n]->expr_type == EXPR_CONSTANT);
+ mpz_set_ui (len, 1);
+ mpz_add (len, len, comp->as->upper[n]->value.integer);
+ mpz_sub (len, len, comp->as->lower[n]->value.integer);
+ if (mpz_cmp (cons->expr->shape[n], len) != 0)
+ {
+ gfc_error ("The shape of component %qs in the structure "
+ "constructor at %L differs from the shape of the "
+ "declared component for dimension %d (%ld/%ld)",
+ comp->name, &cons->expr->where, n+1,
+ mpz_get_si (cons->expr->shape[n]),
+ mpz_get_si (len));
+ t = false;
+ }
+ }
+ mpz_clear (len);
+ }
+
if (!comp->attr.pointer || comp->attr.proc_pointer
|| cons->expr->expr_type == EXPR_NULL)
continue;
@@ -7820,8 +7859,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
}
}
- /* Check for F08:C628. */
- if (allocatable == 0 && pointer == 0 && !unlimited)
+ /* Check for F08:C628 (F2018:C932). Each allocate-object shall be a data
+ pointer or an allocatable variable. */
+ if (allocatable == 0 && pointer == 0)
{
gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
&e->where);
@@ -12339,7 +12379,7 @@ resolve_values (gfc_symbol *sym)
if (sym->value == NULL)
return;
- if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED))
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym->attr.referenced)
gfc_warning (OPT_Wdeprecated_declarations,
"Using parameter %qs declared at %L is deprecated",
sym->name, &sym->declared_at);
@@ -12664,7 +12704,8 @@ can_generate_init (gfc_symbol *sym)
|| a->cray_pointer
|| sym->assoc
|| (!a->referenced && !a->result)
- || (a->dummy && a->intent != INTENT_OUT)
+ || (a->dummy && (a->intent != INTENT_OUT
+ || sym->ns->proc_name->attr.if_source == IFSRC_IFBODY))
|| (a->function && sym != sym->result)
);
}
@@ -12901,7 +12942,9 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
/* Assign default initializer. */
if (!(sym->value || sym->attr.pointer || sym->attr.allocatable)
- && (!no_init_flag || sym->attr.intent == INTENT_OUT))
+ && (!no_init_flag
+ || (sym->attr.intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY)))
sym->value = gfc_generate_initializer (&sym->ts, can_generate_init (sym));
return true;
@@ -16142,7 +16185,8 @@ resolve_symbol (gfc_symbol *sym)
|| sym->ts.u.derived->attr.alloc_comp
|| sym->ts.u.derived->attr.pointer_comp))
&& !(a->function && sym != sym->result))
- || (a->dummy && a->intent == INTENT_OUT && !a->pointer))
+ || (a->dummy && !a->pointer && a->intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY))
apply_default_init (sym);
else if (a->function && sym->result && a->access != ACCESS_PRIVATE
&& (sym->ts.u.derived->attr.alloc_comp
@@ -16154,6 +16198,7 @@ resolve_symbol (gfc_symbol *sym)
if (sym->ts.type == BT_CLASS && sym->ns == gfc_current_ns
&& sym->attr.dummy && sym->attr.intent == INTENT_OUT
+ && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY
&& !CLASS_DATA (sym)->attr.class_pointer
&& !CLASS_DATA (sym)->attr.allocatable)
apply_default_init (sym);
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 39db099..5a45069 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h" /* For set_src_pwd. */
#include "debug.h"
#include "options.h"
+#include "diagnostic-core.h" /* For fatal_error. */
#include "cpp.h"
#include "scanner.h"
@@ -298,17 +299,75 @@ gfc_scanner_done_1 (void)
}
}
+static bool
+gfc_do_check_include_dir (const char *path, bool warn)
+{
+ struct stat st;
+ if (stat (path, &st))
+ {
+ if (errno != ENOENT)
+ gfc_warning_now (0, "Include directory %qs: %s",
+ path, xstrerror(errno));
+ else if (warn)
+ gfc_warning_now (OPT_Wmissing_include_dirs,
+ "Nonexistent include directory %qs", path);
+ return false;
+ }
+ else if (!S_ISDIR (st.st_mode))
+ {
+ gfc_fatal_error ("%qs is not a directory", path);
+ return false;
+ }
+ return true;
+}
+
+/* In order that -W(no-)missing-include-dirs works, the diagnostic can only be
+ run after processing the commandline. */
+static void
+gfc_do_check_include_dirs (gfc_directorylist **list, bool do_warn)
+{
+ gfc_directorylist *prev, *q, *n;
+ prev = NULL;
+ n = *list;
+ while (n)
+ {
+ q = n; n = n->next;
+ if (gfc_do_check_include_dir (q->path, q->warn && do_warn))
+ {
+ prev = q;
+ continue;
+ }
+ if (prev == NULL)
+ *list = n;
+ else
+ prev->next = n;
+ free (q->path);
+ free (q);
+ }
+}
+
+void
+gfc_check_include_dirs (bool verbose_missing_dir_warn)
+{
+ /* This is a bit convoluted: If gfc_cpp_enabled () and
+ verbose_missing_dir_warn, the warning is shown by libcpp. Otherwise,
+ it is shown here, still conditional on OPT_Wmissing_include_dirs. */
+ bool warn = !gfc_cpp_enabled () || !verbose_missing_dir_warn;
+ gfc_do_check_include_dirs (&include_dirs, warn);
+ gfc_do_check_include_dirs (&intrinsic_modules_dirs, verbose_missing_dir_warn);
+ if (gfc_option.module_dir && gfc_cpp_enabled ())
+ gfc_do_check_include_dirs (&include_dirs, true);
+}
/* Adds path to the list pointed to by list. */
static void
add_path_to_list (gfc_directorylist **list, const char *path,
- bool use_for_modules, bool head, bool warn)
+ bool use_for_modules, bool head, bool warn, bool defer_warn)
{
gfc_directorylist *dir;
const char *p;
char *q;
- struct stat st;
size_t len;
int i;
@@ -326,21 +385,8 @@ add_path_to_list (gfc_directorylist **list, const char *path,
while (i >=0 && IS_DIR_SEPARATOR (q[i]))
q[i--] = '\0';
- if (stat (q, &st))
- {
- if (errno != ENOENT)
- gfc_warning_now (0, "Include directory %qs: %s", path,
- xstrerror(errno));
- else if (warn)
- gfc_warning_now (OPT_Wmissing_include_dirs,
- "Nonexistent include directory %qs", path);
- return;
- }
- else if (!S_ISDIR (st.st_mode))
- {
- gfc_fatal_error ("%qs is not a directory", path);
- return;
- }
+ if (!defer_warn && !gfc_do_check_include_dir (q, warn))
+ return;
if (head || *list == NULL)
{
@@ -362,17 +408,20 @@ add_path_to_list (gfc_directorylist **list, const char *path,
if (head)
*list = dir;
dir->use_for_modules = use_for_modules;
+ dir->warn = warn;
dir->path = XCNEWVEC (char, strlen (p) + 2);
strcpy (dir->path, p);
strcat (dir->path, "/"); /* make '/' last character */
}
+/* defer_warn is set to true while parsing the commandline. */
void
gfc_add_include_path (const char *path, bool use_for_modules, bool file_dir,
- bool warn)
+ bool warn, bool defer_warn)
{
- add_path_to_list (&include_dirs, path, use_for_modules, file_dir, warn);
+ add_path_to_list (&include_dirs, path, use_for_modules, file_dir, warn,
+ defer_warn);
/* For '#include "..."' these directories are automatically searched. */
if (!file_dir)
@@ -383,7 +432,7 @@ gfc_add_include_path (const char *path, bool use_for_modules, bool file_dir,
void
gfc_add_intrinsic_modules_path (const char *path)
{
- add_path_to_list (&intrinsic_modules_dirs, path, true, false, false);
+ add_path_to_list (&intrinsic_modules_dirs, path, true, false, false, false);
}
@@ -2182,7 +2231,7 @@ preprocessor_line (gfc_char_t *c)
}
-static bool load_file (const char *, const char *, bool);
+static void load_file (const char *, const char *, bool);
/* include_line()-- Checks a line buffer to see if it is an include
line. If so, we call load_file() recursively to load the included
@@ -2348,9 +2397,7 @@ include_line (gfc_char_t *line)
read by anything else. */
filename = gfc_widechar_to_char (begin, -1);
- if (!load_file (filename, NULL, false))
- exit (FATAL_EXIT_CODE);
-
+ load_file (filename, NULL, false);
free (filename);
return 1;
}
@@ -2457,9 +2504,7 @@ include_stmt (gfc_linebuf *b)
filename[i] = (unsigned char) c;
}
filename[length] = '\0';
- if (!load_file (filename, NULL, false))
- exit (FATAL_EXIT_CODE);
-
+ load_file (filename, NULL, false);
free (filename);
do_ret:
@@ -2477,9 +2522,11 @@ do_ret:
return ret;
}
+
+
/* Load a file into memory by calling load_line until the file ends. */
-static bool
+static void
load_file (const char *realfilename, const char *displayedname, bool initial)
{
gfc_char_t *line;
@@ -2501,13 +2548,8 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
for (f = current_file; f; f = f->up)
if (filename_cmp (filename, f->filename) == 0)
- {
- fprintf (stderr, "%s:%d: Error: File '%s' is being included "
- "recursively\n", current_file->filename, current_file->line,
- filename);
- return false;
- }
-
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "File %qs is being included recursively", filename);
if (initial)
{
if (gfc_src_file)
@@ -2519,10 +2561,7 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
input = gfc_open_file (realfilename);
if (input == NULL)
- {
- gfc_error_now ("Cannot open file %qs", filename);
- return false;
- }
+ gfc_fatal_error ("Cannot open file %qs", filename);
}
else
{
@@ -2531,22 +2570,20 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
{
/* For -fpre-include file, current_file is NULL. */
if (current_file)
- fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
- current_file->filename, current_file->line, filename);
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "Cannot open included file %qs", filename);
else
- fprintf (stderr, "Error: Can't open pre-included file '%s'\n",
- filename);
-
- return false;
+ gfc_fatal_error ("Cannot open pre-included file %qs", filename);
}
stat_result = stat (realfilename, &st);
- if (stat_result == 0 && !S_ISREG(st.st_mode))
+ if (stat_result == 0 && !S_ISREG (st.st_mode))
{
- fprintf (stderr, "%s:%d: Error: Included path '%s'"
- " is not a regular file\n",
- current_file->filename, current_file->line, filename);
fclose (input);
- return false;
+ if (current_file)
+ fatal_error (linemap_line_start (line_table, current_file->line, 0),
+ "Included file %qs is not a regular file", filename);
+ else
+ gfc_fatal_error ("Included file %qs is not a regular file", filename);
}
}
@@ -2720,7 +2757,6 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
add_file_change (NULL, current_file->inclusion_line + 1);
current_file = current_file->up;
linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
- return true;
}
@@ -2729,23 +2765,20 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
it tries to determine the source form from the filename, defaulting
to free form. */
-bool
+void
gfc_new_file (void)
{
- bool result;
-
- if (flag_pre_include != NULL
- && !load_file (flag_pre_include, NULL, false))
- exit (FATAL_EXIT_CODE);
+ if (flag_pre_include != NULL)
+ load_file (flag_pre_include, NULL, false);
if (gfc_cpp_enabled ())
{
- result = gfc_cpp_preprocess (gfc_source_file);
+ gfc_cpp_preprocess (gfc_source_file);
if (!gfc_cpp_preprocess_only ())
- result = load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
+ load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
}
else
- result = load_file (gfc_source_file, NULL, true);
+ load_file (gfc_source_file, NULL, true);
gfc_current_locus.lb = line_head;
gfc_current_locus.nextc = (line_head == NULL) ? NULL : line_head->line;
@@ -2757,8 +2790,6 @@ gfc_new_file (void)
exit (SUCCESS_EXIT_CODE);
#endif
-
- return result;
}
static char *
diff --git a/gcc/fortran/scanner.h b/gcc/fortran/scanner.h
index 0bad63f..8782fe6 100644
--- a/gcc/fortran/scanner.h
+++ b/gcc/fortran/scanner.h
@@ -23,8 +23,8 @@ along with GCC; see the file COPYING3. If not see
typedef struct gfc_directorylist
{
char *path;
- bool use_for_modules;
struct gfc_directorylist *next;
+ bool use_for_modules, warn;
}
gfc_directorylist;
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 4cb73e8..d675f2c 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -4533,14 +4533,7 @@ substring_has_constant_len (gfc_expr *e)
|| !ref->u.ss.start
|| ref->u.ss.start->expr_type != EXPR_CONSTANT
|| !ref->u.ss.end
- || ref->u.ss.end->expr_type != EXPR_CONSTANT
- || !ref->u.ss.length)
- return false;
-
- /* For non-deferred strings the given length shall be constant. */
- if (!e->ts.deferred
- && (!ref->u.ss.length->length
- || ref->u.ss.length->length->expr_type != EXPR_CONSTANT))
+ || ref->u.ss.end->expr_type != EXPR_CONSTANT)
return false;
/* Basic checks on substring starting and ending indices. */
@@ -4551,27 +4544,7 @@ substring_has_constant_len (gfc_expr *e)
iend = gfc_mpz_get_hwi (ref->u.ss.end->value.integer);
if (istart <= iend)
- {
- if (istart < 1)
- {
- gfc_error ("Substring start index (%wd) at %L below 1",
- istart, &ref->u.ss.start->where);
- return false;
- }
-
- /* For deferred strings use end index as proxy for length. */
- if (e->ts.deferred)
- length = iend;
- else
- length = gfc_mpz_get_hwi (ref->u.ss.length->length->value.integer);
- if (iend > length)
- {
- gfc_error ("Substring end index (%wd) at %L exceeds string length",
- iend, &ref->u.ss.end->where);
- return false;
- }
- length = iend - istart + 1;
- }
+ length = iend - istart + 1;
else
length = 0;
@@ -6867,7 +6840,13 @@ gfc_simplify_reshape (gfc_expr *source, gfc_expr *shape_exp,
gfc_extract_int (e, &shape[rank]);
gcc_assert (rank >= 0 && rank < GFC_MAX_DIMENSIONS);
- gcc_assert (shape[rank] >= 0);
+ if (shape[rank] < 0)
+ {
+ gfc_error ("The SHAPE array for the RESHAPE intrinsic at %L has a "
+ "negative value %d for dimension %d",
+ &shape_exp->where, shape[rank], rank+1);
+ return &gfc_bad_expr;
+ }
rank++;
}
@@ -7498,6 +7477,7 @@ simplify_size (gfc_expr *array, gfc_expr *dim, int k)
mpz_t size;
gfc_expr *return_value;
int d;
+ gfc_ref *ref;
/* For unary operations, the size of the result is given by the size
of the operand. For binary ones, it's the size of the first operand
@@ -7554,6 +7534,10 @@ simplify_size (gfc_expr *array, gfc_expr *dim, int k)
return simplified;
}
+ for (ref = array->ref; ref; ref = ref->next)
+ if (ref->type == REF_ARRAY && ref->u.ar.as)
+ gfc_resolve_array_spec (ref->u.ar.as, 0);
+
if (dim == NULL)
{
if (!gfc_array_size (array, &size))
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 6d61bf4..2c4acd5 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -4046,6 +4046,7 @@ gfc_free_namespace (gfc_namespace *ns)
free_tb_tree (ns->tb_uop_root);
gfc_free_finalizer_list (ns->finalizers);
gfc_free_omp_declare_simd_list (ns->omp_declare_simd);
+ gfc_free_omp_declare_variant_list (ns->omp_declare_variant);
gfc_free_charlen (ns->cl_list, NULL);
free_st_labels (ns->st_labels);
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 0d013de..f8c087e 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -103,6 +103,111 @@ gfc_array_dataptr_type (tree desc)
return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
}
+/* Build expressions to access members of the CFI descriptor. */
+#define CFI_FIELD_BASE_ADDR 0
+#define CFI_FIELD_ELEM_LEN 1
+#define CFI_FIELD_VERSION 2
+#define CFI_FIELD_RANK 3
+#define CFI_FIELD_ATTRIBUTE 4
+#define CFI_FIELD_TYPE 5
+#define CFI_FIELD_DIM 6
+
+#define CFI_DIM_FIELD_LOWER_BOUND 0
+#define CFI_DIM_FIELD_EXTENT 1
+#define CFI_DIM_FIELD_SM 2
+
+static tree
+gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
+{
+ tree type = TREE_TYPE (desc);
+ gcc_assert (TREE_CODE (type) == RECORD_TYPE
+ && TYPE_FIELDS (type)
+ && (strcmp ("base_addr",
+ IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
+ == 0));
+ 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);
+}
+
+tree
+gfc_get_cfi_desc_base_addr (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
+}
+
+tree
+gfc_get_cfi_desc_elem_len (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
+}
+
+tree
+gfc_get_cfi_desc_version (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
+}
+
+tree
+gfc_get_cfi_desc_rank (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
+}
+
+tree
+gfc_get_cfi_desc_type (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
+}
+
+tree
+gfc_get_cfi_desc_attribute (tree desc)
+{
+ return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
+}
+
+static tree
+gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
+{
+ tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
+ tmp = gfc_build_array_ref (tmp, idx, NULL);
+ 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),
+ tmp, field, NULL_TREE);
+}
+
+tree
+gfc_get_cfi_dim_lbound (tree desc, tree idx)
+{
+ return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
+}
+
+tree
+gfc_get_cfi_dim_extent (tree desc, tree idx)
+{
+ return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
+}
+
+tree
+gfc_get_cfi_dim_sm (tree desc, tree idx)
+{
+ return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
+}
+
+#undef CFI_FIELD_BASE_ADDR
+#undef CFI_FIELD_ELEM_LEN
+#undef CFI_FIELD_VERSION
+#undef CFI_FIELD_RANK
+#undef CFI_FIELD_ATTRIBUTE
+#undef CFI_FIELD_TYPE
+#undef CFI_FIELD_DIM
+
+#undef CFI_DIM_FIELD_LOWER_BOUND
+#undef CFI_DIM_FIELD_EXTENT
+#undef CFI_DIM_FIELD_SM
/* Build expressions to access the members of an array descriptor.
It's surprisingly easy to mess up here, so never access
@@ -289,6 +394,20 @@ gfc_conv_descriptor_attribute (tree desc)
}
tree
+gfc_conv_descriptor_type (tree desc)
+{
+ tree tmp;
+ tree dtype;
+
+ dtype = gfc_conv_descriptor_dtype (desc);
+ tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
+ gcc_assert (tmp!= NULL_TREE
+ && TREE_TYPE (tmp) == signed_char_type_node);
+ return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+ dtype, tmp, NULL_TREE);
+}
+
+tree
gfc_get_descriptor_dimension (tree desc)
{
tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
@@ -825,7 +944,11 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
{
tree tmp;
- if (is_pointer_array (desc) || get_CFI_desc (NULL, expr, &desc, NULL))
+ if (is_pointer_array (desc)
+ || (get_CFI_desc (NULL, expr, &desc, NULL)
+ && (POINTER_TYPE_P (TREE_TYPE (desc))
+ ? GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (desc)))
+ : GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))))
{
if (POINTER_TYPE_P (TREE_TYPE (desc)))
desc = build_fold_indirect_ref_loc (input_location, desc);
@@ -833,6 +956,14 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
/* This will have the span field set. */
tmp = gfc_conv_descriptor_span_get (desc);
}
+ else if (expr->ts.type == BT_ASSUMED)
+ {
+ if (DECL_LANG_SPECIFIC (desc) && GFC_DECL_SAVED_DESCRIPTOR (desc))
+ desc = GFC_DECL_SAVED_DESCRIPTOR (desc);
+ if (POINTER_TYPE_P (TREE_TYPE (desc)))
+ desc = build_fold_indirect_ref_loc (input_location, desc);
+ tmp = gfc_conv_descriptor_span_get (desc);
+ }
else if (TREE_CODE (desc) == COMPONENT_REF
&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
&& GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
@@ -5104,7 +5235,6 @@ set_loop_bounds (gfc_loopinfo *loop)
if (info->shape)
{
- gcc_assert (info->shape[dim]);
/* The frontend has worked out the size for us. */
if (!loopspec[n]
|| !specinfo->shape
@@ -6287,7 +6417,7 @@ gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
/* Generate code to evaluate non-constant array bounds. Sets *poffset and
returns the size (in elements) of the array. */
-static tree
+tree
gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
stmtblock_t * pblock)
{
@@ -6550,7 +6680,9 @@ gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
/* Add the initialization code to the start of the function. */
- if (sym->attr.optional || sym->attr.not_always_present)
+ if ((sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.optional)
+ || sym->attr.optional
+ || sym->attr.not_always_present)
{
tree nullify;
if (TREE_CODE (parm) != PARM_DECL)
@@ -7754,6 +7886,15 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
tmp = gfc_conv_descriptor_dtype (parm);
if (se->unlimited_polymorphic)
dtype = gfc_get_dtype (TREE_TYPE (desc), &loop.dimen);
+ else if (expr->ts.type == BT_ASSUMED)
+ {
+ tree tmp2 = desc;
+ if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
+ tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
+ if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
+ tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
+ dtype = gfc_conv_descriptor_dtype (tmp2);
+ }
else
dtype = gfc_get_dtype (parmtype);
gfc_add_modify (&loop.pre, tmp, dtype);
@@ -7901,31 +8042,143 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gfc_cleanup_loop (&loop);
}
+
+/* Calculate the array size (number of elements); if dim != NULL_TREE,
+ return size for that dim (dim=0..rank-1; only for GFC_DESCRIPTOR_TYPE_P). */
+tree
+gfc_tree_array_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree dim)
+{
+ if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
+ {
+ gcc_assert (dim == NULL_TREE);
+ return GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
+ }
+ tree size, tmp, rank = NULL_TREE, cond = NULL_TREE;
+ symbol_attribute attr = gfc_expr_attr (expr);
+ gfc_array_spec *as = gfc_get_full_arrayspec_from_expr (expr);
+ gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
+ if ((!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
+ || !dim)
+ {
+ if (expr->rank < 0)
+ rank = fold_convert (signed_char_type_node,
+ gfc_conv_descriptor_rank (desc));
+ else
+ rank = build_int_cst (signed_char_type_node, expr->rank);
+ }
+
+ if (dim || expr->rank == 1)
+ {
+ if (!dim)
+ dim = gfc_index_zero_node;
+ tree ubound = gfc_conv_descriptor_ubound_get (desc, dim);
+ tree lbound = gfc_conv_descriptor_lbound_get (desc, dim);
+
+ size = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, ubound, lbound);
+ size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ size, gfc_index_one_node);
+ /* if (!allocatable && !pointer && assumed rank)
+ size = (idx == rank && ubound[rank-1] == -1 ? -1 : size;
+ else
+ size = max (0, size); */
+ size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
+ size, gfc_index_zero_node);
+ if (!attr.pointer && !attr.allocatable
+ && as && as->type == AS_ASSUMED_RANK)
+ {
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
+ rank, build_int_cst (signed_char_type_node, 1));
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ fold_convert (signed_char_type_node, dim),
+ tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ gfc_conv_descriptor_ubound_get (desc, dim),
+ build_int_cst (gfc_array_index_type, -1));
+ cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = build_int_cst (gfc_array_index_type, -1);
+ size = build3_loc (input_location, COND_EXPR, gfc_array_index_type,
+ cond, tmp, size);
+ }
+ return size;
+ }
+
+ /* size = 1. */
+ size = gfc_create_var (gfc_array_index_type, "size");
+ gfc_add_modify (block, size, build_int_cst (TREE_TYPE (size), 1));
+ tree extent = gfc_create_var (gfc_array_index_type, "extent");
+
+ stmtblock_t cond_block, loop_body;
+ gfc_init_block (&cond_block);
+ gfc_init_block (&loop_body);
+
+ /* Loop: for (i = 0; i < rank; ++i). */
+ tree idx = gfc_create_var (signed_char_type_node, "idx");
+ /* Loop body. */
+ /* #if (assumed-rank + !allocatable && !pointer)
+ if (idx == rank - 1 && dim[idx].ubound == -1)
+ extent = -1;
+ else
+ #endif
+ extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
+ if (extent < 0)
+ extent = 0
+ size *= extent. */
+ cond = NULL_TREE;
+ if (!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
+ {
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
+ rank, build_int_cst (signed_char_type_node, 1));
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ idx, tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ gfc_conv_descriptor_ubound_get (desc, idx),
+ build_int_cst (gfc_array_index_type, -1));
+ cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
+ cond, tmp);
+ }
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_ubound_get (desc, idx),
+ gfc_conv_descriptor_lbound_get (desc, idx));
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ tmp, gfc_index_one_node);
+ gfc_add_modify (&cond_block, extent, tmp);
+ tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
+ extent, gfc_index_zero_node);
+ tmp = build3_v (COND_EXPR, tmp,
+ fold_build2_loc (input_location, MODIFY_EXPR,
+ gfc_array_index_type,
+ extent, gfc_index_zero_node),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&cond_block, tmp);
+ tmp = gfc_finish_block (&cond_block);
+ if (cond)
+ tmp = build3_v (COND_EXPR, cond,
+ fold_build2_loc (input_location, MODIFY_EXPR,
+ gfc_array_index_type, extent,
+ build_int_cst (gfc_array_index_type, -1)),
+ tmp);
+ gfc_add_expr_to_block (&loop_body, tmp);
+ /* size *= extent. */
+ gfc_add_modify (&loop_body, size,
+ fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ size, extent));
+ /* Generate loop. */
+ gfc_simple_for_loop (block, idx, build_int_cst (TREE_TYPE (idx), 0), rank, LT_EXPR,
+ build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ return size;
+}
+
/* Helper function for gfc_conv_array_parameter if array size needs to be
computed. */
static void
-array_parameter_size (tree desc, gfc_expr *expr, tree *size)
+array_parameter_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree *size)
{
tree elem;
- if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
- *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
- else if (expr->rank > 1)
- *size = build_call_expr_loc (input_location,
- gfor_fndecl_size0, 1,
- gfc_build_addr_expr (NULL, desc));
- else
- {
- tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
- tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
-
- *size = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, ubound, lbound);
- *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- *size, gfc_index_one_node);
- *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
- *size, gfc_index_zero_node);
- }
+ *size = gfc_tree_array_size (block, desc, expr, NULL);
elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
*size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
*size, fold_convert (gfc_array_index_type, elem));
@@ -8035,7 +8288,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
else
se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
if (size)
- array_parameter_size (tmp, expr, size);
+ array_parameter_size (&se->pre, tmp, expr, size);
return;
}
@@ -8047,7 +8300,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
tmp = se->expr;
}
if (size)
- array_parameter_size (tmp, expr, size);
+ array_parameter_size (&se->pre, tmp, expr, size);
se->expr = gfc_conv_array_data (tmp);
return;
}
@@ -8122,7 +8375,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
if (expr->ts.type == BT_CHARACTER && expr->expr_type != EXPR_FUNCTION)
se->string_length = expr->ts.u.cl->backend_decl;
if (size)
- array_parameter_size (se->expr, expr, size);
+ array_parameter_size (&se->pre, se->expr, expr, size);
se->expr = gfc_conv_array_data (se->expr);
return;
}
@@ -8132,7 +8385,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
/* Result of the enclosing function. */
gfc_conv_expr_descriptor (se, expr);
if (size)
- array_parameter_size (se->expr, expr, size);
+ array_parameter_size (&se->pre, se->expr, expr, size);
se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
@@ -8149,9 +8402,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
gfc_conv_expr_descriptor (se, expr);
if (size)
- array_parameter_size (build_fold_indirect_ref_loc (input_location,
- se->expr),
- expr, size);
+ array_parameter_size (&se->pre,
+ build_fold_indirect_ref_loc (input_location,
+ se->expr),
+ expr, size);
}
/* Deallocate the allocatable components of structures that are
@@ -8892,7 +9146,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
DECL_ARTIFICIAL (cdesc) = 1;
gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
- gfc_get_dtype_rank_type (1, tmp));
+ gfc_get_dtype_rank_type (1, tmp));
gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
gfc_index_zero_node,
gfc_index_one_node);
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index e4d443d..1d3dc48 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -39,6 +39,8 @@ void gfc_trans_dummy_array_bias (gfc_symbol *, tree, gfc_wrapped_block *);
/* Generate entry and exit code for g77 calling convention arrays. */
void gfc_trans_g77_array (gfc_symbol *, gfc_wrapped_block *);
+tree gfc_tree_array_size (stmtblock_t *, tree, gfc_expr *, tree);
+
tree gfc_full_array_size (stmtblock_t *, tree, int);
tree gfc_duplicate_allocatable (tree, tree, tree, int, tree);
@@ -158,7 +160,8 @@ tree gfc_conv_array_stride (tree, int);
tree gfc_conv_array_lbound (tree, int);
tree gfc_conv_array_ubound (tree, int);
-/* Set cobounds of an array. */
+/* Set (co)bounds of an array. */
+tree gfc_trans_array_bounds (tree, gfc_symbol *, tree *, stmtblock_t *);
void gfc_trans_array_cobounds (tree, stmtblock_t *, const gfc_symbol *);
/* Build expressions for accessing components of an array descriptor. */
@@ -173,6 +176,7 @@ tree gfc_conv_descriptor_dtype (tree);
tree gfc_conv_descriptor_rank (tree);
tree gfc_conv_descriptor_elem_len (tree);
tree gfc_conv_descriptor_attribute (tree);
+tree gfc_conv_descriptor_type (tree);
tree gfc_get_descriptor_dimension (tree);
tree gfc_conv_descriptor_stride_get (tree, tree);
tree gfc_conv_descriptor_lbound_get (tree, tree);
@@ -186,6 +190,18 @@ void gfc_conv_descriptor_stride_set (stmtblock_t *, tree, tree, tree);
void gfc_conv_descriptor_lbound_set (stmtblock_t *, tree, tree, tree);
void gfc_conv_descriptor_ubound_set (stmtblock_t *, tree, tree, tree);
+/* CFI descriptor. */
+tree gfc_get_cfi_desc_base_addr (tree);
+tree gfc_get_cfi_desc_elem_len (tree);
+tree gfc_get_cfi_desc_version (tree);
+tree gfc_get_cfi_desc_rank (tree);
+tree gfc_get_cfi_desc_type (tree);
+tree gfc_get_cfi_desc_attribute (tree);
+tree gfc_get_cfi_dim_lbound (tree, tree);
+tree gfc_get_cfi_dim_extent (tree, tree);
+tree gfc_get_cfi_dim_sm (tree, tree);
+
+
/* Shift lower bound of descriptor, updating ubound and offset. */
void gfc_conv_shift_descriptor_lbound (stmtblock_t*, tree, int, tree);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index bed61e2..de624c8 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -117,8 +117,6 @@ tree gfor_fndecl_fdate;
tree gfor_fndecl_ttynam;
tree gfor_fndecl_in_pack;
tree gfor_fndecl_in_unpack;
-tree gfor_fndecl_cfi_to_gfc;
-tree gfor_fndecl_gfc_to_cfi;
tree gfor_fndecl_associated;
tree gfor_fndecl_system_clock4;
tree gfor_fndecl_system_clock8;
@@ -214,8 +212,6 @@ tree gfor_fndecl_convert_char4_to_char1;
/* Other misc. runtime library functions. */
-tree gfor_fndecl_size0;
-tree gfor_fndecl_size1;
tree gfor_fndecl_iargc;
tree gfor_fndecl_kill;
tree gfor_fndecl_kill_sub;
@@ -743,7 +739,6 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
/* Keep variables larger than max-stack-var-size off stack. */
if (!(sym->ns->proc_name && sym->ns->proc_name->attr.recursive)
- && !(sym->ns->proc_name && sym->ns->proc_name->attr.is_main_program)
&& !sym->attr.automatic
&& sym->attr.save != SAVE_EXPLICIT
&& sym->attr.save != SAVE_IMPLICIT
@@ -757,7 +752,9 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
|| sym->attr.allocatable)
&& !DECL_ARTIFICIAL (decl))
{
- if (flag_max_stack_var_size > 0)
+ if (flag_max_stack_var_size > 0
+ && !(sym->ns->proc_name
+ && sym->ns->proc_name->attr.is_main_program))
gfc_warning (OPT_Wsurprising,
"Array %qs at %L is larger than limit set by "
"%<-fmax-stack-var-size=%>, moved from stack to static "
@@ -1304,7 +1301,8 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
DECL_EXTERNAL (decl) = 0;
/* Avoid uninitialized warnings for optional dummy arguments. */
- if (sym->attr.optional)
+ if ((sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.optional)
+ || sym->attr.optional)
suppress_warning (decl);
/* We should never get deferred shape arrays here. We used to because of
@@ -1548,6 +1546,14 @@ gfc_get_symbol_decl (gfc_symbol * sym)
|| (sym->module && sym->attr.if_source != IFSRC_DECL
&& sym->backend_decl));
+ if (sym->attr.dummy && sym->ns->proc_name->attr.is_bind_c
+ && is_CFI_desc (sym, NULL))
+ {
+ gcc_assert (sym->backend_decl && (sym->ts.type != BT_CHARACTER
+ || sym->ts.u.cl->backend_decl));
+ return sym->backend_decl;
+ }
+
if (sym->ns && sym->ns->proc_name && sym->ns->proc_name->attr.function)
byref = gfc_return_by_reference (sym->ns->proc_name);
else
@@ -1595,9 +1601,6 @@ gfc_get_symbol_decl (gfc_symbol * sym)
sym->ts.u.cl->backend_decl = build_fold_indirect_ref (sym->ts.u.cl->backend_decl);
}
- if (is_CFI_desc (sym, NULL))
- gfc_defer_symbol_init (sym);
-
fun_or_res = byref && (sym->attr.result
|| (sym->attr.function && sym->ts.deferred));
if ((sym->attr.dummy && ! sym->attr.function) || fun_or_res)
@@ -2362,9 +2365,13 @@ module_sym:
pushdecl_top_level (fndecl);
if (sym->formal_ns
- && sym->formal_ns->proc_name == sym
- && sym->formal_ns->omp_declare_simd)
- gfc_trans_omp_declare_simd (sym->formal_ns);
+ && sym->formal_ns->proc_name == sym)
+ {
+ if (sym->formal_ns->omp_declare_simd)
+ gfc_trans_omp_declare_simd (sym->formal_ns);
+ if (flag_openmp)
+ gfc_trans_omp_declare_variant (sym->formal_ns);
+ }
return fndecl;
}
@@ -2755,9 +2762,19 @@ create_function_arglist (gfc_symbol * sym)
if (f->sym->attr.volatile_)
type = build_qualified_type (type, TYPE_QUAL_VOLATILE);
- /* Build the argument declaration. */
- parm = build_decl (input_location,
- PARM_DECL, gfc_sym_identifier (f->sym), type);
+ /* Build the argument declaration. For C descriptors, we use a
+ '_'-prefixed name for the parm_decl and inside the proc the
+ sym->name. */
+ tree parm_name;
+ if (sym->attr.is_bind_c && is_CFI_desc (f->sym, NULL))
+ {
+ strcpy (&name[1], f->sym->name);
+ name[0] = '_';
+ parm_name = get_identifier (name);
+ }
+ else
+ parm_name = gfc_sym_identifier (f->sym);
+ parm = build_decl (input_location, PARM_DECL, parm_name, type);
if (f->sym->attr.volatile_)
{
@@ -3112,6 +3129,12 @@ gfc_create_function_decl (gfc_namespace * ns, bool global)
if (ns->omp_declare_simd)
gfc_trans_omp_declare_simd (ns);
+
+ /* Handle 'declare variant' directives. The applicable directives might
+ be declared in a parent namespace, so this needs to be called even if
+ there are no local directives. */
+ if (flag_openmp)
+ gfc_trans_omp_declare_variant (ns);
}
/* Return the decl used to hold the function return value. If
@@ -3691,18 +3714,6 @@ gfc_build_intrinsic_function_decls (void)
}
/* Other functions. */
- gfor_fndecl_size0 = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("size0")), ". R ",
- gfc_array_index_type, 1, pvoid_type_node);
- DECL_PURE_P (gfor_fndecl_size0) = 1;
- TREE_NOTHROW (gfor_fndecl_size0) = 1;
-
- gfor_fndecl_size1 = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("size1")), ". R . ",
- gfc_array_index_type, 2, pvoid_type_node, gfc_array_index_type);
- DECL_PURE_P (gfor_fndecl_size1) = 1;
- TREE_NOTHROW (gfor_fndecl_size1) = 1;
-
gfor_fndecl_iargc = gfc_build_library_function_decl (
get_identifier (PREFIX ("iargc")), gfc_int4_type_node, 0);
TREE_NOTHROW (gfor_fndecl_iargc) = 1;
@@ -3834,19 +3845,6 @@ gfc_build_builtin_function_decls (void)
get_identifier (PREFIX("internal_unpack")), ". w R ",
void_type_node, 2, pvoid_type_node, pvoid_type_node);
- /* These two builtins write into what the first argument points to and
- read from what the second argument points to, but we can't use R
- for that, because the directly pointed structure contains a pointer
- which is copied into the descriptor pointed by the first argument,
- effectively escaping that way. See PR92123. */
- gfor_fndecl_cfi_to_gfc = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("cfi_desc_to_gfc_desc")), ". w . ",
- void_type_node, 2, pvoid_type_node, ppvoid_type_node);
-
- gfor_fndecl_gfc_to_cfi = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("gfc_desc_to_cfi_desc")), ". w . ",
- void_type_node, 2, ppvoid_type_node, pvoid_type_node);
-
gfor_fndecl_associated = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("associated")), ". R R ",
integer_type_node, 2, ppvoid_type_node, ppvoid_type_node);
@@ -4464,115 +4462,6 @@ gfc_null_and_pass_deferred_len (gfc_symbol *sym, stmtblock_t *init,
}
-/* Convert CFI descriptor dummies into gfc types and back again. */
-static void
-convert_CFI_desc (gfc_wrapped_block * block, gfc_symbol *sym)
-{
- tree gfc_desc;
- tree gfc_desc_ptr;
- tree CFI_desc;
- tree CFI_desc_ptr;
- tree dummy_ptr;
- tree tmp;
- tree present;
- tree incoming;
- tree outgoing;
- stmtblock_t outer_block;
- stmtblock_t tmpblock;
-
- /* dummy_ptr will be the pointer to the passed array descriptor,
- while CFI_desc is the descriptor itself. */
- if (DECL_LANG_SPECIFIC (sym->backend_decl))
- CFI_desc = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
- else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (sym->backend_decl))))
- CFI_desc = sym->backend_decl;
- else
- CFI_desc = NULL;
-
- dummy_ptr = CFI_desc;
-
- if (CFI_desc)
- {
- CFI_desc = build_fold_indirect_ref_loc (input_location, CFI_desc);
-
- /* The compiler will have given CFI_desc the correct gfortran
- type. Use this new variable to store the converted
- descriptor. */
- gfc_desc = gfc_create_var (TREE_TYPE (CFI_desc), "gfc_desc");
- tmp = build_pointer_type (TREE_TYPE (gfc_desc));
- gfc_desc_ptr = gfc_create_var (tmp, "gfc_desc_ptr");
- CFI_desc_ptr = gfc_create_var (pvoid_type_node, "CFI_desc_ptr");
-
- /* Fix the condition for the presence of the argument. */
- gfc_init_block (&outer_block);
- present = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node, dummy_ptr,
- build_int_cst (TREE_TYPE (dummy_ptr), 0));
-
- gfc_init_block (&tmpblock);
- /* Pointer to the gfc descriptor. */
- gfc_add_modify (&tmpblock, gfc_desc_ptr,
- gfc_build_addr_expr (NULL, gfc_desc));
- /* Store the pointer to the CFI descriptor. */
- gfc_add_modify (&tmpblock, CFI_desc_ptr,
- fold_convert (pvoid_type_node, dummy_ptr));
- tmp = gfc_build_addr_expr (ppvoid_type_node, CFI_desc_ptr);
- /* Convert the CFI descriptor. */
- incoming = build_call_expr_loc (input_location,
- gfor_fndecl_cfi_to_gfc, 2, gfc_desc_ptr, tmp);
- gfc_add_expr_to_block (&tmpblock, incoming);
- /* Set the dummy pointer to point to the gfc_descriptor. */
- gfc_add_modify (&tmpblock, dummy_ptr,
- fold_convert (TREE_TYPE (dummy_ptr), gfc_desc_ptr));
-
- /* The hidden string length is not passed to bind(C) procedures so set
- it from the descriptor element length. */
- if (sym->ts.type == BT_CHARACTER
- && sym->ts.u.cl->backend_decl
- && VAR_P (sym->ts.u.cl->backend_decl))
- {
- tmp = build_fold_indirect_ref_loc (input_location, dummy_ptr);
- tmp = gfc_conv_descriptor_elem_len (tmp);
- gfc_add_modify (&tmpblock, sym->ts.u.cl->backend_decl,
- fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
- tmp));
- }
-
- /* Check that the argument is present before executing the above. */
- incoming = build3_v (COND_EXPR, present,
- gfc_finish_block (&tmpblock),
- build_empty_stmt (input_location));
- gfc_add_expr_to_block (&outer_block, incoming);
- incoming = gfc_finish_block (&outer_block);
-
- /* Convert the gfc descriptor back to the CFI type before going
- out of scope, if the CFI type was present at entry. */
- outgoing = NULL_TREE;
- if ((sym->attr.pointer || sym->attr.allocatable)
- && !sym->attr.value
- && sym->attr.intent != INTENT_IN)
- {
- gfc_init_block (&outer_block);
- gfc_init_block (&tmpblock);
-
- tmp = gfc_build_addr_expr (ppvoid_type_node, CFI_desc_ptr);
- outgoing = build_call_expr_loc (input_location,
- gfor_fndecl_gfc_to_cfi, 2,
- tmp, gfc_desc_ptr);
- gfc_add_expr_to_block (&tmpblock, outgoing);
-
- outgoing = build3_v (COND_EXPR, present,
- gfc_finish_block (&tmpblock),
- build_empty_stmt (input_location));
- gfc_add_expr_to_block (&outer_block, outgoing);
- outgoing = gfc_finish_block (&outer_block);
- }
-
- /* Add the lot to the procedure init and finally blocks. */
- gfc_add_init_cleanup (block, incoming, outgoing);
- }
-}
-
/* Get the result expression for a procedure. */
static tree
@@ -5149,13 +5038,6 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
else if (!(UNLIMITED_POLY(sym)) && !is_pdt_type)
gcc_unreachable ();
-
- /* Assumed shape and assumed rank arrays are passed to BIND(C) procedures
- as ISO Fortran Interop descriptors. These have to be converted to
- gfortran descriptors and back again. This has to be done here so that
- the conversion occurs at the start of the init block. */
- if (is_CFI_desc (sym, NULL))
- convert_CFI_desc (block, sym);
}
gfc_init_block (&tmpblock);
@@ -6779,6 +6661,788 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
return;
}
+static void
+gfc_conv_cfi_to_gfc (stmtblock_t *init, stmtblock_t *finally,
+ tree cfi_desc, tree gfc_desc, gfc_symbol *sym)
+{
+ stmtblock_t block;
+ gfc_init_block (&block);
+ tree cfi = build_fold_indirect_ref_loc (input_location, cfi_desc);
+ tree rank, idx, etype, tmp, tmp2, size_var = NULL_TREE;
+ bool do_copy_inout = false;
+
+ /* When allocatable + intent out, free the cfi descriptor. */
+ if (sym->attr.allocatable && sym->attr.intent == INTENT_OUT)
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ tree call = builtin_decl_explicit (BUILT_IN_FREE);
+ call = build_call_expr_loc (input_location, call, 1, tmp);
+ gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
+ gfc_add_modify (&block, tmp,
+ fold_convert (TREE_TYPE (tmp), null_pointer_node));
+ }
+
+ /* -fcheck=bound: Do version, rank, attribute, type and is-NULL checks. */
+ if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ {
+ char *msg;
+ tree tmp3;
+ msg = xasprintf ("Unexpected version %%d (expected %d) in CFI descriptor "
+ "passed to dummy argument %s", CFI_VERSION, sym->name);
+ tmp2 = gfc_get_cfi_desc_version (cfi);
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
+ build_int_cst (TREE_TYPE (tmp2), CFI_VERSION));
+ gfc_trans_runtime_check (true, false, tmp, &block, &sym->declared_at,
+ msg, tmp2);
+ free (msg);
+
+ /* Rank check; however, for character(len=*), assumed/explicit-size arrays
+ are permitted to differ in rank according to the Fortran rules. */
+ if (sym->as && sym->as->type != AS_ASSUMED_SIZE
+ && sym->as->type != AS_EXPLICIT)
+ {
+ if (sym->as->rank != -1)
+ msg = xasprintf ("Invalid rank %%d (expected %d) in CFI descriptor "
+ "passed to dummy argument %s", sym->as->rank,
+ sym->name);
+ else
+ msg = xasprintf ("Invalid rank %%d (expected 0..%d) in CFI "
+ "descriptor passed to dummy argument %s",
+ CFI_MAX_RANK, sym->name);
+
+ tmp3 = tmp2 = tmp = gfc_get_cfi_desc_rank (cfi);
+ if (sym->as->rank != -1)
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, build_int_cst (signed_char_type_node,
+ sym->as->rank));
+ else
+ {
+ tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
+ tmp, build_zero_cst (TREE_TYPE (tmp)));
+ tmp2 = fold_build2_loc (input_location, GT_EXPR,
+ boolean_type_node, tmp2,
+ build_int_cst (TREE_TYPE (tmp2),
+ CFI_MAX_RANK));
+ tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ boolean_type_node, tmp, tmp2);
+ }
+ gfc_trans_runtime_check (true, false, tmp, &block, &sym->declared_at,
+ msg, tmp3);
+ free (msg);
+ }
+
+ tmp3 = tmp = gfc_get_cfi_desc_attribute (cfi);
+ if (sym->attr.allocatable || sym->attr.pointer)
+ {
+ int attr = (sym->attr.pointer ? CFI_attribute_pointer
+ : CFI_attribute_allocatable);
+ msg = xasprintf ("Invalid attribute %%d (expected %d) in CFI "
+ "descriptor passed to dummy argument %s with %s "
+ "attribute", attr, sym->name,
+ sym->attr.pointer ? "pointer" : "allocatable");
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, build_int_cst (TREE_TYPE (tmp), attr));
+ }
+ else
+ {
+ int amin = MIN (CFI_attribute_pointer,
+ MIN (CFI_attribute_allocatable, CFI_attribute_other));
+ int amax = MAX (CFI_attribute_pointer,
+ MAX (CFI_attribute_allocatable, CFI_attribute_other));
+ msg = xasprintf ("Invalid attribute %%d (expected %d..%d) in CFI "
+ "descriptor passed to nonallocatable, nonpointer "
+ "dummy argument %s", amin, amax, sym->name);
+ tmp2 = tmp;
+ tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, tmp,
+ build_int_cst (TREE_TYPE (tmp), amin));
+ tmp2 = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp2,
+ build_int_cst (TREE_TYPE (tmp2), amax));
+ tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ boolean_type_node, tmp, tmp2);
+ gfc_trans_runtime_check (true, false, tmp, &block, &sym->declared_at,
+ msg, tmp3);
+ free (msg);
+ msg = xasprintf ("Invalid unallocatated/unassociated CFI "
+ "descriptor passed to nonallocatable, nonpointer "
+ "dummy argument %s", sym->name);
+ tmp3 = tmp = gfc_get_cfi_desc_base_addr (cfi),
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ tmp, null_pointer_node);
+ }
+ gfc_trans_runtime_check (true, false, tmp, &block, &sym->declared_at,
+ msg, tmp3);
+ free (msg);
+
+ if (sym->ts.type != BT_ASSUMED)
+ {
+ int type = CFI_type_other;
+ if (sym->ts.f90_type == BT_VOID)
+ {
+ type = (sym->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
+ ? CFI_type_cfunptr : CFI_type_cptr);
+ }
+ else
+ switch (sym->ts.type)
+ {
+ case BT_INTEGER:
+ case BT_LOGICAL:
+ case BT_REAL:
+ case BT_COMPLEX:
+ type = CFI_type_from_type_kind (sym->ts.type, sym->ts.kind);
+ break;
+ case BT_CHARACTER:
+ type = CFI_type_from_type_kind (CFI_type_Character,
+ sym->ts.kind);
+ break;
+ case BT_DERIVED:
+ type = CFI_type_struct;
+ break;
+ case BT_VOID:
+ type = (sym->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
+ ? CFI_type_cfunptr : CFI_type_cptr);
+ break;
+ case BT_ASSUMED:
+ case BT_CLASS:
+ case BT_PROCEDURE:
+ case BT_HOLLERITH:
+ case BT_UNION:
+ case BT_BOZ:
+ case BT_UNKNOWN:
+ gcc_unreachable ();
+ }
+ msg = xasprintf ("Unexpected type %%d (expected %d) in CFI descriptor"
+ " passed to dummy argument %s", type, sym->name);
+ tmp2 = tmp = gfc_get_cfi_desc_type (cfi);
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, build_int_cst (TREE_TYPE (tmp), type));
+ gfc_trans_runtime_check (true, false, tmp, &block, &sym->declared_at,
+ msg, tmp2);
+ free (msg);
+ }
+ }
+
+ if (!sym->attr.referenced)
+ goto done;
+
+ /* Set string length for len=* and len=:, otherwise, it is already set. */
+ if (sym->ts.type == BT_CHARACTER && !sym->ts.u.cl->length)
+ {
+ tmp = fold_convert (gfc_array_index_type,
+ gfc_get_cfi_desc_elem_len (cfi));
+ if (sym->ts.kind != 1)
+ tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ gfc_array_index_type, tmp,
+ build_int_cst (gfc_charlen_type_node,
+ sym->ts.kind));
+ gfc_add_modify (&block, sym->ts.u.cl->backend_decl, tmp);
+ }
+
+ /* gfc->data = cfi->base_addr - or for scalars: gfc = cfi->base_addr.
+ assumed-size/explicit-size arrays end up here for character(len=*)
+ only. */
+ if (!sym->attr.dimension || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ gfc_add_modify (&block, gfc_desc,
+ fold_convert (TREE_TYPE (gfc_desc), tmp));
+ if (!sym->attr.dimension)
+ goto done;
+ }
+
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ {
+ /* gfc->dtype = ... (from declaration, not from cfi). */
+ etype = gfc_get_element_type (TREE_TYPE (gfc_desc));
+ gfc_add_modify (&block, gfc_conv_descriptor_dtype (gfc_desc),
+ gfc_get_dtype_rank_type (sym->as->rank, etype));
+ /* gfc->data = cfi->base_addr. */
+ gfc_conv_descriptor_data_set (&block, gfc_desc,
+ gfc_get_cfi_desc_base_addr (cfi));
+ }
+
+ if (sym->ts.type == BT_ASSUMED)
+ {
+ /* For type(*), take elem_len + dtype.type from the actual argument. */
+ gfc_add_modify (&block, gfc_conv_descriptor_elem_len (gfc_desc),
+ gfc_get_cfi_desc_elem_len (cfi));
+ tree cond;
+ tree ctype = gfc_get_cfi_desc_type (cfi);
+ ctype = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (ctype),
+ ctype, build_int_cst (TREE_TYPE (ctype),
+ CFI_type_mask));
+ tree type = gfc_conv_descriptor_type (gfc_desc);
+
+ /* if (CFI_type_cptr) BT_VOID else BT_UNKNOWN */
+ /* Note: BT_VOID is could also be CFI_type_funcptr, but assume c_ptr. */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype), CFI_type_cptr));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_VOID));
+ tmp2 = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ type,
+ build_int_cst (TREE_TYPE (type), BT_UNKNOWN));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (CFI_type_struct) BT_DERIVED else < tmp2 > */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_struct));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_DERIVED));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (CFI_type_Character) BT_CHARACTER else < tmp2 > */
+ /* Note: this is kind=1, CFI_type_ucs4_char is handled in the 'else if'
+ before (see below, as generated bottom up). */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_Character));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_CHARACTER));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (CFI_type_ucs4_char) BT_CHARACTER else < tmp2 > */
+ /* Note: gfc->elem_len = cfi->elem_len/4. */
+ /* However, assuming that CFI_type_ucs4_char cannot be recovered, leave
+ gfc->elem_len == cfi->elem_len, which helps with operations which use
+ sizeof() in Fortran and cfi->elem_len in C. */
+ tmp = gfc_get_cfi_desc_type (cfi);
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, tmp,
+ build_int_cst (TREE_TYPE (tmp),
+ CFI_type_ucs4_char));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_CHARACTER));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (CFI_type_Complex) BT_COMPLEX + cfi->elem_len/2 else < tmp2 > */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_Complex));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_COMPLEX));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (CFI_type_Integer || CFI_type_Logical || CFI_type_Real)
+ ctype else <tmp2> */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_Integer));
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_Logical));
+ cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, ctype,
+ build_int_cst (TREE_TYPE (ctype),
+ CFI_type_Real));
+ cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ type, fold_convert (TREE_TYPE (type), ctype));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ gfc_add_expr_to_block (&block, tmp2);
+ }
+
+ if (sym->as->rank < 0)
+ {
+ /* Set gfc->dtype.rank, if assumed-rank. */
+ rank = gfc_get_cfi_desc_rank (cfi);
+ gfc_add_modify (&block, gfc_conv_descriptor_rank (gfc_desc), rank);
+ }
+ else if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ /* In that case, the CFI rank and the declared rank can differ. */
+ rank = gfc_get_cfi_desc_rank (cfi);
+ else
+ rank = build_int_cst (signed_char_type_node, sym->as->rank);
+
+ /* With bind(C), the standard requires that both Fortran callers and callees
+ handle noncontiguous arrays passed to an dummy with 'contiguous' attribute
+ and with character(len=*) + assumed-size/explicit-size arrays.
+ cf. Fortran 2018, 18.3.6, paragraph 5 (and for the caller: para. 6). */
+ if ((sym->ts.type == BT_CHARACTER && !sym->ts.u.cl->length
+ && (sym->as->type == AS_ASSUMED_SIZE || sym->as->type == AS_EXPLICIT))
+ || sym->attr.contiguous)
+ {
+ do_copy_inout = true;
+ gcc_assert (!sym->attr.pointer);
+ stmtblock_t block2;
+ tree data;
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ data = gfc_conv_descriptor_data_get (gfc_desc);
+ else if (!POINTER_TYPE_P (TREE_TYPE (gfc_desc)))
+ data = gfc_build_addr_expr (NULL, gfc_desc);
+ else
+ data = gfc_desc;
+
+ /* Is copy-in/out needed? */
+ /* do_copyin = rank != 0 && !assumed-size */
+ tree cond_var = gfc_create_var (boolean_type_node, "do_copyin");
+ tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ rank, build_zero_cst (TREE_TYPE (rank)));
+ /* dim[rank-1].extent != -1 -> assumed size*/
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (rank),
+ rank, build_int_cst (TREE_TYPE (rank), 1));
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ gfc_get_cfi_dim_extent (cfi, tmp),
+ build_int_cst (gfc_array_index_type, -1));
+ cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
+ boolean_type_node, cond, tmp);
+ gfc_add_modify (&block, cond_var, cond);
+ /* if (do_copyin) do_copyin = ... || ... || ... */
+ gfc_init_block (&block2);
+ /* dim[0].sm != elem_len */
+ tmp = fold_convert (gfc_array_index_type,
+ gfc_get_cfi_desc_elem_len (cfi));
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ gfc_get_cfi_dim_sm (cfi, gfc_index_zero_node),
+ tmp);
+ gfc_add_modify (&block2, cond_var, cond);
+
+ /* for (i = 1; i < rank; ++i)
+ cond &&= dim[i].sm != (dv->dim[i - 1].sm * dv->dim[i - 1].extent) */
+ idx = gfc_create_var (TREE_TYPE (rank), "idx");
+ stmtblock_t loop_body;
+ gfc_init_block (&loop_body);
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (idx),
+ idx, build_int_cst (TREE_TYPE (idx), 1));
+ tree tmp2 = gfc_get_cfi_dim_sm (cfi, tmp);
+ tmp = gfc_get_cfi_dim_extent (cfi, tmp);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
+ tmp2, tmp);
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ gfc_get_cfi_dim_sm (cfi, idx), tmp);
+ cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
+ cond_var, cond);
+ gfc_add_modify (&loop_body, cond_var, cond);
+ gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 1),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ tmp = build3_v (COND_EXPR, cond_var, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+
+ /* Copy-in body. */
+ gfc_init_block (&block2);
+ /* size = dim[0].extent; for (i = 1; i < rank; ++i) size *= dim[i].extent */
+ size_var = gfc_create_var (size_type_node, "size");
+ tmp = fold_convert (size_type_node,
+ gfc_get_cfi_dim_extent (cfi, gfc_index_zero_node));
+ gfc_add_modify (&block2, size_var, tmp);
+
+ gfc_init_block (&loop_body);
+ tmp = fold_convert (size_type_node,
+ gfc_get_cfi_dim_extent (cfi, idx));
+ tmp = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ size_var, fold_convert (size_type_node, tmp));
+ gfc_add_modify (&loop_body, size_var, tmp);
+ gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 1),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ /* data = malloc (size * elem_len) */
+ tmp = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ size_var, gfc_get_cfi_desc_elem_len (cfi));
+ tree call = builtin_decl_explicit (BUILT_IN_MALLOC);
+ call = build_call_expr_loc (input_location, call, 1, tmp);
+ gfc_add_modify (&block2, data, fold_convert (TREE_TYPE (data), call));
+
+ /* Copy the data:
+ for (idx = 0; idx < size; ++idx)
+ {
+ shift = 0;
+ tmpidx = idx
+ for (dim = 0; dim < rank; ++dim)
+ {
+ shift += (tmpidx % extent[d]) * sm[d]
+ tmpidx = tmpidx / extend[d]
+ }
+ memcpy (lhs + idx*elem_len, rhs + shift, elem_len)
+ } .*/
+ idx = gfc_create_var (size_type_node, "arrayidx");
+ gfc_init_block (&loop_body);
+ tree shift = gfc_create_var (size_type_node, "shift");
+ tree tmpidx = gfc_create_var (size_type_node, "tmpidx");
+ gfc_add_modify (&loop_body, shift, build_zero_cst (TREE_TYPE (shift)));
+ gfc_add_modify (&loop_body, tmpidx, idx);
+ stmtblock_t inner_loop;
+ gfc_init_block (&inner_loop);
+ tree dim = gfc_create_var (TREE_TYPE (rank), "dim");
+ /* shift += (tmpidx % extent[d]) * sm[d] */
+ tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
+ size_type_node, tmpidx,
+ fold_convert (size_type_node,
+ gfc_get_cfi_dim_extent (cfi, dim)));
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ size_type_node, tmp,
+ fold_convert (size_type_node,
+ gfc_get_cfi_dim_sm (cfi, dim)));
+ gfc_add_modify (&inner_loop, shift,
+ fold_build2_loc (input_location, PLUS_EXPR,
+ size_type_node, shift, tmp));
+ /* tmpidx = tmpidx / extend[d] */
+ tmp = fold_convert (size_type_node, gfc_get_cfi_dim_extent (cfi, dim));
+ gfc_add_modify (&inner_loop, tmpidx,
+ fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ size_type_node, tmpidx, tmp));
+ gfc_simple_for_loop (&loop_body, dim, build_zero_cst (TREE_TYPE (rank)),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (dim), 1),
+ gfc_finish_block (&inner_loop));
+ /* Assign. */
+ tmp = fold_convert (pchar_type_node, gfc_get_cfi_desc_base_addr (cfi));
+ tmp = fold_build2 (POINTER_PLUS_EXPR, pchar_type_node, tmp, shift);
+ tree lhs;
+ /* memcpy (lhs + idx*elem_len, rhs + shift, elem_len) */
+ tree elem_len;
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ elem_len = gfc_conv_descriptor_elem_len (gfc_desc);
+ else
+ elem_len = gfc_get_cfi_desc_elem_len (cfi);
+ lhs = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ elem_len, idx);
+ lhs = fold_build2_loc (input_location, POINTER_PLUS_EXPR, pchar_type_node,
+ fold_convert (pchar_type_node, data), lhs);
+ tmp = fold_convert (pvoid_type_node, tmp);
+ lhs = fold_convert (pvoid_type_node, lhs);
+ call = builtin_decl_explicit (BUILT_IN_MEMCPY);
+ call = build_call_expr_loc (input_location, call, 3, lhs, tmp, elem_len);
+ gfc_add_expr_to_block (&loop_body, fold_convert (void_type_node, call));
+ gfc_simple_for_loop (&block2, idx, build_zero_cst (TREE_TYPE (idx)),
+ size_var, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ /* if (cond) { block2 } */
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ data, fold_convert (TREE_TYPE (data),
+ null_pointer_node));
+ tmp = build3_v (COND_EXPR, cond_var, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+ }
+
+ if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ {
+ tree offset, type;
+ type = TREE_TYPE (gfc_desc);
+ gfc_trans_array_bounds (type, sym, &offset, &block);
+ if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
+ gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
+ goto done;
+ }
+
+ /* If cfi->data != NULL. */
+ stmtblock_t block2;
+ gfc_init_block (&block2);
+
+ /* if do_copy_inout: gfc->dspan = gfc->dtype.elem_len
+ We use gfc instead of cfi on the RHS as this might be a constant. */
+ tmp = fold_convert (gfc_array_index_type,
+ gfc_conv_descriptor_elem_len (gfc_desc));
+ if (!do_copy_inout)
+ {
+ /* gfc->dspan = ((cfi->dim[0].sm % gfc->elem_len)
+ ? cfi->dim[0].sm : gfc->elem_len). */
+ tree cond;
+ tree tmp2 = gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]);
+ cond = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
+ gfc_array_index_type, tmp2, tmp);
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ cond, gfc_index_zero_node);
+ tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
+ tmp2, tmp);
+ }
+ gfc_conv_descriptor_span_set (&block2, gfc_desc, tmp);
+
+ /* Calculate offset + set lbound, ubound and stride. */
+ gfc_conv_descriptor_offset_set (&block2, gfc_desc, gfc_index_zero_node);
+ if (sym->as->rank > 0 && !sym->attr.pointer && !sym->attr.allocatable)
+ for (int i = 0; i < sym->as->rank; ++i)
+ {
+ gfc_se se;
+ gfc_init_se (&se, NULL );
+ if (sym->as->lower[i])
+ {
+ gfc_conv_expr (&se, sym->as->lower[i]);
+ tmp = se.expr;
+ }
+ else
+ tmp = gfc_index_one_node;
+ gfc_add_block_to_block (&block2, &se.pre);
+ gfc_conv_descriptor_lbound_set (&block2, gfc_desc, gfc_rank_cst[i],
+ tmp);
+ gfc_add_block_to_block (&block2, &se.post);
+ }
+
+ /* Loop: for (i = 0; i < rank; ++i). */
+ idx = gfc_create_var (TREE_TYPE (rank), "idx");
+
+ /* Loop body. */
+ stmtblock_t loop_body;
+ gfc_init_block (&loop_body);
+ /* gfc->dim[i].lbound = ... */
+ if (sym->attr.pointer || sym->attr.allocatable)
+ {
+ tmp = gfc_get_cfi_dim_lbound (cfi, idx);
+ gfc_conv_descriptor_lbound_set (&loop_body, gfc_desc, idx, tmp);
+ }
+ else if (sym->as->rank < 0)
+ gfc_conv_descriptor_lbound_set (&loop_body, gfc_desc, idx,
+ gfc_index_one_node);
+
+ /* gfc->dim[i].ubound = gfc->dim[i].lbound + cfi->dim[i].extent - 1. */
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_lbound_get (gfc_desc, idx),
+ gfc_index_one_node);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ gfc_get_cfi_dim_extent (cfi, idx), tmp);
+ gfc_conv_descriptor_ubound_set (&loop_body, gfc_desc, idx, tmp);
+
+ if (do_copy_inout)
+ {
+ /* gfc->dim[i].stride
+ = idx == 0 ? 1 : gfc->dim[i-1].stride * cfi->dim[i-1].extent */
+ tree cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ idx, build_zero_cst (TREE_TYPE (idx)));
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (idx),
+ idx, build_int_cst (TREE_TYPE (idx), 1));
+ tree tmp2 = gfc_get_cfi_dim_extent (cfi, tmp);
+ tmp = gfc_conv_descriptor_stride_get (gfc_desc, tmp);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp2),
+ tmp2, tmp);
+ tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
+ gfc_index_one_node, tmp);
+ }
+ else
+ {
+ /* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
+ tmp = gfc_get_cfi_dim_sm (cfi, idx);
+ tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ gfc_array_index_type, tmp,
+ fold_convert (gfc_array_index_type,
+ gfc_get_cfi_desc_elem_len (cfi)));
+ }
+ gfc_conv_descriptor_stride_set (&loop_body, gfc_desc, idx, tmp);
+ /* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
+ tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_stride_get (gfc_desc, idx),
+ gfc_conv_descriptor_lbound_get (gfc_desc, idx));
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_offset_get (gfc_desc), tmp);
+ gfc_conv_descriptor_offset_set (&loop_body, gfc_desc, tmp);
+
+ /* Generate loop. */
+ gfc_simple_for_loop (&block2, idx, build_zero_cst (TREE_TYPE (idx)),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ if (sym->attr.allocatable || sym->attr.pointer)
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi),
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, null_pointer_node);
+ tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+ }
+ else
+ gfc_add_block_to_block (&block, &block2);
+
+done:
+ /* If optional arg: 'if (arg) { block } else { local_arg = NULL; }'. */
+ if (sym->attr.optional)
+ {
+ tree present = fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, cfi_desc,
+ null_pointer_node);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ sym->backend_decl,
+ fold_convert (TREE_TYPE (sym->backend_decl),
+ null_pointer_node));
+ tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block), tmp);
+ gfc_add_expr_to_block (init, tmp);
+ }
+ else
+ gfc_add_block_to_block (init, &block);
+
+ if (!sym->attr.referenced)
+ return;
+
+ /* If pointer not changed, nothing to be done (except copy out) */
+ if (!do_copy_inout && ((!sym->attr.pointer && !sym->attr.allocatable)
+ || sym->attr.intent == INTENT_IN))
+ return;
+
+ gfc_init_block (&block);
+
+ /* For bind(C), Fortran does not permit mixing 'pointer' with 'contiguous' (or
+ len=*). Thus, when copy out is needed, the bounds ofthe descriptor remain
+ unchanged. */
+ if (do_copy_inout)
+ {
+ tree data, call;
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ data = gfc_conv_descriptor_data_get (gfc_desc);
+ else if (!POINTER_TYPE_P (TREE_TYPE (gfc_desc)))
+ data = gfc_build_addr_expr (NULL, gfc_desc);
+ else
+ data = gfc_desc;
+ gfc_init_block (&block2);
+ if (sym->attr.intent != INTENT_IN)
+ {
+ /* First, create the inner copy-out loop.
+ for (idx = 0; idx < size; ++idx)
+ {
+ shift = 0;
+ tmpidx = idx
+ for (dim = 0; dim < rank; ++dim)
+ {
+ shift += (tmpidx % extent[d]) * sm[d]
+ tmpidx = tmpidx / extend[d]
+ }
+ memcpy (lhs + shift, rhs + idx*elem_len, elem_len)
+ } .*/
+ stmtblock_t loop_body;
+ idx = gfc_create_var (size_type_node, "arrayidx");
+ gfc_init_block (&loop_body);
+ tree shift = gfc_create_var (size_type_node, "shift");
+ tree tmpidx = gfc_create_var (size_type_node, "tmpidx");
+ gfc_add_modify (&loop_body, shift,
+ build_zero_cst (TREE_TYPE (shift)));
+ gfc_add_modify (&loop_body, tmpidx, idx);
+ stmtblock_t inner_loop;
+ gfc_init_block (&inner_loop);
+ tree dim = gfc_create_var (TREE_TYPE (rank), "dim");
+ /* shift += (tmpidx % extent[d]) * sm[d] */
+ tmp = fold_convert (size_type_node,
+ gfc_get_cfi_dim_extent (cfi, dim));
+ tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
+ size_type_node, tmpidx, tmp);
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ size_type_node, tmp,
+ fold_convert (size_type_node,
+ gfc_get_cfi_dim_sm (cfi, dim)));
+ gfc_add_modify (&inner_loop, shift,
+ fold_build2_loc (input_location, PLUS_EXPR,
+ size_type_node, shift, tmp));
+ /* tmpidx = tmpidx / extend[d] */
+ tmp = fold_convert (size_type_node,
+ gfc_get_cfi_dim_extent (cfi, dim));
+ gfc_add_modify (&inner_loop, tmpidx,
+ fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ size_type_node, tmpidx, tmp));
+ gfc_simple_for_loop (&loop_body, dim,
+ build_zero_cst (TREE_TYPE (rank)), rank, LT_EXPR,
+ build_int_cst (TREE_TYPE (dim), 1),
+ gfc_finish_block (&inner_loop));
+ /* Assign. */
+ tree rhs;
+ tmp = fold_convert (pchar_type_node,
+ gfc_get_cfi_desc_base_addr (cfi));
+ tmp = fold_build2 (POINTER_PLUS_EXPR, pchar_type_node, tmp, shift);
+ /* memcpy (lhs + shift, rhs + idx*elem_len, elem_len) */
+ tree elem_len;
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_desc)))
+ elem_len = gfc_conv_descriptor_elem_len (gfc_desc);
+ else
+ elem_len = gfc_get_cfi_desc_elem_len (cfi);
+ rhs = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ elem_len, idx);
+ rhs = fold_build2_loc (input_location, POINTER_PLUS_EXPR,
+ pchar_type_node,
+ fold_convert (pchar_type_node, data), rhs);
+ tmp = fold_convert (pvoid_type_node, tmp);
+ rhs = fold_convert (pvoid_type_node, rhs);
+ call = builtin_decl_explicit (BUILT_IN_MEMCPY);
+ call = build_call_expr_loc (input_location, call, 3, tmp, rhs,
+ elem_len);
+ gfc_add_expr_to_block (&loop_body,
+ fold_convert (void_type_node, call));
+ gfc_simple_for_loop (&block2, idx, build_zero_cst (TREE_TYPE (idx)),
+ size_var, LT_EXPR,
+ build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ }
+ call = builtin_decl_explicit (BUILT_IN_FREE);
+ call = build_call_expr_loc (input_location, call, 1, data);
+ gfc_add_expr_to_block (&block2, call);
+
+ /* if (cfi->base_addr != gfc->data) { copy out; free(var) }; return */
+ tree tmp2 = gfc_get_cfi_desc_base_addr (cfi);
+ tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp2, fold_convert (TREE_TYPE (tmp2), data));
+ tmp = build3_v (COND_EXPR, tmp2, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+ goto done_finally;
+ }
+
+ /* Update pointer + array data data on exit. */
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ tmp2 = (!sym->attr.dimension
+ ? gfc_desc : gfc_conv_descriptor_data_get (gfc_desc));
+ gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
+
+ /* Set string length for len=:, only. */
+ if (sym->ts.type == BT_CHARACTER && !sym->ts.u.cl->length)
+ {
+ tmp = sym->ts.u.cl->backend_decl;
+ if (sym->ts.kind != 1)
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type,
+ sym->ts.u.cl->backend_decl, tmp);
+ tmp2 = gfc_get_cfi_desc_elem_len (cfi);
+ gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
+ }
+
+ if (!sym->attr.dimension)
+ goto done_finally;
+
+ gfc_init_block (&block2);
+
+ /* Loop: for (i = 0; i < rank; ++i). */
+ idx = gfc_create_var (TREE_TYPE (rank), "idx");
+
+ /* Loop body. */
+ gfc_init_block (&loop_body);
+ /* cfi->dim[i].lower_bound = gfc->dim[i].lbound */
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_lbound (cfi, idx),
+ gfc_conv_descriptor_lbound_get (gfc_desc, idx));
+ /* cfi->dim[i].extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1. */
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_ubound_get (gfc_desc, idx),
+ gfc_conv_descriptor_lbound_get (gfc_desc, idx));
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, tmp,
+ gfc_index_one_node);
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_extent (cfi, idx), tmp);
+ /* d->dim[n].sm = gfc->dim[i].stride * gfc->span); */
+ tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_stride_get (gfc_desc, idx),
+ gfc_conv_descriptor_span_get (gfc_desc));
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_sm (cfi, idx), tmp);
+
+ /* Generate loop. */
+ gfc_simple_for_loop (&block2, idx, build_zero_cst (TREE_TYPE (idx)),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ /* if (gfc->data != NULL) { block2 }. */
+ tmp = gfc_get_cfi_desc_base_addr (cfi),
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, null_pointer_node);
+ tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+
+done_finally:
+ /* If optional arg: 'if (arg) { block } else { local_arg = NULL; }'. */
+ if (sym->attr.optional)
+ {
+ tree present = fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, cfi_desc,
+ null_pointer_node);
+ tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (finally, tmp);
+ }
+ else
+ gfc_add_block_to_block (finally, &block);
+}
/* Generate code for a function. */
@@ -6790,7 +7454,7 @@ gfc_generate_function_code (gfc_namespace * ns)
tree decl;
tree tmp;
tree fpstate = NULL_TREE;
- stmtblock_t init, cleanup;
+ stmtblock_t init, cleanup, outer_block;
stmtblock_t body;
gfc_wrapped_block try_block;
tree recurcheckvar = NULL_TREE;
@@ -6824,6 +7488,8 @@ gfc_generate_function_code (gfc_namespace * ns)
trans_function_start (sym);
gfc_init_block (&init);
+ gfc_init_block (&cleanup);
+ gfc_init_block (&outer_block);
if (ns->entries && ns->proc_name->ts.type == BT_CHARACTER)
{
@@ -6847,6 +7513,81 @@ gfc_generate_function_code (gfc_namespace * ns)
|| ns->parent == NULL)
parent_fake_result_decl = NULL_TREE;
+ /* For BIND(C):
+ - deallocate intent-out allocatable dummy arguments.
+ - Create GFC variable which will later be populated by convert_CFI_desc */
+ if (sym->attr.is_bind_c)
+ for (gfc_formal_arglist *formal = gfc_sym_get_dummy_args (sym);
+ formal; formal = formal->next)
+ {
+ gfc_symbol *fsym = formal->sym;
+ if (!is_CFI_desc (fsym, NULL))
+ continue;
+ if (!fsym->attr.referenced)
+ {
+ gfc_conv_cfi_to_gfc (&init, &cleanup, fsym->backend_decl,
+ NULL_TREE, fsym);
+ continue;
+ }
+ /* Let's now create a local GFI descriptor. Afterwards:
+ desc is the local descriptor,
+ desc_p is a pointer to it
+ and stored in sym->backend_decl
+ GFC_DECL_SAVED_DESCRIPTOR (desc_p) contains the CFI descriptor
+ -> PARM_DECL and before sym->backend_decl.
+ For scalars, decl == decl_p is a pointer variable. */
+ tree desc_p, desc;
+ location_t loc = gfc_get_location (&sym->declared_at);
+ if (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->length)
+ fsym->ts.u.cl->backend_decl = gfc_create_var (gfc_array_index_type,
+ fsym->name);
+ else if (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->backend_decl)
+ {
+ gfc_se se;
+ gfc_init_se (&se, NULL );
+ gfc_conv_expr (&se, fsym->ts.u.cl->length);
+ gfc_add_block_to_block (&init, &se.pre);
+ fsym->ts.u.cl->backend_decl = se.expr;
+ gcc_assert(se.post.head == NULL_TREE);
+ }
+ /* Nullify, otherwise gfc_sym_type will return the CFI type. */
+ tree tmp = fsym->backend_decl;
+ fsym->backend_decl = NULL;
+ tree type = gfc_sym_type (fsym);
+ gcc_assert (POINTER_TYPE_P (type));
+ if (POINTER_TYPE_P (TREE_TYPE (type)))
+ /* For instance, allocatable scalars. */
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = build_pointer_type (TREE_TYPE (type));
+ desc_p = build_decl (loc, VAR_DECL, get_identifier (fsym->name), type);
+ if (!fsym->attr.dimension)
+ desc = desc_p;
+ else if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (desc_p))))
+ {
+ /* Character(len=*) explict-size/assumed-size array. */
+ desc = desc_p;
+ gfc_build_qualified_array (desc, fsym);
+ }
+ else
+ {
+ tree size = size_in_bytes (TREE_TYPE (TREE_TYPE (desc_p)));
+ tree call = builtin_decl_explicit (BUILT_IN_ALLOCA);
+ call = build_call_expr_loc (input_location, call, 1, size);
+ gfc_add_modify (&outer_block, desc_p,
+ fold_convert (TREE_TYPE(desc_p), call));
+ desc = build_fold_indirect_ref_loc (input_location, desc_p);
+ }
+ pushdecl (desc_p);
+ if (fsym->attr.optional)
+ {
+ gfc_allocate_lang_decl (desc_p);
+ GFC_DECL_OPTIONAL_ARGUMENT (desc_p) = 1;
+ }
+ fsym->backend_decl = desc_p;
+ gfc_conv_cfi_to_gfc (&init, &cleanup, tmp, desc, fsym);
+ }
+
gfc_generate_contained_functions (ns);
has_coarray_vars = false;
@@ -6970,7 +7711,7 @@ gfc_generate_function_code (gfc_namespace * ns)
/* Arrays are not initialized using the default initializer of
their elements. Therefore only check if a default
initializer is available when the result is scalar. */
- init_exp = rsym->as ? NULL
+ init_exp = rsym->as ? NULL
: gfc_generate_initializer (&rsym->ts, true);
if (init_exp)
{
@@ -7002,8 +7743,6 @@ gfc_generate_function_code (gfc_namespace * ns)
gfc_add_expr_to_block (&body, gfc_generate_return ());
}
- gfc_init_block (&cleanup);
-
/* Reset recursion-check variable. */
if (recurcheckvar != NULL_TREE)
{
@@ -7017,8 +7756,8 @@ gfc_generate_function_code (gfc_namespace * ns)
/* Finish the function body and add init and cleanup code. */
tmp = gfc_finish_block (&body);
- gfc_start_wrapped_block (&try_block, tmp);
/* Add code to create and cleanup arrays. */
+ gfc_start_wrapped_block (&try_block, tmp);
gfc_trans_deferred_vars (sym, &try_block);
gfc_add_init_cleanup (&try_block, gfc_finish_block (&init),
gfc_finish_block (&cleanup));
@@ -7036,7 +7775,8 @@ gfc_generate_function_code (gfc_namespace * ns)
}
saved_function_decls = NULL_TREE;
- DECL_SAVED_TREE (fndecl) = gfc_finish_wrapped_block (&try_block);
+ gfc_add_expr_to_block (&outer_block, gfc_finish_wrapped_block (&try_block));
+ DECL_SAVED_TREE (fndecl) = gfc_finish_block (&outer_block);
decl = getdecls ();
/* Finish off this function and send it for code generation. */
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index c4291cc..0138937 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2630,7 +2630,9 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
if (!CONSTANT_CLASS_P (tmp) && !DECL_P (tmp))
end.expr = gfc_evaluate_now (end.expr, &se->pre);
- if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ && (ref->u.ss.start->symtree
+ && !ref->u.ss.start->symtree->n.sym->attr.implied_index))
{
tree nonempty = fold_build2_loc (input_location, LE_EXPR,
logical_type_node, start.expr,
@@ -2864,6 +2866,9 @@ tree
gfc_maybe_dereference_var (gfc_symbol *sym, tree var, bool descriptor_only_p,
bool is_classarray)
{
+ if (is_CFI_desc (sym, NULL))
+ return build_fold_indirect_ref_loc (input_location, var);
+
/* Characters are entirely different from other types, they are treated
separately. */
if (sym->ts.type == BT_CHARACTER)
@@ -4920,7 +4925,7 @@ gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
if (fsym && proc_name)
msg = xasprintf ("An array temporary was created for argument "
- "'%s' of procedure '%s'", fsym->name, proc_name);
+ "'%s' of procedure '%s'", fsym->name, proc_name);
else
msg = xasprintf ("An array temporary was created");
@@ -5218,6 +5223,8 @@ class_array_fcn:
tree post_cond;
type = TREE_TYPE (parmse->expr);
+ if (POINTER_TYPE_P (type) && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
+ type = TREE_TYPE (type);
pointer = gfc_create_var (type, "arg_ptr");
if (check_contiguous)
@@ -5261,17 +5268,25 @@ class_array_fcn:
gfc_add_block_to_block (&se->pre, &(&array_se)->pre);
gfc_add_block_to_block (&se->pre, &(&array_se)->post);
- /* if_stmt = { pointer = &a[0]; } . */
+ /* if_stmt = { descriptor ? pointer = a : pointer = &a[0]; } . */
gfc_init_block (&if_block);
- tmp = gfc_conv_array_data (array_se.expr);
- tmp = fold_convert (type, tmp);
- gfc_add_modify (&if_block, pointer, tmp);
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ gfc_add_modify (&if_block, pointer, array_se.expr);
+ else
+ {
+ tmp = gfc_conv_array_data (array_se.expr);
+ tmp = fold_convert (type, tmp);
+ gfc_add_modify (&if_block, pointer, tmp);
+ }
if_stmt = gfc_finish_block (&if_block);
/* else_stmt = { parmse->pre(); pointer = parmse->expr; } . */
gfc_init_block (&else_block);
gfc_add_block_to_block (&else_block, &parmse->pre);
- gfc_add_modify (&else_block, pointer, parmse->expr);
+ tmp = (GFC_DESCRIPTOR_TYPE_P (type)
+ ? build_fold_indirect_ref_loc (input_location, parmse->expr)
+ : parmse->expr);
+ gfc_add_modify (&else_block, pointer, tmp);
else_stmt = gfc_finish_block (&else_block);
/* And put the above into an if statement. */
@@ -5298,7 +5313,11 @@ class_array_fcn:
/* else_stmt = { pointer = NULL; } . */
gfc_init_block (&else_block);
- gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ gfc_conv_descriptor_data_set (&else_block, pointer,
+ null_pointer_node);
+ else
+ gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
else_stmt = gfc_finish_block (&else_block);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
@@ -5342,6 +5361,24 @@ class_array_fcn:
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, post_cond,
post_stmts, build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->post, tmp);
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ {
+ type = TREE_TYPE (parmse->expr);
+ if (POINTER_TYPE_P (type))
+ {
+ pointer = gfc_build_addr_expr (type, pointer);
+ if (pass_optional)
+ {
+ tmp = gfc_likely (present_var, PRED_FORTRAN_ABSENT_DUMMY);
+ pointer = fold_build3_loc (input_location, COND_EXPR, type,
+ tmp, pointer,
+ fold_convert (type,
+ null_pointer_node));
+ }
+ }
+ else
+ gcc_assert (!pass_optional);
+ }
se->expr = pointer;
}
@@ -5452,7 +5489,8 @@ set_dtype_for_unallocated (gfc_se *parmse, gfc_expr *e)
if (POINTER_TYPE_P (TREE_TYPE (desc)))
desc = build_fold_indirect_ref_loc (input_location, desc);
-
+ if (GFC_CLASS_TYPE_P (TREE_TYPE (desc)))
+ desc = gfc_class_data_get (desc);
if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
return;
@@ -5481,168 +5519,457 @@ set_dtype_for_unallocated (gfc_se *parmse, gfc_expr *e)
static void
gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
{
- tree tmp;
- tree cfi_desc_ptr;
- tree gfc_desc_ptr;
- tree type;
- tree cond;
- tree desc_attr;
- int attribute;
- int cfi_attribute;
- symbol_attribute attr = gfc_expr_attr (e);
+ stmtblock_t block, block2;
+ tree cfi, gfc, tmp, tmp2;
+ tree present = NULL;
+ tree gfc_strlen = NULL;
+ tree rank;
+ gfc_se se;
+
+ if (fsym->attr.optional
+ && e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ present = gfc_conv_expr_present (e->symtree->n.sym);
- /* If this is a full array or a scalar, the allocatable and pointer
- attributes can be passed. Otherwise it is 'CFI_attribute_other'*/
- attribute = 2;
- if (!e->rank || gfc_get_full_arrayspec_from_expr (e))
+ gfc_init_block (&block);
+
+ /* Convert original argument to a tree. */
+ gfc_init_se (&se, NULL);
+ if (e->rank == 0)
{
- if (attr.pointer)
- attribute = 0;
- else if (attr.allocatable)
- attribute = 1;
+ se.want_pointer = 1;
+ gfc_conv_expr (&se, e);
+ gfc = se.expr;
+ /* gfc_conv_constant ignores se.want_poiner, e.g. for string_cst. */
+ if (!POINTER_TYPE_P (TREE_TYPE (gfc)))
+ gfc = gfc_build_addr_expr (NULL, gfc);
}
+ else
+ {
+ /* If the actual argument can be noncontiguous, copy-in/out is required,
+ if the dummy has either the CONTIGUOUS attribute or is an assumed-
+ length assumed-length/assumed-size CHARACTER array. */
+ se.force_no_tmp = 1;
+ if ((fsym->attr.contiguous
+ || (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->length
+ && (fsym->as->type == AS_ASSUMED_SIZE
+ || fsym->as->type == AS_EXPLICIT)))
+ && !gfc_is_simply_contiguous (e, false, true))
+ {
+ bool optional = fsym->attr.optional;
+ fsym->attr.optional = 0;
+ gfc_conv_subref_array_arg (&se, e, false, fsym->attr.intent,
+ fsym->attr.pointer, fsym,
+ fsym->ns->proc_name->name, NULL,
+ /* check_contiguous= */ true);
+ fsym->attr.optional = optional;
+ }
+ else
+ gfc_conv_expr_descriptor (&se, e);
+ gfc = se.expr;
+ /* For dt(:)%var the elem_len*stride != sm, hence, GFC uses
+ elem_len = sizeof(dt) and base_addr = dt(lb) instead.
+ gfc_get_dataptr_offset fixes the base_addr; for elem_len, see below.
+ While sm is fine as it uses span*stride and not elem_len. */
+ if (POINTER_TYPE_P (TREE_TYPE (gfc)))
+ gfc = build_fold_indirect_ref_loc (input_location, gfc);
+ else if (is_subref_array (e) && e->ts.type != BT_CHARACTER)
+ gfc_get_dataptr_offset (&se.pre, gfc, gfc, NULL, true, e);
+ }
+ if (e->ts.type == BT_CHARACTER)
+ {
+ if (se.string_length)
+ gfc_strlen = se.string_length;
+ else if (e->ts.u.cl->backend_decl)
+ gfc_strlen = e->ts.u.cl->backend_decl;
+ else
+ gcc_unreachable ();
+ }
+ gfc_add_block_to_block (&block, &se.pre);
+
+ /* Create array decriptor and set version, rank, attribute, type. */
+ cfi = gfc_create_var (gfc_get_cfi_type (e->rank < 0
+ ? GFC_MAX_DIMENSIONS : e->rank,
+ false), "cfi");
+ /* Convert to CFI_cdesc_t, which has dim[] to avoid TBAA issues,*/
+ if (fsym->attr.dimension && fsym->as->type == AS_ASSUMED_RANK)
+ {
+ tmp = gfc_get_cfi_type (-1, !fsym->attr.pointer && !fsym->attr.target);
+ tmp = build_pointer_type (tmp);
+ parmse->expr = cfi = gfc_build_addr_expr (tmp, cfi);
+ cfi = build_fold_indirect_ref_loc (input_location, cfi);
+ }
+ else
+ parmse->expr = gfc_build_addr_expr (NULL, cfi);
+
+ tmp = gfc_get_cfi_desc_version (cfi);
+ gfc_add_modify (&block, tmp,
+ build_int_cst (TREE_TYPE (tmp), CFI_VERSION));
+ if (e->rank < 0)
+ rank = fold_convert (signed_char_type_node, gfc_conv_descriptor_rank (gfc));
+ else
+ rank = build_int_cst (signed_char_type_node, e->rank);
+ tmp = gfc_get_cfi_desc_rank (cfi);
+ gfc_add_modify (&block, tmp, rank);
+ int itype = CFI_type_other;
+ if (e->ts.f90_type == BT_VOID)
+ itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
+ ? CFI_type_cfunptr : CFI_type_cptr);
+ else
+ switch (e->ts.type)
+ {
+ case BT_INTEGER:
+ case BT_LOGICAL:
+ case BT_REAL:
+ case BT_COMPLEX:
+ itype = CFI_type_from_type_kind (e->ts.type, e->ts.kind);
+ break;
+ case BT_CHARACTER:
+ itype = CFI_type_from_type_kind (CFI_type_Character, e->ts.kind);
+ break;
+ case BT_DERIVED:
+ itype = CFI_type_struct;
+ break;
+ case BT_VOID:
+ itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
+ ? CFI_type_cfunptr : CFI_type_cptr);
+ break;
+ case BT_ASSUMED:
+ itype = CFI_type_other; // FIXME: Or CFI_type_cptr ?
+ break;
+ case BT_CLASS:
+ case BT_PROCEDURE:
+ case BT_HOLLERITH:
+ case BT_UNION:
+ case BT_BOZ:
+ case BT_UNKNOWN:
+ // FIXME: Really unreachable? Or reachable for type(*) ? If so, CFI_type_other?
+ gcc_unreachable ();
+ }
+ tmp = gfc_get_cfi_desc_type (cfi);
+ gfc_add_modify (&block, tmp,
+ build_int_cst (TREE_TYPE (tmp), itype));
+
+ int attr = CFI_attribute_other;
if (fsym->attr.pointer)
- cfi_attribute = 0;
+ attr = CFI_attribute_pointer;
else if (fsym->attr.allocatable)
- cfi_attribute = 1;
- else
- cfi_attribute = 2;
+ attr = CFI_attribute_allocatable;
+ tmp = gfc_get_cfi_desc_attribute (cfi);
+ gfc_add_modify (&block, tmp,
+ build_int_cst (TREE_TYPE (tmp), attr));
- if (e->rank != 0)
+ if (e->rank == 0)
{
- parmse->force_no_tmp = 1;
- if (fsym->attr.contiguous
- && !gfc_is_simply_contiguous (e, false, true))
- gfc_conv_subref_array_arg (parmse, e, false, fsym->attr.intent,
- fsym->attr.pointer);
- else
- gfc_conv_expr_descriptor (parmse, e);
-
- if (POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
- parmse->expr = build_fold_indirect_ref_loc (input_location,
- parmse->expr);
- bool is_artificial = (INDIRECT_REF_P (parmse->expr)
- ? DECL_ARTIFICIAL (TREE_OPERAND (parmse->expr, 0))
- : DECL_ARTIFICIAL (parmse->expr));
-
- /* Unallocated allocatable arrays and unassociated pointer arrays
- need their dtype setting if they are argument associated with
- assumed rank dummies. */
- if (fsym && fsym->as
- && (gfc_expr_attr (e).pointer
- || gfc_expr_attr (e).allocatable))
- set_dtype_for_unallocated (parmse, e);
-
- /* All the temporary descriptors are marked as DECL_ARTIFICIAL. If
- the expression type is different from the descriptor type, then
- the offset must be found (eg. to a component ref or substring)
- and the dtype updated. Assumed type entities are only allowed
- to be dummies in Fortran. They therefore lack the decl specific
- appendiges and so must be treated differently from other fortran
- entities passed to CFI descriptors in the interface decl. */
- type = e->ts.type != BT_ASSUMED ? gfc_typenode_for_spec (&e->ts) :
- NULL_TREE;
-
- if (type && is_artificial
- && type != gfc_get_element_type (TREE_TYPE (parmse->expr)))
- {
- /* Obtain the offset to the data. */
- gfc_get_dataptr_offset (&parmse->pre, parmse->expr, parmse->expr,
- gfc_index_zero_node, true, e);
-
- /* Update the dtype. */
- gfc_add_modify (&parmse->pre,
- gfc_conv_descriptor_dtype (parmse->expr),
- gfc_get_dtype_rank_type (e->rank, type));
- }
- else if (type == NULL_TREE
- || (!is_subref_array (e) && !is_artificial))
- {
- /* Make sure that the span is set for expressions where it
- might not have been done already. */
- tmp = gfc_conv_descriptor_elem_len (parmse->expr);
- tmp = fold_convert (gfc_array_index_type, tmp);
- gfc_conv_descriptor_span_set (&parmse->pre, parmse->expr, tmp);
- }
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), gfc));
}
else
{
- gfc_conv_expr (parmse, e);
-
- if (POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
- parmse->expr = build_fold_indirect_ref_loc (input_location,
- parmse->expr);
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ tmp2 = gfc_conv_descriptor_data_get (gfc);
+ gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
+ }
- parmse->expr = gfc_conv_scalar_to_descriptor (parmse,
- parmse->expr, attr);
+ /* Set elem_len if known - must be before the next if block.
+ Note that allocatable implies 'len=:'. */
+ if (e->ts.type != BT_ASSUMED && e->ts.type != BT_CHARACTER )
+ {
+ /* Length is known at compile time; use use 'block' for it. */
+ tmp = size_in_bytes (gfc_typenode_for_spec (&e->ts));
+ tmp2 = gfc_get_cfi_desc_elem_len (cfi);
+ gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
}
- /* Set the CFI attribute field through a temporary value for the
- gfc attribute. */
- desc_attr = gfc_conv_descriptor_attribute (parmse->expr);
- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- void_type_node, desc_attr,
- build_int_cst (TREE_TYPE (desc_attr), cfi_attribute));
- gfc_add_expr_to_block (&parmse->pre, tmp);
+ /* When allocatable + intent out, free the cfi descriptor. */
+ if (fsym->attr.allocatable && fsym->attr.intent == INTENT_OUT)
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ tree call = builtin_decl_explicit (BUILT_IN_FREE);
+ call = build_call_expr_loc (input_location, call, 1, tmp);
+ gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
+ gfc_add_modify (&block, tmp,
+ fold_convert (TREE_TYPE (tmp), null_pointer_node));
+ goto done;
+ }
- /* Now pass the gfc_descriptor by reference. */
- parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
+ /* If not unallocated/unassociated. */
+ gfc_init_block (&block2);
- /* Variables to point to the gfc and CFI descriptors; cfi = NULL implies
- that the CFI descriptor is allocated by the gfor_fndecl_gfc_to_cfi call. */
- gfc_desc_ptr = parmse->expr;
- cfi_desc_ptr = gfc_create_var (pvoid_type_node, "cfi");
- gfc_add_modify (&parmse->pre, cfi_desc_ptr, null_pointer_node);
+ /* Set elem_len, which may be only known at run time. */
+ if (e->ts.type == BT_CHARACTER)
+ {
+ gcc_assert (gfc_strlen);
+ tmp = gfc_strlen;
+ if (e->ts.kind != 1)
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_charlen_type_node, tmp,
+ build_int_cst (gfc_charlen_type_node,
+ e->ts.kind));
+ tmp2 = gfc_get_cfi_desc_elem_len (cfi);
+ gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
+ }
+ else if (e->ts.type == BT_ASSUMED)
+ {
+ tmp = gfc_conv_descriptor_elem_len (gfc);
+ tmp2 = gfc_get_cfi_desc_elem_len (cfi);
+ gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
+ }
- /* Allocate the CFI descriptor itself and fill the fields. */
- tmp = gfc_build_addr_expr (NULL_TREE, cfi_desc_ptr);
- tmp = build_call_expr_loc (input_location,
- gfor_fndecl_gfc_to_cfi, 2, tmp, gfc_desc_ptr);
- gfc_add_expr_to_block (&parmse->pre, tmp);
+ if (e->ts.type == BT_ASSUMED)
+ {
+ /* Note: type(*) implies assumed-shape/assumed-rank if fsym requires
+ an CFI descriptor. Use the type in the descritor as it provide
+ mode information. (Quality of implementation feature.) */
+ tree cond;
+ tree ctype = gfc_get_cfi_desc_type (cfi);
+ tree type = fold_convert (TREE_TYPE (ctype),
+ gfc_conv_descriptor_type (gfc));
+ tree kind = fold_convert (TREE_TYPE (ctype),
+ gfc_conv_descriptor_elem_len (gfc));
+ kind = fold_build2_loc (input_location, LSHIFT_EXPR, TREE_TYPE (type),
+ kind, build_int_cst (TREE_TYPE (type),
+ CFI_type_kind_shift));
+
+ /* if (BT_VOID) CFI_type_cptr else CFI_type_other */
+ /* Note: BT_VOID is could also be CFI_type_funcptr, but assume c_ptr. */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_VOID));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
+ build_int_cst (TREE_TYPE (type), CFI_type_cptr));
+ tmp2 = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ ctype,
+ build_int_cst (TREE_TYPE (type), CFI_type_other));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (BT_DERIVED) CFI_type_struct else < tmp2 > */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_DERIVED));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
+ build_int_cst (TREE_TYPE (type), CFI_type_struct));
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (BT_CHARACTER) CFI_type_Character + kind=1 else < tmp2 > */
+ /* Note: could also be kind=4, with cfi->elem_len = gfc->elem_len*4. */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_CHARACTER));
+ tmp = build_int_cst (TREE_TYPE (type),
+ CFI_type_from_type_kind (CFI_type_Character, 1));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ ctype, tmp);
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (BT_COMPLEX) CFI_type_Complex + kind/2 else < tmp2 > */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_COMPLEX));
+ tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (type),
+ kind, build_int_cst (TREE_TYPE (type), 2));
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type), tmp,
+ build_int_cst (TREE_TYPE (type),
+ CFI_type_Complex));
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ ctype, tmp);
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ /* if (BT_INTEGER || BT_LOGICAL || BT_REAL) type + kind else <tmp2> */
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_INTEGER));
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_LOGICAL));
+ cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
+ build_int_cst (TREE_TYPE (type), BT_REAL));
+ cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
+ cond, tmp);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type),
+ type, kind);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
+ ctype, tmp);
+ tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
+ tmp, tmp2);
+ gfc_add_expr_to_block (&block2, tmp2);
+ }
- /* Now set the gfc descriptor attribute. */
- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- void_type_node, desc_attr,
- build_int_cst (TREE_TYPE (desc_attr), attribute));
- gfc_add_expr_to_block (&parmse->pre, tmp);
+ if (e->rank != 0)
+ {
+ /* Loop: for (i = 0; i < rank; ++i). */
+ tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
+ /* Loop body. */
+ stmtblock_t loop_body;
+ gfc_init_block (&loop_body);
+ /* cfi->dim[i].lower_bound = (allocatable/pointer)
+ ? gfc->dim[i].lbound : 0 */
+ if (fsym->attr.pointer || fsym->attr.allocatable)
+ tmp = gfc_conv_descriptor_lbound_get (gfc, idx);
+ else
+ tmp = gfc_index_zero_node;
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_lbound (cfi, idx), tmp);
+ /* cfi->dim[i].extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1. */
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_ubound_get (gfc, idx),
+ gfc_conv_descriptor_lbound_get (gfc, idx));
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ tmp, gfc_index_one_node);
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_extent (cfi, idx), tmp);
+ /* d->dim[n].sm = gfc->dim[i].stride * gfc->span); */
+ tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_stride_get (gfc, idx),
+ gfc_conv_descriptor_span_get (gfc));
+ gfc_add_modify (&loop_body, gfc_get_cfi_dim_sm (cfi, idx), tmp);
- /* The CFI descriptor is passed to the bind_C procedure. */
- parmse->expr = cfi_desc_ptr;
+ /* Generate loop. */
+ gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
- /* Free the CFI descriptor. */
- tmp = gfc_call_free (cfi_desc_ptr);
- gfc_prepend_expr_to_block (&parmse->post, tmp);
+ if (e->expr_type == EXPR_VARIABLE
+ && e->ref
+ && e->ref->u.ar.type == AR_FULL
+ && e->symtree->n.sym->attr.dummy
+ && e->symtree->n.sym->as
+ && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
+ {
+ tmp = gfc_get_cfi_dim_extent (cfi, gfc_rank_cst[e->rank-1]),
+ gfc_add_modify (&block2, tmp, build_int_cst (TREE_TYPE (tmp), -1));
+ }
+ }
- /* Transfer values back to gfc descriptor. */
- if (cfi_attribute != 2 /* CFI_attribute_other. */
- && !fsym->attr.value
- && fsym->attr.intent != INTENT_IN)
+ if (fsym->attr.allocatable || fsym->attr.pointer)
{
- tmp = gfc_build_addr_expr (NULL_TREE, parmse->expr);
- tmp = build_call_expr_loc (input_location,
- gfor_fndecl_cfi_to_gfc, 2, gfc_desc_ptr, tmp);
- gfc_prepend_expr_to_block (&parmse->post, tmp);
+ tmp = gfc_get_cfi_desc_base_addr (cfi),
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, null_pointer_node);
+ tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
}
+ else
+ gfc_add_block_to_block (&block, &block2);
- /* Deal with an optional dummy being passed to an optional formal arg
- by finishing the pre and post blocks and making their execution
- conditional on the dummy being present. */
- if (fsym->attr.optional && e->expr_type == EXPR_VARIABLE
- && e->symtree->n.sym->attr.optional)
+
+done:
+ if (present)
{
- cond = gfc_conv_expr_present (e->symtree->n.sym);
- tmp = fold_build2 (MODIFY_EXPR, void_type_node,
- cfi_desc_ptr,
- build_int_cst (pvoid_type_node, 0));
- tmp = build3_v (COND_EXPR, cond,
- gfc_finish_block (&parmse->pre), tmp);
+ parmse->expr = build3_loc (input_location, COND_EXPR,
+ TREE_TYPE (parmse->expr),
+ present, parmse->expr, null_pointer_node);
+ tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
+ build_empty_stmt (input_location));
gfc_add_expr_to_block (&parmse->pre, tmp);
- tmp = build3_v (COND_EXPR, cond,
- gfc_finish_block (&parmse->post),
+ }
+ else
+ gfc_add_block_to_block (&parmse->pre, &block);
+
+ gfc_init_block (&block);
+
+ if ((!fsym->attr.allocatable && !fsym->attr.pointer)
+ || fsym->attr.intent == INTENT_IN)
+ goto post_call;
+
+ gfc_init_block (&block2);
+ if (e->rank == 0)
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ gfc_add_modify (&block, gfc, fold_convert (TREE_TYPE (gfc), tmp));
+ }
+ else
+ {
+ tmp = gfc_get_cfi_desc_base_addr (cfi);
+ gfc_conv_descriptor_data_set (&block, gfc, tmp);
+
+ if (fsym->attr.allocatable)
+ {
+ /* gfc->span = cfi->elem_len. */
+ tmp = fold_convert (gfc_array_index_type,
+ gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]));
+ }
+ else
+ {
+ /* gfc->span = ((cfi->dim[0].sm % cfi->elem_len)
+ ? cfi->dim[0].sm : cfi->elem_len). */
+ tmp = gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]);
+ tmp2 = fold_convert (gfc_array_index_type,
+ gfc_get_cfi_desc_elem_len (cfi));
+ tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
+ gfc_array_index_type, tmp, tmp2);
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, gfc_index_zero_node);
+ tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, tmp,
+ gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]), tmp2);
+ }
+ gfc_conv_descriptor_span_set (&block2, gfc, tmp);
+
+ /* Calculate offset + set lbound, ubound and stride. */
+ gfc_conv_descriptor_offset_set (&block2, gfc, gfc_index_zero_node);
+ /* Loop: for (i = 0; i < rank; ++i). */
+ tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
+ /* Loop body. */
+ stmtblock_t loop_body;
+ gfc_init_block (&loop_body);
+ /* gfc->dim[i].lbound = ... */
+ tmp = gfc_get_cfi_dim_lbound (cfi, idx);
+ gfc_conv_descriptor_lbound_set (&loop_body, gfc, idx, tmp);
+
+ /* gfc->dim[i].ubound = gfc->dim[i].lbound + cfi->dim[i].extent - 1. */
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_lbound_get (gfc, idx),
+ gfc_index_one_node);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
+ gfc_get_cfi_dim_extent (cfi, idx), tmp);
+ gfc_conv_descriptor_ubound_set (&loop_body, gfc, idx, tmp);
+
+ /* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
+ tmp = gfc_get_cfi_dim_sm (cfi, idx);
+ tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ gfc_array_index_type, tmp,
+ fold_convert (gfc_array_index_type,
+ gfc_get_cfi_desc_elem_len (cfi)));
+ gfc_conv_descriptor_stride_set (&loop_body, gfc, idx, tmp);
+
+ /* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
+ tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_stride_get (gfc, idx),
+ gfc_conv_descriptor_lbound_get (gfc, idx));
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ gfc_conv_descriptor_offset_get (gfc), tmp);
+ gfc_conv_descriptor_offset_set (&loop_body, gfc, tmp);
+ /* Generate loop. */
+ gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
+ rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
+ gfc_finish_block (&loop_body));
+ }
+
+ if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
+ {
+ tmp = fold_convert (gfc_charlen_type_node,
+ gfc_get_cfi_desc_elem_len (cfi));
+ if (e->ts.kind != 1)
+ tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
+ gfc_charlen_type_node, tmp,
+ build_int_cst (gfc_charlen_type_node,
+ e->ts.kind));
+ gfc_add_modify (&block2, gfc_strlen, tmp);
+ }
+
+ tmp = gfc_get_cfi_desc_base_addr (cfi),
+ tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ tmp, null_pointer_node);
+ tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&block, tmp);
+
+post_call:
+ gfc_add_block_to_block (&block, &se.post);
+ if (present && block.head)
+ {
+ tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
build_empty_stmt (input_location));
gfc_add_expr_to_block (&parmse->post, tmp);
}
+ else if (block.head)
+ gfc_add_block_to_block (&parmse->post, &block);
}
@@ -5761,17 +6088,12 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
arg = arg->next, formal = formal ? formal->next : NULL, ++argc)
{
bool finalized = false;
- bool assumed_length_string = false;
tree derived_array = NULL_TREE;
e = arg->expr;
fsym = formal ? formal->sym : NULL;
parm_kind = MISSING;
- if (fsym && fsym->ts.type == BT_CHARACTER
- && (!fsym->ts.u.cl || !fsym->ts.u.cl->length))
- assumed_length_string = true;
-
/* If the procedure requires an explicit interface, the actual
argument is passed according to the corresponding formal
argument. If the corresponding formal argument is a POINTER,
@@ -6002,9 +6324,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
parmse.expr = convert (type, tmp);
}
- else if (sym->attr.is_bind_c && e
- && (is_CFI_desc (fsym, NULL)
- || assumed_length_string))
+ else if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
@@ -6214,7 +6534,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if (fsym && fsym->attr.intent == INTENT_OUT
&& (fsym->attr.allocatable
|| (fsym->ts.type == BT_CLASS
- && CLASS_DATA (fsym)->attr.allocatable)))
+ && CLASS_DATA (fsym)->attr.allocatable))
+ && !is_CFI_desc (fsym, NULL))
{
stmtblock_t block;
tree ptr;
@@ -6448,8 +6769,30 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
parmse.force_tmp = 1;
}
- if (sym->attr.is_bind_c && e
- && (is_CFI_desc (fsym, NULL) || assumed_length_string))
+ /* Special case for assumed-rank arrays: when passing an
+ argument to a nonallocatable/nonpointer dummy, the bounds have
+ to be reset as otherwise a last-dim ubound of -1 is
+ indistinguishable from an assumed-size array in the callee. */
+ if (!sym->attr.is_bind_c && e && fsym && fsym->as
+ && fsym->as->type == AS_ASSUMED_RANK
+ && e->rank != -1
+ && e->expr_type == EXPR_VARIABLE
+ && ((fsym->ts.type == BT_CLASS
+ && !CLASS_DATA (fsym)->attr.class_pointer
+ && !CLASS_DATA (fsym)->attr.allocatable)
+ || (fsym->ts.type != BT_CLASS
+ && !fsym->attr.pointer && !fsym->attr.allocatable)))
+ {
+ /* Change AR_FULL to a (:,:,:) ref to force bounds update. */
+ gfc_ref *ref;
+ for (ref = e->ref; ref->next; ref = ref->next)
+ ;
+ if (ref->u.ar.type == AR_FULL
+ && ref->u.ar.as->type != AS_ASSUMED_SIZE)
+ ref->u.ar.type = AR_SECTION;
+ }
+
+ if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
/* Implement F2018, 18.3.6, list item (5), bullet point 2. */
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
@@ -6508,37 +6851,12 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym,
sym->name, NULL);
- /* Unallocated allocatable arrays and unassociated pointer arrays
- need their dtype setting if they are argument associated with
- assumed rank dummies, unless already assumed rank. */
- if (!sym->attr.is_bind_c && e && fsym && fsym->as
- && fsym->as->type == AS_ASSUMED_RANK
- && e->rank != -1)
- {
- if (gfc_expr_attr (e).pointer
- || gfc_expr_attr (e).allocatable)
- set_dtype_for_unallocated (&parmse, e);
- else if (e->expr_type == EXPR_VARIABLE
- && e->ref
- && e->ref->u.ar.type == AR_FULL
- && e->symtree->n.sym->attr.dummy
- && e->symtree->n.sym->as
- && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
- {
- tree minus_one;
- tmp = build_fold_indirect_ref_loc (input_location,
- parmse.expr);
- minus_one = build_int_cst (gfc_array_index_type, -1);
- gfc_conv_descriptor_ubound_set (&parmse.pre, tmp,
- gfc_rank_cst[e->rank - 1],
- minus_one);
- }
- }
-
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
- allocated on entry, it must be deallocated. */
+ allocated on entry, it must be deallocated.
+ CFI descriptors are handled elsewhere. */
if (fsym && fsym->attr.allocatable
- && fsym->attr.intent == INTENT_OUT)
+ && fsym->attr.intent == INTENT_OUT
+ && !is_CFI_desc (fsym, NULL))
{
if (fsym->ts.type == BT_DERIVED
&& fsym->ts.u.derived->attr.alloc_comp)
@@ -6546,6 +6864,17 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
// deallocate the components first
tmp = gfc_deallocate_alloc_comp (fsym->ts.u.derived,
parmse.expr, e->rank);
+ /* But check whether dummy argument is optional. */
+ if (tmp != NULL_TREE
+ && fsym->attr.optional
+ && e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ {
+ tree present;
+ present = gfc_conv_expr_present (e->symtree->n.sym);
+ tmp = build3_v (COND_EXPR, present, tmp,
+ build_empty_stmt (input_location));
+ }
if (tmp != NULL_TREE)
gfc_add_expr_to_block (&se->pre, tmp);
}
@@ -6575,6 +6904,46 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
}
}
}
+ /* Special case for an assumed-rank dummy argument. */
+ if (!sym->attr.is_bind_c && e && fsym && e->rank > 0
+ && (fsym->ts.type == BT_CLASS
+ ? (CLASS_DATA (fsym)->as
+ && CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
+ : (fsym->as && fsym->as->type == AS_ASSUMED_RANK)))
+ {
+ if (fsym->ts.type == BT_CLASS
+ ? (CLASS_DATA (fsym)->attr.class_pointer
+ || CLASS_DATA (fsym)->attr.allocatable)
+ : (fsym->attr.pointer || fsym->attr.allocatable))
+ {
+ /* Unallocated allocatable arrays and unassociated pointer
+ arrays need their dtype setting if they are argument
+ associated with assumed rank dummies to set the rank. */
+ set_dtype_for_unallocated (&parmse, e);
+ }
+ else if (e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.dummy
+ && (e->ts.type == BT_CLASS
+ ? (e->ref && e->ref->next
+ && e->ref->next->type == REF_ARRAY
+ && e->ref->next->u.ar.type == AR_FULL
+ && e->ref->next->u.ar.as->type == AS_ASSUMED_SIZE)
+ : (e->ref && e->ref->type == REF_ARRAY
+ && e->ref->u.ar.type == AR_FULL
+ && e->ref->u.ar.as->type == AS_ASSUMED_SIZE)))
+ {
+ /* Assumed-size actual to assumed-rank dummy requires
+ dim[rank-1].ubound = -1. */
+ tree minus_one;
+ tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
+ if (fsym->ts.type == BT_CLASS)
+ tmp = gfc_class_data_get (tmp);
+ minus_one = build_int_cst (gfc_array_index_type, -1);
+ gfc_conv_descriptor_ubound_set (&parmse.pre, tmp,
+ gfc_rank_cst[e->rank - 1],
+ minus_one);
+ }
+ }
/* The case with fsym->attr.optional is that of a user subroutine
with an interface indicating an optional argument. When we call
@@ -11715,3 +12084,37 @@ gfc_trans_assign (gfc_code * code)
{
return gfc_trans_assignment (code->expr1, code->expr2, false, true);
}
+
+/* Generate a simple loop for internal use of the form
+ for (var = begin; var <cond> end; var += step)
+ body; */
+void
+gfc_simple_for_loop (stmtblock_t *block, tree var, tree begin, tree end,
+ enum tree_code cond, tree step, tree body)
+{
+ tree tmp;
+
+ /* var = begin. */
+ gfc_add_modify (block, var, begin);
+
+ /* Loop: for (var = begin; var <cond> end; var += step). */
+ tree label_loop = gfc_build_label_decl (NULL_TREE);
+ tree label_cond = gfc_build_label_decl (NULL_TREE);
+ TREE_USED (label_loop) = 1;
+ TREE_USED (label_cond) = 1;
+
+ gfc_add_expr_to_block (block, build1_v (GOTO_EXPR, label_cond));
+ gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_loop));
+
+ /* Loop body. */
+ gfc_add_expr_to_block (block, body);
+
+ /* End of loop body. */
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var, step);
+ gfc_add_modify (block, var, tmp);
+ gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_cond));
+ tmp = fold_build2_loc (input_location, cond, boolean_type_node, var, end);
+ tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (block, tmp);
+}
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 46670ba..2a2829c 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -175,7 +175,7 @@ gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
if (gfc_real_kinds[i].c_float128)
{
- /* For __float128, the story is a bit different, because we return
+ /* For _Float128, the story is a bit different, because we return
a decl to a library function rather than a built-in. */
gfc_intrinsic_map_t *m;
for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
@@ -387,7 +387,7 @@ build_round_expr (tree arg, tree restype)
resprec = TYPE_PRECISION (restype);
/* Depending on the type of the result, choose the int intrinsic (iround,
- available only as a builtin, therefore cannot use it for __float128), long
+ available only as a builtin, therefore cannot use it for _Float128), long
int intrinsic (lround family) or long long intrinsic (llround). If we
don't have an appropriate function that converts directly to the integer
type (such as kind == 16), just use ROUND, and then convert the result to
@@ -689,7 +689,7 @@ gfc_build_intrinsic_lib_fndecls (void)
if (gfc_real16_is_float128)
{
/* If we have soft-float types, we create the decls for their
- C99-like library functions. For now, we only handle __float128
+ C99-like library functions. For now, we only handle _Float128
q-suffixed functions. */
tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
@@ -6697,6 +6697,8 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
gfc_expr *e;
gfc_array_spec *as;
gfc_ss *ss;
+ symbol_attribute attr;
+ tree result_desc = se->expr;
/* Remove the KIND argument, if present. */
s = expr->value.function.actual;
@@ -6707,17 +6709,25 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
gfc_conv_intrinsic_funcall (se, expr);
- as = gfc_get_full_arrayspec_from_expr (s->expr);;
- ss = gfc_walk_expr (s->expr);
-
/* According to F2018 16.9.172, para 5, an assumed rank entity, argument
associated with an assumed size array, has the ubound of the final
dimension set to -1 and SHAPE must return this. */
- if (as && as->type == AS_ASSUMED_RANK
- && se->expr && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))
- && ss && ss->info->type == GFC_SS_SECTION)
+
+ as = gfc_get_full_arrayspec_from_expr (s->expr);
+ if (!as || as->type != AS_ASSUMED_RANK)
+ return;
+ attr = gfc_expr_attr (s->expr);
+ ss = gfc_walk_expr (s->expr);
+ if (attr.pointer || attr.allocatable
+ || !ss || ss->info->type != GFC_SS_SECTION)
+ return;
+ if (se->expr)
+ result_desc = se->expr;
+ if (POINTER_TYPE_P (TREE_TYPE (result_desc)))
+ result_desc = build_fold_indirect_ref_loc (input_location, result_desc);
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (result_desc)))
{
- tree desc, rank, minus_one, cond, ubound, tmp;
+ tree rank, minus_one, cond, ubound, tmp;
stmtblock_t block;
gfc_se ase;
@@ -6745,8 +6755,7 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
/* Obtain the last element of the result from the library shape
intrinsic and set it to -1 if that is the value of ubound. */
- desc = se->expr;
- tmp = gfc_conv_array_data (desc);
+ tmp = gfc_conv_array_data (result_desc);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
tmp = gfc_build_array_ref (tmp, rank, NULL, NULL);
@@ -6758,7 +6767,6 @@ gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->pre, cond);
}
-
}
static void
@@ -7968,8 +7976,7 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
gfc_actual_arglist *actual;
tree arg1;
tree type;
- tree fncall0;
- tree fncall1;
+ tree size;
gfc_se argse;
gfc_expr *e;
gfc_symbol *sym = NULL;
@@ -8046,37 +8053,31 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
/* For functions that return a class array conv_expr_descriptor is not
able to get the descriptor right. Therefore this special case. */
gfc_conv_expr_reference (&argse, e);
- argse.expr = gfc_build_addr_expr (NULL_TREE,
- gfc_class_data_get (argse.expr));
+ argse.expr = gfc_class_data_get (argse.expr);
}
else if (sym && sym->backend_decl)
{
gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
- argse.expr = sym->backend_decl;
- argse.expr = gfc_build_addr_expr (NULL_TREE,
- gfc_class_data_get (argse.expr));
+ argse.expr = gfc_class_data_get (sym->backend_decl);
}
else
- {
- argse.want_pointer = 1;
- gfc_conv_expr_descriptor (&argse, actual->expr);
- }
+ gfc_conv_expr_descriptor (&argse, actual->expr);
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
- arg1 = gfc_evaluate_now (argse.expr, &se->pre);
-
- /* Build the call to size0. */
- fncall0 = build_call_expr_loc (input_location,
- gfor_fndecl_size0, 1, arg1);
+ arg1 = argse.expr;
actual = actual->next;
-
if (actual->expr)
{
+ stmtblock_t block;
+ gfc_init_block (&block);
gfc_init_se (&argse, NULL);
gfc_conv_expr_type (&argse, actual->expr,
gfc_array_index_type);
- gfc_add_block_to_block (&se->pre, &argse.pre);
+ gfc_add_block_to_block (&block, &argse.pre);
+ tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ argse.expr, gfc_index_one_node);
+ size = gfc_tree_array_size (&block, arg1, e, tmp);
/* Unusually, for an intrinsic, size does not exclude
an optional arg2, so we must test for it. */
@@ -8084,59 +8085,35 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
&& actual->expr->symtree->n.sym->attr.dummy
&& actual->expr->symtree->n.sym->attr.optional)
{
- tree tmp;
- /* Build the call to size1. */
- fncall1 = build_call_expr_loc (input_location,
- gfor_fndecl_size1, 2,
- arg1, argse.expr);
-
+ tree cond;
+ stmtblock_t block2;
+ gfc_init_block (&block2);
gfc_init_se (&argse, NULL);
argse.want_pointer = 1;
argse.data_not_needed = 1;
gfc_conv_expr (&argse, actual->expr);
gfc_add_block_to_block (&se->pre, &argse.pre);
- tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- argse.expr, null_pointer_node);
- tmp = gfc_evaluate_now (tmp, &se->pre);
- se->expr = fold_build3_loc (input_location, COND_EXPR,
- pvoid_type_node, tmp, fncall1, fncall0);
+ cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ argse.expr, null_pointer_node);
+ cond = gfc_evaluate_now (cond, &se->pre);
+ /* 'block2' contains the arg2 absent case, 'block' the arg2 present
+ case; size_var can be used in both blocks. */
+ tree size_var = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+ TREE_TYPE (size_var), size_var, size);
+ gfc_add_expr_to_block (&block, tmp);
+ tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
+ gfc_finish_block (&block2));
+ gfc_add_expr_to_block (&se->pre, tmp);
+ size = size_var;
}
else
- {
- se->expr = NULL_TREE;
- argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type,
- argse.expr, gfc_index_one_node);
- }
- }
- else if (expr->value.function.actual->expr->rank == 1)
- {
- argse.expr = gfc_index_zero_node;
- se->expr = NULL_TREE;
+ gfc_add_block_to_block (&se->pre, &block);
}
else
- se->expr = fncall0;
-
- if (se->expr == NULL_TREE)
- {
- tree ubound, lbound;
-
- arg1 = build_fold_indirect_ref_loc (input_location,
- arg1);
- ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
- lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
- se->expr = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, ubound, lbound);
- se->expr = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type,
- se->expr, gfc_index_one_node);
- se->expr = fold_build2_loc (input_location, MAX_EXPR,
- gfc_array_index_type, se->expr,
- gfc_index_zero_node);
- }
-
+ size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
type = gfc_typenode_for_spec (&expr->ts);
- se->expr = convert (type, se->expr);
+ se->expr = convert (type, size);
}
@@ -8887,50 +8864,63 @@ caf_this_image_ref (gfc_ref *ref)
static void
gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
{
- gfc_actual_arglist *arg1;
gfc_se arg1se;
tree tmp;
- symbol_attribute caf_attr;
+ bool coindexed_caf_comp = false;
+ gfc_expr *e = expr->value.function.actual->expr;
gfc_init_se (&arg1se, NULL);
- arg1 = expr->value.function.actual;
-
- if (arg1->expr->ts.type == BT_CLASS)
+ if (e->ts.type == BT_CLASS)
{
/* Make sure that class array expressions have both a _data
component reference and an array reference.... */
- if (CLASS_DATA (arg1->expr)->attr.dimension)
- gfc_add_class_array_ref (arg1->expr);
+ if (CLASS_DATA (e)->attr.dimension)
+ gfc_add_class_array_ref (e);
/* .... whilst scalars only need the _data component. */
else
- gfc_add_data_component (arg1->expr);
+ gfc_add_data_component (e);
}
- /* When arg1 references an allocatable component in a coarray, then call
+ /* When 'e' references an allocatable component in a coarray, then call
the caf-library function caf_is_present (). */
- if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
- && arg1->expr->value.function.isym
- && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
- caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
- else
- gfc_clear_attr (&caf_attr);
- if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
- && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
- tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
+ if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym
+ && e->value.function.isym->id == GFC_ISYM_CAF_GET)
+ {
+ e = e->value.function.actual->expr;
+ if (gfc_expr_attr (e).codimension)
+ {
+ /* Last partref is the coindexed coarray. As coarrays are collectively
+ (de)allocated, the allocation status must be the same as the one of
+ the local allocation. Convert to local access. */
+ for (gfc_ref *ref = e->ref; ref; ref = ref->next)
+ if (ref->type == REF_ARRAY && ref->u.ar.codimen)
+ {
+ for (int i = ref->u.ar.dimen;
+ i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
+ ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
+ break;
+ }
+ }
+ else if (!caf_this_image_ref (e->ref))
+ coindexed_caf_comp = true;
+ }
+ if (coindexed_caf_comp)
+ tmp = trans_caf_is_present (se, e);
else
{
- if (arg1->expr->rank == 0)
+ if (e->rank == 0)
{
/* Allocatable scalar. */
arg1se.want_pointer = 1;
- gfc_conv_expr (&arg1se, arg1->expr);
+ gfc_conv_expr (&arg1se, e);
tmp = arg1se.expr;
}
else
{
/* Allocatable array. */
arg1se.descriptor_only = 1;
- gfc_conv_expr_descriptor (&arg1se, arg1->expr);
+ gfc_conv_expr_descriptor (&arg1se, e);
tmp = gfc_conv_descriptor_data_get (arg1se.expr);
}
@@ -8961,7 +8951,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
gfc_se arg2se;
tree tmp2;
tree tmp;
- tree nonzero_arraylen;
+ tree nonzero_arraylen = NULL_TREE;
gfc_ss *ss;
bool scalar;
@@ -9061,14 +9051,16 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
{
tmp = gfc_conv_descriptor_rank (arg1se.expr);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- TREE_TYPE (tmp), tmp, gfc_index_one_node);
+ TREE_TYPE (tmp), tmp,
+ build_int_cst (TREE_TYPE (tmp), 1));
}
else
tmp = gfc_rank_cst[arg1->expr->rank - 1];
tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
- nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node, tmp,
- build_int_cst (TREE_TYPE (tmp), 0));
+ if (arg2->expr->rank != 0)
+ nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
/* A pointer to an array, call library function _gfor_associated. */
arg1se.want_pointer = 1;
@@ -9078,16 +9070,26 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
arg2se.want_pointer = 1;
arg2se.force_no_tmp = 1;
- gfc_conv_expr_descriptor (&arg2se, arg2->expr);
+ if (arg2->expr->rank != 0)
+ gfc_conv_expr_descriptor (&arg2se, arg2->expr);
+ else
+ {
+ gfc_conv_expr (&arg2se, arg2->expr);
+ arg2se.expr
+ = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
+ gfc_expr_attr (arg2->expr));
+ arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
+ }
gfc_add_block_to_block (&se->pre, &arg2se.pre);
gfc_add_block_to_block (&se->post, &arg2se.post);
se->expr = build_call_expr_loc (input_location,
gfor_fndecl_associated, 2,
arg1se.expr, arg2se.expr);
se->expr = convert (logical_type_node, se->expr);
- se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
- logical_type_node, se->expr,
- nonzero_arraylen);
+ if (arg2->expr->rank != 0)
+ se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ logical_type_node, se->expr,
+ nonzero_arraylen);
}
/* If target is present zero character length pointers cannot
@@ -9124,21 +9126,14 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
a = expr->value.function.actual->expr;
b = expr->value.function.actual->next->expr;
- if (UNLIMITED_POLY (a))
- {
- tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
- conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), 0));
- }
-
- if (UNLIMITED_POLY (b))
+ bool unlimited_poly_a = UNLIMITED_POLY (a);
+ bool unlimited_poly_b = UNLIMITED_POLY (b);
+ if (unlimited_poly_a)
{
- tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
- condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), 0));
+ se1.want_pointer = 1;
+ gfc_add_vptr_component (a);
}
-
- if (a->ts.type == BT_CLASS)
+ else if (a->ts.type == BT_CLASS)
{
gfc_add_vptr_component (a);
gfc_add_hash_component (a);
@@ -9147,7 +9142,12 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
a->ts.u.derived->hash_value);
- if (b->ts.type == BT_CLASS)
+ if (unlimited_poly_b)
+ {
+ se2.want_pointer = 1;
+ gfc_add_vptr_component (b);
+ }
+ else if (b->ts.type == BT_CLASS)
{
gfc_add_vptr_component (b);
gfc_add_hash_component (b);
@@ -9159,6 +9159,22 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
gfc_conv_expr (&se1, a);
gfc_conv_expr (&se2, b);
+ if (unlimited_poly_a)
+ {
+ conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ se1.expr,
+ build_int_cst (TREE_TYPE (se1.expr), 0));
+ se1.expr = gfc_vptr_hash_get (se1.expr);
+ }
+
+ if (unlimited_poly_b)
+ {
+ condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ se2.expr,
+ build_int_cst (TREE_TYPE (se2.expr), 0));
+ se2.expr = gfc_vptr_hash_get (se2.expr);
+ }
+
tmp = fold_build2_loc (input_location, EQ_EXPR,
logical_type_node, se1.expr,
fold_convert (TREE_TYPE (se1.expr), se2.expr));
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 40d2fd2..4f1b346 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -72,7 +72,8 @@ gfc_omp_is_allocatable_or_ptr (const_tree decl)
static bool
gfc_omp_is_optional_argument (const_tree decl)
{
- return (TREE_CODE (decl) == PARM_DECL
+ /* Note: VAR_DECL can occur with BIND(C) and array descriptors. */
+ return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl)
&& TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
@@ -105,8 +106,9 @@ gfc_omp_check_optional_argument (tree decl, bool for_present_check)
|| GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
+ /* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */
if (decl == NULL_TREE
- || TREE_CODE (decl) != PARM_DECL
+ || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
|| !DECL_LANG_SPECIFIC (decl)
|| !GFC_DECL_OPTIONAL_ARGUMENT (decl))
return NULL_TREE;
@@ -3803,6 +3805,8 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (clauses->order_concurrent)
{
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
+ OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
+ OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -3950,6 +3954,10 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
OMP_CLAUSE_DEVICE_ID (c) = device;
+
+ if (clauses->ancestor)
+ OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
+
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -5409,7 +5417,8 @@ gfc_trans_omp_flush (gfc_code *code)
{
tree call;
if (!code->ext.omp_clauses
- || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET)
+ || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
+ || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
{
call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
call = build_call_expr_loc (input_location, call, 0);
@@ -5887,6 +5896,10 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->collapse;
clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
= code->ext.omp_clauses->order_concurrent;
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
+ = code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_PARALLEL)
{
@@ -5941,6 +5954,10 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->collapse;
clausesa[GFC_OMP_SPLIT_DO].order_concurrent
= code->ext.omp_clauses->order_concurrent;
+ clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
+ = code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_DO].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
}
if (mask & GFC_OMP_MASK_SIMD)
{
@@ -5957,6 +5974,10 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
= code->ext.omp_clauses->order_concurrent;
+ clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
+ = code->ext.omp_clauses->order_unconstrained;
+ clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
+ = code->ext.omp_clauses->order_reproducible;
/* And this is copied to all. */
clausesa[GFC_OMP_SPLIT_SIMD].if_expr
= code->ext.omp_clauses->if_expr;
@@ -7239,3 +7260,207 @@ gfc_trans_omp_declare_simd (gfc_namespace *ns)
DECL_ATTRIBUTES (fndecl) = c;
}
}
+
+void
+gfc_trans_omp_declare_variant (gfc_namespace *ns)
+{
+ tree base_fn_decl = ns->proc_name->backend_decl;
+ gfc_namespace *search_ns = ns;
+ gfc_omp_declare_variant *next;
+
+ for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
+ search_ns; odv = next)
+ {
+ /* Look in the parent namespace if there are no more directives in the
+ current namespace. */
+ if (!odv)
+ {
+ search_ns = search_ns->parent;
+ if (search_ns)
+ next = search_ns->omp_declare_variant;
+ continue;
+ }
+
+ next = odv->next;
+
+ if (odv->error_p)
+ continue;
+
+ /* Check directive the first time it is encountered. */
+ bool error_found = true;
+
+ if (odv->checked_p)
+ error_found = false;
+ if (odv->base_proc_symtree == NULL)
+ {
+ if (!search_ns->proc_name->attr.function
+ && !search_ns->proc_name->attr.subroutine)
+ gfc_error ("The base name for 'declare variant' must be "
+ "specified at %L ", &odv->where);
+ else
+ error_found = false;
+ }
+ else
+ {
+ if (!search_ns->contained
+ && strcmp (odv->base_proc_symtree->name,
+ ns->proc_name->name))
+ gfc_error ("The base name at %L does not match the name of the "
+ "current procedure", &odv->where);
+ else if (odv->base_proc_symtree->n.sym->attr.entry)
+ gfc_error ("The base name at %L must not be an entry name",
+ &odv->where);
+ else if (odv->base_proc_symtree->n.sym->attr.generic)
+ gfc_error ("The base name at %L must not be a generic name",
+ &odv->where);
+ else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
+ gfc_error ("The base name at %L must not be a procedure pointer",
+ &odv->where);
+ else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
+ gfc_error ("The base procedure at %L must have an explicit "
+ "interface", &odv->where);
+ else
+ error_found = false;
+ }
+
+ odv->checked_p = true;
+ if (error_found)
+ {
+ odv->error_p = true;
+ continue;
+ }
+
+ /* Ignore directives that do not apply to the current procedure. */
+ if ((odv->base_proc_symtree == NULL && search_ns != ns)
+ || (odv->base_proc_symtree != NULL
+ && strcmp (odv->base_proc_symtree->name, ns->proc_name->name)))
+ continue;
+
+ tree set_selectors = NULL_TREE;
+ gfc_omp_set_selector *oss;
+
+ for (oss = odv->set_selectors; oss; oss = oss->next)
+ {
+ tree selectors = NULL_TREE;
+ gfc_omp_selector *os;
+ for (os = oss->trait_selectors; os; os = os->next)
+ {
+ tree properties = NULL_TREE;
+ gfc_omp_trait_property *otp;
+
+ for (otp = os->properties; otp; otp = otp->next)
+ {
+ switch (otp->property_kind)
+ {
+ case CTX_PROPERTY_USER:
+ case CTX_PROPERTY_EXPR:
+ {
+ gfc_se se;
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, otp->expr);
+ properties = tree_cons (NULL_TREE, se.expr,
+ properties);
+ }
+ break;
+ case CTX_PROPERTY_ID:
+ properties = tree_cons (get_identifier (otp->name),
+ NULL_TREE, properties);
+ break;
+ case CTX_PROPERTY_NAME_LIST:
+ {
+ tree prop = NULL_TREE, value = NULL_TREE;
+ if (otp->is_name)
+ prop = get_identifier (otp->name);
+ else
+ value = gfc_conv_constant_to_tree (otp->expr);
+
+ properties = tree_cons (prop, value, properties);
+ }
+ break;
+ case CTX_PROPERTY_SIMD:
+ properties = gfc_trans_omp_clauses (NULL, otp->clauses,
+ odv->where, true);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (os->score)
+ {
+ gfc_se se;
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, os->score);
+ properties = tree_cons (get_identifier (" score"),
+ se.expr, properties);
+ }
+
+ selectors = tree_cons (get_identifier (os->trait_selector_name),
+ properties, selectors);
+ }
+
+ set_selectors
+ = tree_cons (get_identifier (oss->trait_set_selector_name),
+ selectors, set_selectors);
+ }
+
+ const char *variant_proc_name = odv->variant_proc_symtree->name;
+ gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
+ if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
+ {
+ gfc_symtree *proc_st;
+ gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
+ variant_proc_sym = proc_st->n.sym;
+ }
+ if (variant_proc_sym == NULL)
+ {
+ gfc_error ("Cannot find symbol %qs", variant_proc_name);
+ continue;
+ }
+ set_selectors = omp_check_context_selector
+ (gfc_get_location (&odv->where), set_selectors);
+ if (set_selectors != error_mark_node)
+ {
+ if (!variant_proc_sym->attr.implicit_type
+ && !variant_proc_sym->attr.subroutine
+ && !variant_proc_sym->attr.function)
+ {
+ gfc_error ("variant %qs at %L is not a function or subroutine",
+ variant_proc_name, &odv->where);
+ variant_proc_sym = NULL;
+ }
+ else if (omp_get_context_selector (set_selectors, "construct",
+ "simd") == NULL_TREE)
+ {
+ char err[256];
+ if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
+ variant_proc_sym->name, 0, 1,
+ err, sizeof (err), NULL, NULL))
+ {
+ gfc_error ("variant %qs and base %qs at %L have "
+ "incompatible types: %s",
+ variant_proc_name, ns->proc_name->name,
+ &odv->where, err);
+ variant_proc_sym = NULL;
+ }
+ }
+ if (variant_proc_sym != NULL)
+ {
+ gfc_set_sym_referenced (variant_proc_sym);
+ tree construct = omp_get_context_selector (set_selectors,
+ "construct", NULL);
+ omp_mark_declare_variant (gfc_get_location (&odv->where),
+ gfc_get_symbol_decl (variant_proc_sym),
+ construct);
+ if (omp_context_selector_matches (set_selectors))
+ {
+ tree id = get_identifier ("omp declare variant base");
+ tree variant = gfc_get_symbol_decl (variant_proc_sym);
+ DECL_ATTRIBUTES (base_fn_decl)
+ = tree_cons (id, build_tree_list (variant, set_selectors),
+ DECL_ATTRIBUTES (base_fn_decl));
+ }
+ }
+ }
+ }
+}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 11df186..c66a3be 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1788,9 +1788,10 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
/* Go straight to the class data. */
if (sym2->attr.dummy && !sym2->attr.optional)
{
- class_decl = DECL_LANG_SPECIFIC (sym2->backend_decl) ?
- GFC_DECL_SAVED_DESCRIPTOR (sym2->backend_decl) :
- sym2->backend_decl;
+ class_decl = sym2->backend_decl;
+ if (DECL_LANG_SPECIFIC (class_decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (class_decl))
+ class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl);
if (POINTER_TYPE_P (TREE_TYPE (class_decl)))
class_decl = build_fold_indirect_ref_loc (input_location,
class_decl);
@@ -3669,10 +3670,7 @@ gfc_trans_select_rank_cases (gfc_code * code)
tree tmp;
tree cond;
tree low;
- tree sexpr;
tree rank;
- tree rank_minus_one;
- tree minus_one;
gfc_se se;
gfc_se cse;
stmtblock_t block;
@@ -3686,24 +3684,25 @@ gfc_trans_select_rank_cases (gfc_code * code)
gfc_conv_expr_descriptor (&se, code->expr1);
rank = gfc_conv_descriptor_rank (se.expr);
rank = gfc_evaluate_now (rank, &block);
- minus_one = build_int_cst (TREE_TYPE (rank), -1);
- tmp = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type,
- fold_convert (gfc_array_index_type, rank),
- build_int_cst (gfc_array_index_type, 1));
- rank_minus_one = gfc_evaluate_now (tmp, &block);
- tmp = gfc_conv_descriptor_ubound_get (se.expr, rank_minus_one);
- cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
- tmp, build_int_cst (TREE_TYPE (tmp), -1));
- tmp = fold_build3_loc (input_location, COND_EXPR,
- TREE_TYPE (rank), cond,
- rank, minus_one);
- cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
- rank, build_int_cst (TREE_TYPE (rank), 0));
- sexpr = fold_build3_loc (input_location, COND_EXPR,
- TREE_TYPE (rank), cond,
- rank, tmp);
- sexpr = gfc_evaluate_now (sexpr, &block);
+ symbol_attribute attr = gfc_expr_attr (code->expr1);
+ if (!attr.pointer || !attr.allocatable)
+ {
+ /* Special case for assumed-rank ('rank(*)', internally -1):
+ rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1. */
+ cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+ rank, build_int_cst (TREE_TYPE (rank), 0));
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
+ fold_convert (gfc_array_index_type, rank),
+ gfc_index_one_node);
+ tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp);
+ tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ tmp, build_int_cst (TREE_TYPE (tmp), -1));
+ cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
+ logical_type_node, cond, tmp);
+ tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank),
+ cond, rank, build_int_cst (TREE_TYPE (rank), -1));
+ rank = gfc_evaluate_now (tmp, &block);
+ }
TREE_USED (code->exit_label) = 0;
repeat:
@@ -3747,8 +3746,8 @@ repeat:
if (low != NULL_TREE)
{
cond = fold_build2_loc (input_location, EQ_EXPR,
- TREE_TYPE (sexpr), sexpr,
- fold_convert (TREE_TYPE (sexpr), low));
+ TREE_TYPE (rank), rank,
+ fold_convert (TREE_TYPE (rank), low));
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
cond, tmp,
build_empty_stmt (input_location));
diff --git a/gcc/fortran/trans-stmt.h b/gcc/fortran/trans-stmt.h
index 763f894..1a24d9b 100644
--- a/gcc/fortran/trans-stmt.h
+++ b/gcc/fortran/trans-stmt.h
@@ -71,6 +71,7 @@ tree gfc_trans_deallocate_array (tree);
/* trans-openmp.c */
tree gfc_trans_omp_directive (gfc_code *);
void gfc_trans_omp_declare_simd (gfc_namespace *);
+void gfc_trans_omp_declare_variant (gfc_namespace *);
tree gfc_trans_oacc_directive (gfc_code *);
tree gfc_trans_oacc_declare (gfc_namespace *);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 1c78a90..50fceeb 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -77,6 +77,7 @@ static GTY(()) tree gfc_desc_dim_type;
static GTY(()) tree gfc_max_array_element_size;
static GTY(()) tree gfc_array_descriptor_base[2 * (GFC_MAX_DIMENSIONS+1)];
static GTY(()) tree gfc_array_descriptor_base_caf[2 * (GFC_MAX_DIMENSIONS+1)];
+static GTY(()) tree gfc_cfi_descriptor_base[2 * (CFI_MAX_RANK + 2)];
/* Arrays for all integral and real kinds. We'll fill this in at runtime
after the target has a chance to process command-line options. */
@@ -1575,8 +1576,9 @@ gfc_get_dtype_rank_type (int rank, tree etype)
field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
GFC_DTYPE_RANK);
- CONSTRUCTOR_APPEND_ELT (v, field,
- build_int_cst (TREE_TYPE (field), rank));
+ if (rank >= 0)
+ CONSTRUCTOR_APPEND_ELT (v, field,
+ build_int_cst (TREE_TYPE (field), rank));
field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
GFC_DTYPE_TYPE);
@@ -2244,7 +2246,7 @@ gfc_nonrestricted_type (tree t)
especially for character and array types. */
tree
-gfc_sym_type (gfc_symbol * sym)
+gfc_sym_type (gfc_symbol * sym, bool is_bind_c)
{
tree type;
int byref;
@@ -2299,7 +2301,11 @@ gfc_sym_type (gfc_symbol * sym)
if (!restricted)
type = gfc_nonrestricted_type (type);
- if (sym->attr.dimension || sym->attr.codimension)
+ /* Dummy argument to a bind(C) procedure. */
+ if (is_bind_c && is_CFI_desc (sym, NULL))
+ type = gfc_get_cfi_type (sym->attr.dimension ? sym->as->rank : 0,
+ /* restricted = */ false);
+ else if (sym->attr.dimension || sym->attr.codimension)
{
if (gfc_is_nodesc_array (sym))
{
@@ -2342,7 +2348,8 @@ gfc_sym_type (gfc_symbol * sym)
{
/* We must use pointer types for potentially absent variables. The
optimizers assume a reference type argument is never NULL. */
- if (sym->attr.optional
+ if ((sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.optional)
+ || sym->attr.optional
|| (sym->ns->proc_name && sym->ns->proc_name->attr.entry_master))
type = build_pointer_type (type);
else
@@ -3131,7 +3138,7 @@ gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args,
type = build_pointer_type (type);
}
else
- type = gfc_sym_type (arg);
+ type = gfc_sym_type (arg, sym->attr.is_bind_c);
/* Parameter Passing Convention
@@ -3722,4 +3729,95 @@ gfc_get_caf_reference_type ()
return reference_type;
}
+static tree
+gfc_get_cfi_dim_type ()
+{
+ static tree CFI_dim_t = NULL;
+
+ if (CFI_dim_t)
+ return CFI_dim_t;
+
+ CFI_dim_t = make_node (RECORD_TYPE);
+ TYPE_NAME (CFI_dim_t) = get_identifier ("CFI_dim_t");
+ TYPE_NAMELESS (CFI_dim_t) = 1;
+ tree field;
+ tree *chain = NULL;
+ field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("lower_bound"),
+ gfc_array_index_type, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("extent"),
+ gfc_array_index_type, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_dim_t, get_identifier ("sm"),
+ gfc_array_index_type, &chain);
+ suppress_warning (field);
+ gfc_finish_type (CFI_dim_t);
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (CFI_dim_t)) = 1;
+ return CFI_dim_t;
+}
+
+
+/* Return the CFI type; use dimen == -1 for dim[] (only for pointers);
+ otherwise dim[dimen] is used. */
+
+tree
+gfc_get_cfi_type (int dimen, bool restricted)
+{
+ gcc_assert (dimen >= -1 && dimen <= CFI_MAX_RANK);
+
+ int idx = 2*(dimen + 1) + restricted;
+
+ if (gfc_cfi_descriptor_base[idx])
+ return gfc_cfi_descriptor_base[idx];
+
+ /* Build the type node. */
+ tree CFI_cdesc_t = make_node (RECORD_TYPE);
+ char name[GFC_MAX_SYMBOL_LEN + 1];
+ if (dimen != -1)
+ sprintf (name, "CFI_cdesc_t" GFC_RANK_PRINTF_FORMAT, dimen);
+ TYPE_NAME (CFI_cdesc_t) = get_identifier (dimen < 0 ? "CFI_cdesc_t" : name);
+ TYPE_NAMELESS (CFI_cdesc_t) = 1;
+
+ tree field;
+ tree *chain = NULL;
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("base_addr"),
+ (restricted ? prvoid_type_node
+ : ptr_type_node), &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("elem_len"),
+ size_type_node, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("version"),
+ integer_type_node, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("rank"),
+ signed_char_type_node, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("attribute"),
+ signed_char_type_node, &chain);
+ suppress_warning (field);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("type"),
+ get_typenode_from_name (INT16_TYPE),
+ &chain);
+ suppress_warning (field);
+
+ if (dimen != 0)
+ {
+ tree range = NULL_TREE;
+ if (dimen > 0)
+ range = gfc_rank_cst[dimen - 1];
+ range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
+ range);
+ tree CFI_dim_t = build_array_type (gfc_get_cfi_dim_type (), range);
+ field = gfc_add_field_to_struct_1 (CFI_cdesc_t, get_identifier ("dim"),
+ CFI_dim_t, &chain);
+ suppress_warning (field);
+ }
+
+ TYPE_TYPELESS_STORAGE (CFI_cdesc_t) = 1;
+ gfc_finish_type (CFI_cdesc_t);
+ gfc_cfi_descriptor_base[idx] = CFI_cdesc_t;
+ return CFI_cdesc_t;
+}
+
#include "gt-fortran-trans-types.h"
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 3b45ce2..15d206b 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -55,7 +55,7 @@ extern GTY(()) tree gfc_charlen_type_node;
/* The following flags give us information on the correspondence of
real (and complex) kinds with C floating-point types long double
- and __float128. */
+ and _Float128. */
extern bool gfc_real16_is_float128;
enum gfc_packed {
@@ -84,7 +84,8 @@ tree gfc_get_character_type (int, gfc_charlen *);
tree gfc_get_character_type_len (int, tree);
tree gfc_get_character_type_len_for_eltype (tree, tree);
-tree gfc_sym_type (gfc_symbol *);
+tree gfc_sym_type (gfc_symbol *, bool is_bind_c_arg = false);
+tree gfc_get_cfi_type (int dimen, bool restricted);
tree gfc_typenode_for_spec (gfc_typespec *, int c = 0);
int gfc_copy_dt_decls_ifequal (gfc_symbol *, gfc_symbol *, bool);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index eb5682a..22f2676 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -608,9 +608,9 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
if (once)
{
- tmpvar = gfc_create_var (logical_type_node, "print_warning");
+ tmpvar = gfc_create_var (boolean_type_node, "print_warning");
TREE_STATIC (tmpvar) = 1;
- DECL_INITIAL (tmpvar) = logical_true_node;
+ DECL_INITIAL (tmpvar) = boolean_true_node;
gfc_add_expr_to_block (pblock, tmpvar);
}
@@ -631,7 +631,7 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
va_end (ap);
if (once)
- gfc_add_modify (&block, tmpvar, logical_false_node);
+ gfc_add_modify (&block, tmpvar, boolean_false_node);
body = gfc_finish_block (&block);
@@ -643,9 +643,8 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
{
if (once)
cond = fold_build2_loc (gfc_get_location (where), TRUTH_AND_EXPR,
- long_integer_type_node, tmpvar, cond);
- else
- cond = fold_convert (long_integer_type_node, cond);
+ boolean_type_node, tmpvar,
+ fold_convert (boolean_type_node, cond));
tmp = fold_build3_loc (gfc_get_location (where), COND_EXPR, void_type_node,
cond, body,
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 78578cf..7ec4ca53 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -438,7 +438,7 @@ tree gfc_class_vtab_def_init_get (tree);
tree gfc_class_vtab_copy_get (tree);
tree gfc_class_vtab_final_get (tree);
/* Get an accessor to the vtab's * field, when a vptr handle is present. */
-tree gfc_vtpr_hash_get (tree);
+tree gfc_vptr_hash_get (tree);
tree gfc_vptr_size_get (tree);
tree gfc_vptr_extends_get (tree);
tree gfc_vptr_def_init_get (tree);
@@ -518,6 +518,8 @@ tree gfc_string_to_single_character (tree len, tree str, int kind);
tree gfc_get_tree_for_caf_expr (gfc_expr *);
void gfc_get_caf_token_offset (gfc_se*, tree *, tree *, tree, tree, gfc_expr *);
tree gfc_caf_get_image_index (stmtblock_t *, gfc_expr *, tree);
+void gfc_simple_for_loop (stmtblock_t *, tree, tree, tree, enum tree_code, tree,
+ tree);
/* Find the decl containing the auxiliary variables for assigned variables. */
void gfc_conv_label_variable (gfc_se * se, gfc_expr * expr);
@@ -855,8 +857,6 @@ extern GTY(()) tree gfor_fndecl_ctime;
extern GTY(()) tree gfor_fndecl_fdate;
extern GTY(()) tree gfor_fndecl_in_pack;
extern GTY(()) tree gfor_fndecl_in_unpack;
-extern GTY(()) tree gfor_fndecl_cfi_to_gfc;
-extern GTY(()) tree gfor_fndecl_gfc_to_cfi;
extern GTY(()) tree gfor_fndecl_associated;
extern GTY(()) tree gfor_fndecl_system_clock4;
extern GTY(()) tree gfor_fndecl_system_clock8;
@@ -958,8 +958,6 @@ extern GTY(()) tree gfor_fndecl_convert_char1_to_char4;
extern GTY(()) tree gfor_fndecl_convert_char4_to_char1;
/* Other misc. runtime library functions. */
-extern GTY(()) tree gfor_fndecl_size0;
-extern GTY(()) tree gfor_fndecl_size1;
extern GTY(()) tree gfor_fndecl_iargc;
extern GTY(()) tree gfor_fndecl_kill;
extern GTY(()) tree gfor_fndecl_kill_sub;
diff --git a/gcc/function.h b/gcc/function.h
index 0db5177..36003e7 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -312,7 +312,8 @@ struct GTY(()) function {
/* Range query mechanism for functions. The default is to pick up
global ranges. If a pass wants on-demand ranges OTOH, it must
- call enable/disable_ranger(). */
+ call enable/disable_ranger(). The pointer is never null. It
+ should be queried by calling get_range_query(). */
range_query * GTY ((skip)) x_range_query;
/* Last statement uid. */
@@ -719,10 +720,10 @@ extern const char *current_function_name (void);
extern void used_types_insert (tree);
/* Returns the currently active range access class. When there is no active
- range class, global ranges are used. */
+ range class, global ranges are used. Never returns null. */
-inline range_query *
-get_range_query (struct function *fun)
+ATTRIBUTE_RETURNS_NONNULL inline range_query *
+get_range_query (const struct function *fun)
{
return fun->x_range_query;
}
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 0074763..2a9e5db 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -21,14 +21,16 @@ along with GCC; see the file COPYING3. If not see
#define GCC_RICH_LOCATION_H
/* A gcc_rich_location is libcpp's rich_location with additional
- helper methods for working with gcc's types. */
+ helper methods for working with gcc's types. The class is not
+ copyable or assignable because rich_location isn't. */
+
class gcc_rich_location : public rich_location
{
public:
/* Constructors. */
/* Constructing from a location. */
- gcc_rich_location (location_t loc, const range_label *label = NULL)
+ explicit gcc_rich_location (location_t loc, const range_label *label = NULL)
: rich_location (line_table, loc, label)
{
}
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 3e98bc7..506c2ac 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -367,6 +367,7 @@ static void putenv_from_prefixes (const struct path_prefix *, const char *,
bool);
static int access_check (const char *, int);
static char *find_a_file (const struct path_prefix *, const char *, int, bool);
+static char *find_a_program (const char *);
static void add_prefix (struct path_prefix *, const char *, const char *,
int, int, int);
static void add_sysrooted_prefix (struct path_prefix *, const char *,
@@ -3052,22 +3053,7 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
{
struct file_at_path_info info;
-#ifdef DEFAULT_ASSEMBLER
- if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
- return xstrdup (DEFAULT_ASSEMBLER);
-#endif
-
-#ifdef DEFAULT_LINKER
- if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
- return xstrdup (DEFAULT_LINKER);
-#endif
-
-#ifdef DEFAULT_DSYMUTIL
- if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, mode) == 0)
- return xstrdup (DEFAULT_DSYMUTIL);
-#endif
-
- /* Determine the filename to execute (special case for absolute paths). */
+ /* Find the filename in question (special case for absolute paths). */
if (IS_ABSOLUTE_PATH (name))
{
@@ -3088,6 +3074,32 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
file_at_path, &info);
}
+/* Specialization of find_a_file for programs that also takes into account
+ configure-specified default programs. */
+
+static char*
+find_a_program (const char *name)
+{
+ /* Do not search if default matches query. */
+
+#ifdef DEFAULT_ASSEMBLER
+ if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, X_OK) == 0)
+ return xstrdup (DEFAULT_ASSEMBLER);
+#endif
+
+#ifdef DEFAULT_LINKER
+ if (! strcmp (name, "ld") && access (DEFAULT_LINKER, X_OK) == 0)
+ return xstrdup (DEFAULT_LINKER);
+#endif
+
+#ifdef DEFAULT_DSYMUTIL
+ if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, X_OK) == 0)
+ return xstrdup (DEFAULT_DSYMUTIL);
+#endif
+
+ return find_a_file (&exec_prefixes, name, X_OK, false);
+}
+
/* Ranking of prefixes in the sort list. -B prefixes are put before
all others. */
@@ -3243,8 +3255,7 @@ execute (void)
if (wrapper_string)
{
- string = find_a_file (&exec_prefixes,
- argbuf[0], X_OK, false);
+ string = find_a_program (argbuf[0]);
if (string)
argbuf[0] = string;
insert_wrapper (wrapper_string);
@@ -3269,7 +3280,7 @@ execute (void)
if (!wrapper_string)
{
- string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
+ string = find_a_program(commands[0].prog);
if (string)
commands[0].argv[0] = string;
}
@@ -3284,8 +3295,7 @@ execute (void)
commands[n_commands].prog = argbuf[i + 1];
commands[n_commands].argv
= &(argbuf.address ())[i + 1];
- string = find_a_file (&exec_prefixes, commands[n_commands].prog,
- X_OK, false);
+ string = find_a_program(commands[n_commands].prog);
if (string)
commands[n_commands].argv[0] = string;
n_commands++;
@@ -8556,8 +8566,7 @@ driver::maybe_putenv_COLLECT_LTO_WRAPPER () const
if (have_c)
lto_wrapper_file = NULL;
else
- lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
- X_OK, false);
+ lto_wrapper_file = find_a_program ("lto-wrapper");
if (lto_wrapper_file)
{
lto_wrapper_file = convert_white_space (lto_wrapper_file);
@@ -8671,7 +8680,7 @@ driver::maybe_print_and_exit () const
#endif
print_prog_name = concat (print_prog_name, use_ld, NULL);
}
- char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
+ char *newname = find_a_program (print_prog_name);
printf ("%s\n", (newname ? newname : print_prog_name));
return (0);
}
@@ -9070,7 +9079,7 @@ driver::maybe_run_linker (const char *argv0) const
/* We'll use ld if we can't find collect2. */
if (! strcmp (linker_name_spec, "collect2"))
{
- char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
+ char *s = find_a_program ("collect2");
if (s == NULL)
set_static_spec_shared (&linker_name_spec, "ld");
}
diff --git a/gcc/gcov-dump.c b/gcc/gcov-dump.c
index f1489fe..bfaf735 100644
--- a/gcc/gcov-dump.c
+++ b/gcc/gcov-dump.c
@@ -206,11 +206,12 @@ dump_gcov_file (const char *filename)
}
/* stamp */
- {
- unsigned stamp = gcov_read_unsigned ();
+ unsigned stamp = gcov_read_unsigned ();
+ printf ("%s:stamp %lu\n", filename, (unsigned long)stamp);
- printf ("%s:stamp %lu\n", filename, (unsigned long)stamp);
- }
+ /* Checksum */
+ unsigned checksum = gcov_read_unsigned ();
+ printf ("%s:checksum %lu\n", filename, (unsigned long)checksum);
if (!is_data_type)
{
diff --git a/gcc/gcov.c b/gcc/gcov.c
index cf0a49d..34f53ac 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -638,6 +638,9 @@ static int flag_preserve_paths = 0;
static int flag_counts = 0;
+/* Return code of the tool invocation. */
+static int return_code = 0;
+
/* Forward declarations. */
static int process_args (int, char **);
static void print_usage (int) ATTRIBUTE_NORETURN;
@@ -843,7 +846,6 @@ get_cycles_count (line_info &linfo)
Therefore, operating on a permuted order (i.e., non-sorted) only
has the effect of permuting the output cycles. */
- bool loop_found = false;
gcov_type count = 0;
for (vector<block_info *>::iterator it = linfo.blocks.begin ();
it != linfo.blocks.end (); it++)
@@ -851,8 +853,7 @@ get_cycles_count (line_info &linfo)
arc_vector_t path;
block_vector_t blocked;
vector<block_vector_t > block_lists;
- loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
- count);
+ circuit (*it, path, *it, blocked, block_lists, linfo, count);
}
return count;
@@ -909,7 +910,7 @@ main (int argc, char **argv)
if (!flag_use_stdout)
executed_summary (total_lines, total_executed);
- return 0;
+ return return_code;
}
/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
@@ -1469,12 +1470,18 @@ output_gcov_file (const char *file_name, source_info *src)
fnotice (stdout, "Creating '%s'\n", gcov_file_name);
output_lines (gcov_file, src);
if (ferror (gcov_file))
- fnotice (stderr, "Error writing output file '%s'\n",
- gcov_file_name);
+ {
+ fnotice (stderr, "Error writing output file '%s'\n",
+ gcov_file_name);
+ return_code = 6;
+ }
fclose (gcov_file);
}
else
- fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
+ {
+ fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
+ return_code = 6;
+ }
}
else
{
@@ -1596,6 +1603,7 @@ generate_results (const char *file_name)
{
fnotice (stderr, "Cannot open JSON output file %s\n",
gcov_intermediate_filename.c_str ());
+ return_code = 6;
return;
}
@@ -1604,6 +1612,7 @@ generate_results (const char *file_name)
{
fnotice (stderr, "Error writing JSON output file %s\n",
gcov_intermediate_filename.c_str ());
+ return_code = 6;
return;
}
}
@@ -1792,12 +1801,14 @@ read_graph_file (void)
if (!gcov_open (bbg_file_name, 1))
{
fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
+ return_code = 1;
return;
}
bbg_file_time = gcov_time ();
if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
{
fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
+ return_code = 2;
gcov_close ();
return;
}
@@ -1812,8 +1823,11 @@ read_graph_file (void)
fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
bbg_file_name, v, e);
+ return_code = 3;
}
bbg_stamp = gcov_read_unsigned ();
+ /* Read checksum. */
+ gcov_read_unsigned ();
bbg_cwd = xstrdup (gcov_read_string ());
bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
@@ -1977,6 +1991,7 @@ read_graph_file (void)
{
corrupt:;
fnotice (stderr, "%s:corrupted\n", bbg_file_name);
+ return_code = 4;
break;
}
}
@@ -2009,6 +2024,7 @@ read_count_file (void)
if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
{
fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
+ return_code = 2;
cleanup:;
gcov_close ();
return 1;
@@ -2023,14 +2039,19 @@ read_count_file (void)
fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
da_file_name, v, e);
+ return_code = 3;
}
tag = gcov_read_unsigned ();
if (tag != bbg_stamp)
{
fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
+ return_code = 5;
goto cleanup;
}
+ /* Read checksum. */
+ gcov_read_unsigned ();
+
while ((tag = gcov_read_unsigned ()))
{
unsigned length = gcov_read_unsigned ();
@@ -2085,6 +2106,7 @@ read_count_file (void)
? N_("%s:overflowed\n")
: N_("%s:corrupted\n"),
da_file_name);
+ return_code = 4;
goto cleanup;
}
}
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 31d4bf4..a77cfd9 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -3685,8 +3685,8 @@ write_types (outf_p output_header, type_p structures,
output_mangled_typename (output_header, s);
oprintf (output_header, "(X) do { \\\n");
oprintf (output_header,
- " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
- s_id_for_tag);
+ " if ((intptr_t)(X) != 0) gt_%sx_%s (X);\\\n",
+ wtd->prefix, s_id_for_tag);
oprintf (output_header, " } while (0)\n");
for (opt = s->u.s.opt; opt; opt = opt->next)
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 3f2c176..7fcfef4 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -67,6 +67,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "tree-ssa-strlen.h"
#include "varasm.h"
+#include "memmodel.h"
+#include "optabs.h"
enum strlen_range_kind {
/* Compute the exact constant string length. */
@@ -957,14 +959,17 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
= build_int_cst (build_pointer_type_for_mode (char_type_node,
ptr_mode, true), 0);
- /* If we can perform the copy efficiently with first doing all loads
- and then all stores inline it that way. Currently efficiently
- means that we can load all the memory into a single integer
- register which is what MOVE_MAX gives us. */
+ /* If we can perform the copy efficiently with first doing all loads and
+ then all stores inline it that way. Currently efficiently means that
+ we can load all the memory with a single set operation and that the
+ total size is less than MOVE_MAX * MOVE_RATIO. */
src_align = get_pointer_alignment (src);
dest_align = get_pointer_alignment (dest);
if (tree_fits_uhwi_p (len)
- && compare_tree_int (len, MOVE_MAX) <= 0
+ && (compare_tree_int
+ (len, (MOVE_MAX
+ * MOVE_RATIO (optimize_function_for_size_p (cfun))))
+ <= 0)
/* FIXME: Don't transform copies from strings with known length.
Until GCC 9 this prevented a case in gcc.dg/strlenopt-8.c
from being handled, and the case was XFAILed for that reason.
@@ -996,10 +1001,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
return false;
scalar_int_mode mode;
- tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
- if (type
- && is_a <scalar_int_mode> (TYPE_MODE (type), &mode)
+ if (int_mode_for_size (ilen * 8, 0).exists (&mode)
&& GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
+ && have_insn_for (SET, mode)
/* If the destination pointer is not aligned we must be able
to emit an unaligned store. */
&& (dest_align >= GET_MODE_ALIGNMENT (mode)
@@ -1007,6 +1011,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
|| (optab_handler (movmisalign_optab, mode)
!= CODE_FOR_nothing)))
{
+ tree type = build_nonstandard_integer_type (ilen * 8, 1);
tree srctype = type;
tree desttype = type;
if (src_align < GET_MODE_ALIGNMENT (mode))
@@ -4518,12 +4523,14 @@ clear_padding_add_padding (clear_padding_struct *buf,
}
}
-static void clear_padding_type (clear_padding_struct *, tree, HOST_WIDE_INT);
+static void clear_padding_type (clear_padding_struct *, tree,
+ HOST_WIDE_INT, bool);
/* Clear padding bits of union type TYPE. */
static void
-clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+clear_padding_union (clear_padding_struct *buf, tree type,
+ HOST_WIDE_INT sz, bool for_auto_init)
{
clear_padding_struct *union_buf;
HOST_WIDE_INT start_off = 0, next_off = 0;
@@ -4568,7 +4575,7 @@ clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
continue;
gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (TREE_TYPE (field)));
- if (!buf->clear_in_mask)
+ if (!buf->clear_in_mask && !for_auto_init)
error_at (buf->loc, "flexible array member %qD does not have "
"well defined padding bits for %qs",
field, "__builtin_clear_padding");
@@ -4579,7 +4586,7 @@ clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
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_type (union_buf, TREE_TYPE (field), fldsz, for_auto_init);
clear_padding_add_padding (union_buf, sz - fldsz);
clear_padding_flush (union_buf, true);
}
@@ -4625,7 +4632,7 @@ clear_padding_real_needs_padding_p (tree type)
/* Return true if TYPE might contain any padding bits. */
-static bool
+bool
clear_padding_type_may_have_padding_p (tree type)
{
switch (TREE_CODE (type))
@@ -4649,7 +4656,8 @@ clear_padding_type_may_have_padding_p (tree type)
__builtin_clear_padding (buf.base); */
static void
-clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
+clear_padding_emit_loop (clear_padding_struct *buf, tree type,
+ tree end, bool for_auto_init)
{
tree l1 = create_artificial_label (buf->loc);
tree l2 = create_artificial_label (buf->loc);
@@ -4660,7 +4668,7 @@ clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
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_type (buf, type, buf->sz, for_auto_init);
clear_padding_flush (buf, true);
g = gimple_build_assign (buf->base, POINTER_PLUS_EXPR, buf->base,
size_int (buf->sz));
@@ -4678,10 +4686,16 @@ clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
}
/* Clear padding bits for TYPE. Called recursively from
- gimple_fold_builtin_clear_padding. */
+ gimple_fold_builtin_clear_padding. If FOR_AUTO_INIT is true,
+ the __builtin_clear_padding is not called by the end user,
+ instead, it's inserted by the compiler to initialize the
+ paddings of automatic variable. Therefore, we should not
+ emit the error messages for flexible array members to confuse
+ the end user. */
static void
-clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+clear_padding_type (clear_padding_struct *buf, tree type,
+ HOST_WIDE_INT sz, bool for_auto_init)
{
switch (TREE_CODE (type))
{
@@ -4765,7 +4779,7 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
continue;
gcc_assert (TREE_CODE (ftype) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (ftype));
- if (!buf->clear_in_mask)
+ if (!buf->clear_in_mask && !for_auto_init)
error_at (buf->loc, "flexible array member %qD does not "
"have well defined padding bits for %qs",
field, "__builtin_clear_padding");
@@ -4781,7 +4795,8 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
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);
+ clear_padding_type (buf, TREE_TYPE (field),
+ fldsz, for_auto_init);
cur_pos += fldsz;
}
}
@@ -4821,7 +4836,7 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
buf->align = TYPE_ALIGN (elttype);
buf->off = 0;
buf->size = 0;
- clear_padding_emit_loop (buf, elttype, end);
+ clear_padding_emit_loop (buf, elttype, end, for_auto_init);
buf->base = base;
buf->sz = prev_sz;
buf->align = prev_align;
@@ -4831,10 +4846,10 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
break;
}
for (HOST_WIDE_INT i = 0; i < nelts; i++)
- clear_padding_type (buf, TREE_TYPE (type), fldsz);
+ clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
break;
case UNION_TYPE:
- clear_padding_union (buf, type, sz);
+ clear_padding_union (buf, type, sz, for_auto_init);
break;
case REAL_TYPE:
gcc_assert ((size_t) sz <= clear_padding_unit);
@@ -4858,14 +4873,14 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT 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);
+ clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
+ clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
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);
+ clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
break;
case NULLPTR_TYPE:
gcc_assert ((size_t) sz <= clear_padding_unit);
@@ -4901,7 +4916,7 @@ clear_type_padding_in_mask (tree type, unsigned char *mask)
buf.sz = int_size_in_bytes (type);
buf.size = 0;
buf.union_ptr = mask;
- clear_padding_type (&buf, type, buf.sz);
+ clear_padding_type (&buf, type, buf.sz, false);
clear_padding_flush (&buf, true);
}
@@ -4911,9 +4926,13 @@ static bool
gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
- gcc_assert (gimple_call_num_args (stmt) == 2);
+ gcc_assert (gimple_call_num_args (stmt) == 3);
tree ptr = gimple_call_arg (stmt, 0);
tree typearg = gimple_call_arg (stmt, 1);
+ /* the 3rd argument of __builtin_clear_padding is to distinguish whether
+ this call is made by the user or by the compiler for automatic variable
+ initialization. */
+ bool for_auto_init = (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 2));
tree type = TREE_TYPE (TREE_TYPE (typearg));
location_t loc = gimple_location (stmt);
clear_padding_struct buf;
@@ -4970,7 +4989,7 @@ gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
buf.sz = eltsz;
buf.align = TYPE_ALIGN (elttype);
buf.alias_type = build_pointer_type (elttype);
- clear_padding_emit_loop (&buf, elttype, end);
+ clear_padding_emit_loop (&buf, elttype, end, for_auto_init);
}
}
else
@@ -4983,7 +5002,7 @@ gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
gsi_insert_before (gsi, g, GSI_SAME_STMT);
}
buf.alias_type = build_pointer_type (type);
- clear_padding_type (&buf, type, buf.sz);
+ clear_padding_type (&buf, type, buf.sz, for_auto_init);
clear_padding_flush (&buf, true);
}
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 2401646..397f4ae 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -36,6 +36,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 bool clear_padding_type_may_have_padding_p (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 *);
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index 2c78a08..38e9093 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -260,10 +260,7 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
op2, tcode_tree);
}
- }
- if (icode == CODE_FOR_nothing)
- {
gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0))
&& can_compute_op0
&& (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index da8c212..ee4e63a 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -162,6 +162,9 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
case GSI_CONTINUE_LINKING:
i->ptr = first;
break;
+ case GSI_LAST_NEW_STMT:
+ i->ptr = last;
+ break;
case GSI_SAME_STMT:
break;
default:
@@ -271,6 +274,7 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
case GSI_NEW_STMT:
i->ptr = first;
break;
+ case GSI_LAST_NEW_STMT:
case GSI_CONTINUE_LINKING:
i->ptr = last;
break;
diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
index 6047a73..0e384f7 100644
--- a/gcc/gimple-iterator.h
+++ b/gcc/gimple-iterator.h
@@ -46,8 +46,8 @@ struct gphi_iterator : public gimple_stmt_iterator
enum gsi_iterator_update
{
- GSI_NEW_STMT, /* Only valid when single statement is added, move
- iterator to it. */
+ GSI_NEW_STMT = 2, /* Move the iterator to the first statement added. */
+ GSI_LAST_NEW_STMT, /* Move the iterator to the last statement added. */
GSI_SAME_STMT, /* Leave the iterator at the same statement. */
GSI_CONTINUE_LINKING /* Move iterator to whatever position is suitable
for linking other statements in the same
diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c
index d212e39..611d380 100644
--- a/gcc/gimple-loop-jam.c
+++ b/gcc/gimple-loop-jam.c
@@ -587,8 +587,7 @@ tree_loop_unroll_and_jam (void)
"applying unroll and jam with factor %d\n",
unroll_factor);
initialize_original_copy_tables ();
- tree_unroll_loop (outer, unroll_factor, single_dom_exit (outer),
- &desc);
+ tree_unroll_loop (outer, unroll_factor, &desc);
free_original_copy_tables ();
fuse_loops (outer->inner);
todo |= TODO_cleanup_cfg;
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index 7112c116..9d88b2f 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -870,6 +870,10 @@ try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
switch (num_ops - 2)
{
+ case 1:
+ if (!gimple_resimplify1 (seq, &cond_op, valueize))
+ return false;
+ break;
case 2:
if (!gimple_resimplify2 (seq, &cond_op, valueize))
return false;
diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
new file mode 100644
index 0000000..f0c8444
--- /dev/null
+++ b/gcc/gimple-predicate-analysis.cc
@@ -0,0 +1,2404 @@
+/* Support for simple predicate analysis.
+
+ Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ Contributed by Xinliang David Li <davidxl@google.com>
+ Generalized by Martin Sebor <msebor@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/>. */
+
+#define INCLUDE_STRING
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
+#include "fold-const.h"
+#include "gimple-iterator.h"
+#include "tree-ssa.h"
+#include "tree-cfg.h"
+#include "cfghooks.h"
+#include "attribs.h"
+#include "builtins.h"
+#include "calls.h"
+#include "value-query.h"
+
+#include "gimple-predicate-analysis.h"
+
+#define DEBUG_PREDICATE_ANALYZER 1
+
+/* Find the immediate postdominator of the specified basic block BB. */
+
+static inline basic_block
+find_pdom (basic_block bb)
+{
+ basic_block exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
+ if (bb == exit_bb)
+ return exit_bb;
+
+ if (basic_block pdom = get_immediate_dominator (CDI_POST_DOMINATORS, bb))
+ return pdom;
+
+ return exit_bb;
+}
+
+/* Find the immediate dominator of the specified basic block BB. */
+
+static inline basic_block
+find_dom (basic_block bb)
+{
+ basic_block entry_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+ if (bb == entry_bb)
+ return entry_bb;
+
+ if (basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb))
+ return dom;
+
+ return entry_bb;
+}
+
+/* Return true if BB1 is postdominating BB2 and BB1 is not a loop exit
+ bb. The loop exit bb check is simple and does not cover all cases. */
+
+static bool
+is_non_loop_exit_postdominating (basic_block bb1, basic_block bb2)
+{
+ if (!dominated_by_p (CDI_POST_DOMINATORS, bb2, bb1))
+ return false;
+
+ if (single_pred_p (bb1) && !single_succ_p (bb2))
+ return false;
+
+ return true;
+}
+
+/* Find BB's closest postdominator that is its control equivalent (i.e.,
+ that's controlled by the same predicate). */
+
+static inline basic_block
+find_control_equiv_block (basic_block bb)
+{
+ basic_block pdom = find_pdom (bb);
+
+ /* Skip the postdominating bb that is also a loop exit. */
+ if (!is_non_loop_exit_postdominating (pdom, bb))
+ return NULL;
+
+ /* If the postdominator is dominated by BB, return it. */
+ if (dominated_by_p (CDI_DOMINATORS, pdom, bb))
+ return pdom;
+
+ return NULL;
+}
+
+/* Return true if X1 is the negation of X2. */
+
+static inline bool
+pred_neg_p (const pred_info &x1, const pred_info &x2)
+{
+ if (!operand_equal_p (x1.pred_lhs, x2.pred_lhs, 0)
+ || !operand_equal_p (x1.pred_rhs, x2.pred_rhs, 0))
+ return false;
+
+ tree_code c1 = x1.cond_code, c2;
+ if (x1.invert == x2.invert)
+ c2 = invert_tree_comparison (x2.cond_code, false);
+ else
+ c2 = x2.cond_code;
+
+ return c1 == c2;
+}
+
+/* Return whether the condition (VAL CMPC BOUNDARY) is true. */
+
+static bool
+is_value_included_in (tree val, tree boundary, tree_code cmpc)
+{
+ /* Only handle integer constant here. */
+ if (TREE_CODE (val) != INTEGER_CST || TREE_CODE (boundary) != INTEGER_CST)
+ return true;
+
+ bool inverted = false;
+ if (cmpc == GE_EXPR || cmpc == GT_EXPR || cmpc == NE_EXPR)
+ {
+ cmpc = invert_tree_comparison (cmpc, false);
+ inverted = true;
+ }
+
+ bool result;
+ if (cmpc == EQ_EXPR)
+ result = tree_int_cst_equal (val, boundary);
+ else if (cmpc == LT_EXPR)
+ result = tree_int_cst_lt (val, boundary);
+ else
+ {
+ gcc_assert (cmpc == LE_EXPR);
+ result = tree_int_cst_le (val, boundary);
+ }
+
+ if (inverted)
+ result ^= 1;
+
+ return result;
+}
+
+/* Format the vector of edges EV as a string. */
+
+static std::string
+format_edge_vec (const vec<edge> &ev)
+{
+ std::string str;
+
+ unsigned n = ev.length ();
+ for (unsigned i = 0; i < n; ++i)
+ {
+ char es[32];
+ const_edge e = ev[i];
+ sprintf (es, "%u", e->src->index);
+ str += es;
+ if (i + 1 < n)
+ str += " -> ";
+ }
+ return str;
+}
+
+/* Format the first N elements of the array of vector of edges EVA as
+ a string. */
+
+static std::string
+format_edge_vecs (const vec<edge> eva[], unsigned n)
+{
+ std::string str;
+
+ for (unsigned i = 0; i != n; ++i)
+ {
+ str += '{';
+ str += format_edge_vec (eva[i]);
+ str += '}';
+ if (i + 1 < n)
+ str += ", ";
+ }
+ return str;
+}
+
+/* Dump a single pred_info to DUMP_FILE. */
+
+static void
+dump_pred_info (const pred_info &pred)
+{
+ if (pred.invert)
+ fprintf (dump_file, "NOT (");
+ print_generic_expr (dump_file, pred.pred_lhs);
+ fprintf (dump_file, " %s ", op_symbol_code (pred.cond_code));
+ print_generic_expr (dump_file, pred.pred_rhs);
+ if (pred.invert)
+ fputc (')', dump_file);
+}
+
+/* Dump a pred_chain to DUMP_FILE. */
+
+static void
+dump_pred_chain (const pred_chain &chain)
+{
+ unsigned np = chain.length ();
+ if (np > 1)
+ fprintf (dump_file, "AND (");
+
+ for (unsigned j = 0; j < np; j++)
+ {
+ dump_pred_info (chain[j]);
+ if (j < np - 1)
+ fprintf (dump_file, ", ");
+ else if (j > 0)
+ fputc (')', dump_file);
+ }
+}
+
+/* Dump the predicate chain PREDS for STMT, prefixed by MSG. */
+
+static void
+dump_predicates (gimple *stmt, const pred_chain_union &preds, const char *msg)
+{
+ fprintf (dump_file, "%s", msg);
+ if (stmt)
+ {
+ print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, "is guarded by:\n");
+ }
+
+ unsigned np = preds.length ();
+ if (np > 1)
+ fprintf (dump_file, "OR (");
+ for (unsigned i = 0; i < np; i++)
+ {
+ dump_pred_chain (preds[i]);
+ if (i < np - 1)
+ fprintf (dump_file, ", ");
+ else if (i > 0)
+ fputc (')', dump_file);
+ }
+ fputc ('\n', dump_file);
+}
+
+/* Dump the first NCHAINS elements of the DEP_CHAINS array into DUMP_FILE. */
+
+static void
+dump_dep_chains (const auto_vec<edge> dep_chains[], unsigned nchains)
+{
+ if (!dump_file)
+ return;
+
+ for (unsigned i = 0; i != nchains; ++i)
+ {
+ const auto_vec<edge> &v = dep_chains[i];
+ unsigned n = v.length ();
+ for (unsigned j = 0; j != n; ++j)
+ {
+ fprintf (dump_file, "%u", v[j]->src->index);
+ if (j + 1 < n)
+ fprintf (dump_file, " -> ");
+ }
+ fputc ('\n', dump_file);
+ }
+}
+
+/* Return the 'normalized' conditional code with operand swapping
+ and condition inversion controlled by SWAP_COND and INVERT. */
+
+static tree_code
+get_cmp_code (tree_code orig_cmp_code, bool swap_cond, bool invert)
+{
+ tree_code tc = orig_cmp_code;
+
+ if (swap_cond)
+ tc = swap_tree_comparison (orig_cmp_code);
+ if (invert)
+ tc = invert_tree_comparison (tc, false);
+
+ switch (tc)
+ {
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ break;
+ default:
+ return ERROR_MARK;
+ }
+ return tc;
+}
+
+/* Return true if PRED is common among all predicate chains in PREDS
+ (and therefore can be factored out). */
+
+static bool
+find_matching_predicate_in_rest_chains (const pred_info &pred,
+ const pred_chain_union &preds)
+{
+ /* Trival case. */
+ if (preds.length () == 1)
+ return true;
+
+ for (unsigned i = 1; i < preds.length (); i++)
+ {
+ bool found = false;
+ const pred_chain &chain = preds[i];
+ unsigned n = chain.length ();
+ for (unsigned j = 0; j < n; j++)
+ {
+ const pred_info &pred2 = chain[j];
+ /* Can relax the condition comparison to not use address
+ comparison. However, the most common case is that
+ multiple control dependent paths share a common path
+ prefix, so address comparison should be ok. */
+ if (operand_equal_p (pred2.pred_lhs, pred.pred_lhs, 0)
+ && operand_equal_p (pred2.pred_rhs, pred.pred_rhs, 0)
+ && pred2.invert == pred.invert)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ }
+ return true;
+}
+
+/* Find a predicate to examine against paths of interest. If there
+ is no predicate of the "FLAG_VAR CMP CONST" form, try to find one
+ of that's the form "FLAG_VAR CMP FLAG_VAR" with value range info.
+ PHI is the phi node whose incoming (interesting) paths need to be
+ examined. On success, return the comparison code, set defintion
+ gimple of FLAG_DEF and BOUNDARY_CST. Otherwise return ERROR_MARK. */
+
+static tree_code
+find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
+ tree *boundary_cst)
+{
+ tree_code vrinfo_code = ERROR_MARK;
+ gimple *vrinfo_def = NULL;
+ tree vrinfo_cst = NULL;
+
+ gcc_assert (preds.length () > 0);
+ pred_chain chain = preds[0];
+ for (unsigned i = 0; i < chain.length (); i++)
+ {
+ bool use_vrinfo_p = false;
+ const pred_info &pred = chain[i];
+ tree cond_lhs = pred.pred_lhs;
+ tree cond_rhs = pred.pred_rhs;
+ if (cond_lhs == NULL_TREE || cond_rhs == NULL_TREE)
+ continue;
+
+ tree_code code = get_cmp_code (pred.cond_code, false, pred.invert);
+ if (code == ERROR_MARK)
+ continue;
+
+ /* Convert to the canonical form SSA_NAME CMP CONSTANT. */
+ 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. */
+ tree type = TREE_TYPE (cond_lhs);
+ value_range r;
+ if (!INTEGRAL_TYPE_P (type)
+ || !get_range_query (cfun)->range_of_expr (r, cond_rhs)
+ || r.kind () != VR_RANGE)
+ continue;
+
+ wide_int min = r.lower_bound ();
+ wide_int max = r.upper_bound ();
+ 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 (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;
+}
+
+/* Return true if all interesting opnds are pruned, false otherwise.
+ PHI is the phi node with interesting operands, OPNDS is the bitmap
+ of the interesting operand positions, FLAG_DEF is the statement
+ defining the flag guarding the use of the PHI output, BOUNDARY_CST
+ is the const value used in the predicate associated with the flag,
+ CMP_CODE is the comparison code used in the predicate, VISITED_PHIS
+ is the pointer set of phis visited, and VISITED_FLAG_PHIS is
+ the pointer to the pointer set of flag definitions that are also
+ phis.
+
+ Example scenario:
+
+ BB1:
+ flag_1 = phi <0, 1> // (1)
+ var_1 = phi <undef, some_val>
+
+
+ BB2:
+ flag_2 = phi <0, flag_1, flag_1> // (2)
+ var_2 = phi <undef, var_1, var_1>
+ if (flag_2 == 1)
+ goto BB3;
+
+ BB3:
+ use of var_2 // (3)
+
+ Because some flag arg in (1) is not constant, if we do not look into
+ the flag phis recursively, it is conservatively treated as unknown and
+ var_1 is thought to flow into use at (3). Since var_1 is potentially
+ uninitialized a false warning will be emitted.
+ Checking recursively into (1), the compiler can find out that only
+ some_val (which is defined) can flow into (3) which is OK. */
+
+static bool
+prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def,
+ tree boundary_cst, tree_code cmp_code,
+ predicate::func_t &eval,
+ hash_set<gphi *> *visited_phis,
+ bitmap *visited_flag_phis)
+{
+ /* The Boolean predicate guarding the PHI definition. Initialized
+ lazily from PHI in the first call to is_use_guarded() and cached
+ for subsequent iterations. */
+ predicate def_preds (eval);
+
+ unsigned n = MIN (eval.max_phi_args, gimple_phi_num_args (flag_def));
+ for (unsigned i = 0; i < n; i++)
+ {
+ if (!MASK_TEST_BIT (opnds, i))
+ continue;
+
+ tree flag_arg = gimple_phi_arg_def (flag_def, i);
+ if (!is_gimple_constant (flag_arg))
+ {
+ if (TREE_CODE (flag_arg) != SSA_NAME)
+ return false;
+
+ gphi *flag_arg_def = dyn_cast<gphi *> (SSA_NAME_DEF_STMT (flag_arg));
+ if (!flag_arg_def)
+ return false;
+
+ tree phi_arg = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (phi_arg) != SSA_NAME)
+ return false;
+
+ gphi *phi_arg_def = dyn_cast<gphi *> (SSA_NAME_DEF_STMT (phi_arg));
+ if (!phi_arg_def)
+ return false;
+
+ if (gimple_bb (phi_arg_def) != gimple_bb (flag_arg_def))
+ return false;
+
+ if (!*visited_flag_phis)
+ *visited_flag_phis = BITMAP_ALLOC (NULL);
+
+ tree phi_result = gimple_phi_result (flag_arg_def);
+ if (bitmap_bit_p (*visited_flag_phis, SSA_NAME_VERSION (phi_result)))
+ return false;
+
+ bitmap_set_bit (*visited_flag_phis, SSA_NAME_VERSION (phi_result));
+
+ /* Now recursively try to prune the interesting phi args. */
+ unsigned opnds_arg_phi = eval.phi_arg_set (phi_arg_def);
+ if (!prune_phi_opnds (phi_arg_def, opnds_arg_phi, flag_arg_def,
+ boundary_cst, cmp_code, eval, visited_phis,
+ visited_flag_phis))
+ return false;
+
+ bitmap_clear_bit (*visited_flag_phis, SSA_NAME_VERSION (phi_result));
+ continue;
+ }
+
+ /* Now check if the constant is in the guarded range. */
+ if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
+ {
+ /* Now that we know that this undefined edge is not pruned.
+ If the operand is defined by another phi, we can further
+ prune the incoming edges of that phi by checking
+ the predicates of this operands. */
+
+ tree opnd = gimple_phi_arg_def (phi, i);
+ gimple *opnd_def = SSA_NAME_DEF_STMT (opnd);
+ if (gphi *opnd_def_phi = dyn_cast <gphi *> (opnd_def))
+ {
+ unsigned opnds2 = eval.phi_arg_set (opnd_def_phi);
+ if (!MASK_EMPTY (opnds2))
+ {
+ edge opnd_edge = gimple_phi_arg_edge (phi, i);
+ if (def_preds.is_use_guarded (phi, opnd_edge->src,
+ opnd_def_phi, opnds2,
+ visited_phis))
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Recursively compute the set PHI's incoming edges with "uninteresting"
+ operands of a phi chain, i.e., those for which EVAL returns false.
+ CD_ROOT is the control dependence root from which edges are collected
+ up the CFG nodes that it's dominated by. *EDGES holds the result, and
+ VISITED is used for detecting cycles. */
+
+static void
+collect_phi_def_edges (gphi *phi, basic_block cd_root, auto_vec<edge> *edges,
+ predicate::func_t &eval, hash_set<gimple *> *visited)
+{
+ if (visited->elements () == 0
+ && DEBUG_PREDICATE_ANALYZER
+ && dump_file)
+ {
+ fprintf (dump_file, "%s for cd_root %u and ",
+ __func__, cd_root->index);
+ print_gimple_stmt (dump_file, phi, 0);
+
+ }
+
+ if (visited->add (phi))
+ return;
+
+ unsigned n = gimple_phi_num_args (phi);
+ for (unsigned i = 0; i < n; i++)
+ {
+ edge opnd_edge = gimple_phi_arg_edge (phi, i);
+ tree opnd = gimple_phi_arg_def (phi, i);
+
+ if (TREE_CODE (opnd) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (opnd);
+
+ if (gimple_code (def) == GIMPLE_PHI
+ && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root))
+ collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges, eval,
+ visited);
+ else if (!eval (opnd))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "\tFound def edge %i -> %i for cd_root %i "
+ "and operand %u of: ",
+ opnd_edge->src->index, opnd_edge->dest->index,
+ cd_root->index, i);
+ print_gimple_stmt (dump_file, phi, 0);
+ }
+ edges->safe_push (opnd_edge);
+ }
+ }
+ else
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "\tFound def edge %i -> %i for cd_root %i "
+ "and operand %u of: ",
+ opnd_edge->src->index, opnd_edge->dest->index,
+ cd_root->index, i);
+ print_gimple_stmt (dump_file, phi, 0);
+ }
+
+ if (!eval (opnd))
+ edges->safe_push (opnd_edge);
+ }
+ }
+}
+
+/* Return an expression corresponding to the predicate PRED. */
+
+static tree
+build_pred_expr (const pred_info &pred)
+{
+ tree_code cond_code = pred.cond_code;
+ tree lhs = pred.pred_lhs;
+ tree rhs = pred.pred_rhs;
+
+ if (pred.invert)
+ cond_code = invert_tree_comparison (cond_code, false);
+
+ return build2 (cond_code, TREE_TYPE (lhs), lhs, rhs);
+}
+
+/* Return an expression corresponding to PREDS. */
+
+static tree
+build_pred_expr (const pred_chain_union &preds, bool invert = false)
+{
+ tree_code code = invert ? TRUTH_AND_EXPR : TRUTH_OR_EXPR;
+ tree_code subcode = invert ? TRUTH_OR_EXPR : TRUTH_AND_EXPR;
+
+ tree expr = NULL_TREE;
+ for (unsigned i = 0; i != preds.length (); ++i)
+ {
+ tree subexpr = NULL_TREE;
+ for (unsigned j = 0; j != preds[i].length (); ++j)
+ {
+ const pred_info &pi = preds[i][j];
+ tree cond = build_pred_expr (pi);
+ if (invert)
+ cond = invert_truthvalue (cond);
+ subexpr = subexpr ? build2 (subcode, boolean_type_node,
+ subexpr, cond) : cond;
+ }
+ if (expr)
+ expr = build2 (code, boolean_type_node, expr, subexpr);
+ else
+ expr = subexpr;
+ }
+
+ return expr;
+}
+
+/* Return a bitset of all PHI arguments or zero if there are too many. */
+
+unsigned
+predicate::func_t::phi_arg_set (gphi *phi)
+{
+ unsigned n = gimple_phi_num_args (phi);
+
+ if (max_phi_args < n)
+ return 0;
+
+ /* Set the least significant N bits. */
+ return (1U << n) - 1;
+}
+
+/* Determine if the predicate set of the use does not overlap with that
+ of the interesting paths. The most common senario of guarded use is
+ in Example 1:
+ Example 1:
+ if (some_cond)
+ {
+ x = ...; // set x to valid
+ flag = true;
+ }
+
+ ... some code ...
+
+ if (flag)
+ use (x); // use when x is valid
+
+ The real world examples are usually more complicated, but similar
+ and usually result from inlining:
+
+ bool init_func (int * x)
+ {
+ if (some_cond)
+ return false;
+ *x = ...; // set *x to valid
+ return true;
+ }
+
+ void foo (..)
+ {
+ int x;
+
+ if (!init_func (&x))
+ return;
+
+ .. some_code ...
+ use (x); // use when x is valid
+ }
+
+ Another possible use scenario is in the following trivial example:
+
+ Example 2:
+ if (n > 0)
+ x = 1;
+ ...
+ if (n > 0)
+ {
+ if (m < 2)
+ ... = x;
+ }
+
+ Predicate analysis needs to compute the composite predicate:
+
+ 1) 'x' use predicate: (n > 0) .AND. (m < 2)
+ 2) 'x' default value (non-def) predicate: .NOT. (n > 0)
+ (the predicate chain for phi operand defs can be computed
+ starting from a bb that is control equivalent to the phi's
+ bb and is dominating the operand def.)
+
+ and check overlapping:
+ (n > 0) .AND. (m < 2) .AND. (.NOT. (n > 0))
+ <==> false
+
+ This implementation provides a framework that can handle different
+ scenarios. (Note that many simple cases are handled properly without
+ the predicate analysis if jump threading eliminates the merge point
+ thus makes path-sensitive analysis unnecessary.)
+
+ PHI is the phi node whose incoming (undefined) paths need to be
+ pruned, and OPNDS is the bitmap holding interesting operand
+ positions. VISITED is the pointer set of phi stmts being
+ checked. */
+
+bool
+predicate::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited)
+{
+ gimple *flag_def = NULL;
+ tree boundary_cst = NULL_TREE;
+ bitmap visited_flag_phis = NULL;
+
+ /* Find within the common prefix of multiple predicate chains
+ a predicate that is a comparison of a flag variable against
+ a constant. */
+ tree_code cmp_code = find_var_cmp_const (m_preds, phi, &flag_def,
+ &boundary_cst);
+ if (cmp_code == ERROR_MARK)
+ return true;
+
+ /* Now check all the uninit incoming edges have a constant flag
+ value that is in conflict with the use guard/predicate. */
+ gphi *phi_def = as_a<gphi *> (flag_def);
+ bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst,
+ cmp_code, m_eval, visited,
+ &visited_flag_phis);
+
+ if (visited_flag_phis)
+ BITMAP_FREE (visited_flag_phis);
+
+ return !all_pruned;
+}
+
+/* Return true if two predicates PRED1 and X2 are equivalent. Assume
+ the expressions have already properly re-associated. */
+
+static inline bool
+pred_equal_p (const pred_info &pred1, const pred_info &pred2)
+{
+ if (!operand_equal_p (pred1.pred_lhs, pred2.pred_lhs, 0)
+ || !operand_equal_p (pred1.pred_rhs, pred2.pred_rhs, 0))
+ return false;
+
+ tree_code c1 = pred1.cond_code, c2;
+ if (pred1.invert != pred2.invert
+ && TREE_CODE_CLASS (pred2.cond_code) == tcc_comparison)
+ c2 = invert_tree_comparison (pred2.cond_code, false);
+ else
+ c2 = pred2.cond_code;
+
+ return c1 == c2;
+}
+
+/* Return true if PRED tests inequality (i.e., X != Y). */
+
+static inline bool
+is_neq_relop_p (const pred_info &pred)
+{
+
+ return ((pred.cond_code == NE_EXPR && !pred.invert)
+ || (pred.cond_code == EQ_EXPR && pred.invert));
+}
+
+/* Returns true if PRED is of the form X != 0. */
+
+static inline bool
+is_neq_zero_form_p (const pred_info &pred)
+{
+ if (!is_neq_relop_p (pred) || !integer_zerop (pred.pred_rhs)
+ || TREE_CODE (pred.pred_lhs) != SSA_NAME)
+ return false;
+ return true;
+}
+
+/* Return true if PRED is equivalent to X != 0. */
+
+static inline bool
+pred_expr_equal_p (const pred_info &pred, tree expr)
+{
+ if (!is_neq_zero_form_p (pred))
+ return false;
+
+ return operand_equal_p (pred.pred_lhs, expr, 0);
+}
+
+/* Return true if VAL satisfies (x CMPC BOUNDARY) predicate. CMPC can
+ be either one of the range comparison codes ({GE,LT,EQ,NE}_EXPR and
+ the like), or BIT_AND_EXPR. EXACT_P is only meaningful for the latter.
+ Modify the question from VAL & BOUNDARY != 0 to VAL & BOUNDARY == VAL.
+ For other values of CMPC, EXACT_P is ignored. */
+
+static bool
+value_sat_pred_p (tree val, tree boundary, tree_code cmpc,
+ bool exact_p = false)
+{
+ if (cmpc != BIT_AND_EXPR)
+ return is_value_included_in (val, boundary, cmpc);
+
+ wide_int andw = wi::to_wide (val) & wi::to_wide (boundary);
+ if (exact_p)
+ return andw == wi::to_wide (val);
+
+ return andw.to_uhwi ();
+}
+
+/* Return true if the domain of single predicate expression PRED1
+ is a subset of that of PRED2, and false if it cannot be proved. */
+
+static bool
+subset_of (const pred_info &pred1, const pred_info &pred2)
+{
+ if (pred_equal_p (pred1, pred2))
+ return true;
+
+ if ((TREE_CODE (pred1.pred_rhs) != INTEGER_CST)
+ || (TREE_CODE (pred2.pred_rhs) != INTEGER_CST))
+ return false;
+
+ if (!operand_equal_p (pred1.pred_lhs, pred2.pred_lhs, 0))
+ return false;
+
+ tree_code code1 = pred1.cond_code;
+ if (pred1.invert)
+ code1 = invert_tree_comparison (code1, false);
+ tree_code code2 = pred2.cond_code;
+ if (pred2.invert)
+ code2 = invert_tree_comparison (code2, false);
+
+ if (code2 == NE_EXPR && code1 == NE_EXPR)
+ return false;
+
+ if (code2 == NE_EXPR)
+ return !value_sat_pred_p (pred2.pred_rhs, pred1.pred_rhs, code1);
+
+ if (code1 == EQ_EXPR)
+ return value_sat_pred_p (pred1.pred_rhs, pred2.pred_rhs, code2);
+
+ if (code1 == code2)
+ return value_sat_pred_p (pred1.pred_rhs, pred2.pred_rhs, code2,
+ code1 == BIT_AND_EXPR);
+
+ return false;
+}
+
+/* Return true if the domain of CHAIN1 is a subset of that of CHAIN2.
+ Return false if it cannot be proven so. */
+
+static bool
+subset_of (const pred_chain &chain1, const pred_chain &chain2)
+{
+ unsigned np1 = chain1.length ();
+ unsigned np2 = chain2.length ();
+ for (unsigned i2 = 0; i2 < np2; i2++)
+ {
+ bool found = false;
+ const pred_info &info2 = chain2[i2];
+ for (unsigned i1 = 0; i1 < np1; i1++)
+ {
+ const pred_info &info1 = chain1[i1];
+ if (subset_of (info1, info2))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ }
+ return true;
+}
+
+/* Return true if the domain defined by the predicate chain PREDS is
+ a subset of the domain of *THIS. Return false if PREDS's domain
+ is not a subset of any of the sub-domains of *THIS (corresponding
+ to each individual chains in it), even though it may be still be
+ a subset of whole domain of *THIS which is the union (ORed) of all
+ its subdomains. In other words, the result is conservative. */
+
+bool
+predicate::includes (const pred_chain &chain) const
+{
+ for (unsigned i = 0; i < m_preds.length (); i++)
+ if (subset_of (chain, m_preds[i]))
+ return true;
+
+ return false;
+}
+
+/* Return true if the domain defined by *THIS is a superset of PREDS's
+ domain.
+ Avoid building generic trees (and rely on the folding capability
+ of the compiler), and instead perform brute force comparison of
+ individual predicate chains (this won't be a computationally costly
+ since the chains are pretty short). Returning false does not
+ necessarily mean *THIS is not a superset of *PREDS, only that
+ it need not be since the analysis cannot prove it. */
+
+bool
+predicate::superset_of (const predicate &preds) const
+{
+ for (unsigned i = 0; i < preds.m_preds.length (); i++)
+ if (!includes (preds.m_preds[i]))
+ return false;
+
+ return true;
+}
+
+/* Create a predicate of the form OP != 0 and push it the work list CHAIN. */
+
+static void
+push_to_worklist (tree op, pred_chain *chain, hash_set<tree> *mark_set)
+{
+ if (mark_set->contains (op))
+ return;
+ mark_set->add (op);
+
+ pred_info arg_pred;
+ arg_pred.pred_lhs = op;
+ arg_pred.pred_rhs = integer_zero_node;
+ arg_pred.cond_code = NE_EXPR;
+ arg_pred.invert = false;
+ chain->safe_push (arg_pred);
+}
+
+/* Return a pred_info for a gimple assignment CMP_ASSIGN with comparison
+ rhs. */
+
+static pred_info
+get_pred_info_from_cmp (const gimple *cmp_assign)
+{
+ pred_info pred;
+ pred.pred_lhs = gimple_assign_rhs1 (cmp_assign);
+ pred.pred_rhs = gimple_assign_rhs2 (cmp_assign);
+ pred.cond_code = gimple_assign_rhs_code (cmp_assign);
+ pred.invert = false;
+ return pred;
+}
+
+/* If PHI is a degenerate phi with all operands having the same value (relop)
+ update *PRED to that value and return true. Otherwise return false. */
+
+static bool
+is_degenerate_phi (gimple *phi, pred_info *pred)
+{
+ tree op0 = gimple_phi_arg_def (phi, 0);
+
+ if (TREE_CODE (op0) != SSA_NAME)
+ return false;
+
+ gimple *def0 = SSA_NAME_DEF_STMT (op0);
+ if (gimple_code (def0) != GIMPLE_ASSIGN)
+ return false;
+
+ if (TREE_CODE_CLASS (gimple_assign_rhs_code (def0)) != tcc_comparison)
+ return false;
+
+ pred_info pred0 = get_pred_info_from_cmp (def0);
+
+ unsigned n = gimple_phi_num_args (phi);
+ for (unsigned i = 1; i < n; ++i)
+ {
+ tree op = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (op) != SSA_NAME)
+ return false;
+
+ gimple *def = SSA_NAME_DEF_STMT (op);
+ if (gimple_code (def) != GIMPLE_ASSIGN)
+ return false;
+
+ if (TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison)
+ return false;
+
+ pred_info pred = get_pred_info_from_cmp (def);
+ if (!pred_equal_p (pred, pred0))
+ return false;
+ }
+
+ *pred = pred0;
+ return true;
+}
+
+/* Recursively compute the control dependence chains (paths of edges)
+ from the dependent basic block, DEP_BB, up to the dominating basic
+ block, DOM_BB (the head node of a chain should be dominated by it),
+ storing them in the CD_CHAINS array.
+ CUR_CD_CHAIN is the current chain being computed.
+ *NUM_CHAINS is total number of chains in the CD_CHAINS array.
+ *NUM_CALLS is the number of recursive calls to control unbounded
+ recursion.
+ Return true if the information is successfully computed, false if
+ there is no control dependence or not computed. */
+
+static bool
+compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb,
+ vec<edge> cd_chains[], unsigned *num_chains,
+ vec<edge> &cur_cd_chain, unsigned *num_calls,
+ unsigned depth = 0)
+{
+ if (*num_calls > (unsigned)param_uninit_control_dep_attempts)
+ {
+ if (dump_file)
+ fprintf (dump_file, "param_uninit_control_dep_attempts exceeded: %u\n",
+ *num_calls);
+ return false;
+ }
+ ++*num_calls;
+
+ /* FIXME: Use a set instead. */
+ unsigned cur_chain_len = cur_cd_chain.length ();
+ if (cur_chain_len > MAX_CHAIN_LEN)
+ {
+ if (dump_file)
+ fprintf (dump_file, "MAX_CHAIN_LEN exceeded: %u\n", cur_chain_len);
+
+ return false;
+ }
+
+ if (cur_chain_len > 5)
+ {
+ if (dump_file)
+ fprintf (dump_file, "chain length exceeds 5: %u\n", cur_chain_len);
+ }
+
+ for (unsigned i = 0; i < cur_chain_len; i++)
+ {
+ edge e = cur_cd_chain[i];
+ /* Cycle detected. */
+ if (e->src == dom_bb)
+ {
+ if (dump_file)
+ fprintf (dump_file, "cycle detected\n");
+ return false;
+ }
+ }
+
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ fprintf (dump_file,
+ "%*s%s (dom_bb = %u, dep_bb = %u, cd_chains = { %s }, ...)\n",
+ depth, "", __func__, dom_bb->index, dep_bb->index,
+ format_edge_vecs (cd_chains, *num_chains).c_str ());
+
+ bool found_cd_chain = false;
+
+ /* Iterate over DOM_BB's successors. */
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, dom_bb->succs)
+ {
+ int post_dom_check = 0;
+ if (e->flags & (EDGE_FAKE | EDGE_ABNORMAL))
+ continue;
+
+ basic_block cd_bb = e->dest;
+ cur_cd_chain.safe_push (e);
+ while (!is_non_loop_exit_postdominating (cd_bb, dom_bb))
+ {
+ if (cd_bb == dep_bb)
+ {
+ /* Found a direct control dependence. */
+ if (*num_chains < MAX_NUM_CHAINS)
+ {
+ cd_chains[*num_chains] = cur_cd_chain.copy ();
+ (*num_chains)++;
+ }
+ found_cd_chain = true;
+ /* Check path from next edge. */
+ break;
+ }
+
+ /* Check if DEP_BB is indirectly control-dependent on DOM_BB. */
+ if (compute_control_dep_chain (cd_bb, dep_bb, cd_chains,
+ num_chains, cur_cd_chain,
+ num_calls, depth + 1))
+ {
+ found_cd_chain = true;
+ break;
+ }
+
+ cd_bb = find_pdom (cd_bb);
+ post_dom_check++;
+ if (cd_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+ || post_dom_check > MAX_POSTDOM_CHECK)
+ break;
+ }
+ cur_cd_chain.pop ();
+ gcc_assert (cur_cd_chain.length () == cur_chain_len);
+ }
+
+ gcc_assert (cur_cd_chain.length () == cur_chain_len);
+ return found_cd_chain;
+}
+
+/* Return true if PRED can be invalidated by any predicate in GUARD. */
+
+static bool
+can_be_invalidated_p (const pred_info &pred, const pred_chain &guard)
+{
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Testing if predicate: ");
+ dump_pred_info (pred);
+ fprintf (dump_file, "\n...can be invalidated by a USE guard of: ");
+ dump_pred_chain (guard);
+ fputc ('\n', dump_file);
+ }
+
+ unsigned n = guard.length ();
+ for (unsigned i = 0; i < n; ++i)
+ {
+ if (pred_neg_p (pred, guard[i]))
+ {
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, " Predicate invalidated by: ");
+ dump_pred_info (guard[i]);
+ fputc ('\n', dump_file);
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Return true if all predicates in PREDS are invalidated by GUARD being
+ true. */
+
+static bool
+can_be_invalidated_p (const pred_chain_union &preds, const pred_chain &guard)
+{
+ if (preds.is_empty ())
+ return false;
+
+ if (dump_file && dump_flags & TDF_DETAILS)
+ dump_predicates (NULL, preds,
+ "Testing if anything here can be invalidated: ");
+
+ for (unsigned i = 0; i < preds.length (); ++i)
+ {
+ const pred_chain &chain = preds[i];
+ for (unsigned j = 0; j < chain.length (); ++j)
+ if (can_be_invalidated_p (chain[j], guard))
+ return true;
+
+ /* If we were unable to invalidate any predicate in C, then there
+ is a viable path from entry to the PHI where the PHI takes
+ an interesting value and continues to a use of the PHI. */
+ return false;
+ }
+ return true;
+}
+
+/* Return true if none of the PHI arguments in OPNDS is used given
+ the use guards in *THIS that guard the PHI's use. */
+
+bool
+predicate::use_cannot_happen (gphi *phi, unsigned opnds)
+{
+ if (!m_eval.phi_arg_set (phi))
+ return false;
+
+ /* PHI_USE_GUARDS are OR'ed together. If we have more than one
+ possible guard, there's no way of knowing which guard was true.
+ Since we need to be absolutely sure that the uninitialized
+ operands will be invalidated, bail. */
+ const pred_chain_union &phi_use_guards = m_preds;
+ if (phi_use_guards.length () != 1)
+ return false;
+
+ const pred_chain &use_guard = phi_use_guards[0];
+
+ /* Look for the control dependencies of all the interesting operands
+ and build guard predicates describing them. */
+ unsigned n = gimple_phi_num_args (phi);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ if (!MASK_TEST_BIT (opnds, i))
+ continue;
+
+ edge e = gimple_phi_arg_edge (phi, i);
+ auto_vec<edge> dep_chains[MAX_NUM_CHAINS];
+ auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
+ unsigned num_chains = 0;
+ unsigned num_calls = 0;
+
+ /* Build the control dependency chain for the PHI argument... */
+ if (!compute_control_dep_chain (ENTRY_BLOCK_PTR_FOR_FN (cfun),
+ e->src, dep_chains, &num_chains,
+ cur_chain, &num_calls))
+ return false;
+
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ {
+ fprintf (dump_file, "predicate::use_cannot_happen (...) "
+ "dep_chains for arg %u:\n\t", i);
+ dump_dep_chains (dep_chains, num_chains);
+ }
+
+ /* ...and convert it into a set of predicates guarding its
+ definition. */
+ predicate def_preds (m_eval);
+ def_preds.init_from_control_deps (dep_chains, num_chains);
+ if (def_preds.is_empty ())
+ /* If there's no predicate there's no basis to rule the use out. */
+ return false;
+
+ def_preds.simplify ();
+ def_preds.normalize ();
+
+ /* Can the guard for this PHI argument be negated by the one
+ guarding the PHI use? */
+ if (!can_be_invalidated_p (def_preds.chain (), use_guard))
+ return false;
+ }
+
+ return true;
+}
+
+/* Implemented simplifications:
+
+ 1) ((x IOR y) != 0) AND (x != 0) is equivalent to (x != 0);
+ 2) (X AND Y) OR (!X AND Y) is equivalent to Y;
+ 3) X OR (!X AND Y) is equivalent to (X OR Y);
+ 4) ((x IAND y) != 0) || (x != 0 AND y != 0)) is equivalent to
+ (x != 0 AND y != 0)
+ 5) (X AND Y) OR (!X AND Z) OR (!Y AND Z) is equivalent to
+ (X AND Y) OR Z
+
+ PREDS is the predicate chains, and N is the number of chains. */
+
+/* Implement rule 1 above. PREDS is the AND predicate to simplify
+ in place. */
+
+static void
+simplify_1 (pred_chain &chain)
+{
+ bool simplified = false;
+ pred_chain s_chain = vNULL;
+
+ unsigned n = chain.length ();
+ for (unsigned i = 0; i < n; i++)
+ {
+ pred_info &a_pred = chain[i];
+
+ if (!a_pred.pred_lhs
+ || !is_neq_zero_form_p (a_pred))
+ continue;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (a_pred.pred_lhs);
+ if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
+ continue;
+
+ if (gimple_assign_rhs_code (def_stmt) != BIT_IOR_EXPR)
+ continue;
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ const pred_info &b_pred = chain[j];
+
+ if (!b_pred.pred_lhs
+ || !is_neq_zero_form_p (b_pred))
+ continue;
+
+ if (pred_expr_equal_p (b_pred, gimple_assign_rhs1 (def_stmt))
+ || pred_expr_equal_p (b_pred, gimple_assign_rhs2 (def_stmt)))
+ {
+ /* Mark A_PRED for removal from PREDS. */
+ a_pred.pred_lhs = NULL;
+ a_pred.pred_rhs = NULL;
+ simplified = true;
+ break;
+ }
+ }
+ }
+
+ if (!simplified)
+ return;
+
+ /* Remove predicates marked above. */
+ for (unsigned i = 0; i < n; i++)
+ {
+ pred_info &a_pred = chain[i];
+ if (!a_pred.pred_lhs)
+ continue;
+ s_chain.safe_push (a_pred);
+ }
+
+ chain.release ();
+ chain = s_chain;
+}
+
+/* Implements rule 2 for the OR predicate PREDS:
+
+ 2) (X AND Y) OR (!X AND Y) is equivalent to Y. */
+
+bool
+predicate::simplify_2 ()
+{
+ bool simplified = false;
+
+ /* (X AND Y) OR (!X AND Y) is equivalent to Y.
+ (X AND Y) OR (X AND !Y) is equivalent to X. */
+
+ unsigned n = m_preds.length ();
+ for (unsigned i = 0; i < n; i++)
+ {
+ pred_chain &a_chain = m_preds[i];
+ if (a_chain.length () != 2)
+ continue;
+
+ /* Create copies since the chain may be released below before
+ the copy is added to the other chain. */
+ const pred_info x = a_chain[0];
+ const pred_info y = a_chain[1];
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ if (j == i)
+ continue;
+
+ pred_chain &b_chain = m_preds[j];
+ if (b_chain.length () != 2)
+ continue;
+
+ const pred_info &x2 = b_chain[0];
+ const pred_info &y2 = b_chain[1];
+
+ if (pred_equal_p (x, x2) && pred_neg_p (y, y2))
+ {
+ /* Kill a_chain. */
+ b_chain.release ();
+ a_chain.release ();
+ b_chain.safe_push (x);
+ simplified = true;
+ break;
+ }
+ if (pred_neg_p (x, x2) && pred_equal_p (y, y2))
+ {
+ /* Kill a_chain. */
+ a_chain.release ();
+ b_chain.release ();
+ b_chain.safe_push (y);
+ simplified = true;
+ break;
+ }
+ }
+ }
+ /* Now clean up the chain. */
+ if (simplified)
+ {
+ pred_chain_union s_preds = vNULL;
+ for (unsigned i = 0; i < n; i++)
+ {
+ if (m_preds[i].is_empty ())
+ continue;
+ s_preds.safe_push (m_preds[i]);
+ }
+ m_preds.release ();
+ m_preds = s_preds;
+ s_preds = vNULL;
+ }
+
+ return simplified;
+}
+
+/* Implement rule 3 for the OR predicate PREDS:
+
+ 3) x OR (!x AND y) is equivalent to x OR y. */
+
+bool
+predicate::simplify_3 ()
+{
+ /* Now iteratively simplify X OR (!X AND Z ..)
+ into X OR (Z ...). */
+
+ unsigned n = m_preds.length ();
+ if (n < 2)
+ return false;
+
+ bool simplified = false;
+ for (unsigned i = 0; i < n; i++)
+ {
+ const pred_chain &a_chain = m_preds[i];
+
+ if (a_chain.length () != 1)
+ continue;
+
+ const pred_info &x = a_chain[0];
+ for (unsigned j = 0; j < n; j++)
+ {
+ if (j == i)
+ continue;
+
+ pred_chain b_chain = m_preds[j];
+ if (b_chain.length () < 2)
+ continue;
+
+ for (unsigned k = 0; k < b_chain.length (); k++)
+ {
+ const pred_info &x2 = b_chain[k];
+ if (pred_neg_p (x, x2))
+ {
+ b_chain.unordered_remove (k);
+ simplified = true;
+ break;
+ }
+ }
+ }
+ }
+ return simplified;
+}
+
+/* Implement rule 4 for the OR predicate PREDS:
+
+ 2) ((x AND y) != 0) OR (x != 0 AND y != 0) is equivalent to
+ (x != 0 ANd y != 0). */
+
+bool
+predicate::simplify_4 ()
+{
+ bool simplified = false;
+ pred_chain_union s_preds = vNULL;
+
+ unsigned n = m_preds.length ();
+ for (unsigned i = 0; i < n; i++)
+ {
+ pred_chain a_chain = m_preds[i];
+ if (a_chain.length () != 1)
+ continue;
+
+ const pred_info &z = a_chain[0];
+ if (!is_neq_zero_form_p (z))
+ continue;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (z.pred_lhs);
+ if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
+ continue;
+
+ if (gimple_assign_rhs_code (def_stmt) != BIT_AND_EXPR)
+ continue;
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ if (j == i)
+ continue;
+
+ pred_chain b_chain = m_preds[j];
+ if (b_chain.length () != 2)
+ continue;
+
+ const pred_info &x2 = b_chain[0];
+ const pred_info &y2 = b_chain[1];
+ if (!is_neq_zero_form_p (x2) || !is_neq_zero_form_p (y2))
+ continue;
+
+ if ((pred_expr_equal_p (x2, gimple_assign_rhs1 (def_stmt))
+ && pred_expr_equal_p (y2, gimple_assign_rhs2 (def_stmt)))
+ || (pred_expr_equal_p (x2, gimple_assign_rhs2 (def_stmt))
+ && pred_expr_equal_p (y2, gimple_assign_rhs1 (def_stmt))))
+ {
+ /* Kill a_chain. */
+ a_chain.release ();
+ simplified = true;
+ break;
+ }
+ }
+ }
+ /* Now clean up the chain. */
+ if (simplified)
+ {
+ for (unsigned i = 0; i < n; i++)
+ {
+ if (m_preds[i].is_empty ())
+ continue;
+ s_preds.safe_push (m_preds[i]);
+ }
+
+ m_preds.release ();
+ m_preds = s_preds;
+ s_preds = vNULL;
+ }
+
+ return simplified;
+}
+
+/* Simplify predicates in *THIS. */
+
+void
+predicate::simplify (gimple *use_or_def, bool is_use)
+{
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Before simplication ");
+ dump (use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n");
+ }
+
+ unsigned n = m_preds.length ();
+ for (unsigned i = 0; i < n; i++)
+ ::simplify_1 (m_preds[i]);
+
+ if (n < 2)
+ return;
+
+ bool changed;
+ do
+ {
+ changed = false;
+ if (simplify_2 ())
+ changed = true;
+
+ if (simplify_3 ())
+ changed = true;
+
+ if (simplify_4 ())
+ changed = true;
+ }
+ while (changed);
+}
+
+/* Attempt to normalize predicate chains by following UD chains by
+ building up a big tree of either IOR operations or AND operations,
+ and converting the IOR tree into a pred_chain_union or the BIT_AND
+ tree into a pred_chain.
+ Example:
+
+ _3 = _2 RELOP1 _1;
+ _6 = _5 RELOP2 _4;
+ _9 = _8 RELOP3 _7;
+ _10 = _3 | _6;
+ _12 = _9 | _0;
+ _t = _10 | _12;
+
+ then _t != 0 will be normalized into a pred_chain_union
+
+ (_2 RELOP1 _1) OR (_5 RELOP2 _4) OR (_8 RELOP3 _7) OR (_0 != 0)
+
+ Similarly given:
+
+ _3 = _2 RELOP1 _1;
+ _6 = _5 RELOP2 _4;
+ _9 = _8 RELOP3 _7;
+ _10 = _3 & _6;
+ _12 = _9 & _0;
+
+ then _t != 0 will be normalized into a pred_chain:
+ (_2 RELOP1 _1) AND (_5 RELOP2 _4) AND (_8 RELOP3 _7) AND (_0 != 0)
+ */
+
+/* Store a PRED in *THIS. */
+
+void
+predicate::push_pred (const pred_info &pred)
+{
+ pred_chain chain = vNULL;
+ chain.safe_push (pred);
+ m_preds.safe_push (chain);
+}
+
+/* Dump predicates in *THIS for STMT prepended by MSG. */
+
+void
+predicate::dump (gimple *stmt, const char *msg) const
+{
+ fprintf (dump_file, "%s", msg);
+ if (stmt)
+ {
+ fputc ('\t', dump_file);
+ print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, " is conditional on:\n");
+ }
+
+ unsigned np = m_preds.length ();
+ if (np == 0)
+ {
+ fprintf (dump_file, "\t(empty)\n");
+ return;
+ }
+
+ {
+ tree expr = build_pred_expr (m_preds);
+ char *str = print_generic_expr_to_str (expr);
+ fprintf (dump_file, "\t%s (expanded)\n", str);
+ free (str);
+ }
+
+ if (np > 1)
+ fprintf (dump_file, "\tOR (");
+ else
+ fputc ('\t', dump_file);
+ for (unsigned i = 0; i < np; i++)
+ {
+ dump_pred_chain (m_preds[i]);
+ if (i < np - 1)
+ fprintf (dump_file, ", ");
+ else if (i > 0)
+ fputc (')', dump_file);
+ }
+ fputc ('\n', dump_file);
+}
+
+/* Initialize *THIS with the predicates of the control dependence chains
+ between the basic block DEF_BB that defines a variable of interst and
+ USE_BB that uses the variable, respectively. */
+
+predicate::predicate (basic_block def_bb, basic_block use_bb, func_t &eval)
+ : m_preds (vNULL), m_eval (eval)
+{
+ /* Set CD_ROOT to the basic block closest to USE_BB that is the control
+ equivalent of (is guarded by the same predicate as) DEF_BB that also
+ dominates USE_BB. */
+ basic_block cd_root = def_bb;
+ while (dominated_by_p (CDI_DOMINATORS, use_bb, cd_root))
+ {
+ /* Find CD_ROOT's closest postdominator that's its control
+ equivalent. */
+ if (basic_block bb = find_control_equiv_block (cd_root))
+ if (dominated_by_p (CDI_DOMINATORS, use_bb, bb))
+ {
+ cd_root = bb;
+ continue;
+ }
+
+ break;
+ }
+
+ /* Set DEP_CHAINS to the set of edges between CD_ROOT and USE_BB.
+ Each DEP_CHAINS element is a series of edges whose conditions
+ are logical conjunctions. Together, the DEP_CHAINS vector is
+ used below to initialize an OR expression of the conjunctions. */
+ unsigned num_calls = 0;
+ unsigned num_chains = 0;
+ auto_vec<edge> dep_chains[MAX_NUM_CHAINS];
+ auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
+
+ compute_control_dep_chain (cd_root, use_bb, dep_chains, &num_chains,
+ cur_chain, &num_calls);
+
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ {
+ fprintf (dump_file, "predicate::predicate (def_bb = %u, use_bb = %u, func_t) "
+ "initialized from %u dep_chains:\n\t",
+ def_bb->index, use_bb->index, num_chains);
+ dump_dep_chains (dep_chains, num_chains);
+ }
+
+ /* From the set of edges computed above initialize *THIS as the OR
+ condition under which the definition in DEF_BB is used in USE_BB.
+ Each OR subexpression is represented by one element of DEP_CHAINS,
+ where each element consists of a series of AND subexpressions. */
+ init_from_control_deps (dep_chains, num_chains);
+}
+
+/* Release resources in *THIS. */
+
+predicate::~predicate ()
+{
+ unsigned n = m_preds.length ();
+ for (unsigned i = 0; i != n; ++i)
+ m_preds[i].release ();
+ m_preds.release ();
+}
+
+/* Copy-assign RHS to *THIS. */
+
+predicate&
+predicate::operator= (const predicate &rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ /* FIXME: Make this a compile-time constraint? */
+ gcc_assert (&m_eval == &rhs.m_eval);
+
+ unsigned n = m_preds.length ();
+ for (unsigned i = 0; i != n; ++i)
+ m_preds[i].release ();
+ m_preds.release ();
+
+ n = rhs.m_preds.length ();
+ for (unsigned i = 0; i != n; ++i)
+ {
+ const pred_chain &chain = rhs.m_preds[i];
+ m_preds.safe_push (chain.copy ());
+ }
+
+ return *this;
+}
+
+/* For each use edge of PHI, compute all control dependence chains
+ and convert those to the composite predicates in M_PREDS.
+ Return true if a nonempty predicate has been obtained. */
+
+bool
+predicate::init_from_phi_def (gphi *phi)
+{
+ gcc_assert (is_empty ());
+
+ basic_block phi_bb = gimple_bb (phi);
+ /* Find the closest dominating bb to be the control dependence root. */
+ basic_block cd_root = find_dom (phi_bb);
+ if (!cd_root)
+ return false;
+
+ /* Set DEF_EDGES to the edges to the PHI from the bb's that provide
+ definitions of each of the PHI operands for which M_EVAL is false. */
+ auto_vec<edge> def_edges;
+ hash_set<gimple *> visited_phis;
+ collect_phi_def_edges (phi, cd_root, &def_edges, m_eval, &visited_phis);
+
+ unsigned nedges = def_edges.length ();
+ if (nedges == 0)
+ return false;
+
+ unsigned num_chains = 0;
+ auto_vec<edge> dep_chains[MAX_NUM_CHAINS];
+ auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
+ for (unsigned i = 0; i < nedges; i++)
+ {
+ edge e = def_edges[i];
+ unsigned num_calls = 0;
+ unsigned prev_nc = num_chains;
+ compute_control_dep_chain (cd_root, e->src, dep_chains,
+ &num_chains, cur_chain, &num_calls);
+
+ /* Update the newly added chains with the phi operand edge. */
+ if (EDGE_COUNT (e->src->succs) > 1)
+ {
+ if (prev_nc == num_chains && num_chains < MAX_NUM_CHAINS)
+ dep_chains[num_chains++] = vNULL;
+ for (unsigned j = prev_nc; j < num_chains; j++)
+ dep_chains[j].safe_push (e);
+ }
+ }
+
+ /* Convert control dependence chains to the predicate in *THIS under
+ which the PHI operands are defined to values for which M_EVAL is
+ false. */
+ init_from_control_deps (dep_chains, num_chains);
+ return !is_empty ();
+}
+
+/* Compute the predicates that guard the use USE_STMT and check if
+ the incoming paths that have an empty (or possibly empty) definition
+ can be pruned. Return true if it can be determined that the use of
+ PHI's def in USE_STMT is guarded by a predicate set that does not
+ overlap with the predicate sets of all runtime paths that do not
+ have a definition.
+
+ Return false if the use is not guarded or if it cannot be determined.
+ USE_BB is the bb of the use (for phi operand use, the bb is not the bb
+ of the phi stmt, but the source bb of the operand edge).
+
+ OPNDS is a bitmap with a bit set for each PHI operand of interest.
+
+ THIS->M_PREDS contains the (memoized) defining predicate chains of
+ a PHI. If THIS->M_PREDS is empty, the PHI's defining predicate
+ chains are computed and stored into THIS->M_PREDS as needed.
+
+ VISITED_PHIS is a pointer set of phis being visited. */
+
+bool
+predicate::is_use_guarded (gimple *use_stmt, basic_block use_bb,
+ gphi *phi, unsigned opnds,
+ hash_set<gphi *> *visited)
+{
+ if (visited->add (phi))
+ return false;
+
+ /* The basic block where the PHI is defined. */
+ basic_block def_bb = gimple_bb (phi);
+
+ /* Try to build the predicate expression under which the PHI flows
+ into its use. This will be empty if the PHI is defined and used
+ in the same bb. */
+ predicate use_preds (def_bb, use_bb, m_eval);
+
+ if (is_non_loop_exit_postdominating (use_bb, def_bb))
+ {
+ if (is_empty ())
+ {
+ /* Lazily initialize *THIS from the PHI and build its use
+ expression. */
+ init_from_phi_def (phi);
+ m_use_expr = build_pred_expr (use_preds.m_preds);
+ }
+
+ /* The use is not guarded. */
+ return false;
+ }
+
+ if (use_preds.is_empty ())
+ return false;
+
+ /* Try to prune the dead incoming phi edges. */
+ if (!use_preds.overlap (phi, opnds, visited))
+ {
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ fputs ("found predicate overlap\n", dump_file);
+
+ return true;
+ }
+
+ /* We might be able to prove that if the control dependencies for OPNDS
+ are true, the control dependencies for USE_STMT can never be true. */
+ if (use_preds.use_cannot_happen (phi, opnds))
+ return true;
+
+ if (is_empty ())
+ {
+ /* Lazily initialize *THIS from PHI. */
+ if (!init_from_phi_def (phi))
+ {
+ m_use_expr = build_pred_expr (use_preds.m_preds);
+ return false;
+ }
+
+ simplify (phi);
+ normalize (phi);
+ }
+
+ use_preds.simplify (use_stmt, /*is_use=*/true);
+ use_preds.normalize (use_stmt, /*is_use=*/true);
+
+ /* Return true if the predicate guarding the valid definition (i.e.,
+ *THIS) is a superset of the predicate guarding the use (i.e.,
+ USE_PREDS). */
+ if (superset_of (use_preds))
+ return true;
+
+ m_use_expr = build_pred_expr (use_preds.m_preds);
+
+ return false;
+}
+
+/* Public interface to the above. */
+
+bool
+predicate::is_use_guarded (gimple *stmt, basic_block use_bb, gphi *phi,
+ unsigned opnds)
+{
+ hash_set<gphi *> visited;
+ return is_use_guarded (stmt, use_bb, phi, opnds, &visited);
+}
+
+/* Normalize predicate PRED:
+ 1) if PRED can no longer be normalized, append it to *THIS.
+ 2) otherwise if PRED is of the form x != 0, follow x's definition
+ and put normalized predicates into WORK_LIST. */
+
+void
+predicate::normalize (pred_chain *norm_chain,
+ pred_info pred,
+ tree_code and_or_code,
+ pred_chain *work_list,
+ hash_set<tree> *mark_set)
+{
+ if (!is_neq_zero_form_p (pred))
+ {
+ if (and_or_code == BIT_IOR_EXPR)
+ push_pred (pred);
+ else
+ norm_chain->safe_push (pred);
+ return;
+ }
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (pred.pred_lhs);
+
+ if (gimple_code (def_stmt) == GIMPLE_PHI
+ && is_degenerate_phi (def_stmt, &pred))
+ /* PRED has been modified above. */
+ work_list->safe_push (pred);
+ else if (gimple_code (def_stmt) == GIMPLE_PHI && and_or_code == BIT_IOR_EXPR)
+ {
+ unsigned n = gimple_phi_num_args (def_stmt);
+
+ /* Punt for a nonzero constant. The predicate should be one guarding
+ the phi edge. */
+ for (unsigned i = 0; i < n; ++i)
+ {
+ tree op = gimple_phi_arg_def (def_stmt, i);
+ if (TREE_CODE (op) == INTEGER_CST && !integer_zerop (op))
+ {
+ push_pred (pred);
+ return;
+ }
+ }
+
+ for (unsigned i = 0; i < n; ++i)
+ {
+ tree op = gimple_phi_arg_def (def_stmt, i);
+ if (integer_zerop (op))
+ continue;
+
+ push_to_worklist (op, work_list, mark_set);
+ }
+ }
+ else if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
+ {
+ if (and_or_code == BIT_IOR_EXPR)
+ push_pred (pred);
+ else
+ norm_chain->safe_push (pred);
+ }
+ else if (gimple_assign_rhs_code (def_stmt) == and_or_code)
+ {
+ /* Avoid splitting up bit manipulations like x & 3 or y | 1. */
+ if (is_gimple_min_invariant (gimple_assign_rhs2 (def_stmt)))
+ {
+ /* But treat x & 3 as a condition. */
+ if (and_or_code == BIT_AND_EXPR)
+ {
+ pred_info n_pred;
+ n_pred.pred_lhs = gimple_assign_rhs1 (def_stmt);
+ n_pred.pred_rhs = gimple_assign_rhs2 (def_stmt);
+ n_pred.cond_code = and_or_code;
+ n_pred.invert = false;
+ norm_chain->safe_push (n_pred);
+ }
+ }
+ else
+ {
+ push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set);
+ push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set);
+ }
+ }
+ else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
+ == tcc_comparison)
+ {
+ pred_info n_pred = get_pred_info_from_cmp (def_stmt);
+ if (and_or_code == BIT_IOR_EXPR)
+ push_pred (n_pred);
+ else
+ norm_chain->safe_push (n_pred);
+ }
+ else
+ {
+ if (and_or_code == BIT_IOR_EXPR)
+ push_pred (pred);
+ else
+ norm_chain->safe_push (pred);
+ }
+}
+
+/* Normalize PRED and store the normalized predicates in THIS->M_PREDS. */
+
+void
+predicate::normalize (const pred_info &pred)
+{
+ if (!is_neq_zero_form_p (pred))
+ {
+ push_pred (pred);
+ return;
+ }
+
+ tree_code and_or_code = ERROR_MARK;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (pred.pred_lhs);
+ if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
+ and_or_code = gimple_assign_rhs_code (def_stmt);
+ if (and_or_code != BIT_IOR_EXPR && and_or_code != BIT_AND_EXPR)
+ {
+ if (TREE_CODE_CLASS (and_or_code) == tcc_comparison)
+ {
+ pred_info n_pred = get_pred_info_from_cmp (def_stmt);
+ push_pred (n_pred);
+ }
+ else
+ push_pred (pred);
+ return;
+ }
+
+
+ pred_chain norm_chain = vNULL;
+ pred_chain work_list = vNULL;
+ work_list.safe_push (pred);
+ hash_set<tree> mark_set;
+
+ while (!work_list.is_empty ())
+ {
+ pred_info a_pred = work_list.pop ();
+ normalize (&norm_chain, a_pred, and_or_code, &work_list, &mark_set);
+ }
+
+ if (and_or_code == BIT_AND_EXPR)
+ m_preds.safe_push (norm_chain);
+
+ work_list.release ();
+}
+
+/* Normalize a single predicate PRED_CHAIN and append it to *THIS. */
+
+void
+predicate::normalize (const pred_chain &chain)
+{
+ pred_chain work_list = vNULL;
+ hash_set<tree> mark_set;
+ for (unsigned i = 0; i < chain.length (); i++)
+ {
+ work_list.safe_push (chain[i]);
+ mark_set.add (chain[i].pred_lhs);
+ }
+
+ /* Normalized chain of predicates built up below. */
+ pred_chain norm_chain = vNULL;
+ while (!work_list.is_empty ())
+ {
+ pred_info pi = work_list.pop ();
+ predicate pred (m_eval);
+ /* The predicate object is not modified here, only NORM_CHAIN and
+ WORK_LIST are appended to. */
+ pred.normalize (&norm_chain, pi, BIT_AND_EXPR, &work_list, &mark_set);
+ }
+
+ m_preds.safe_push (norm_chain);
+ work_list.release ();
+}
+
+/* Normalize predicate chains in THIS. */
+
+void
+predicate::normalize (gimple *use_or_def, bool is_use)
+{
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Before normalization ");
+ dump (use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n");
+ }
+
+ predicate norm_preds (m_eval);
+ for (unsigned i = 0; i < m_preds.length (); i++)
+ {
+ if (m_preds[i].length () != 1)
+ norm_preds.normalize (m_preds[i]);
+ else
+ norm_preds.normalize (m_preds[i][0]);
+ }
+
+ *this = norm_preds;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "After normalization ");
+ dump (use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n");
+ }
+}
+
+/* Add a predicate for the condition or logical assignment STMT to CHAIN.
+ Expand SSA_NAME into constituent subexpressions. Invert the result
+ if INVERT is true. Return true if the predicate has been added. */
+
+static bool
+add_pred (pred_chain *chain, gimple *stmt, bool invert)
+{
+ if (gimple_code (stmt) == GIMPLE_COND)
+ {
+ tree lhs = gimple_cond_lhs (stmt);
+ if (TREE_CODE (lhs) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (lhs);
+ if (is_gimple_assign (def)
+ && add_pred (chain, def, invert))
+ return true;
+ }
+
+ pred_info pred;
+ pred.pred_lhs = lhs;
+ pred.pred_rhs = gimple_cond_rhs (stmt);
+ pred.cond_code = gimple_cond_code (stmt);
+ pred.invert = invert;
+ chain->safe_push (pred);
+ return true;
+ }
+
+ if (!is_gimple_assign (stmt))
+ return false;
+
+ if (gimple_assign_single_p (stmt))
+ // FIXME: handle this?
+ return false;
+
+ if (TREE_TYPE (gimple_assign_lhs (stmt)) != boolean_type_node)
+ return false;
+
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ tree rhs2 = gimple_assign_rhs2 (stmt);
+ tree_code code = gimple_assign_rhs_code (stmt);
+ if (code == BIT_AND_EXPR)
+ {
+ if (TREE_CODE (rhs1) == SSA_NAME
+ && add_pred (chain, SSA_NAME_DEF_STMT (rhs1), invert)
+ && TREE_CODE (rhs2) == SSA_NAME
+ /* FIXME: Need to handle failure below! */
+ && add_pred (chain, SSA_NAME_DEF_STMT (rhs2), invert))
+ return true;
+ }
+ else if (TREE_CODE_CLASS (code) != tcc_comparison)
+ return false;
+
+ pred_info pred;
+ pred.pred_lhs = rhs1;
+ pred.pred_rhs = rhs2;
+ pred.cond_code = code;
+ pred.invert = invert;
+ chain->safe_push (pred);
+ return true;
+}
+
+/* Convert the chains of control dependence edges into a set of predicates.
+ A control dependence chain is represented by a vector edges. DEP_CHAINS
+ points to an array of NUM_CHAINS dependence chains. One edge in
+ a dependence chain is mapped to predicate expression represented by
+ pred_info type. One dependence chain is converted to a composite
+ predicate that is the result of AND operation of pred_info mapped to
+ each edge. A composite predicate is represented by a vector of
+ pred_info. Sets M_PREDS to the resulting composite predicates. */
+
+void
+predicate::init_from_control_deps (const vec<edge> *dep_chains,
+ unsigned num_chains)
+{
+ gcc_assert (is_empty ());
+
+ bool has_valid_pred = false;
+ if (num_chains == 0)
+ return;
+
+ if (num_chains >= MAX_NUM_CHAINS)
+ {
+ if (dump_file)
+ fprintf (dump_file, "MAX_NUM_CHAINS exceeded: %u\n", num_chains);
+ return;
+ }
+
+ /* Convert the control dependency chain into a set of predicates. */
+ m_preds.reserve (num_chains);
+
+ for (unsigned i = 0; i < num_chains; i++)
+ {
+ /* One path through the CFG represents a logical conjunction
+ of the predicates. */
+ const vec<edge> &path = dep_chains[i];
+
+ has_valid_pred = false;
+ /* The chain of predicates guarding the definition along this path. */
+ pred_chain t_chain{ };
+ for (unsigned j = 0; j < path.length (); j++)
+ {
+ edge e = path[j];
+ basic_block guard_bb = e->src;
+ /* Ignore empty forwarder blocks. */
+ if (empty_block_p (guard_bb) && single_succ_p (guard_bb))
+ continue;
+
+ /* An empty basic block here is likely a PHI, and is not one
+ of the cases we handle below. */
+ gimple_stmt_iterator gsi = gsi_last_bb (guard_bb);
+ if (gsi_end_p (gsi))
+ {
+ has_valid_pred = false;
+ break;
+ }
+ /* Get the conditional controlling the bb exit edge. */
+ gimple *cond_stmt = gsi_stmt (gsi);
+ if (is_gimple_call (cond_stmt) && EDGE_COUNT (e->src->succs) >= 2)
+ /* Ignore EH edge. Can add assertion on the other edge's flag. */
+ continue;
+ /* Skip if there is essentially one succesor. */
+ if (EDGE_COUNT (e->src->succs) == 2)
+ {
+ edge e1;
+ edge_iterator ei1;
+ bool skip = false;
+
+ FOR_EACH_EDGE (e1, ei1, e->src->succs)
+ {
+ if (EDGE_COUNT (e1->dest->succs) == 0)
+ {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+ }
+ if (gimple_code (cond_stmt) == GIMPLE_COND)
+ {
+ /* The true edge corresponds to the uninteresting condition.
+ Add the negated predicate(s) for the edge to record
+ the interesting condition. */
+ pred_info one_pred;
+ one_pred.pred_lhs = gimple_cond_lhs (cond_stmt);
+ one_pred.pred_rhs = gimple_cond_rhs (cond_stmt);
+ one_pred.cond_code = gimple_cond_code (cond_stmt);
+ one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE);
+
+ t_chain.safe_push (one_pred);
+
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ {
+ fprintf (dump_file, "one_pred = ");
+ dump_pred_info (one_pred);
+ fputc ('\n', dump_file);
+ }
+
+ has_valid_pred = true;
+ }
+ else if (gswitch *gs = dyn_cast<gswitch *> (cond_stmt))
+ {
+ /* Avoid quadratic behavior. */
+ if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES)
+ {
+ has_valid_pred = false;
+ break;
+ }
+ /* Find the case label. */
+ tree l = NULL_TREE;
+ unsigned idx;
+ for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
+ {
+ tree tl = gimple_switch_label (gs, idx);
+ if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
+ {
+ if (!l)
+ l = tl;
+ else
+ {
+ l = NULL_TREE;
+ break;
+ }
+ }
+ }
+ /* If more than one label reaches this block or the case
+ label doesn't have a single value (like the default one)
+ fail. */
+ if (!l
+ || !CASE_LOW (l)
+ || (CASE_HIGH (l)
+ && !operand_equal_p (CASE_LOW (l), CASE_HIGH (l), 0)))
+ {
+ has_valid_pred = false;
+ break;
+ }
+
+ pred_info one_pred;
+ one_pred.pred_lhs = gimple_switch_index (gs);
+ one_pred.pred_rhs = CASE_LOW (l);
+ one_pred.cond_code = EQ_EXPR;
+ one_pred.invert = false;
+ t_chain.safe_push (one_pred);
+ has_valid_pred = true;
+ }
+ else
+ {
+ /* Disabled. See PR 90994.
+ has_valid_pred = false; */
+ break;
+ }
+ }
+
+ if (!has_valid_pred)
+ break;
+ else
+ m_preds.safe_push (t_chain);
+ }
+
+ if (DEBUG_PREDICATE_ANALYZER && dump_file)
+ {
+ fprintf (dump_file, "init_from_control_deps {%s}:\n",
+ format_edge_vecs (dep_chains, num_chains).c_str ());
+ dump (NULL, "");
+ }
+
+ if (has_valid_pred)
+ gcc_assert (m_preds.length () != 0);
+ else
+ /* Clear M_PREDS to indicate failure. */
+ m_preds.release ();
+}
+
+/* Return the predicate expression guarding the definition of
+ the interesting variable. When INVERT is set, return the logical
+ NOT of the predicate. */
+
+tree
+predicate::def_expr (bool invert /* = false */) const
+{
+ /* The predicate is stored in an inverted form. */
+ return build_pred_expr (m_preds, !invert);
+}
+
+/* Return the predicate expression guarding the use of the interesting
+ variable or null if the use predicate hasn't been determined yet. */
+
+tree
+predicate::use_expr () const
+{
+ return m_use_expr;
+}
+
+/* Return a logical AND expression with the (optionally inverted) predicate
+ expression guarding the definition of the interesting variable and one
+ guarding its use. Return null if the use predicate hasn't yet been
+ determined. */
+
+tree
+predicate::expr (bool invert /* = false */) const
+{
+ if (!m_use_expr)
+ return NULL_TREE;
+
+ tree expr = build_pred_expr (m_preds, !invert);
+ return build2 (TRUTH_AND_EXPR, boolean_type_node, expr, m_use_expr);
+}
diff --git a/gcc/gimple-predicate-analysis.h b/gcc/gimple-predicate-analysis.h
new file mode 100644
index 0000000..fbf6f8e
--- /dev/null
+++ b/gcc/gimple-predicate-analysis.h
@@ -0,0 +1,158 @@
+/* Support for simple predicate analysis.
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Martin Sebor <msebor@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 GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED
+#define GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED
+
+#define MAX_NUM_CHAINS 8
+#define MAX_CHAIN_LEN 5
+#define MAX_POSTDOM_CHECK 8
+#define MAX_SWITCH_CASES 40
+
+/* Represents a simple Boolean predicate. */
+struct pred_info
+{
+ tree pred_lhs;
+ tree pred_rhs;
+ enum tree_code cond_code;
+ bool invert;
+};
+
+/* The type to represent a sequence of predicates grouped
+ with .AND. operation. */
+typedef vec<pred_info, va_heap, vl_ptr> pred_chain;
+
+/* The type to represent a sequence of pred_chains grouped
+ with .OR. operation. */
+typedef vec<pred_chain, va_heap, vl_ptr> pred_chain_union;
+
+/* Represents a complex Boolean predicate expression. */
+class predicate
+{
+ public:
+ /* Base function object type used to determine whether an expression
+ is of interest. */
+ struct func_t
+ {
+ typedef unsigned phi_arg_set_t;
+
+ /* Return true if the argument is an expression of interest. */
+ virtual bool operator()(tree) = 0;
+ /* Return a bitset of PHI arguments of interest. By default returns
+ bitset with a bit set for each argument. Should be called in
+ the overriden function first and, if nonzero, the result then
+ refined as appropriate. */
+ virtual phi_arg_set_t phi_arg_set (gphi *);
+
+ /* Maximum number of PHI arguments supported by phi_arg_set(). */
+ static constexpr unsigned max_phi_args =
+ sizeof (phi_arg_set_t) * CHAR_BIT;
+ };
+
+ /* Construct with the specified EVAL object. */
+ predicate (func_t &eval)
+ : m_preds (vNULL), m_eval (eval), m_use_expr () { }
+
+ /* Copy. */
+ predicate (const predicate &rhs)
+ : m_preds (vNULL), m_eval (rhs.m_eval), m_use_expr ()
+ {
+ *this = rhs;
+ }
+
+ predicate (basic_block, basic_block, func_t &);
+
+ ~predicate ();
+
+ /* Assign. */
+ predicate& operator= (const predicate &);
+
+ bool is_empty () const
+ {
+ return m_preds.is_empty ();
+ }
+
+ const pred_chain_union chain () const
+ {
+ return m_preds;
+ }
+
+ /* Return true if the use by a statement in the basic block of
+ a PHI operand is ruled out (i.e., guarded) by *THIS. */
+ bool is_use_guarded (gimple *, basic_block, gphi *, unsigned);
+
+ void init_from_control_deps (const vec<edge> *, unsigned);
+
+ void dump (gimple *, const char *) const;
+
+ void normalize (gimple * = NULL, bool = false);
+ void simplify (gimple * = NULL, bool = false);
+
+ bool is_use_guarded (gimple *, basic_block, gphi *, unsigned,
+ hash_set<gphi *> *);
+
+ /* Return the predicate expression guarding the definition of
+ the interesting variable, optionally inverted. */
+ tree def_expr (bool = false) const;
+ /* Return the predicate expression guarding the use of the interesting
+ variable. */
+ tree use_expr () const;
+
+ tree expr (bool = false) const;
+
+private:
+ bool includes (const pred_chain &) const;
+ bool superset_of (const predicate &) const;
+ bool overlap (gphi *, unsigned, hash_set<gphi *> *);
+ bool use_cannot_happen (gphi *, unsigned);
+
+ bool init_from_phi_def (gphi *);
+
+ void push_pred (const pred_info &);
+
+ /* Normalization functions. */
+ void normalize (pred_chain *, pred_info, tree_code, pred_chain *,
+ hash_set<tree> *);
+
+ void normalize (const pred_info &);
+ void normalize (const pred_chain &);
+
+ /* Simplification functions. */
+ bool simplify_2 ();
+ bool simplify_3 ();
+ bool simplify_4 ();
+
+private:
+ /* Representation of the predicate expression(s). */
+ pred_chain_union m_preds;
+ /* Callback to evaluate an operand. Return true if it's interesting. */
+ func_t &m_eval;
+ /* The predicate expression guarding the use of the interesting
+ variable. */
+ tree m_use_expr;
+};
+
+/* Bit mask handling macros. */
+#define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
+#define MASK_TEST_BIT(mask, pos) (mask & (1 << pos))
+#define MASK_EMPTY(mask) (mask == 0)
+
+#endif // GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 53e7759..1cd1597 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -677,11 +677,18 @@ dump_gimple_assign (pretty_printer *buffer, const gassign *gs, int spc,
}
if (gimple_num_ops (gs) == 2)
- dump_unary_rhs (buffer, gs, spc, flags);
+ dump_unary_rhs (buffer, gs, spc,
+ ((flags & TDF_GIMPLE)
+ && gimple_assign_rhs_class (gs) != GIMPLE_SINGLE_RHS)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else if (gimple_num_ops (gs) == 3)
- dump_binary_rhs (buffer, gs, spc, flags);
+ dump_binary_rhs (buffer, gs, spc,
+ (flags & TDF_GIMPLE)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else if (gimple_num_ops (gs) == 4)
- dump_ternary_rhs (buffer, gs, spc, flags);
+ dump_ternary_rhs (buffer, gs, spc,
+ (flags & TDF_GIMPLE)
+ ? (flags | TDF_GIMPLE_VAL) : flags);
else
gcc_unreachable ();
if (!(flags & TDF_RHS_ONLY))
@@ -1085,11 +1092,15 @@ dump_gimple_cond (pretty_printer *buffer, const gcond *gs, int spc,
{
if (!(flags & TDF_RHS_ONLY))
pp_string (buffer, "if (");
- dump_generic_node (buffer, gimple_cond_lhs (gs), spc, flags, false);
+ dump_generic_node (buffer, gimple_cond_lhs (gs), spc,
+ flags | ((flags & TDF_GIMPLE) ? TDF_GIMPLE_VAL : TDF_NONE),
+ false);
pp_space (buffer);
pp_string (buffer, op_symbol_code (gimple_cond_code (gs)));
pp_space (buffer);
- dump_generic_node (buffer, gimple_cond_rhs (gs), spc, flags, false);
+ dump_generic_node (buffer, gimple_cond_rhs (gs), spc,
+ flags | ((flags & TDF_GIMPLE) ? TDF_GIMPLE_VAL : TDF_NONE),
+ false);
if (!(flags & TDF_RHS_ONLY))
{
edge_iterator ei;
@@ -2563,6 +2574,8 @@ dump_gimple_omp_atomic_load (pretty_printer *buffer, const gomp_atomic_load *gs,
gimple_omp_atomic_memory_order (gs));
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, " [needed]");
+ if (gimple_omp_atomic_weak_p (gs))
+ pp_string (buffer, " [weak]");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, gimple_omp_atomic_load_lhs (gs),
spc, flags, false);
@@ -2597,6 +2610,8 @@ dump_gimple_omp_atomic_store (pretty_printer *buffer,
pp_space (buffer);
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, "[needed] ");
+ if (gimple_omp_atomic_weak_p (gs))
+ pp_string (buffer, "[weak] ");
pp_left_paren (buffer);
dump_generic_node (buffer, gimple_omp_atomic_store_val (gs),
spc, flags, false);
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index facf981..9cbc63d 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -37,8 +37,8 @@ along with GCC; see the file COPYING3. If not see
non_null_ref::non_null_ref ()
{
- m_nn.create (0);
- m_nn.safe_grow_cleared (num_ssa_names);
+ m_nn.create (num_ssa_names);
+ m_nn.quick_grow_cleared (num_ssa_names);
bitmap_obstack_initialize (&m_bitmaps);
}
@@ -61,6 +61,9 @@ non_null_ref::non_null_deref_p (tree name, basic_block bb, bool search_dom)
return false;
unsigned v = SSA_NAME_VERSION (name);
+ if (v >= m_nn.length ())
+ m_nn.safe_grow_cleared (num_ssa_names + 1);
+
if (!m_nn[v])
process_name (name);
@@ -98,15 +101,16 @@ non_null_ref::adjust_range (irange &r, tree name, basic_block bb,
return false;
// We only care about the null / non-null property of pointers.
- if (!POINTER_TYPE_P (TREE_TYPE (name)) || r.zero_p () || r.nonzero_p ())
+ if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ return false;
+ if (r.undefined_p () || r.lower_bound () != 0 || r.upper_bound () == 0)
return false;
-
// Check if pointers have any non-null dereferences.
if (non_null_deref_p (name, bb, search_dom))
{
- int_range<2> nz;
- nz.set_nonzero (TREE_TYPE (name));
- r.intersect (nz);
+ // Remove zero from the range.
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
+ r.intersect (wi::one (prec), wi::max_value (prec, UNSIGNED));
return true;
}
return false;
@@ -750,7 +754,8 @@ temporal_cache::set_always_current (tree name)
// --------------------------------------------------------------------------
-ranger_cache::ranger_cache ()
+ranger_cache::ranger_cache (int not_executable_flag)
+ : m_gori (not_executable_flag)
{
m_workback.create (0);
m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun));
@@ -760,7 +765,7 @@ ranger_cache::ranger_cache ()
m_temporal = new temporal_cache;
// If DOM info is available, spawn an oracle as well.
if (dom_info_available_p (CDI_DOMINATORS))
- m_oracle = new relation_oracle ();
+ m_oracle = new dom_oracle ();
else
m_oracle = NULL;
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 3b55673..4937a0b 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -92,7 +92,7 @@ private:
class ranger_cache : public range_query
{
public:
- ranger_cache ();
+ ranger_cache (int not_executable_flag);
~ranger_cache ();
virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index d11153e..afffc8d 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -65,9 +65,10 @@ gcond_edge_range (irange &r, edge e)
}
-gimple_outgoing_range::gimple_outgoing_range ()
+gimple_outgoing_range::gimple_outgoing_range (int max_sw_edges)
{
m_edge_table = NULL;
+ m_max_edges = max_sw_edges;
}
@@ -192,6 +193,10 @@ gimple_outgoing_range::edge_range_p (irange &r, edge e)
return s;
}
+ // Only process switches if it within the size limit.
+ if (EDGE_COUNT (e->src->succs) > (unsigned)m_max_edges)
+ return NULL;
+
gcc_checking_assert (is_a<gswitch *> (s));
gswitch *sw = as_a<gswitch *> (s);
tree type = TREE_TYPE (gimple_switch_index (sw));
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index 87b4124..03e8e82 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -38,13 +38,14 @@ along with GCC; see the file COPYING3. If not see
class gimple_outgoing_range
{
public:
- gimple_outgoing_range ();
+ gimple_outgoing_range (int max_sw_edges = INT_MAX);
~gimple_outgoing_range ();
gimple *edge_range_p (irange &r, edge e);
private:
void calc_switch_ranges (gswitch *sw);
bool get_edge_range (irange &r, gimple *s, edge e);
+ int m_max_edges;
hash_map<edge, irange *> *m_edge_table;
irange_allocator m_range_allocator;
};
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 94dd042..ed2fbe1 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -195,7 +195,7 @@ void
fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2)
{
if (m_oracle)
- m_oracle->register_relation (s, k, op1, op2);
+ m_oracle->register_stmt (s, k, op1, op2);
}
// Register a relation on an edge if there is an oracle.
@@ -204,7 +204,7 @@ void
fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
{
if (m_oracle)
- m_oracle->register_relation (e, k, op1, op2);
+ m_oracle->register_edge (e, k, op1, op2);
}
// This version of fur_source will pick a range up from a list of ranges
@@ -360,23 +360,83 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
&& integer_zerop (gimple_call_arg (call, 1)))
{
tree max = vrp_val_max (ptrdiff_type_node);
- wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree expr_type = gimple_range_type (diff_stmt);
- tree range_min = build_zero_cst (expr_type);
- tree range_max = wide_int_to_tree (expr_type, wmax - 1);
- int_range<2> r (range_min, range_max);
- res.intersect (r);
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (max));
+ wide_int wmaxm1 = wi::to_wide (max, prec) - 1;
+ res.intersect (wi::zero (prec), wmaxm1);
+ }
+}
+
+// Adjust the range for an IMAGPART_EXPR.
+
+static void
+adjust_imagpart_expr (irange &res, const gimple *stmt)
+{
+ tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+
+ if (TREE_CODE (name) != SSA_NAME || !SSA_NAME_DEF_STMT (name))
+ return;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ if (is_gimple_call (def_stmt) && gimple_call_internal_p (def_stmt))
+ {
+ switch (gimple_call_internal_fn (def_stmt))
+ {
+ case IFN_ADD_OVERFLOW:
+ case IFN_SUB_OVERFLOW:
+ case IFN_MUL_OVERFLOW:
+ case IFN_ATOMIC_COMPARE_EXCHANGE:
+ {
+ int_range<2> r;
+ r.set_varying (boolean_type_node);
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+ range_cast (r, type);
+ res.intersect (r);
+ }
+ default:
+ break;
+ }
+ return;
+ }
+ if (is_gimple_assign (def_stmt))
+ {
+ tree cst = gimple_assign_rhs1 (def_stmt);
+ if (TREE_CODE (cst) == COMPLEX_CST)
+ {
+ wide_int imag = wi::to_wide (TREE_IMAGPART (cst));
+ res.intersect (imag, imag);
+ }
+ }
+}
+
+// Adjust the range for a REALPART_EXPR.
+
+static void
+adjust_realpart_expr (irange &res, const gimple *stmt)
+{
+ tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+
+ if (TREE_CODE (name) != SSA_NAME)
+ return;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ if (!SSA_NAME_DEF_STMT (name))
+ return;
+
+ if (is_gimple_assign (def_stmt))
+ {
+ tree cst = gimple_assign_rhs1 (def_stmt);
+ if (TREE_CODE (cst) == COMPLEX_CST)
+ {
+ tree imag = TREE_REALPART (cst);
+ int_range<2> tmp (imag, imag);
+ res.intersect (tmp);
+ }
}
}
// This function looks for situations when walking the use/def chains
// may provide additonal contextual range information not exposed on
-// this statement. Like knowing the IMAGPART return value from a
-// builtin function is a boolean result.
-
-// We should rework how we're called, as we have an op_unknown entry
-// for IMAGPART_EXPR and POINTER_DIFF_EXPR in range-ops just so this
-// function gets called.
+// this statement.
static void
gimple_range_adjustment (irange &res, const gimple *stmt)
@@ -388,34 +448,12 @@ gimple_range_adjustment (irange &res, const gimple *stmt)
return;
case IMAGPART_EXPR:
- {
- tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
- if (TREE_CODE (name) == SSA_NAME)
- {
- gimple *def_stmt = SSA_NAME_DEF_STMT (name);
- if (def_stmt && is_gimple_call (def_stmt)
- && gimple_call_internal_p (def_stmt))
- {
- switch (gimple_call_internal_fn (def_stmt))
- {
- case IFN_ADD_OVERFLOW:
- case IFN_SUB_OVERFLOW:
- case IFN_MUL_OVERFLOW:
- case IFN_ATOMIC_COMPARE_EXCHANGE:
- {
- int_range<2> r;
- r.set_varying (boolean_type_node);
- tree type = TREE_TYPE (gimple_assign_lhs (stmt));
- range_cast (r, type);
- res.intersect (r);
- }
- default:
- break;
- }
- }
- }
- break;
- }
+ adjust_imagpart_expr (res, stmt);
+ return;
+
+ case REALPART_EXPR:
+ adjust_realpart_expr (res, stmt);
+ return;
default:
break;
@@ -608,8 +646,20 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
src.register_relation (s, rel, lhs, op2);
}
}
- else if (is_a<gcond *> (s))
- postfold_gcond_edges (as_a<gcond *> (s), r, src);
+ // Check for an existing BB, as we maybe asked to fold an
+ // artificial statement not in the CFG.
+ else if (is_a<gcond *> (s) && gimple_bb (s))
+ {
+ basic_block bb = gimple_bb (s);
+ edge e0 = EDGE_SUCC (bb, 0);
+ edge e1 = EDGE_SUCC (bb, 1);
+
+ if (!single_pred_p (e0->dest))
+ e0 = NULL;
+ if (!single_pred_p (e1->dest))
+ e1 = NULL;
+ src.register_outgoing_edges (as_a<gcond *> (s), r, e0, e1);
+ }
}
else
r.set_varying (type);
@@ -718,6 +768,10 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
if (!type)
return false;
+ // Track if all executable arguments are the same.
+ tree single_arg = NULL_TREE;
+ bool seen_arg = false;
+
// Start with an empty range, unioning in each argument's range.
r.set_undefined ();
for (x = 0; x < gimple_phi_num_args (phi); x++)
@@ -725,19 +779,48 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
tree arg = gimple_phi_arg_def (phi, x);
edge e = gimple_phi_arg_edge (phi, x);
- // Register potential dependencies for stale value tracking.
- if (gimple_range_ssa_p (arg) && src.gori ())
- src.gori ()->register_dependency (phi_def, arg);
-
// Get the range of the argument on its edge.
src.get_phi_operand (arg_range, arg, e);
- // If we're recomputing the argument elsewhere, try to refine it.
- r.union_ (arg_range);
+
+ if (!arg_range.undefined_p ())
+ {
+ // Register potential dependencies for stale value tracking.
+ r.union_ (arg_range);
+ if (gimple_range_ssa_p (arg) && src.gori ())
+ src.gori ()->register_dependency (phi_def, arg);
+
+ // Track if all arguments are the same.
+ if (!seen_arg)
+ {
+ seen_arg = true;
+ single_arg = arg;
+ }
+ else if (single_arg != arg)
+ single_arg = NULL_TREE;
+ }
+
// Once the value reaches varying, stop looking.
- if (r.varying_p ())
+ if (r.varying_p () && single_arg == NULL_TREE)
break;
}
+ // If the PHI boils down to a single effective argument, look at it.
+ if (single_arg)
+ {
+ // Symbolic arguments are equivalences.
+ if (gimple_range_ssa_p (single_arg))
+ src.register_relation (phi, EQ_EXPR, phi_def, single_arg);
+ else if (src.get_operand (arg_range, single_arg)
+ && arg_range.singleton_p ())
+ {
+ // Numerical arguments that are a constant can be returned as
+ // the constant. This can help fold later cases where even this
+ // constant might have been UNDEFINED via an unreachable edge.
+ r = arg_range;
+ return true;
+ }
+ }
+
// If SCEV is available, query if this PHI has any knonwn values.
if (scev_initialized_p () && !POINTER_TYPE_P (TREE_TYPE (phi_def)))
{
@@ -1271,6 +1354,10 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1));
range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2));
+ // If either handler is not present, no relation is found.
+ if (!handler1 || !handler2)
+ return;
+
int_range<2> bool_one (boolean_true_node, boolean_true_node);
relation_kind relation1 = handler1->op1_op2_relation (bool_one);
@@ -1309,8 +1396,7 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
// Register any outgoing edge relations from a conditional branch.
void
-fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
- fur_source &src)
+fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e1)
{
int_range_max r;
int_range<2> e0_range, e1_range;
@@ -1318,10 +1404,7 @@ fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
range_operator *handler;
basic_block bb = gimple_bb (s);
- edge e0 = EDGE_SUCC (bb, 0);
- if (!single_pred_p (e0->dest))
- e0 = NULL;
- else
+ if (e0)
{
// If this edge is never taken, ignore it.
gcond_edge_range (e0_range, e0);
@@ -1331,10 +1414,7 @@ fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
}
- edge e1 = EDGE_SUCC (bb, 1);
- if (!single_pred_p (e1->dest))
- e1 = NULL;
- else
+ if (e1)
{
// If this edge is never taken, ignore it.
gcond_edge_range (e1_range, e1);
@@ -1343,7 +1423,6 @@ fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
e1 = NULL;
}
- // At least one edge needs to be single pred.
if (!e0 && !e1)
return;
@@ -1359,27 +1438,25 @@ fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
{
relation_kind relation = handler->op1_op2_relation (e0_range);
if (relation != VREL_NONE)
- src.register_relation (e0, relation, ssa1, ssa2);
+ register_relation (e0, relation, ssa1, ssa2);
}
if (e1)
{
relation_kind relation = handler->op1_op2_relation (e1_range);
if (relation != VREL_NONE)
- src.register_relation (e1, relation, ssa1, ssa2);
+ register_relation (e1, relation, ssa1, ssa2);
}
}
// Outgoing relations of GORI exports require a gori engine.
- if (!src.gori ())
+ if (!gori ())
return;
- range_query *q = src.query ();
// Now look for other relations in the exports. This will find stmts
// leading to the condition such as:
// c_2 = a_4 < b_7
// if (c_2)
-
- FOR_EACH_GORI_EXPORT_NAME (*(src.gori ()), bb, name)
+ FOR_EACH_GORI_EXPORT_NAME (*(gori ()), bb, name)
{
if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE)
continue;
@@ -1391,19 +1468,19 @@ fold_using_range::postfold_gcond_edges (gcond *s, irange& lhs_range,
tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
if (ssa1 && ssa2)
{
- if (e0 && src.gori ()->outgoing_edge_range_p (r, e0, name, *q)
+ if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
&& r.singleton_p ())
{
relation_kind relation = handler->op1_op2_relation (r);
if (relation != VREL_NONE)
- src.register_relation (e0, relation, ssa1, ssa2);
+ register_relation (e0, relation, ssa1, ssa2);
}
- if (e1 && src.gori ()->outgoing_edge_range_p (r, e1, name, *q)
+ if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query)
&& r.singleton_p ())
{
relation_kind relation = handler->op1_op2_relation (r);
if (relation != VREL_NONE)
- src.register_relation (e1, relation, ssa1, ssa2);
+ register_relation (e1, relation, ssa1, ssa2);
}
}
}
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index ceed7ba..350e2c4 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -93,6 +93,7 @@ gimple_range_ssa_p (tree exp)
{
if (exp && TREE_CODE (exp) == SSA_NAME &&
!SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
+ !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
irange::supports_type_p (TREE_TYPE (exp)))
return exp;
return NULL_TREE;
@@ -129,6 +130,7 @@ public:
tree op2);
virtual void register_relation (edge e, relation_kind k, tree op1,
tree op2);
+ void register_outgoing_edges (gcond *, irange &lhs_range, edge e0, edge e1);
protected:
range_query *m_query;
gori_compute *m_gori;
@@ -159,7 +161,7 @@ public:
tree op2) OVERRIDE;
virtual void register_relation (edge e, relation_kind k, tree op1,
tree op2) OVERRIDE;
-private:
+protected:
relation_oracle *m_oracle;
};
@@ -188,6 +190,5 @@ protected:
void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *,
fur_source &src);
void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src);
- void postfold_gcond_edges (gcond *s, irange &lhs_range, fur_source &src);
};
#endif // GCC_GIMPLE_RANGE_FOLD_H
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index f788295..6946fa6 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -565,6 +565,9 @@ gori_map::calculate_gori (basic_block bb)
}
else
{
+ // Do not process switches if they are too large.
+ if (EDGE_COUNT (bb->succs) > (unsigned)param_evrp_switch_limit)
+ return;
gswitch *gs = as_a<gswitch *>(stmt);
name = gimple_range_ssa_p (gimple_switch_index (gs));
maybe_add_gori (name, gimple_bb (stmt));
@@ -634,8 +637,10 @@ debug (gori_map &g)
// Construct a gori_compute object.
-gori_compute::gori_compute () : tracer ("GORI ")
+gori_compute::gori_compute (int not_executable_flag)
+ : outgoing (param_evrp_switch_limit), tracer ("GORI ")
{
+ m_not_executable_flag = not_executable_flag;
// Create a boolean_type true and false range.
m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node);
m_bool_one = int_range<2> (boolean_true_node, boolean_true_node);
@@ -1214,6 +1219,15 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
int_range_max lhs;
unsigned idx;
+ if ((e->flags & m_not_executable_flag))
+ {
+ r.set_undefined ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Outgoing edge %d->%d unexecutable.\n",
+ e->src->index, e->dest->index);
+ return true;
+ }
+
gcc_checking_assert (gimple_range_ssa_p (name));
// Determine if there is an outgoing edge.
gimple *stmt = outgoing.edge_range_p (lhs, e);
@@ -1221,22 +1235,6 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
return false;
fur_stmt src (stmt, &q);
-
- // If this edge is never taken, return undefined.
- gcond *gc = dyn_cast<gcond *> (stmt);
- if (gc)
- {
- if (((e->flags & EDGE_TRUE_VALUE) && gimple_cond_false_p (gc))
- || ((e->flags & EDGE_FALSE_VALUE) && gimple_cond_true_p (gc)))
- {
- r.set_undefined ();
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Outgoing edge %d->%d unexecutable.\n",
- e->src->index, e->dest->index);
- return true;
- }
- }
-
// If NAME can be calculated on the edge, use that.
if (is_export_p (name, e->src))
{
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 688468c..ec0b951 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -147,12 +147,16 @@ private:
// expr_range_in_bb is simply a wrapper which calls ssa_range_in_bb for
// SSA_NAMES and otherwise simply calculates the range of the expression.
//
+// The constructor takes a flag value to use on edges to check for the
+// NON_EXECUTABLE_EDGE property. The zero default means no flag is checked.
+// All value requests from NON_EXECUTABLE_EDGE edges are returned UNDEFINED.
+//
// The remaining routines are internal use only.
class gori_compute : public gori_map
{
public:
- gori_compute ();
+ gori_compute (int not_executable_flag = 0);
bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
bool has_edge_range_p (tree name, edge e = NULL);
void dump (FILE *f);
@@ -181,6 +185,7 @@ private:
gimple_outgoing_range outgoing; // Edge values for COND_EXPR & SWITCH_EXPR.
range_tracer tracer;
+ int m_not_executable_flag;
};
// These routines provide a GIMPLE interface to the range-ops code.
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index a8226a6..6942713 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -30,22 +30,27 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "gimple-range-path.h"
#include "ssa.h"
+#include "tree-cfg.h"
+#include "gimple-iterator.h"
// Internal construct to help facilitate debugging of solver.
-#define DEBUG_SOLVER (0 && dump_file)
+#define DEBUG_SOLVER (dump_file && dump_flags & TDF_THREADING)
-path_range_query::path_range_query (gimple_ranger &ranger)
+path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
: m_ranger (ranger)
{
m_cache = new ssa_global_cache;
m_has_cache_entry = BITMAP_ALLOC (NULL);
m_path = NULL;
+ m_resolve = resolve;
+ m_oracle = new path_oracle (ranger.oracle ());
}
path_range_query::~path_range_query ()
{
BITMAP_FREE (m_has_cache_entry);
delete m_cache;
+ delete m_oracle;
}
// Mark cache entry for NAME as unused.
@@ -85,14 +90,15 @@ path_range_query::set_cache (const irange &r, tree name)
void
path_range_query::dump (FILE *dump_file)
{
+ push_dump_file save (dump_file, dump_flags & ~TDF_DETAILS);
+
if (m_path->is_empty ())
return;
unsigned i;
bitmap_iterator bi;
- extern void dump_ranger (FILE *, const vec<basic_block> &);
- fprintf (dump_file, "Path is:\n");
+ fprintf (dump_file, "\nPath is (length=%d):\n", m_path->length ());
dump_ranger (dump_file, *m_path);
fprintf (dump_file, "Imports:\n");
@@ -112,10 +118,48 @@ path_range_query::debug ()
dump (stderr);
}
+// Return TRUE if NAME is defined outside the current path.
+
+bool
+path_range_query::defined_outside_path (tree name)
+{
+ gimple *def = SSA_NAME_DEF_STMT (name);
+ basic_block bb = gimple_bb (def);
+
+ return !bb || !m_path->contains (bb);
+}
+
+// Return the range of NAME on entry to the path.
+
+void
+path_range_query::range_on_path_entry (irange &r, tree name)
+{
+ gcc_checking_assert (defined_outside_path (name));
+ int_range_max tmp;
+ basic_block entry = entry_bb ();
+ bool changed = false;
+
+ r.set_undefined ();
+ for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i)
+ {
+ edge e = EDGE_PRED (entry, i);
+ if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
+ && m_ranger.range_on_edge (tmp, e, name))
+ {
+ r.union_ (tmp);
+ changed = true;
+ }
+ }
+
+ // Make sure we don't return UNDEFINED by mistake.
+ if (!changed)
+ r.set_varying (TREE_TYPE (name));
+}
+
// Return the range of NAME at the end of the path being analyzed.
bool
-path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
+path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
{
if (!irange::supports_type_p (TREE_TYPE (name)))
return false;
@@ -123,10 +167,19 @@ path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
if (get_cache (r, name))
return true;
+ if (m_resolve && defined_outside_path (name))
+ {
+ range_on_path_entry (r, name);
+ set_cache (r, name);
+ return true;
+ }
basic_block bb = stmt ? gimple_bb (stmt) : exit_bb ();
if (stmt && range_defined_in_block (r, name, bb))
{
+ if (TREE_CODE (name) == SSA_NAME)
+ r.intersect (gimple_range_global (name));
+
set_cache (r, name);
return true;
}
@@ -135,22 +188,23 @@ path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
return true;
}
-// Return the range of STMT at the end of the path being analyzed.
-// Anything but the final conditional in a BB will return VARYING.
-
bool
-path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
+path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
{
- tree type = gimple_range_type (stmt);
-
- if (!irange::supports_type_p (type))
- return false;
+ if (internal_range_of_expr (r, name, stmt))
+ {
+ if (r.undefined_p ())
+ m_undefined_path = true;
- if (gimple_code (stmt) == GIMPLE_COND && fold_range (r, stmt, this))
- return true;
+ return true;
+ }
+ return false;
+}
- r.set_varying (type);
- return true;
+bool
+path_range_query::unreachable_path_p ()
+{
+ return m_undefined_path;
}
// Initialize the current path to PATH. The current block is set to
@@ -176,10 +230,11 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
tree name = gimple_phi_result (phi);
basic_block bb = gimple_bb (phi);
- // We experimented with querying ranger's range_on_entry here, but
- // the performance penalty was too high, for hardly any improvements.
if (at_entry ())
{
+ if (m_resolve && m_ranger.range_of_expr (r, name, phi))
+ return;
+
// Try fold just in case we can resolve simple things like PHI <5(99), 6(88)>.
if (!fold_range (r, phi, this))
r.set_varying (TREE_TYPE (name));
@@ -197,8 +252,23 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
tree arg = gimple_phi_arg_def (phi, i);
if (!get_cache (r, arg))
- r.set_varying (TREE_TYPE (name));
-
+ {
+ if (m_resolve)
+ {
+ int_range_max tmp;
+ // Using both the range on entry to the path, and the
+ // range on this edge yields significantly better
+ // results.
+ if (defined_outside_path (arg))
+ range_on_path_entry (r, arg);
+ else
+ r.set_varying (TREE_TYPE (name));
+ m_ranger.range_on_edge (tmp, e_in, arg);
+ r.intersect (tmp);
+ return;
+ }
+ r.set_varying (TREE_TYPE (name));
+ }
return;
}
gcc_unreachable ();
@@ -218,25 +288,29 @@ path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
if (gimple_code (def_stmt) == GIMPLE_PHI)
ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
- else if (!fold_range (r, def_stmt, this))
+ else if (!range_of_stmt (r, def_stmt, name))
r.set_varying (TREE_TYPE (name));
- if (DEBUG_SOLVER)
+ if (bb)
+ m_non_null.adjust_range (r, name, bb);
+
+ if (DEBUG_SOLVER && (bb || !r.varying_p ()))
{
- fprintf (dump_file, "range_defined_in_block (BB%d) for ", bb->index);
+ fprintf (dump_file, "range_defined_in_block (BB%d) for ", bb ? bb->index : -1);
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, " is ");
r.dump (dump_file);
fprintf (dump_file, "\n");
}
+
return true;
}
-// Precompute ranges defined in the current block, or ranges
-// that are exported on an edge to the next block.
+// Compute ranges defined in the current block, or exported to the
+// next block.
void
-path_range_query::precompute_ranges_in_block (basic_block bb)
+path_range_query::compute_ranges_in_block (basic_block bb)
{
bitmap_iterator bi;
int_range_max r, cached_range;
@@ -297,26 +371,154 @@ path_range_query::precompute_ranges_in_block (basic_block bb)
}
}
-// Precompute the ranges for IMPORTS along PATH.
+// Adjust all pointer imports in BB with non-null information.
+
+void
+path_range_query::adjust_for_non_null_uses (basic_block bb)
+{
+ int_range_max r;
+ bitmap_iterator bi;
+ unsigned i;
+
+ EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
+ {
+ tree name = ssa_name (i);
+
+ if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ continue;
+
+ if (get_cache (r, name))
+ {
+ if (r.nonzero_p ())
+ continue;
+ }
+ else
+ r.set_varying (TREE_TYPE (name));
+
+ if (m_non_null.adjust_range (r, name, bb))
+ set_cache (r, name);
+ }
+}
+
+// If NAME is a supported SSA_NAME, add it the bitmap in IMPORTS.
+
+bool
+path_range_query::add_to_imports (tree name, bitmap imports)
+{
+ if (TREE_CODE (name) == SSA_NAME
+ && irange::supports_type_p (TREE_TYPE (name)))
+ return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
+ return false;
+}
+
+// Add the copies of any SSA names in IMPORTS to IMPORTS.
+//
+// These are hints for the solver. Adding more elements (within
+// reason) doesn't slow us down, because we don't solve anything that
+// doesn't appear in the path. On the other hand, not having enough
+// imports will limit what we can solve.
+
+void
+path_range_query::add_copies_to_imports ()
+{
+ auto_vec<tree> worklist (bitmap_count_bits (m_imports));
+ bitmap_iterator bi;
+ unsigned i;
+
+ EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
+ {
+ tree name = ssa_name (i);
+ worklist.quick_push (name);
+ }
+
+ while (!worklist.is_empty ())
+ {
+ tree name = worklist.pop ();
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+
+ if (is_gimple_assign (def_stmt))
+ {
+ // ?? Adding assignment copies doesn't get us much. At the
+ // time of writing, we got 63 more threaded paths across the
+ // .ii files from a bootstrap.
+ add_to_imports (gimple_assign_rhs1 (def_stmt), m_imports);
+ tree rhs = gimple_assign_rhs2 (def_stmt);
+ if (rhs && add_to_imports (rhs, m_imports))
+ worklist.safe_push (rhs);
+ rhs = gimple_assign_rhs3 (def_stmt);
+ if (rhs && add_to_imports (rhs, m_imports))
+ worklist.safe_push (rhs);
+ }
+ else if (gphi *phi = dyn_cast <gphi *> (def_stmt))
+ {
+ for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
+ {
+ edge e = gimple_phi_arg_edge (phi, i);
+ tree arg = gimple_phi_arg (phi, i)->def;
+
+ if (TREE_CODE (arg) == SSA_NAME
+ && m_path->contains (e->src)
+ && bitmap_set_bit (m_imports, SSA_NAME_VERSION (arg)))
+ worklist.safe_push (arg);
+ }
+ }
+ }
+}
+
+// Compute the ranges for IMPORTS along PATH.
//
// IMPORTS are the set of SSA names, any of which could potentially
// change the value of the final conditional in PATH.
void
-path_range_query::precompute_ranges (const vec<basic_block> &path,
- const bitmap_head *imports)
+path_range_query::compute_ranges (const vec<basic_block> &path,
+ const bitmap_head *imports)
{
+ if (DEBUG_SOLVER)
+ fprintf (dump_file, "\n*********** path_range_query ******************\n");
+
set_path (path);
- m_imports = imports;
+ bitmap_copy (m_imports, imports);
+ m_undefined_path = false;
+
+ if (m_resolve)
+ {
+ add_copies_to_imports ();
+ get_path_oracle ()->reset_path ();
+ compute_relations (path);
+ }
if (DEBUG_SOLVER)
- fprintf (dump_file, "path_range_query: precompute_ranges\n");
+ {
+ fprintf (dump_file, "\npath_range_query: compute_ranges for path: ");
+ for (unsigned i = path.length (); i > 0; --i)
+ {
+ basic_block bb = path[i - 1];
+ fprintf (dump_file, "BB %d", bb->index);
+ if (i > 1)
+ fprintf (dump_file, ", ");
+ }
+ fprintf (dump_file, "\n");
+ }
while (1)
{
basic_block bb = curr_bb ();
- precompute_ranges_in_block (bb);
+ if (m_resolve)
+ {
+ gori_compute &gori = m_ranger.gori ();
+ tree name;
+
+ // Exported booleans along the path, may help conditionals.
+ // Add them as interesting imports.
+ FOR_EACH_GORI_EXPORT_NAME (gori, bb, name)
+ if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
+ bitmap_set_bit (m_imports, SSA_NAME_VERSION (name));
+ }
+
+ compute_ranges_in_block (bb);
+ adjust_for_non_null_uses (bb);
if (at_exit ())
break;
@@ -327,3 +529,178 @@ path_range_query::precompute_ranges (const vec<basic_block> &path,
if (DEBUG_SOLVER)
dump (dump_file);
}
+
+// A folding aid used to register and query relations along a path.
+// When queried, it returns relations as they would appear on exit to
+// the path.
+//
+// Relations are registered on entry so the path_oracle knows which
+// block to query the root oracle at when a relation lies outside the
+// path. However, when queried we return the relation on exit to the
+// path, since the root_oracle ignores the registered.
+
+class jt_fur_source : public fur_depend
+{
+public:
+ jt_fur_source (gimple *s, path_range_query *, gori_compute *,
+ const vec<basic_block> &);
+ relation_kind query_relation (tree op1, tree op2) override;
+ void register_relation (gimple *, relation_kind, tree op1, tree op2) override;
+ void register_relation (edge, relation_kind, tree op1, tree op2) override;
+private:
+ basic_block m_entry;
+};
+
+jt_fur_source::jt_fur_source (gimple *s,
+ path_range_query *query,
+ gori_compute *gori,
+ const vec<basic_block> &path)
+ : fur_depend (s, gori, query)
+{
+ gcc_checking_assert (!path.is_empty ());
+
+ m_entry = path[path.length () - 1];
+
+ if (dom_info_available_p (CDI_DOMINATORS))
+ m_oracle = query->oracle ();
+ else
+ m_oracle = NULL;
+}
+
+// Ignore statement and register relation on entry to path.
+
+void
+jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
+{
+ if (m_oracle)
+ m_oracle->register_relation (m_entry, k, op1, op2);
+}
+
+// Ignore edge and register relation on entry to path.
+
+void
+jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
+{
+ if (m_oracle)
+ m_oracle->register_relation (m_entry, k, op1, op2);
+}
+
+relation_kind
+jt_fur_source::query_relation (tree op1, tree op2)
+{
+ if (!m_oracle)
+ return VREL_NONE;
+
+ if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
+ return VREL_NONE;
+
+ return m_oracle->query_relation (m_entry, op1, op2);
+}
+
+// Return the range of STMT at the end of the path being analyzed.
+
+bool
+path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
+{
+ tree type = gimple_range_type (stmt);
+
+ if (!irange::supports_type_p (type))
+ return false;
+
+ // If resolving unknowns, fold the statement as it would have
+ // appeared at the end of the path.
+ if (m_resolve)
+ {
+ fold_using_range f;
+ jt_fur_source src (stmt, this, &m_ranger.gori (), *m_path);
+ if (!f.fold_stmt (r, stmt, src))
+ r.set_varying (type);
+ }
+ // Otherwise, use the global ranger to fold it as it would appear in
+ // the original IL. This is more conservative, but faster.
+ else if (!fold_range (r, stmt, this))
+ r.set_varying (type);
+
+ return true;
+}
+
+// Compute relations on a path. This involves two parts: relations
+// along the conditionals joining a path, and relations determined by
+// examining PHIs.
+
+void
+path_range_query::compute_relations (const vec<basic_block> &path)
+{
+ if (!dom_info_available_p (CDI_DOMINATORS))
+ return;
+
+ jt_fur_source src (NULL, this, &m_ranger.gori (), path);
+ basic_block prev = NULL;
+ for (unsigned i = path.length (); i > 0; --i)
+ {
+ basic_block bb = path[i - 1];
+ gimple *stmt = last_stmt (bb);
+
+ compute_phi_relations (bb, prev);
+
+ // Compute relations in outgoing edges along the path. Skip the
+ // final conditional which we don't know yet.
+ if (i > 1
+ && stmt
+ && gimple_code (stmt) == GIMPLE_COND
+ && irange::supports_type_p (TREE_TYPE (gimple_cond_lhs (stmt))))
+ {
+ basic_block next = path[i - 2];
+ int_range<2> r;
+ gcond *cond = as_a<gcond *> (stmt);
+ edge e0 = EDGE_SUCC (bb, 0);
+ edge e1 = EDGE_SUCC (bb, 1);
+
+ if (e0->dest == next)
+ gcond_edge_range (r, e0);
+ else if (e1->dest == next)
+ gcond_edge_range (r, e1);
+ else
+ gcc_unreachable ();
+
+ src.register_outgoing_edges (cond, r, e0, e1);
+ }
+ prev = bb;
+ }
+}
+
+// Compute relations for each PHI in BB. For example:
+//
+// x_5 = PHI<y_9(5),...>
+//
+// If the path flows through BB5, we can register that x_5 == y_9.
+
+void
+path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
+{
+ if (prev == NULL)
+ return;
+
+ basic_block entry = entry_bb ();
+ edge e_in = find_edge (prev, bb);
+ gcc_checking_assert (e_in);
+
+ for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
+ gsi_next (&iter))
+ {
+ gphi *phi = iter.phi ();
+ tree result = gimple_phi_result (phi);
+ unsigned nargs = gimple_phi_num_args (phi);
+
+ for (size_t i = 0; i < nargs; ++i)
+ if (e_in == gimple_phi_arg_edge (phi, i))
+ {
+ tree arg = gimple_phi_arg_def (phi, i);
+
+ if (gimple_range_ssa_p (arg))
+ m_oracle->register_relation (entry, EQ_EXPR, arg, result);
+
+ break;
+ }
+ }
+}
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index 0d2d2e7..5f4e73a 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -26,34 +26,41 @@ along with GCC; see the file COPYING3. If not see
// will calculate the range of an SSA or STMT as if the BBs in the
// path would have been executed in order.
//
-// Only SSA names passed in IMPORTS are precomputed, and can be
-// queried.
-//
// Note that the blocks are in reverse order, thus the exit block is
// path[0].
class path_range_query : public range_query
{
public:
- path_range_query (class gimple_ranger &ranger);
+ path_range_query (class gimple_ranger &ranger, bool resolve);
virtual ~path_range_query ();
- void precompute_ranges (const vec<basic_block> &path,
- const bitmap_head *imports);
+ void compute_ranges (const vec<basic_block> &, const bitmap_head *imports);
bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
+ bool unreachable_path_p ();
void dump (FILE *) override;
void debug ();
private:
+ bool internal_range_of_expr (irange &r, tree name, gimple *);
+ bool defined_outside_path (tree name);
+ void range_on_path_entry (irange &r, tree name);
+ path_oracle *get_path_oracle () { return (path_oracle *)m_oracle; }
+
// Cache manipulation.
void set_cache (const irange &r, tree name);
bool get_cache (irange &r, tree name);
void clear_cache (tree name);
- // Methods to precompute ranges for the given path.
+ // Methods to compute ranges for the given path.
bool range_defined_in_block (irange &, tree name, basic_block bb);
- void precompute_ranges_in_block (basic_block bb);
+ void compute_ranges_in_block (basic_block bb);
+ void adjust_for_non_null_uses (basic_block bb);
void ssa_range_in_phi (irange &r, gphi *phi);
+ void compute_relations (const vec<basic_block> &);
+ void compute_phi_relations (basic_block bb, basic_block prev);
+ void add_copies_to_imports ();
+ bool add_to_imports (tree name, bitmap imports);
// Path navigation.
void set_path (const vec<basic_block> &);
@@ -75,11 +82,18 @@ private:
// Path being analyzed.
const vec<basic_block> *m_path;
+ auto_bitmap m_imports;
+ gimple_ranger &m_ranger;
+ non_null_ref m_non_null;
+
// Current path position.
unsigned m_pos;
- const bitmap_head *m_imports;
- gimple_ranger &m_ranger;
+ // Use ranger to resolve anything not known on entry.
+ bool m_resolve;
+
+ // Set if there were any undefined expressions while pre-calculating path.
+ bool m_undefined_path;
};
#endif // GCC_TREE_SSA_THREADSOLVER_H
diff --git a/gcc/gimple-range-trace.cc b/gcc/gimple-range-trace.cc
index 1feb978..2417c21 100644
--- a/gcc/gimple-range-trace.cc
+++ b/gcc/gimple-range-trace.cc
@@ -130,7 +130,7 @@ range_tracer::trailer (unsigned counter, const char *caller, bool result,
// Query all statements in the IL to precalculate computable ranges in RANGER.
-static DEBUG_FUNCTION void
+DEBUG_FUNCTION void
debug_seed_ranger (gimple_ranger &ranger)
{
// Recalculate SCEV to make sure the dump lists everything.
@@ -155,12 +155,37 @@ debug_seed_ranger (gimple_ranger &ranger)
}
}
+// Change the current dump_file and dump_flags to F and FLAGS while
+// saving them for later restoring.
+
+push_dump_file::push_dump_file (FILE *f, dump_flags_t flags)
+{
+ old_dump_file = dump_file;
+ old_dump_flags = dump_flags;
+ dump_file = f;
+ dump_flags = flags;
+}
+
+// Restore saved dump_file and dump_flags.
+
+push_dump_file::~push_dump_file ()
+{
+ dump_file = old_dump_file;
+ dump_flags = old_dump_flags;
+}
+
// Dump all that ranger knows for the current function.
-DEBUG_FUNCTION void
+void
dump_ranger (FILE *out)
{
+ push_dump_file save (out, dump_flags);
gimple_ranger ranger;
+
+ fprintf (out, ";; Function ");
+ print_generic_expr (out, current_function_decl);
+ fprintf (out, "\n");
+
debug_seed_ranger (ranger);
ranger.dump (out);
}
@@ -176,7 +201,7 @@ debug_ranger ()
// Note that the blocks are in reverse order, thus the exit block is
// path[0].
-DEBUG_FUNCTION void
+void
dump_ranger (FILE *dump_file, const vec<basic_block> &path)
{
if (path.length () == 0)
diff --git a/gcc/gimple-range-trace.h b/gcc/gimple-range-trace.h
index d2d1a8b..d3e69e0 100644
--- a/gcc/gimple-range-trace.h
+++ b/gcc/gimple-range-trace.h
@@ -58,4 +58,21 @@ range_tracer::header (const char *str)
return do_header (str);
return 0;
}
+
+// RAII class to change current dump_file and dump_flags, and restore
+// when the object goes out of scope.
+
+class push_dump_file
+{
+public:
+ push_dump_file (FILE *, dump_flags_t);
+ ~push_dump_file ();
+private:
+ FILE *old_dump_file;
+ dump_flags_t old_dump_flags;
+};
+
+void dump_ranger (FILE *);
+void dump_ranger (FILE *, const vec<basic_block> &path);
+
#endif // GCC_GIMPLE_RANGE_TRACE_H
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index d74cea3..85ef974 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -35,12 +35,28 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "gimple-range.h"
-gimple_ranger::gimple_ranger () : tracer ("")
+gimple_ranger::gimple_ranger () :
+ non_executable_edge_flag (cfun),
+ m_cache (non_executable_edge_flag),
+ tracer ("")
{
// If the cache has a relation oracle, use it.
m_oracle = m_cache.oracle ();
if (dump_file && (param_evrp_mode & EVRP_MODE_TRACE))
tracer.enable_trace ();
+
+ // Ensure the not_executable flag is clear everywhere.
+ if (flag_checking)
+ {
+ basic_block bb;
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ gcc_checking_assert ((e->flags & non_executable_edge_flag) == 0);
+ }
+ }
}
bool
@@ -164,9 +180,9 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
int_range_max edge_range;
gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
- // PHI arguments can be constants, catch these here.
- if (!gimple_range_ssa_p (name))
- return range_of_expr (r, name);
+ // Do not process values along abnormal or EH edges.
+ if (e->flags & (EDGE_ABNORMAL|EDGE_EH))
+ return false;
unsigned idx;
if ((idx = tracer.header ("range_on_edge (")))
@@ -175,16 +191,32 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
fprintf (dump_file, ") on edge %d->%d\n", e->src->index, e->dest->index);
}
- range_on_exit (r, e->src, name);
- gcc_checking_assert (r.undefined_p ()
- || range_compatible_p (r.type(), TREE_TYPE (name)));
+ // Check to see if the edge is executable.
+ if ((e->flags & non_executable_edge_flag))
+ {
+ r.set_undefined ();
+ if (idx)
+ tracer.trailer (idx, "range_on_edge [Unexecutable] ", true,
+ name, r);
+ return true;
+ }
- // Check to see if NAME is defined on edge e.
- if (m_cache.range_on_edge (edge_range, e, name))
- r.intersect (edge_range);
+ bool res = true;
+ if (!gimple_range_ssa_p (name))
+ res = range_of_expr (r, name);
+ else
+ {
+ range_on_exit (r, e->src, name);
+ gcc_checking_assert (r.undefined_p ()
+ || range_compatible_p (r.type(), TREE_TYPE (name)));
+
+ // Check to see if NAME is defined on edge e.
+ if (m_cache.range_on_edge (edge_range, e, name))
+ r.intersect (edge_range);
+ }
if (idx)
- tracer.trailer (idx, "range_on_edge", true, name, r);
+ tracer.trailer (idx, "range_on_edge", res, name, r);
return true;
}
@@ -384,6 +416,12 @@ gimple_ranger::dump (FILE *f)
m_cache.dump (f);
}
+void
+gimple_ranger::debug ()
+{
+ dump (stderr);
+}
+
/* Create a new ranger instance and associate it with function FUN.
Each call must be paired with a call to disable_ranger to release
resources. */
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index eaebb9c5..0713af4 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -55,7 +55,9 @@ public:
void export_global_ranges ();
inline gori_compute &gori () { return m_cache.m_gori; }
virtual void dump (FILE *f) OVERRIDE;
+ void debug ();
void dump_bb (FILE *f, basic_block bb);
+ auto_edge_flag non_executable_edge_flag;
protected:
bool fold_range_internal (irange &r, gimple *s, tree name);
ranger_cache m_cache;
diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index 0a70a1e..4cf82e6 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -38,13 +38,6 @@ class evrp_range_analyzer : public vr_values
/* Record a new unwindable range. */
void push_value_range (tree var, value_range_equiv *vr);
- /* A bit of a wart. This should ideally go away. */
- void vrp_visit_cond_stmt (gcond *cond, edge *e)
- {
- simplify_using_ranges simpl (this);
- simpl.vrp_visit_cond_stmt (cond, e);
- }
-
private:
DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 61de501..7f20555 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -43,299 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-ssa-evrp-analyze.h"
#include "gimple-range.h"
#include "fold-const.h"
-
-// Unwindable SSA equivalence table for pointers.
-//
-// The main query point is get_replacement() which returns what a
-// given SSA can be replaced with in the current scope.
-
-class ssa_equiv_stack
-{
-public:
- ssa_equiv_stack ();
- void enter (basic_block);
- void leave (basic_block);
- void push_replacement (tree name, tree replacement);
- tree get_replacement (tree name) const;
-
-private:
- auto_vec<std::pair <tree, tree>> m_stack;
- auto_vec<tree> m_replacements;
- const std::pair <tree, tree> m_marker = std::make_pair (NULL, NULL);
-};
-
-ssa_equiv_stack::ssa_equiv_stack ()
-{
- m_replacements.safe_grow_cleared (num_ssa_names);
-}
-
-// Pushes a marker at the given point.
-
-void
-ssa_equiv_stack::enter (basic_block)
-{
- m_stack.safe_push (m_marker);
-}
-
-// Pops the stack to the last marker, while performing replacements
-// along the way.
-
-void
-ssa_equiv_stack::leave (basic_block)
-{
- gcc_checking_assert (!m_stack.is_empty ());
- while (m_stack.last () != m_marker)
- {
- std::pair<tree, tree> e = m_stack.pop ();
- m_replacements[SSA_NAME_VERSION (e.first)] = e.second;
- }
- m_stack.pop ();
-}
-
-// Set the equivalence of NAME to REPLACEMENT.
-
-void
-ssa_equiv_stack::push_replacement (tree name, tree replacement)
-{
- tree old = m_replacements[SSA_NAME_VERSION (name)];
- m_replacements[SSA_NAME_VERSION (name)] = replacement;
- m_stack.safe_push (std::make_pair (name, old));
-}
-
-// Return the equivalence of NAME.
-
-tree
-ssa_equiv_stack::get_replacement (tree name) const
-{
- return m_replacements[SSA_NAME_VERSION (name)];
-}
-
-// Return TRUE if EXPR is an SSA holding a pointer.
-
-static bool inline
-is_pointer_ssa (tree expr)
-{
- return TREE_CODE (expr) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (expr));
-}
-
-// Simple context-aware pointer equivalency analyzer that returns what
-// a pointer SSA name is equivalent to at a given point during a walk
-// of the IL.
-//
-// Note that global equivalency take priority over conditional
-// equivalency. That is, p = &q takes priority over a later p == &t.
-//
-// This class is meant to be called during a DOM walk.
-
-class pointer_equiv_analyzer
-{
-public:
- pointer_equiv_analyzer (gimple_ranger *r);
- ~pointer_equiv_analyzer ();
- void enter (basic_block);
- void leave (basic_block);
- void visit_stmt (gimple *stmt);
- tree get_equiv (tree ssa) const;
-
-private:
- void visit_edge (edge e);
- tree get_equiv_expr (tree_code code, tree expr) const;
- void set_global_equiv (tree ssa, tree pointee);
- void set_cond_equiv (tree ssa, tree pointee);
-
- gimple_ranger *m_ranger;
- // Global pointer equivalency indexed by SSA_NAME_VERSION.
- tree *m_global_points;
- // Conditional pointer equivalency.
- ssa_equiv_stack m_cond_points;
-};
-
-pointer_equiv_analyzer::pointer_equiv_analyzer (gimple_ranger *r)
-{
- m_ranger = r;
- m_global_points = new tree[num_ssa_names] ();
-}
-
-pointer_equiv_analyzer::~pointer_equiv_analyzer ()
-{
- delete[] m_global_points;
-}
-
-// Set the global pointer equivalency for SSA to POINTEE.
-
-void
-pointer_equiv_analyzer::set_global_equiv (tree ssa, tree pointee)
-{
- m_global_points[SSA_NAME_VERSION (ssa)] = pointee;
-}
-
-// Set the conditional pointer equivalency for SSA to POINTEE.
-
-void
-pointer_equiv_analyzer::set_cond_equiv (tree ssa, tree pointee)
-{
- m_cond_points.push_replacement (ssa, pointee);
-}
-
-// Return the current pointer equivalency info for SSA, or NULL if
-// none is available. Note that global info takes priority over
-// conditional info.
-
-tree
-pointer_equiv_analyzer::get_equiv (tree ssa) const
-{
- tree ret = m_global_points[SSA_NAME_VERSION (ssa)];
- if (ret)
- return ret;
- return m_cond_points.get_replacement (ssa);
-}
-
-// Method to be called on entry to a BB.
-
-void
-pointer_equiv_analyzer::enter (basic_block bb)
-{
- m_cond_points.enter (bb);
-
- for (gphi_iterator iter = gsi_start_phis (bb);
- !gsi_end_p (iter);
- gsi_next (&iter))
- {
- gphi *phi = iter.phi ();
- tree lhs = gimple_phi_result (phi);
- if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
- continue;
- tree arg0 = gimple_phi_arg_def (phi, 0);
- if (TREE_CODE (arg0) == SSA_NAME && !is_gimple_min_invariant (arg0))
- arg0 = get_equiv (arg0);
- if (arg0 && is_gimple_min_invariant (arg0))
- {
- // If all the PHI args point to the same place, set the
- // pointer equivalency info for the PHI result. This can
- // happen for passes that create redundant PHIs like
- // PHI<&foo, &foo> or PHI<&foo>.
- for (size_t i = 1; i < gimple_phi_num_args (phi); ++i)
- {
- tree argi = gimple_phi_arg_def (phi, i);
- if (TREE_CODE (argi) == SSA_NAME
- && !is_gimple_min_invariant (argi))
- argi = get_equiv (argi);
- if (!argi || !operand_equal_p (arg0, argi))
- return;
- }
- set_global_equiv (lhs, arg0);
- }
- }
-
- edge pred = single_pred_edge_ignoring_loop_edges (bb, false);
- if (pred)
- visit_edge (pred);
-}
-
-// Method to be called on exit from a BB.
-
-void
-pointer_equiv_analyzer::leave (basic_block bb)
-{
- m_cond_points.leave (bb);
-}
-
-// Helper function to return the pointer equivalency information for
-// EXPR from a gimple statement with CODE. This returns either the
-// cached pointer equivalency info for an SSA, or an invariant in case
-// EXPR is one (i.e. &foo). Returns NULL if EXPR is neither an SSA
-// nor an invariant.
-
-tree
-pointer_equiv_analyzer::get_equiv_expr (tree_code code, tree expr) const
-{
- if (code == SSA_NAME)
- return get_equiv (expr);
-
- if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
- && is_gimple_min_invariant (expr))
- return expr;
-
- return NULL;
-}
-
-// Hack to provide context to the gimple fold callback.
-static struct
-{
- gimple *m_stmt;
- gimple_ranger *m_ranger;
- pointer_equiv_analyzer *m_pta;
-} x_fold_context;
-
-// Gimple fold callback.
-static tree
-pta_valueize (tree name)
-{
- tree ret
- = x_fold_context.m_ranger->value_of_expr (name, x_fold_context.m_stmt);
-
- if (!ret && is_pointer_ssa (name))
- ret = x_fold_context.m_pta->get_equiv (name);
-
- return ret ? ret : name;
-}
-
-// Method to be called on gimple statements during traversal of the IL.
-
-void
-pointer_equiv_analyzer::visit_stmt (gimple *stmt)
-{
- if (gimple_code (stmt) != GIMPLE_ASSIGN)
- return;
-
- tree lhs = gimple_assign_lhs (stmt);
- if (!is_pointer_ssa (lhs))
- return;
-
- tree rhs = gimple_assign_rhs1 (stmt);
- rhs = get_equiv_expr (gimple_assign_rhs_code (stmt), rhs);
- if (rhs)
- {
- set_global_equiv (lhs, rhs);
- return;
- }
-
- // If we couldn't find anything, try fold.
- x_fold_context = { stmt, m_ranger, this};
- rhs = gimple_fold_stmt_to_constant_1 (stmt, pta_valueize, pta_valueize);
- if (rhs)
- {
- rhs = get_equiv_expr (TREE_CODE (rhs), rhs);
- if (rhs)
- {
- set_global_equiv (lhs, rhs);
- return;
- }
- }
-}
-
-// If the edge in E is a conditional that sets a pointer equality, set the
-// conditional pointer equivalency information.
-
-void
-pointer_equiv_analyzer::visit_edge (edge e)
-{
- gimple *stmt = last_stmt (e->src);
- tree lhs;
- // Recognize: x_13 [==,!=] &foo.
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND
- && (lhs = gimple_cond_lhs (stmt))
- && TREE_CODE (lhs) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (lhs))
- && TREE_CODE (gimple_cond_rhs (stmt)) == ADDR_EXPR)
- {
- tree_code code = gimple_cond_code (stmt);
- if ((code == EQ_EXPR && e->flags & EDGE_TRUE_VALUE)
- || ((code == NE_EXPR && e->flags & EDGE_FALSE_VALUE)))
- set_cond_equiv (lhs, gimple_cond_rhs (stmt));
- }
-}
+#include "value-pointer-equiv.h"
// This is the classic EVRP folder which uses a dominator walk and pushes
// ranges into the next block if it is a single predecessor block.
@@ -413,7 +121,7 @@ public:
rvrp_folder () : substitute_and_fold_engine (), m_simplifier ()
{
m_ranger = enable_ranger (cfun);
- m_simplifier.set_range_query (m_ranger);
+ m_simplifier.set_range_query (m_ranger, m_ranger->non_executable_edge_flag);
m_pta = new pointer_equiv_analyzer (m_ranger);
}
@@ -429,22 +137,31 @@ public:
tree value_of_expr (tree name, gimple *s = NULL) OVERRIDE
{
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
tree ret = m_ranger->value_of_expr (name, s);
- if (!ret && is_pointer_ssa (name))
+ if (!ret && supported_pointer_equiv_p (name))
ret = m_pta->get_equiv (name);
return ret;
}
tree value_on_edge (edge e, tree name) OVERRIDE
{
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
tree ret = m_ranger->value_on_edge (e, name);
- if (!ret && is_pointer_ssa (name))
+ if (!ret && supported_pointer_equiv_p (name))
ret = m_pta->get_equiv (name);
return ret;
}
tree value_of_stmt (gimple *s, tree name = NULL) OVERRIDE
{
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
return m_ranger->value_of_stmt (s, name);
}
@@ -497,12 +214,16 @@ public:
if (evrp_first)
{
first = &m_range_analyzer;
+ first_exec_flag = 0;
second = m_ranger;
+ second_exec_flag = m_ranger->non_executable_edge_flag;
}
else
{
first = m_ranger;
+ first_exec_flag = m_ranger->non_executable_edge_flag;
second = &m_range_analyzer;
+ second_exec_flag = 0;
}
m_pta = new pointer_equiv_analyzer (m_ranger);
}
@@ -519,11 +240,11 @@ public:
bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
{
- simplifier.set_range_query (first);
+ simplifier.set_range_query (first, first_exec_flag);
if (simplifier.simplify (gsi))
return true;
- simplifier.set_range_query (second);
+ simplifier.set_range_query (second, second_exec_flag);
if (simplifier.simplify (gsi))
{
if (dump_file)
@@ -559,7 +280,9 @@ private:
DISABLE_COPY_AND_ASSIGN (hybrid_folder);
gimple_ranger *m_ranger;
range_query *first;
+ int first_exec_flag;
range_query *second;
+ int second_exec_flag;
pointer_equiv_analyzer *m_pta;
tree choose_value (tree evrp_val, tree ranger_val);
};
@@ -569,9 +292,15 @@ tree
hybrid_folder::value_of_expr (tree op, gimple *stmt)
{
tree evrp_ret = evrp_folder::value_of_expr (op, stmt);
- tree ranger_ret = m_ranger->value_of_expr (op, stmt);
- if (!ranger_ret && is_pointer_ssa (op))
- ranger_ret = m_pta->get_equiv (op);
+ tree ranger_ret;
+ if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
+ ranger_ret = NULL;
+ else
+ {
+ ranger_ret = m_ranger->value_of_expr (op, stmt);
+ if (!ranger_ret && supported_pointer_equiv_p (op))
+ ranger_ret = m_pta->get_equiv (op);
+ }
return choose_value (evrp_ret, ranger_ret);
}
@@ -581,9 +310,15 @@ hybrid_folder::value_on_edge (edge e, tree op)
// Call evrp::value_of_expr directly. Otherwise another dual call is made
// via hybrid_folder::value_of_expr, but without an edge.
tree evrp_ret = evrp_folder::value_of_expr (op, NULL);
- tree ranger_ret = m_ranger->value_on_edge (e, op);
- if (!ranger_ret && is_pointer_ssa (op))
- ranger_ret = m_pta->get_equiv (op);
+ tree ranger_ret;
+ if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
+ ranger_ret = NULL;
+ else
+ {
+ ranger_ret = m_ranger->value_on_edge (e, op);
+ if (!ranger_ret && supported_pointer_equiv_p (op))
+ ranger_ret = m_pta->get_equiv (op);
+ }
return choose_value (evrp_ret, ranger_ret);
}
@@ -598,7 +333,11 @@ hybrid_folder::value_of_stmt (gimple *stmt, tree op)
else
evrp_ret = NULL_TREE;
- tree ranger_ret = m_ranger->value_of_stmt (stmt, op);
+ tree ranger_ret;
+ if (op && TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
+ ranger_ret = NULL;
+ else
+ ranger_ret = m_ranger->value_of_stmt (stmt, op);
return choose_value (evrp_ret, ranger_ret);
}
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 781c02d..4efa200 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -1020,7 +1020,8 @@ public:
first. */
static tree
-bswap_view_convert (gimple_stmt_iterator *gsi, tree type, tree val)
+bswap_view_convert (gimple_stmt_iterator *gsi, tree type, tree val,
+ bool before)
{
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (val))
|| POINTER_TYPE_P (TREE_TYPE (val)));
@@ -1032,12 +1033,18 @@ bswap_view_convert (gimple_stmt_iterator *gsi, tree type, tree val)
gimple *g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node),
NOP_EXPR, val);
- gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ if (before)
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ else
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
val = gimple_assign_lhs (g);
}
tree itype = build_nonstandard_integer_type (prec, 1);
gimple *g = gimple_build_assign (make_ssa_name (itype), NOP_EXPR, val);
- gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ if (before)
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ else
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
val = gimple_assign_lhs (g);
}
return build1 (VIEW_CONVERT_EXPR, type, val);
@@ -1165,7 +1172,8 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
gimple_set_vuse (load_stmt, n->vuse);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
if (conv_code == VIEW_CONVERT_EXPR)
- val_tmp = bswap_view_convert (&gsi, TREE_TYPE (tgt), val_tmp);
+ val_tmp = bswap_view_convert (&gsi, TREE_TYPE (tgt), val_tmp,
+ true);
gimple_assign_set_rhs_with_ops (&gsi, conv_code, val_tmp);
update_stmt (cur_stmt);
}
@@ -1209,7 +1217,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
if (!is_gimple_val (src))
return NULL_TREE;
if (conv_code == VIEW_CONVERT_EXPR)
- src = bswap_view_convert (&gsi, TREE_TYPE (tgt), src);
+ src = bswap_view_convert (&gsi, TREE_TYPE (tgt), src, true);
g = gimple_build_assign (tgt, conv_code, src);
}
else if (cur_stmt)
@@ -1296,14 +1304,13 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
/* Convert the result if necessary. */
if (!useless_type_conversion_p (TREE_TYPE (tgt), bswap_type))
{
- gimple *convert_stmt;
-
tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst");
tree atmp = tmp;
+ gimple_stmt_iterator gsi2 = gsi;
if (conv_code == VIEW_CONVERT_EXPR)
- atmp = bswap_view_convert (&gsi, TREE_TYPE (tgt), tmp);
- convert_stmt = gimple_build_assign (tgt, conv_code, atmp);
- gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
+ atmp = bswap_view_convert (&gsi2, TREE_TYPE (tgt), tmp, false);
+ gimple *convert_stmt = gimple_build_assign (tgt, conv_code, atmp);
+ gsi_insert_after (&gsi2, convert_stmt, GSI_SAME_STMT);
}
gimple_set_lhs (mask_stmt ? mask_stmt : bswap_stmt, tmp);
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 5df97a6..00c3ea0 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -1190,10 +1190,11 @@ warn_for_access (location_t loc, tree func, tree expr, int opt,
by BNDRNG if nonnull and valid. */
static void
-get_size_range (tree bound, tree range[2], const offset_int bndrng[2])
+get_size_range (range_query *query, tree bound, tree range[2],
+ const offset_int bndrng[2])
{
if (bound)
- get_size_range (bound, range);
+ get_size_range (query, bound, NULL, range);
if (!bndrng || (bndrng[0] == 0 && bndrng[1] == HOST_WIDE_INT_M1U))
return;
@@ -1337,7 +1338,7 @@ check_access (GimpleOrTree exp, tree dstwrite,
/* Set RANGE to that of DSTWRITE if non-null, bounded by PAD->DST.BNDRNG
if valid. */
- get_size_range (dstwrite, range, pad ? pad->dst.bndrng : NULL);
+ get_size_range (NULL, dstwrite, range, pad ? pad->dst.bndrng : NULL);
tree func = get_callee_fndecl (exp);
/* Read vs write access by built-ins can be determined from the const
@@ -1431,7 +1432,7 @@ check_access (GimpleOrTree exp, tree dstwrite,
{
/* Set RANGE to that of MAXREAD, bounded by PAD->SRC.BNDRNG if
PAD is nonnull and BNDRNG is valid. */
- get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
+ get_size_range (NULL, maxread, range, pad ? pad->src.bndrng : NULL);
location_t loc = get_location (exp);
tree size = dstsize;
@@ -1478,7 +1479,7 @@ check_access (GimpleOrTree exp, tree dstwrite,
{
/* Set RANGE to that of MAXREAD, bounded by PAD->SRC.BNDRNG if
PAD is nonnull and BNDRNG is valid. */
- get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
+ get_size_range (NULL, maxread, range, pad ? pad->src.bndrng : NULL);
/* Set OVERREAD for reads starting just past the end of an object. */
overread = pad->src.sizrng[1] - pad->src.offrng[0] < pad->src.bndrng[0];
range[0] = wide_int_to_tree (sizetype, pad->src.bndrng[0]);
@@ -1529,41 +1530,6 @@ check_access (tree expr, tree dstwrite,
mode, pad);
}
-/* Helper to determine and check the sizes of the source and the destination
- of calls to __builtin_{bzero,memcpy,mempcpy,memset} calls. EXP is the
- call expression, DEST is the destination argument, SRC is the source
- argument or null, and LEN is the number of bytes. Use Object Size type-0
- regardless of the OPT_Wstringop_overflow_ setting. Return true on success
- (no overflow or invalid sizes), false otherwise. */
-
-template <class GimpleOrTree>
-static bool
-check_memop_access (GimpleOrTree expr, tree dest, tree src, tree size)
-{
- /* For functions like memset and memcpy that operate on raw memory
- try to determine the size of the largest source and destination
- object using type-0 Object Size regardless of the object size
- type specified by the option. */
- access_data data (expr, access_read_write);
- tree srcsize = src ? compute_objsize (src, 0, &data.src) : NULL_TREE;
- tree dstsize = compute_objsize (dest, 0, &data.dst);
-
- return check_access (expr, size, /*maxread=*/NULL_TREE,
- srcsize, dstsize, data.mode, &data);
-}
-
-bool
-check_memop_access (gimple *stmt, tree dest, tree src, tree size)
-{
- return check_memop_access<gimple *>(stmt, dest, src, size);
-}
-
-bool
-check_memop_access (tree expr, tree dest, tree src, tree size)
-{
- return check_memop_access<tree>(expr, dest, src, size);
-}
-
/* A convenience wrapper for check_access above to check access
by a read-only function like puts. */
@@ -2111,135 +2077,6 @@ warn_dealloc_offset (location_t loc, gimple *call, const access_ref &aref)
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. */
-
-static void
-maybe_check_dealloc_call (gcall *call)
-{
- tree fndecl = gimple_call_fndecl (call);
- if (!fndecl)
- return;
-
- unsigned argno = fndecl_dealloc_argno (fndecl);
- if ((unsigned) call_nargs (call) <= argno)
- return;
-
- tree ptr = gimple_call_arg (call, argno);
- if (integer_zerop (ptr))
- return;
-
- access_ref aref;
- if (!compute_objsize (ptr, 0, &aref))
- return;
-
- tree ref = aref.ref;
- if (integer_zerop (ref))
- return;
-
- tree dealloc_decl = fndecl;
- location_t loc = gimple_location (call);
-
- if (DECL_P (ref) || EXPR_P (ref))
- {
- /* Diagnose freeing a declared object. */
- if (aref.ref_declared ()
- && warning_at (loc, OPT_Wfree_nonheap_object,
- "%qD called on unallocated object %qD",
- dealloc_decl, ref))
- {
- inform (get_location (ref), "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, call, aref))
- return;
- }
- else if (CONSTANT_CLASS_P (ref))
- {
- if (warning_at (loc, OPT_Wfree_nonheap_object,
- "%qD called on a pointer to an unallocated "
- "object %qE", 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, call, aref))
- return;
- }
- else
- {
- tree alloc_decl = gimple_call_fndecl (def_stmt);
- const opt_code 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,
- "%qD called on pointer returned "
- "from a mismatched allocation "
- "function", 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,
- "%qD called on pointer to "
- "an unallocated object",
- dealloc_decl);
- else if (warn_dealloc_offset (loc, call, 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, call, aref))
- return;
- }
- }
-}
-
namespace {
const pass_data pass_data_waccess = {
@@ -2267,6 +2104,11 @@ class pass_waccess : public gimple_opt_pass
virtual bool gate (function *);
virtual unsigned int execute (function *);
+private:
+ /* Not copyable or assignable. */
+ pass_waccess (pass_waccess &) = delete;
+ void operator= (pass_waccess &) = delete;
+
/* Check a call to a built-in function. */
bool check_builtin (gcall *);
@@ -2277,28 +2119,33 @@ class pass_waccess : public gimple_opt_pass
void check (basic_block);
/* Check a call to a function. */
- void check (gcall *);
+ void check (gcall *);
-private:
- /* Not copyable or assignable. */
- pass_waccess (pass_waccess &) = delete;
- void operator= (pass_waccess &) = delete;
+ /* Check a call to the named built-in function. */
+ void check_alloca (gcall *);
+ void check_alloc_size_call (gcall *);
+ void check_strcat (gcall *);
+ void check_strncat (gcall *);
+ void check_stxcpy (gcall *);
+ void check_stxncpy (gcall *);
+ void check_strncmp (gcall *);
+ void check_memop_access (gimple *, tree, tree, tree);
+
+ void maybe_check_dealloc_call (gcall *);
+ void maybe_check_access_sizes (rdwr_map *, tree, tree, gimple *);
/* 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;
-
- gimple_ranger *m_ranger;
+ pointer_query m_ptr_qry;
+ pointer_query::cache_type m_var_cache;
};
/* Construct the pass. */
pass_waccess::pass_waccess (gcc::context *ctxt)
: gimple_opt_pass (pass_data_waccess, ctxt),
- ptr_qry (m_ranger, &var_cache),
- var_cache (),
- m_ranger ()
+ m_ptr_qry (NULL, &m_var_cache),
+ m_var_cache ()
{
}
@@ -2306,7 +2153,7 @@ pass_waccess::pass_waccess (gcc::context *ctxt)
pass_waccess::~pass_waccess ()
{
- ptr_qry.flush_cache ();
+ m_ptr_qry.flush_cache ();
}
/* Return true when any checks performed by the pass are enabled. */
@@ -2433,7 +2280,7 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree args[2],
}
}
- if (!argrange[0])
+ if (!argrange[0][0])
return;
/* For a two-argument alloc_size, validate the product of the two
@@ -2494,8 +2341,8 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree args[2],
/* Check a call to an alloca function for an excessive size. */
-static void
-check_alloca (gimple *stmt)
+void
+pass_waccess::check_alloca (gcall *stmt)
{
if ((warn_vla_limit >= HOST_WIDE_INT_MAX
&& warn_alloc_size_limit < warn_vla_limit)
@@ -2515,8 +2362,8 @@ check_alloca (gimple *stmt)
/* Check a call to an allocation function for an excessive size. */
-static void
-check_alloc_size_call (gimple *stmt)
+void
+pass_waccess::check_alloc_size_call (gcall *stmt)
{
if (gimple_call_num_args (stmt) < 1)
/* Avoid invalid calls to functions without a prototype. */
@@ -2565,8 +2412,8 @@ check_alloc_size_call (gimple *stmt)
/* Check a call STMT to strcat() for overflow and warn if it does. */
-static void
-check_strcat (gimple *stmt)
+void
+pass_waccess::check_strcat (gcall *stmt)
{
if (!warn_stringop_overflow && !warn_stringop_overread)
return;
@@ -2581,8 +2428,8 @@ check_strcat (gimple *stmt)
access_data data (stmt, access_read_write, NULL_TREE, true,
NULL_TREE, true);
const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
- compute_objsize (src, ost, &data.src);
- tree destsize = compute_objsize (dest, ost, &data.dst);
+ compute_objsize (src, ost, &data.src, &m_ptr_qry);
+ tree destsize = compute_objsize (dest, ost, &data.dst, &m_ptr_qry);
check_access (stmt, /*dstwrite=*/NULL_TREE, /*maxread=*/NULL_TREE,
src, destsize, data.mode, &data);
@@ -2590,8 +2437,8 @@ check_strcat (gimple *stmt)
/* Check a call STMT to strcat() for overflow and warn if it does. */
-static void
-check_strncat (gimple *stmt)
+void
+pass_waccess::check_strncat (gcall *stmt)
{
if (!warn_stringop_overflow && !warn_stringop_overread)
return;
@@ -2623,7 +2470,8 @@ check_strncat (gimple *stmt)
/* Try to verify that the destination is big enough for the shortest
string. First try to determine the size of the destination object
into which the source is being copied. */
- tree destsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
+ const int ost = warn_stringop_overflow - 1;
+ tree destsize = compute_objsize (dest, ost, &data.dst, &m_ptr_qry);
/* Add one for the terminating nul. */
tree srclen = (maxlen
@@ -2658,8 +2506,8 @@ check_strncat (gimple *stmt)
/* Check a call STMT to stpcpy() or strcpy() for overflow and warn
if it does. */
-static void
-check_stxcpy (gimple *stmt)
+void
+pass_waccess::check_stxcpy (gcall *stmt)
{
tree dst = call_arg (stmt, 0);
tree src = call_arg (stmt, 1);
@@ -2679,8 +2527,8 @@ check_stxcpy (gimple *stmt)
access_data data (stmt, access_read_write, NULL_TREE, true,
NULL_TREE, true);
const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
- compute_objsize (src, ost, &data.src);
- tree dstsize = compute_objsize (dst, ost, &data.dst);
+ compute_objsize (src, ost, &data.src, &m_ptr_qry);
+ tree dstsize = compute_objsize (dst, ost, &data.dst, &m_ptr_qry);
check_access (stmt, /*dstwrite=*/ NULL_TREE,
/*maxread=*/ NULL_TREE, /*srcstr=*/ src,
dstsize, data.mode, &data);
@@ -2696,8 +2544,8 @@ check_stxcpy (gimple *stmt)
/* Check a call STMT to stpncpy() or strncpy() for overflow and warn
if it does. */
-static void
-check_stxncpy (gimple *stmt)
+void
+pass_waccess::check_stxncpy (gcall *stmt)
{
if (!warn_stringop_overflow)
return;
@@ -2709,8 +2557,8 @@ check_stxncpy (gimple *stmt)
access_data data (stmt, access_read_write, len, true, len, true);
const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
- compute_objsize (src, ost, &data.src);
- tree dstsize = compute_objsize (dst, ost, &data.dst);
+ compute_objsize (src, ost, &data.src, &m_ptr_qry);
+ tree dstsize = compute_objsize (dst, ost, &data.dst, &m_ptr_qry);
check_access (stmt, /*dstwrite=*/len,
/*maxread=*/len, src, dstsize, data.mode, &data);
@@ -2719,8 +2567,8 @@ check_stxncpy (gimple *stmt)
/* Check a call STMT to stpncpy() or strncpy() for overflow and warn
if it does. */
-static void
-check_strncmp (gimple *stmt)
+void
+pass_waccess::check_strncmp (gcall *stmt)
{
if (!warn_stringop_overread)
return;
@@ -2764,7 +2612,7 @@ check_strncmp (gimple *stmt)
/* Determine the range of the bound first and bail if it fails; it's
cheaper than computing the size of the objects. */
tree bndrng[2] = { NULL_TREE, NULL_TREE };
- get_size_range (bound, bndrng, adata1.src.bndrng);
+ get_size_range (m_ptr_qry.rvals, bound, bndrng, adata1.src.bndrng);
if (!bndrng[0] || integer_zerop (bndrng[0]))
return;
@@ -2775,8 +2623,8 @@ check_strncmp (gimple *stmt)
/* compute_objsize almost never fails (and ultimately should never
fail). Don't bother to handle the rare case when it does. */
- if (!compute_objsize (arg1, 1, &adata1.src)
- || !compute_objsize (arg2, 1, &adata2.src))
+ if (!compute_objsize (arg1, 1, &adata1.src, &m_ptr_qry)
+ || !compute_objsize (arg2, 1, &adata2.src, &m_ptr_qry))
return;
/* Compute the size of the remaining space in each array after
@@ -2810,6 +2658,29 @@ check_strncmp (gimple *stmt)
}
}
+/* Determine and check the sizes of the source and the destination
+ of calls to __builtin_{bzero,memcpy,mempcpy,memset} calls. STMT is
+ the call statement, DEST is the destination argument, SRC is the source
+ argument or null, and SIZE is the number of bytes being accessed. Use
+ Object Size type-0 regardless of the OPT_Wstringop_overflow_ setting.
+ Return true on success (no overflow or invalid sizes), false otherwise. */
+
+void
+pass_waccess::check_memop_access (gimple *stmt, tree dest, tree src, tree size)
+{
+ /* For functions like memset and memcpy that operate on raw memory
+ try to determine the size of the largest source and destination
+ object using type-0 Object Size regardless of the object size
+ type specified by the option. */
+ access_data data (stmt, access_read_write);
+ tree srcsize
+ = src ? compute_objsize (src, 0, &data.src, &m_ptr_qry) : NULL_TREE;
+ tree dstsize = compute_objsize (dest, 0, &data.dst, &m_ptr_qry);
+
+ check_access (stmt, size, /*maxread=*/NULL_TREE,
+ srcsize, dstsize, data.mode, &data);
+}
+
/* Check call STMT to a built-in function for invalid accesses. Return
true if a call has been handled. */
@@ -2968,8 +2839,9 @@ append_attrname (const std::pair<int, attr_access> &access,
arguments and diagnose past-the-end accesses and related problems
in the function call EXP. */
-static void
-maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, gimple *stmt)
+void
+pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
+ gimple *stmt)
{
auto_diagnostic_group adg;
@@ -3028,7 +2900,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, gimple *stmt)
/* Format the value or range to avoid an explosion of messages. */
char sizstr[80];
tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
- if (get_size_range (access_size, sizrng, true))
+ if (get_size_range (m_ptr_qry.rvals, access_size, NULL, sizrng, 1))
{
char *s0 = print_generic_expr_to_str (sizrng[0]);
if (tree_int_cst_equal (sizrng[0], sizrng[1]))
@@ -3160,7 +3032,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, gimple *stmt)
NULL_TREE, false);
access_ref* const pobj = (access.second.mode == access_write_only
? &data.dst : &data.src);
- tree objsize = compute_objsize (ptr, 1, pobj);
+ tree objsize = compute_objsize (ptr, 1, pobj, &m_ptr_qry);
/* The size of the destination or source object. */
tree dstsize = NULL_TREE, srcsize = NULL_TREE;
@@ -3276,7 +3148,7 @@ pass_waccess::check_call (gcall *stmt)
/* Check attribute access arguments. */
tree fndecl = gimple_call_fndecl (stmt);
- maybe_warn_rdwr_sizes (&rdwr_idx, fndecl, fntype, stmt);
+ maybe_check_access_sizes (&rdwr_idx, fndecl, fntype, stmt);
check_alloc_size_call (stmt);
return true;
@@ -3294,6 +3166,138 @@ check_nonstring_args (gcall *stmt)
maybe_warn_nonstring_arg (fndecl, stmt);
}
+/* 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
+pass_waccess::maybe_check_dealloc_call (gcall *call)
+{
+ tree fndecl = gimple_call_fndecl (call);
+ if (!fndecl)
+ return;
+
+ unsigned argno = fndecl_dealloc_argno (fndecl);
+ if ((unsigned) call_nargs (call) <= argno)
+ return;
+
+ tree ptr = gimple_call_arg (call, argno);
+ if (integer_zerop (ptr))
+ return;
+
+ access_ref aref;
+ if (!compute_objsize (ptr, 0, &aref, &m_ptr_qry))
+ return;
+
+ tree ref = aref.ref;
+ if (integer_zerop (ref))
+ return;
+
+ tree dealloc_decl = fndecl;
+ location_t loc = gimple_location (call);
+
+ if (DECL_P (ref) || EXPR_P (ref))
+ {
+ /* Diagnose freeing a declared object. */
+ if (aref.ref_declared ()
+ && warning_at (loc, OPT_Wfree_nonheap_object,
+ "%qD called on unallocated object %qD",
+ dealloc_decl, ref))
+ {
+ inform (get_location (ref), "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, call, aref))
+ return;
+ }
+ else if (CONSTANT_CLASS_P (ref))
+ {
+ if (warning_at (loc, OPT_Wfree_nonheap_object,
+ "%qD called on a pointer to an unallocated "
+ "object %qE", 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 (!def_stmt)
+ return;
+
+ 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, call, aref))
+ return;
+ }
+ else
+ {
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ const opt_code 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,
+ "%qD called on pointer returned "
+ "from a mismatched allocation "
+ "function", 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,
+ "%qD called on pointer to "
+ "an unallocated object",
+ dealloc_decl);
+ else if (warn_dealloc_offset (loc, call, 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, call, aref))
+ return;
+ }
+ }
+}
+
/* Check call STMT for invalid accesses. */
void
@@ -3329,14 +3333,21 @@ unsigned
pass_waccess::execute (function *fun)
{
/* Create a new ranger instance and associate it with FUN. */
- m_ranger = enable_ranger (fun);
+ m_ptr_qry.rvals = enable_ranger (fun);
basic_block bb;
FOR_EACH_BB_FN (bb, fun)
check (bb);
- /* Release the ranger instance and replace it with a global ranger. */
+ if (dump_file)
+ m_ptr_qry.dump (dump_file, (dump_flags & TDF_DETAILS) != 0);
+
+ m_ptr_qry.flush_cache ();
+
+ /* Release the ranger instance and replace it with a global ranger.
+ Also reset the pointer since calling disable_ranger() deletes it. */
disable_ranger (fun);
+ m_ptr_qry.rvals = NULL;
return 0;
}
diff --git a/gcc/gimple-ssa-warn-access.h b/gcc/gimple-ssa-warn-access.h
index 1cd3a28..00f5bb1 100644
--- a/gcc/gimple-ssa-warn-access.h
+++ b/gcc/gimple-ssa-warn-access.h
@@ -45,7 +45,6 @@ class access_data;
extern bool check_access (tree, tree, tree, tree, tree, access_mode,
const access_data * = NULL);
-extern bool check_memop_access (tree, tree, tree, tree);
extern bool check_read_access (gimple *, tree, tree = NULL_TREE, int ost = 1);
extern bool check_read_access (tree, tree, tree = NULL_TREE, int = 1);
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 4fc7125..d59cea8 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -221,10 +221,9 @@ alloca_call_type (gimple *stmt, bool is_vla)
&& !r.varying_p ())
{
// The invalid bits are anything outside of [0, MAX_SIZE].
- static int_range<2> invalid_range (build_int_cst (size_type_node, 0),
- build_int_cst (size_type_node,
- max_size),
- VR_ANTI_RANGE);
+ int_range<2> invalid_range (build_int_cst (size_type_node, 0),
+ build_int_cst (size_type_node, max_size),
+ VR_ANTI_RANGE);
r.intersect (invalid_range);
if (r.undefined_p ())
diff --git a/gcc/gimple.c b/gcc/gimple.c
index bed7ff9..cc7a88e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1549,12 +1549,12 @@ gimple_call_fnspec (const gcall *stmt)
&& DECL_IS_OPERATOR_DELETE_P (fndecl)
&& DECL_IS_REPLACEABLE_OPERATOR (fndecl)
&& gimple_call_from_new_or_delete (stmt))
- return ".co ";
+ return ". o ";
/* 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 "m ";
return "";
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 479a1c7..303623b 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -194,8 +194,9 @@ enum gf_mask {
GF_OMP_RETURN_NOWAIT = 1 << 0,
GF_OMP_SECTION_LAST = 1 << 0,
- GF_OMP_ATOMIC_MEMORY_ORDER = (1 << 3) - 1,
- GF_OMP_ATOMIC_NEED_VALUE = 1 << 3,
+ GF_OMP_ATOMIC_MEMORY_ORDER = (1 << 6) - 1,
+ GF_OMP_ATOMIC_NEED_VALUE = 1 << 6,
+ GF_OMP_ATOMIC_WEAK = 1 << 7,
GF_PREDICT_TAKEN = 1 << 15
};
@@ -2446,6 +2447,29 @@ gimple_omp_atomic_set_need_value (gimple *g)
}
+/* Return true if OMP atomic load/store statement G has the
+ GF_OMP_ATOMIC_WEAK flag set. */
+
+static inline bool
+gimple_omp_atomic_weak_p (const gimple *g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ return (gimple_omp_subcode (g) & GF_OMP_ATOMIC_WEAK) != 0;
+}
+
+
+/* Set the GF_OMP_ATOMIC_WEAK flag on G. */
+
+static inline void
+gimple_omp_atomic_set_weak (gimple *g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ g->subcode |= GF_OMP_ATOMIC_WEAK;
+}
+
+
/* Return the memory order of the OMP atomic load/store statement G. */
static inline enum omp_memory_order
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 070d0e4..d8e4b13 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1743,6 +1743,97 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
return NULL_TREE;
}
+/* Generate an initialization to automatic variable DECL based on INIT_TYPE.
+ Build a call to internal const function DEFERRED_INIT:
+ 1st argument: SIZE of the DECL;
+ 2nd argument: INIT_TYPE;
+ 3rd argument: IS_VLA, 0 NO, 1 YES;
+
+ as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA)
+ if IS_VLA is false, the LHS is the DECL itself,
+ if IS_VLA is true, the LHS is a MEM_REF whose address is the pointer
+ to this DECL. */
+static void
+gimple_add_init_for_auto_var (tree decl,
+ enum auto_init_type init_type,
+ bool is_vla,
+ gimple_seq *seq_p)
+{
+ gcc_assert (auto_var_p (decl));
+ gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
+ location_t loc = EXPR_LOCATION (decl);
+ tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+
+ tree init_type_node
+ = build_int_cst (integer_type_node, (int) init_type);
+ tree is_vla_node
+ = build_int_cst (integer_type_node, (int) is_vla);
+
+ tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
+ TREE_TYPE (decl), 3,
+ decl_size, init_type_node,
+ is_vla_node);
+
+ gimplify_assign (decl, call, seq_p);
+}
+
+/* Generate padding initialization for automatic vairable DECL.
+ C guarantees that brace-init with fewer initializers than members
+ aggregate will initialize the rest of the aggregate as-if it were
+ static initialization. In turn static initialization guarantees
+ that padding is initialized to zero. So, we always initialize paddings
+ to zeroes regardless INIT_TYPE.
+ To do the padding initialization, we insert a call to
+ __BUILTIN_CLEAR_PADDING (&decl, 0, for_auto_init = true).
+ Note, we add an additional dummy argument for __BUILTIN_CLEAR_PADDING,
+ 'for_auto_init' to distinguish whether this call is for automatic
+ variable initialization or not.
+ */
+static void
+gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
+ gimple_seq *seq_p)
+{
+ tree addr_of_decl = NULL_TREE;
+ bool for_auto_init = true;
+ tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
+
+ if (is_vla)
+ {
+ /* The temporary address variable for this vla should be
+ created in gimplify_vla_decl. */
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
+ gcc_assert (TREE_CODE (DECL_VALUE_EXPR (decl)) == INDIRECT_REF);
+ addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
+ }
+ else
+ {
+ mark_addressable (decl);
+ addr_of_decl = build_fold_addr_expr (decl);
+ }
+
+ gimple *call = gimple_build_call (fn,
+ 3, addr_of_decl,
+ build_zero_cst (TREE_TYPE (addr_of_decl)),
+ build_int_cst (integer_type_node,
+ (int) for_auto_init));
+ gimplify_seq_add_stmt (seq_p, call);
+}
+
+/* Return true if the DECL need to be automaticly initialized by the
+ compiler. */
+static bool
+is_var_need_auto_init (tree decl)
+{
+ if (auto_var_p (decl)
+ && (TREE_CODE (decl) != VAR_DECL
+ || !DECL_HARD_REGISTER (decl))
+ && (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
+ && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
+ && !is_empty_type (TREE_TYPE (decl)))
+ return true;
+ return false;
+}
+
/* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
and initialization explicit. */
@@ -1781,6 +1872,12 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
{
tree init = DECL_INITIAL (decl);
bool is_vla = false;
+ /* Check whether a decl has FE created VALUE_EXPR here BEFORE
+ gimplify_vla_decl creates VALUE_EXPR for a vla decl.
+ If the decl has VALUE_EXPR that was created by FE (usually
+ C++FE), it's a proxy varaible, and FE already initialized
+ the VALUE_EXPR of it, we should not initialize it anymore. */
+ bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
poly_uint64 size;
if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
@@ -1831,7 +1928,8 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
gimplify_and_add (init, seq_p);
ggc_free (init);
/* Clear TREE_READONLY if we really have an initialization. */
- if (!DECL_INITIAL (decl) && !omp_is_reference (decl))
+ if (!DECL_INITIAL (decl)
+ && !omp_privatize_by_reference (decl))
TREE_READONLY (decl) = 0;
}
else
@@ -1839,6 +1937,27 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
as they may contain a label address. */
walk_tree (&init, force_labels_r, NULL, NULL);
}
+ /* When there is no explicit initializer, if the user requested,
+ We should insert an artifical initializer for this automatic
+ variable. */
+ else if (is_var_need_auto_init (decl)
+ && !decl_had_value_expr_p)
+ {
+ gimple_add_init_for_auto_var (decl,
+ flag_auto_var_init,
+ is_vla,
+ seq_p);
+ /* The expanding of a call to the above .DEFERRED_INIT will apply
+ block initialization to the whole space covered by this variable.
+ As a result, all the paddings will be initialized to zeroes
+ for zero initialization and 0xFE byte-repeatable patterns for
+ pattern initialization.
+ In order to make the paddings as zeroes for pattern init, We
+ should add a call to __builtin_clear_padding to clear the
+ paddings to zero in compatiple with CLANG. */
+ if (flag_auto_var_init == AUTO_INIT_PATTERN)
+ gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
+ }
}
return GS_ALL_DONE;
@@ -3410,11 +3529,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
{
/* Remember the original type of the argument in an internal
dummy second argument, as in GIMPLE pointer conversions are
- useless. */
+ useless. also mark this call as not for automatic initialization
+ in the internal dummy third argument. */
p = CALL_EXPR_ARG (*expr_p, 0);
+ bool for_auto_init = false;
*expr_p
- = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
- build_zero_cst (TREE_TYPE (p)));
+ = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 3, p,
+ build_zero_cst (TREE_TYPE (p)),
+ build_int_cst (integer_type_node,
+ (int) for_auto_init));
return GS_OK;
}
break;
@@ -4871,6 +4994,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
tree object, ctor, type;
enum gimplify_status ret;
vec<constructor_elt, va_gc> *elts;
+ bool cleared = false;
+ bool is_empty_ctor = false;
+ bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
@@ -4913,7 +5039,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
struct gimplify_init_ctor_preeval_data preeval_data;
HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
HOST_WIDE_INT num_unique_nonzero_elements;
- bool cleared, complete_p, valid_const_initializer;
+ bool complete_p, valid_const_initializer;
/* Aggregate types must lower constructors to initialization of
individual elements. The exception is that a CONSTRUCTOR node
@@ -4922,6 +5048,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
{
if (notify_temp_creation)
return GS_OK;
+ is_empty_ctor = true;
break;
}
@@ -5247,13 +5374,28 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
if (want_value)
{
*expr_p = object;
- return GS_OK;
+ ret = GS_OK;
}
else
{
*expr_p = NULL;
- return GS_ALL_DONE;
- }
+ ret = GS_ALL_DONE;
+ }
+
+ /* If the user requests to initialize automatic variables, we
+ should initialize paddings inside the variable. Add a call to
+ __BUILTIN_CLEAR_PADDING (&object, 0, for_auto_init = true) to
+ initialize paddings of object always to zero regardless of
+ INIT_TYPE. Note, we will not insert this call if the aggregate
+ variable has be completely cleared already or it's initialized
+ with an empty constructor. */
+ if (is_init_expr
+ && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
+ || !AGGREGATE_TYPE_P (type))
+ && is_var_need_auto_init (object))
+ gimple_add_padding_init_for_auto_var (object, false, pre_p);
+
+ return ret;
}
/* Given a pointer value OP0, return a simplified version of an
@@ -5394,10 +5536,12 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
crack at this before we break it down. */
if (ret != GS_UNHANDLED)
break;
+
/* If we're initializing from a CONSTRUCTOR, break this into
individual MODIFY_EXPRs. */
- return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
- false);
+ ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
+ false);
+ return ret;
case COND_EXPR:
/* If we're assigning to a non-register type, push the assignment
@@ -6097,6 +6241,9 @@ gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
val = TREE_OPERAND (*expr_p, 0);
+ if (TREE_TYPE (val) == error_mark_node)
+ return GS_ERROR;
+
/* If the SAVE_EXPR has not been resolved, then evaluate it once. */
if (!SAVE_EXPR_RESOLVED_P (*expr_p))
{
@@ -7064,7 +7211,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
}
else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
- && lang_hooks.decls.omp_privatize_by_reference (decl))
+ && omp_privatize_by_reference (decl))
{
omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
@@ -7234,6 +7381,18 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
default_kind = kind;
else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
default_kind = OMP_CLAUSE_DEFAULT_SHARED;
+ /* For C/C++ default({,first}private), variables with static storage duration
+ declared in a namespace or global scope and referenced in construct
+ must be explicitly specified, i.e. acts as default(none). */
+ else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
+ || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
+ && VAR_P (decl)
+ && is_global_var (decl)
+ && (DECL_FILE_SCOPE_P (decl)
+ || (DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
+ && !lang_GNU_Fortran ())
+ default_kind = OMP_CLAUSE_DEFAULT_NONE;
switch (default_kind)
{
@@ -7322,7 +7481,7 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
bool declared = is_oacc_declared (decl);
tree type = TREE_TYPE (decl);
- if (lang_hooks.decls.omp_privatize_by_reference (decl))
+ if (omp_privatize_by_reference (decl))
type = TREE_TYPE (type);
/* For Fortran COMMON blocks, only used variables in those blocks are
@@ -7586,7 +7745,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
tree type = TREE_TYPE (decl);
if (gimplify_omp_ctxp->target_firstprivatize_array_bases
- && lang_hooks.decls.omp_privatize_by_reference (decl))
+ && omp_privatize_by_reference (decl))
type = TREE_TYPE (type);
if (!lang_hooks.types.omp_mappable_type (type))
{
@@ -7660,7 +7819,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
n2->value |= GOVD_SEEN;
}
- else if (lang_hooks.decls.omp_privatize_by_reference (decl)
+ else if (omp_privatize_by_reference (decl)
&& TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
&& (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
!= INTEGER_CST))
@@ -7785,7 +7944,7 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
if (copyprivate)
return true;
- if (lang_hooks.decls.omp_privatize_by_reference (decl))
+ if (omp_privatize_by_reference (decl))
return false;
/* Treat C++ privatized non-static data members outside
@@ -10045,7 +10204,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true);
if (check_non_private
- && region_type == ORT_WORKSHARE
+ && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
|| decl == OMP_CLAUSE_DECL (c)
|| (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
@@ -10107,6 +10266,38 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_THREAD_LIMIT:
case OMP_CLAUSE_DIST_SCHEDULE:
case OMP_CLAUSE_DEVICE:
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
+ && OMP_CLAUSE_DEVICE_ANCESTOR (c))
+ {
+ if (code != OMP_TARGET)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<device%> clause with %<ancestor%> is only "
+ "allowed on %<target%> construct");
+ remove = true;
+ break;
+ }
+
+ tree clauses = *orig_list_p;
+ for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
+ if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
+ && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
+ && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
+ && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
+ )
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "with %<ancestor%>, only the %<device%>, "
+ "%<firstprivate%>, %<private%>, %<defaultmap%>, "
+ "and %<map%> clauses may appear on the "
+ "construct");
+ remove = true;
+ break;
+ }
+ }
+ /* Fall through. */
+
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
@@ -10373,7 +10564,7 @@ omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
HOST_WIDE_INT len = int_size_in_bytes (type);
if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
return false;
- if (lang_hooks.decls.omp_privatize_by_reference (decl))
+ if (omp_privatize_by_reference (decl))
return false;
return true;
}
@@ -10698,7 +10889,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
OMP_CLAUSE_CHAIN (clause) = nc;
}
else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
- && lang_hooks.decls.omp_privatize_by_reference (decl))
+ && omp_privatize_by_reference (decl))
{
OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
OMP_CLAUSE_SIZE (clause)
@@ -10735,8 +10926,12 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
*list_p = clause;
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
gimplify_omp_ctxp = ctx->outer_context;
- lang_hooks.decls.omp_finish_clause (clause, pre_p,
- (ctx->region_type & ORT_ACC) != 0);
+ /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
+ in simd. Those are only added for the local vars inside of simd body
+ and they don't need to be e.g. default constructible. */
+ if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
+ lang_hooks.decls.omp_finish_clause (clause, pre_p,
+ (ctx->region_type & ORT_ACC) != 0);
if (gimplify_omp_ctxp)
for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
@@ -13692,30 +13887,36 @@ goa_lhs_expr_p (tree expr, tree addr)
static int
goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
- tree lhs_var)
+ tree lhs_var, tree &target_expr, bool rhs, int depth)
{
tree expr = *expr_p;
- int saw_lhs;
+ int saw_lhs = 0;
if (goa_lhs_expr_p (expr, lhs_addr))
{
- *expr_p = lhs_var;
+ if (pre_p)
+ *expr_p = lhs_var;
return 1;
}
if (is_gimple_val (expr))
return 0;
- saw_lhs = 0;
+ /* Maximum depth of lhs in expression is for the
+ __builtin_clear_padding (...), __builtin_clear_padding (...),
+ __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
+ if (++depth > 7)
+ goto finish;
+
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_binary:
case tcc_comparison:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
- lhs_var);
+ lhs_var, target_expr, true, depth);
/* FALLTHRU */
case tcc_unary:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
- lhs_var);
+ lhs_var, target_expr, true, depth);
break;
case tcc_expression:
switch (TREE_CODE (expr))
@@ -13727,36 +13928,149 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
case TRUTH_XOR_EXPR:
case BIT_INSERT_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
/* FALLTHRU */
case TRUTH_NOT_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ break;
+ case MODIFY_EXPR:
+ if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
+ target_expr, true, depth))
+ break;
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var, target_expr, false,
+ depth);
+ break;
+ /* FALLTHRU */
+ case ADDR_EXPR:
+ if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
+ target_expr, true, depth))
+ break;
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var, target_expr, false,
+ depth);
break;
case COMPOUND_EXPR:
/* Break out any preevaluations from cp_build_modify_expr. */
for (; TREE_CODE (expr) == COMPOUND_EXPR;
expr = TREE_OPERAND (expr, 1))
- gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+ {
+ /* Special-case __builtin_clear_padding call before
+ __builtin_memcmp. */
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
+ {
+ tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
+ if (fndecl
+ && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
+ && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
+ && (!pre_p
+ || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
+ lhs_addr, lhs_var,
+ target_expr, true, depth)))
+ {
+ if (pre_p)
+ *expr_p = expr;
+ saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, true, depth);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, rhs, depth);
+ return saw_lhs;
+ }
+ }
+
+ if (pre_p)
+ gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+ }
+ if (!pre_p)
+ return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
+ target_expr, rhs, depth);
*expr_p = expr;
- return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
+ return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
+ target_expr, rhs, depth);
+ case COND_EXPR:
+ if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
+ lhs_var, target_expr, true, depth))
+ break;
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ break;
+ case TARGET_EXPR:
+ if (TARGET_EXPR_INITIAL (expr))
+ {
+ if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
+ lhs_var, target_expr, true,
+ depth))
+ break;
+ if (expr == target_expr)
+ saw_lhs = 1;
+ else
+ {
+ saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, true, depth);
+ if (saw_lhs && target_expr == NULL_TREE && pre_p)
+ target_expr = expr;
+ }
+ }
+ break;
default:
break;
}
break;
case tcc_reference:
- if (TREE_CODE (expr) == BIT_FIELD_REF)
+ if (TREE_CODE (expr) == BIT_FIELD_REF
+ || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true,
+ depth);
+ break;
+ case tcc_vl_exp:
+ if (TREE_CODE (expr) == CALL_EXPR)
+ {
+ if (tree fndecl = get_callee_fndecl (expr))
+ if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
+ || fndecl_built_in_p (fndecl, BUILT_IN_MEMCMP))
+ {
+ int nargs = call_expr_nargs (expr);
+ for (int i = 0; i < nargs; i++)
+ saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, true, depth);
+ }
+ }
break;
default:
break;
}
- if (saw_lhs == 0)
+ finish:
+ if (saw_lhs == 0 && pre_p)
{
enum gimplify_status gs;
- gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
+ if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
+ {
+ gimplify_stmt (&expr, pre_p);
+ return saw_lhs;
+ }
+ else if (rhs)
+ gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
+ else
+ gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
if (gs != GS_ALL_DONE)
saw_lhs = -1;
}
@@ -13776,9 +14090,12 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
tree tmp_load;
gomp_atomic_load *loadstmt;
gomp_atomic_store *storestmt;
+ tree target_expr = NULL_TREE;
tmp_load = create_tmp_reg (type);
- if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
+ if (rhs
+ && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
+ true, 0) < 0)
return GS_ERROR;
if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
@@ -13792,11 +14109,14 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
{
/* BIT_INSERT_EXPR is not valid for non-integral bitfield
representatives. Use BIT_FIELD_REF on the lhs instead. */
- if (TREE_CODE (rhs) == BIT_INSERT_EXPR
+ tree rhsarg = rhs;
+ if (TREE_CODE (rhs) == COND_EXPR)
+ rhsarg = TREE_OPERAND (rhs, 1);
+ if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
&& !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
{
- tree bitpos = TREE_OPERAND (rhs, 2);
- tree op1 = TREE_OPERAND (rhs, 1);
+ tree bitpos = TREE_OPERAND (rhsarg, 2);
+ tree op1 = TREE_OPERAND (rhsarg, 1);
tree bitsize;
tree tmp_store = tmp_load;
if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
@@ -13805,17 +14125,25 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
else
bitsize = TYPE_SIZE (TREE_TYPE (op1));
- gcc_assert (TREE_OPERAND (rhs, 0) == tmp_load);
- tree t = build2_loc (EXPR_LOCATION (rhs),
+ gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
+ tree t = build2_loc (EXPR_LOCATION (rhsarg),
MODIFY_EXPR, void_type_node,
- build3_loc (EXPR_LOCATION (rhs), BIT_FIELD_REF,
- TREE_TYPE (op1), tmp_store, bitsize,
- bitpos), op1);
+ build3_loc (EXPR_LOCATION (rhsarg),
+ BIT_FIELD_REF, TREE_TYPE (op1),
+ tmp_store, bitsize, bitpos), op1);
+ if (TREE_CODE (rhs) == COND_EXPR)
+ t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
+ TREE_OPERAND (rhs, 0), t, void_node);
gimplify_and_add (t, pre_p);
rhs = tmp_store;
}
- if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
- != GS_ALL_DONE)
+ bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
+ if (TREE_CODE (rhs) == COND_EXPR)
+ gimplify_ctxp->allow_rhs_cond_expr = true;
+ enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
+ is_gimple_val, fb_rvalue);
+ gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
+ if (gs != GS_ALL_DONE)
return GS_ERROR;
}
@@ -13823,6 +14151,11 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
rhs = tmp_load;
storestmt
= gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
+ if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
+ {
+ gimple_omp_atomic_set_weak (loadstmt);
+ gimple_omp_atomic_set_weak (storestmt);
+ }
gimplify_seq_add_stmt (pre_p, storestmt);
switch (TREE_CODE (*expr_p))
{
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 60ebb89..c17e3a4 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * go-lang.c (go_langhook_init_options_struct): Set also
+ x_flag_default_complex_method.
+
2021-06-29 Ian Lance Taylor <iant@golang.org>
* go-gcc.cc (Gcc_backend::static_chain_variable): Set
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index a01db8d..c3ae6f0 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -174,6 +174,7 @@ go_langhook_init_options_struct (struct gcc_options *opts)
/* Default to avoiding range issues for complex multiply and
divide. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
/* The builtin math functions should not set errno. */
opts->x_flag_errno_math = 0;
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 950f179..affba73 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-77bc32767b61feb6499ca7921e96b356603517dc
+925ace70ac7426c3f8b5c0bfb75aa9601f071de4
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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 8d4d168..ddb1d91 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -9350,7 +9350,7 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
ref2 = Expression::make_cast(uint_type, ref2, loc);
cond = Expression::make_binary(OPERATOR_GT, ref, ref2, loc);
zero = Expression::make_integer_ul(0, int_type, loc);
- call = Expression::make_conditional(cond, call, zero, loc);
+ call = Expression::make_conditional(cond, zero, call, loc);
}
}
else
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 9f8f4e9..9348354 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -999,7 +999,9 @@ class Expression
determine_type_no_context();
// Return the current type of the expression. This may be changed
- // by determine_type.
+ // by determine_type. This should not be called before the lowering
+ // pass, unless the is_type_expression method returns true (i.e.,
+ // this is an EXPRESSION_TYPE).
Type*
type()
{ return this->do_type(); }
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index e76600d..0f66661 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -2259,7 +2259,7 @@ Named_object*
Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
Function_type* equal_fntype)
{
- std::pair<Type*, Named_object*> val(name != NULL ? name : this, NULL);
+ std::pair<Type*, Named_object*> val(name != NULL ? name : this, nullptr);
std::pair<Type_function::iterator, bool> ins =
Type::type_equal_functions_table.insert(val);
if (!ins.second)
@@ -5050,6 +5050,7 @@ Function_type::get_backend_fntype(Gogo* gogo)
Struct_type* st = Type::make_struct_type(sfl,
this->location());
st->set_is_struct_incomparable();
+ st->set_is_results_struct();
ins.first->second = st->get_backend(gogo);
}
bresult_struct = ins.first->second;
@@ -6412,7 +6413,7 @@ Struct_type::interface_method_table(Interface_type* interface,
bool is_pointer)
{
std::pair<Struct_type*, Struct_type::Struct_method_table_pair*>
- val(this, NULL);
+ val(this, nullptr);
std::pair<Struct_type::Struct_method_tables::iterator, bool> ins =
Struct_type::struct_method_tables.insert(val);
@@ -6458,7 +6459,7 @@ get_backend_struct_fields(Gogo* gogo, Struct_type* type, bool use_placeholder,
saw_nonzero = true;
}
go_assert(i == fields->size());
- if (saw_nonzero && lastsize == 0)
+ if (saw_nonzero && lastsize == 0 && !type->is_results_struct())
{
// For nonzero-sized structs which end in a zero-sized thing, we add
// an extra byte of padding to the type. This padding ensures that
@@ -11788,8 +11789,9 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
{
stub = gogo->start_function(stub_name, stub_type, false,
fntype->location());
- Type::build_one_stub_method(gogo, m, buf, stub_params,
- fntype->is_varargs(), location);
+ Type::build_one_stub_method(gogo, m, buf, receiver_type, stub_params,
+ fntype->is_varargs(), stub_results,
+ location);
gogo->finish_function(fntype->location());
if (type->named_type() == NULL && stub->is_function())
@@ -11809,16 +11811,20 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
void
Type::build_one_stub_method(Gogo* gogo, Method* method,
const char* receiver_name,
+ const Type* receiver_type,
const Typed_identifier_list* params,
bool is_varargs,
+ const Typed_identifier_list* results,
Location location)
{
Named_object* receiver_object = gogo->lookup(receiver_name, NULL);
go_assert(receiver_object != NULL);
Expression* expr = Expression::make_var_reference(receiver_object, location);
- expr = Type::apply_field_indexes(expr, method->field_indexes(), location);
- if (expr->type()->points_to() == NULL)
+ const Type* expr_type = receiver_type;
+ expr = Type::apply_field_indexes(expr, method->field_indexes(), location,
+ &expr_type);
+ if (expr_type->points_to() == NULL)
expr = Expression::make_unary(OPERATOR_AND, expr, location);
Expression_list* arguments;
@@ -11843,8 +11849,7 @@ Type::build_one_stub_method(Gogo* gogo, Method* method,
go_assert(func != NULL);
Call_expression* call = Expression::make_call(func, arguments, is_varargs,
location);
-
- gogo->add_statement(Statement::make_return_from_call(call, location));
+ Type::add_return_from_results(gogo, call, results, location);
}
// Build direct interface stub methods for TYPE as needed. METHODS
@@ -11953,8 +11958,9 @@ Type::build_direct_iface_stub_methods(Gogo* gogo, const Type* type,
{
stub = gogo->start_function(stub_name, stub_type, false,
fntype->location());
- Type::build_one_iface_stub_method(gogo, m, buf, stub_params,
- fntype->is_varargs(), loc);
+ Type::build_one_iface_stub_method(gogo, m, buf, stub_params,
+ fntype->is_varargs(), stub_results,
+ loc);
gogo->finish_function(fntype->location());
if (type->named_type() == NULL && stub->is_function())
@@ -11981,7 +11987,9 @@ void
Type::build_one_iface_stub_method(Gogo* gogo, Method* method,
const char* receiver_name,
const Typed_identifier_list* params,
- bool is_varargs, Location loc)
+ bool is_varargs,
+ const Typed_identifier_list* results,
+ Location loc)
{
Named_object* receiver_object = gogo->lookup(receiver_name, NULL);
go_assert(receiver_object != NULL);
@@ -12013,31 +12021,63 @@ Type::build_one_iface_stub_method(Gogo* gogo, Method* method,
go_assert(func != NULL);
Call_expression* call = Expression::make_call(func, arguments, is_varargs,
loc);
+ Type::add_return_from_results(gogo, call, results, loc);
+}
- gogo->add_statement(Statement::make_return_from_call(call, loc));
+// Build and add a return statement from a call expression and a list
+// of result parameters. All we need to know is the number of
+// results.
+
+void
+Type::add_return_from_results(Gogo* gogo, Call_expression* call,
+ const Typed_identifier_list* results,
+ Location loc)
+{
+ Statement* s;
+ if (results == NULL || results->empty())
+ s = Statement::make_statement(call, true);
+ else
+ {
+ Expression_list* vals = new Expression_list();
+ size_t rc = results->size();
+ if (rc == 1)
+ vals->push_back(call);
+ else
+ {
+ for (size_t i = 0; i < rc; ++i)
+ vals->push_back(Expression::make_call_result(call, i));
+ }
+ s = Statement::make_return_statement(vals, loc);
+ }
+
+ gogo->add_statement(s);
}
// Apply FIELD_INDEXES to EXPR. The field indexes have to be applied
-// in reverse order.
+// in reverse order. *PEXPR_TYPE maintains the type of EXPR; we use
+// this to avoid calling EXPR->type() before the lowering pass.
Expression*
Type::apply_field_indexes(Expression* expr,
const Method::Field_indexes* field_indexes,
- Location location)
+ Location location,
+ const Type** pexpr_type)
{
if (field_indexes == NULL)
return expr;
- expr = Type::apply_field_indexes(expr, field_indexes->next, location);
- Struct_type* stype = expr->type()->deref()->struct_type();
+ expr = Type::apply_field_indexes(expr, field_indexes->next, location,
+ pexpr_type);
+ const Type* expr_type = *pexpr_type;
+ const Struct_type* stype = expr_type->deref()->struct_type();
go_assert(stype != NULL
&& field_indexes->field_index < stype->field_count());
- if (expr->type()->struct_type() == NULL)
+ if (expr_type->struct_type() == NULL)
{
- go_assert(expr->type()->points_to() != NULL);
+ go_assert(expr_type->points_to()->struct_type() == stype);
expr = Expression::make_dereference(expr, Expression::NIL_CHECK_DEFAULT,
location);
- go_assert(expr->type()->struct_type() == stype);
}
+ *pexpr_type = stype->field(field_indexes->field_index)->type();
return Expression::make_field_reference(expr, field_indexes->field_index,
location);
}
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index ca1ab49..a33453a 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1355,8 +1355,9 @@ class Type
static void
build_one_stub_method(Gogo*, Method*, const char* receiver_name,
+ const Type* receiver_type,
const Typed_identifier_list*, bool is_varargs,
- Location);
+ const Typed_identifier_list*, Location);
// Build direct interface stub methods for a type.
static void
@@ -1364,12 +1365,16 @@ class Type
static void
build_one_iface_stub_method(Gogo*, Method*, const char*,
- const Typed_identifier_list*,
- bool, Location);
+ const Typed_identifier_list*, bool,
+ const Typed_identifier_list*, Location);
+
+ static void
+ add_return_from_results(Gogo*, Call_expression*,
+ const Typed_identifier_list*, Location);
static Expression*
apply_field_indexes(Expression*, const Method::Field_indexes*,
- Location);
+ Location, const Type**);
// Look for a field or method named NAME in TYPE.
static bool
@@ -2501,7 +2506,8 @@ class Struct_type : public Type
Struct_type(Struct_field_list* fields, Location location)
: Type(TYPE_STRUCT),
fields_(fields), location_(location), all_methods_(NULL),
- is_struct_incomparable_(false), has_padding_(false)
+ is_struct_incomparable_(false), has_padding_(false),
+ is_results_struct_(false)
{ }
// Return the field NAME. This only looks at local fields, not at
@@ -2632,6 +2638,17 @@ class Struct_type : public Type
set_has_padding()
{ this->has_padding_ = true; }
+ // Return whether this is a results struct created to hold the
+ // results of a function that returns multiple results.
+ bool
+ is_results_struct() const
+ { return this->is_results_struct_; }
+
+ // Record that this is a results struct.
+ void
+ set_is_results_struct()
+ { this->is_results_struct_ = true; }
+
// Write the hash function for this type.
void
write_hash_function(Gogo*, Function_type*);
@@ -2742,6 +2759,9 @@ class Struct_type : public Type
// True if this struct's backend type has padding, due to trailing
// zero-sized field.
bool has_padding_;
+ // True if this is a results struct created to hold the results of a
+ // function that returns multiple results.
+ bool is_results_struct_;
};
// The type of an array.
diff --git a/gcc/graph.c b/gcc/graph.c
index ce8de33..9acd1d5 100644
--- a/gcc/graph.c
+++ b/gcc/graph.c
@@ -133,10 +133,11 @@ draw_cfg_node_succ_edges (pretty_printer *pp, int funcdef_no, basic_block bb)
weight = 10;
}
else if (e->flags & EDGE_FALLTHRU)
- {
- color = "blue";
- weight = 100;
- }
+ weight = 100;
+ else if (e->flags & EDGE_TRUE_VALUE)
+ color = "forestgreen";
+ else if (e->flags & EDGE_FALSE_VALUE)
+ color = "darkorange";
if (e->flags & EDGE_ABNORMAL)
color = "red";
diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c
index 6acc0d4..511d434 100644
--- a/gcc/hash-map-tests.c
+++ b/gcc/hash-map-tests.c
@@ -317,7 +317,8 @@ test_map_of_type_with_ctor_and_dtor ()
}
}
-/* Verify aspects of 'hash_table::expand'. */
+/* Verify aspects of 'hash_table::expand', in particular that it doesn't leak
+ Value objects. */
static void
test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline)
@@ -400,9 +401,9 @@ test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline)
ASSERT_EQ (val_t::ncopy, n_expand_moved);
ASSERT_EQ (val_t::nassign, 0);
if (remove_some_inline)
- ASSERT_EQ (val_t::ndtor, (i + 2) / 3);
+ ASSERT_EQ (val_t::ndtor, n_expand_moved + (i + 2) / 3);
else
- ASSERT_EQ (val_t::ndtor, 0);
+ ASSERT_EQ (val_t::ndtor, n_expand_moved);
/* Remove some inline. This never triggers an 'expand' here, but via
'm_n_deleted' does influence any following one. */
@@ -416,7 +417,7 @@ test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline)
ASSERT_EQ (val_t::ndefault, 1 + i);
ASSERT_EQ (val_t::ncopy, n_expand_moved);
ASSERT_EQ (val_t::nassign, 0);
- ASSERT_EQ (val_t::ndtor, 1 + (i + 2) / 3);
+ ASSERT_EQ (val_t::ndtor, n_expand_moved + 1 + (i + 2) / 3);
}
}
ASSERT_EQ (expand_c, expand_c_expected);
@@ -439,6 +440,7 @@ test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline)
ASSERT_EQ (val_t::nassign, nassign);
ASSERT_EQ (val_t::ndtor, ndtor);
}
+ ASSERT_EQ (val_t::ndefault + val_t::ncopy, val_t::ndtor);
}
/* Test calling empty on a hash_map that has a key type with non-zero
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index a6e0ac8..ff415c7 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -820,6 +820,9 @@ hash_table<Descriptor, Lazy, Allocator>::expand ()
{
value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
new ((void*) q) value_type (std::move (x));
+ /* After the resources of 'x' have been moved to a new object at 'q',
+ we now have to destroy the 'x' object, to end its lifetime. */
+ x.~value_type ();
}
p++;
diff --git a/gcc/input.c b/gcc/input.c
index 4b80986..dd753de 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -1437,6 +1437,11 @@ string_concat_db::record_string_concatenation (int num, location_t *locs)
gcc_assert (locs);
location_t key_loc = get_key_loc (locs[0]);
+ /* We don't record data for 'RESERVED_LOCATION_P (key_loc)' key values:
+ any data now recorded under key 'key_loc' would be overwritten by a
+ subsequent call with the same key 'key_loc'. */
+ if (RESERVED_LOCATION_P (key_loc))
+ return;
string_concat *concat
= new (ggc_alloc <string_concat> ()) string_concat (num, locs);
@@ -1460,6 +1465,10 @@ string_concat_db::get_string_concatenation (location_t loc,
gcc_assert (out_locs);
location_t key_loc = get_key_loc (loc);
+ /* We don't record data for 'RESERVED_LOCATION_P (key_loc)' key values; see
+ discussion in 'string_concat_db::record_string_concatenation'. */
+ if (RESERVED_LOCATION_P (key_loc))
+ return false;
string_concat **concat = m_table->get (key_loc);
if (!concat)
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 1360a00..9e10da0 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -53,6 +53,9 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "gimple-range.h"
+/* For lang_hooks.types.type_for_mode. */
+#include "langhooks.h"
+
/* The names of each internal function, indexed by function number. */
const char *const internal_fn_name_array[] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
@@ -2931,6 +2934,36 @@ expand_VEC_CONVERT (internal_fn, gcall *)
gcc_unreachable ();
}
+/* Expand IFN_RAWMEMCHAR internal function. */
+
+void
+expand_RAWMEMCHR (internal_fn, gcall *stmt)
+{
+ expand_operand ops[3];
+
+ tree lhs = gimple_call_lhs (stmt);
+ if (!lhs)
+ return;
+ machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
+ rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+ create_output_operand (&ops[0], lhs_rtx, lhs_mode);
+
+ tree mem = gimple_call_arg (stmt, 0);
+ rtx mem_rtx = get_memory_rtx (mem, NULL);
+ create_fixed_operand (&ops[1], mem_rtx);
+
+ tree pattern = gimple_call_arg (stmt, 1);
+ machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
+ rtx pattern_rtx = expand_normal (pattern);
+ create_input_operand (&ops[2], pattern_rtx, mode);
+
+ insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
+
+ expand_insn (icode, 3, ops);
+ if (!rtx_equal_p (lhs_rtx, ops[0].value))
+ emit_move_insn (lhs_rtx, ops[0].value);
+}
+
/* Expand the IFN_UNIQUE function according to its first argument. */
static void
@@ -2977,6 +3010,98 @@ expand_UNIQUE (internal_fn, gcall *stmt)
emit_insn (pattern);
}
+/* Expand the IFN_DEFERRED_INIT function:
+ LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA);
+
+ if IS_VLA is false, the LHS is the DECL itself,
+ if IS_VLA is true, the LHS is a MEM_REF whose address is the pointer
+ to this DECL.
+
+ Initialize the LHS with zero/pattern according to its second argument
+ INIT_TYPE:
+ if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
+ if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
+ to initialize;
+ The LHS variable is initialized including paddings.
+ The reasons to choose 0xFE for pattern initialization are:
+ 1. It is a non-canonical virtual address on x86_64, and at the
+ high end of the i386 kernel address space.
+ 2. It is a very large float value (-1.694739530317379e+38).
+ 3. It is also an unusual number for integers. */
+#define INIT_PATTERN_VALUE 0xFE
+static void
+expand_DEFERRED_INIT (internal_fn, gcall *stmt)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ tree var_size = gimple_call_arg (stmt, 0);
+ enum auto_init_type init_type
+ = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
+ bool reg_lhs = true;
+
+ tree var_type = TREE_TYPE (lhs);
+ gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
+
+ if (TREE_CODE (lhs) == SSA_NAME)
+ reg_lhs = true;
+ else
+ {
+ tree lhs_base = lhs;
+ while (handled_component_p (lhs_base))
+ lhs_base = TREE_OPERAND (lhs_base, 0);
+ reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
+ || non_mem_decl_p (lhs_base));
+ }
+
+ if (!reg_lhs)
+ {
+ /* If this is a VLA or the variable is not in register,
+ expand to a memset to initialize it. */
+ mark_addressable (lhs);
+ tree var_addr = build_fold_addr_expr (lhs);
+
+ tree value = (init_type == AUTO_INIT_PATTERN) ?
+ build_int_cst (integer_type_node,
+ INIT_PATTERN_VALUE) :
+ integer_zero_node;
+ tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
+ 3, var_addr, value, var_size);
+ /* Expand this memset call. */
+ expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
+ }
+ else
+ {
+ /* If this variable is in a register use expand_assignment. */
+ tree init;
+ if (tree_fits_uhwi_p (var_size)
+ && (init_type == AUTO_INIT_PATTERN
+ || !is_gimple_reg_type (var_type))
+ && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
+ 0).exists ())
+ {
+ unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
+ unsigned char *buf = (unsigned char *) xmalloc (total_bytes);
+ memset (buf, (init_type == AUTO_INIT_PATTERN
+ ? INIT_PATTERN_VALUE : 0), total_bytes);
+ if (can_native_interpret_type_p (var_type))
+ init = native_interpret_expr (var_type, buf, total_bytes);
+ else
+ {
+ tree itype = build_nonstandard_integer_type
+ (total_bytes * BITS_PER_UNIT, 1);
+ wide_int w = wi::from_buffer (buf, total_bytes);
+ init = wide_int_to_tree (itype, w);
+ /* Pun the LHS to make sure its type has constant size. */
+ lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
+ }
+ }
+ else
+ /* Use zero-init also for variable-length sizes. */
+ init = build_zero_cst (var_type);
+
+ expand_assignment (lhs, init, false);
+ }
+}
+
/* The size of an OpenACC compute dimension. */
static void
@@ -3784,7 +3909,8 @@ static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
T (BIT_IOR_EXPR, IFN_COND_IOR) \
T (BIT_XOR_EXPR, IFN_COND_XOR) \
T (LSHIFT_EXPR, IFN_COND_SHL) \
- T (RSHIFT_EXPR, IFN_COND_SHR)
+ T (RSHIFT_EXPR, IFN_COND_SHR) \
+ T (NEGATE_EXPR, IFN_COND_NEG)
/* Return a function that only performs CODE when a certain condition is met
and that uses a given fallback value otherwise. For example, if CODE is
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 3ac9ae6..bb13c6c 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -204,6 +204,8 @@ DEF_INTERNAL_OPTAB_FN (COND_FMS, ECF_CONST, cond_fms, cond_ternary)
DEF_INTERNAL_OPTAB_FN (COND_FNMA, ECF_CONST, cond_fnma, cond_ternary)
DEF_INTERNAL_OPTAB_FN (COND_FNMS, ECF_CONST, cond_fnms, cond_ternary)
+DEF_INTERNAL_OPTAB_FN (COND_NEG, ECF_CONST, cond_neg, cond_unary)
+
DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary)
DEF_INTERNAL_OPTAB_FN (REDUC_PLUS, ECF_CONST | ECF_NOTHROW,
@@ -352,6 +354,7 @@ DEF_INTERNAL_FN (MUL_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (TSAN_FUNC_EXIT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
DEF_INTERNAL_FN (VEC_CONVERT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (RAWMEMCHR, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL)
/* An unduplicable, uncombinable function. Generally used to preserve
a CFG property in the face of jump threading, tail merging or
@@ -360,6 +363,10 @@ DEF_INTERNAL_FN (VEC_CONVERT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (PHI, 0, NULL)
+/* A function to represent an artifical initialization to an uninitialized
+ automatic variable. */
+DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
/* DIM_SIZE and DIM_POS return the size of a particular compute
dimension and the executing thread's position within that
dimension. DIM_POS is pure (and not const) so that it isn't
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 55b9216..b987d97 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -184,30 +184,52 @@ public:
/* The actual value for the given parameter. */
valtype value;
/* The list of sources from which this value originates. */
- ipcp_value_source <valtype> *sources;
+ ipcp_value_source <valtype> *sources = nullptr;
/* Next pointers in a linked list of all values in a lattice. */
- ipcp_value *next;
+ ipcp_value *next = nullptr;
/* Next pointers in a linked list of values in a strongly connected component
of values. */
- ipcp_value *scc_next;
+ ipcp_value *scc_next = nullptr;
/* Next pointers in a linked list of SCCs of values sorted topologically
according their sources. */
- ipcp_value *topo_next;
+ ipcp_value *topo_next = nullptr;
/* A specialized node created for this value, NULL if none has been (so far)
created. */
- cgraph_node *spec_node;
+ cgraph_node *spec_node = nullptr;
/* Depth first search number and low link for topological sorting of
values. */
- int dfs, low_link;
+ int dfs = 0;
+ int low_link = 0;
+ /* SCC number to identify values which recursively feed into each other.
+ Values in the same SCC have the same SCC number. */
+ int scc_no = 0;
+ /* Non zero if the value is generated from another value in the same lattice
+ for a self-recursive call, the actual number is how many times the
+ operation has been performed. In the unlikely event of the value being
+ present in two chains fo self-recursive value generation chains, it is the
+ maximum. */
+ unsigned self_recursion_generated_level = 0;
/* True if this value is currently on the topo-sort stack. */
- bool on_stack;
-
- ipcp_value()
- : sources (0), next (0), scc_next (0), topo_next (0),
- spec_node (0), dfs (0), low_link (0), on_stack (false) {}
+ bool on_stack = false;
void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
HOST_WIDE_INT offset);
+
+ /* Return true if both THIS value and O feed into each other. */
+
+ bool same_scc (const ipcp_value<valtype> *o)
+ {
+ return o->scc_no == scc_no;
+ }
+
+/* Return true, if a this value has been generated for a self-recursive call as
+ a result of an arithmetic pass-through jump-function acting on a value in
+ the same lattice function. */
+
+ bool self_recursion_generated_p ()
+ {
+ return self_recursion_generated_level > 0;
+ }
};
/* Lattice describing potential values of a formal parameter of a function, or
@@ -239,7 +261,7 @@ public:
ipcp_value<valtype> *src_val = NULL,
int src_idx = 0, HOST_WIDE_INT offset = -1,
ipcp_value<valtype> **val_p = NULL,
- bool unlimited = false);
+ unsigned same_lat_gen_level = 0);
void print (FILE * f, bool dump_sources, bool dump_benefits);
};
@@ -498,7 +520,11 @@ ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
{
ipcp_value_source<valtype> *s;
- fprintf (f, " [from:");
+ if (val->self_recursion_generated_p ())
+ fprintf (f, " [self_gen(%i), from:",
+ val->self_recursion_generated_level);
+ else
+ fprintf (f, " [scc: %i, from:", val->scc_no);
for (s = val->sources; s; s = s->next)
fprintf (f, " %i(%f)", s->cs->caller->order,
s->cs->sreal_frequency ().to_double ());
@@ -1837,12 +1863,13 @@ ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
SOURCE and clear all other fields. */
static ipcp_value<tree> *
-allocate_and_init_ipcp_value (tree source)
+allocate_and_init_ipcp_value (tree cst, unsigned same_lat_gen_level)
{
ipcp_value<tree> *val;
val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>();
- val->value = source;
+ val->value = cst;
+ val->self_recursion_generated_level = same_lat_gen_level;
return val;
}
@@ -1850,14 +1877,15 @@ allocate_and_init_ipcp_value (tree source)
value to SOURCE and clear all other fields. */
static ipcp_value<ipa_polymorphic_call_context> *
-allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
+allocate_and_init_ipcp_value (ipa_polymorphic_call_context ctx,
+ unsigned same_lat_gen_level)
{
ipcp_value<ipa_polymorphic_call_context> *val;
- // TODO
val = new (ipcp_poly_ctx_values_pool.allocate ())
ipcp_value<ipa_polymorphic_call_context>();
- val->value = source;
+ val->value = ctx;
+ val->self_recursion_generated_level = same_lat_gen_level;
return val;
}
@@ -1865,8 +1893,12 @@ allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
meaning. OFFSET -1 means the source is scalar and not a part of an
aggregate. If non-NULL, VAL_P records address of existing or newly added
- ipcp_value. UNLIMITED means whether value count should not exceed the limit
- given by PARAM_IPA_CP_VALUE_LIST_SIZE. */
+ ipcp_value.
+
+ If the value is generated for a self-recursive call as a result of an
+ arithmetic pass-through jump-function acting on a value in the same lattice,
+ SAME_LAT_GEN_LEVEL must be the length of such chain, otherwise it must be
+ zero. If it is non-zero, PARAM_IPA_CP_VALUE_LIST_SIZE limit is ignored. */
template <typename valtype>
bool
@@ -1874,7 +1906,7 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
ipcp_value<valtype> *src_val,
int src_idx, HOST_WIDE_INT offset,
ipcp_value<valtype> **val_p,
- bool unlimited)
+ unsigned same_lat_gen_level)
{
ipcp_value<valtype> *val, *last_val = NULL;
@@ -1890,6 +1922,9 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
if (val_p)
*val_p = val;
+ if (val->self_recursion_generated_level < same_lat_gen_level)
+ val->self_recursion_generated_level = same_lat_gen_level;
+
if (ipa_edge_within_scc (cs))
{
ipcp_value_source<valtype> *s;
@@ -1904,7 +1939,7 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
return false;
}
- if (!unlimited && values_count == opt_for_fn (cs->caller->decl,
+ if (!same_lat_gen_level && values_count == opt_for_fn (cs->caller->decl,
param_ipa_cp_value_list_size))
{
/* We can only free sources, not the values themselves, because sources
@@ -1923,7 +1958,7 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
}
values_count++;
- val = allocate_and_init_ipcp_value (newval);
+ val = allocate_and_init_ipcp_value (newval, same_lat_gen_level);
val->add_source (cs, src_val, src_idx, offset);
val->next = NULL;
@@ -1940,60 +1975,6 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
return true;
}
-/* Return true, if a ipcp_value VAL is orginated from parameter value of
- self-feeding recursive function via some kind of pass-through jump
- function. */
-
-static bool
-self_recursively_generated_p (ipcp_value<tree> *val)
-{
- class ipa_node_params *info = NULL;
-
- for (ipcp_value_source<tree> *src = val->sources; src; src = src->next)
- {
- cgraph_edge *cs = src->cs;
-
- if (!src->val || cs->caller != cs->callee->function_symbol ())
- return false;
-
- if (src->val == val)
- continue;
-
- if (!info)
- info = ipa_node_params_sum->get (cs->caller);
-
- class ipcp_param_lattices *plats = ipa_get_parm_lattices (info,
- src->index);
- ipcp_lattice<tree> *src_lat;
- ipcp_value<tree> *src_val;
-
- if (src->offset == -1)
- src_lat = &plats->itself;
- else
- {
- struct ipcp_agg_lattice *src_aglat;
-
- for (src_aglat = plats->aggs; src_aglat; src_aglat = src_aglat->next)
- if (src_aglat->offset == src->offset)
- break;
-
- if (!src_aglat)
- return false;
-
- src_lat = src_aglat;
- }
-
- for (src_val = src_lat->values; src_val; src_val = src_val->next)
- if (src_val == val)
- break;
-
- if (!src_val)
- return false;
- }
-
- return true;
-}
-
/* A helper function that returns result of operation specified by OPCODE on
the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
value of SRC_VAL. If the operation is binary, OPND2 is a constant value
@@ -2068,7 +2049,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
source, this is absolutely conservative, but could avoid explosion
of lattice's value space, especially when one recursive function
calls another recursive. */
- if (self_recursively_generated_p (src_val))
+ if (src_val->self_recursion_generated_p ())
{
ipcp_value_source<tree> *s;
@@ -2096,7 +2077,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
break;
ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
- src_offset, &src_val, true);
+ src_offset, &src_val, j);
gcc_checking_assert (src_val);
}
}
@@ -2108,7 +2089,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
/* Now we do not use self-recursively generated value as propagation
source, otherwise it is easy to make value space of normal lattice
overflow. */
- if (self_recursively_generated_p (src_val))
+ if (src_val->self_recursion_generated_p ())
{
ret |= dest_lat->set_contains_variable ();
continue;
@@ -3732,6 +3713,7 @@ value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
v = stack;
stack = v->topo_next;
v->on_stack = false;
+ v->scc_no = cur_val->dfs;
v->scc_next = scc_list;
scc_list = v;
@@ -3905,8 +3887,25 @@ value_topo_info<valtype>::propagate_effects ()
else
continue;
}
+
+ int special_factor = 1;
+ if (val->same_scc (src->val))
+ special_factor
+ = opt_for_fn(src->cs->caller->decl,
+ param_ipa_cp_recursive_freq_factor);
+ else if (val->self_recursion_generated_p ()
+ && (src->cs->callee->function_symbol ()
+ == src->cs->caller))
+ {
+ int max_recur_gen_depth
+ = opt_for_fn(src->cs->caller->decl,
+ param_ipa_cp_max_recursive_depth);
+ special_factor = max_recur_gen_depth
+ - val->self_recursion_generated_level + 1;
+ }
+
src->val->prop_time_benefit
- += time * src->cs->sreal_frequency ();
+ += time * special_factor * src->cs->sreal_frequency ();
}
if (size < INT_MAX)
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 2470937..3119991 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -4652,7 +4652,6 @@ ipa_fn_summary_write (void)
info->time.stream_out (ob);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, info->inlinable, 1);
- bp_pack_value (&bp, false, 1);
bp_pack_value (&bp, info->fp_expressions, 1);
streamer_write_bitpack (&bp);
streamer_write_uhwi (ob, vec_safe_length (info->conds));
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 413446b..012b326 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -396,6 +396,23 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
e->inline_failed = CIF_SANITIZE_ATTRIBUTE_MISMATCH;
inlinable = false;
}
+ else if (profile_arc_flag
+ && (lookup_attribute ("no_profile_instrument_function",
+ DECL_ATTRIBUTES (caller->decl)) == NULL_TREE)
+ != (lookup_attribute ("no_profile_instrument_function",
+ DECL_ATTRIBUTES (callee->decl)) == NULL_TREE))
+ {
+ cgraph_node *origin = caller;
+ while (origin->clone_of)
+ origin = origin->clone_of;
+
+ if (!DECL_STRUCT_FUNCTION (origin->decl)->always_inline_functions_inlined)
+ {
+ e->inline_failed = CIF_UNSPECIFIED;
+ inlinable = false;
+ }
+ }
+
if (!inlinable && report)
report_inline_failed_reason (e);
return inlinable;
diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h
index a86e684..9976e48 100644
--- a/gcc/ipa-modref-tree.h
+++ b/gcc/ipa-modref-tree.h
@@ -110,8 +110,11 @@ struct GTY(()) modref_access_node
if (!a.parm_offset_known)
return false;
/* Accesses are never below parm_offset, so look
- for smaller offset. */
- if (!known_le (parm_offset, a.parm_offset))
+ for smaller offset.
+ If access ranges are known still allow merging
+ when bit offsets comparsion passes. */
+ if (!known_le (parm_offset, a.parm_offset)
+ && !range_info_useful_p ())
return false;
aoffset_adj = (a.parm_offset - parm_offset)
<< LOG2_BITS_PER_UNIT;
@@ -145,7 +148,8 @@ struct GTY(()) modref_access_node
poly_int64 offset1, poly_int64 size1, poly_int64 max_size1,
bool record_adjustments)
{
- if (known_eq (offset, offset1)
+ if (known_eq (parm_offset, parm_offset1)
+ && known_eq (offset, offset1)
&& known_eq (size, size1)
&& known_eq (max_size, max_size1))
return;
@@ -196,8 +200,9 @@ struct GTY(()) modref_access_node
was prolonged and punt when there are too many. */
bool merge (const modref_access_node &a, bool record_adjustments)
{
- poly_int64 aoffset_adj = 0, offset_adj = 0;
- poly_int64 new_parm_offset = parm_offset;
+ poly_int64 offset1 = 0;
+ poly_int64 aoffset1 = 0;
+ poly_int64 new_parm_offset = 0;
/* We assume that containment was tested earlier. */
gcc_checking_assert (!contains (a) && !a.contains (*this));
@@ -209,29 +214,13 @@ struct GTY(()) modref_access_node
{
if (!a.parm_offset_known)
return false;
- if (known_le (a.parm_offset, parm_offset))
- {
- offset_adj = (parm_offset - a.parm_offset)
- << LOG2_BITS_PER_UNIT;
- aoffset_adj = 0;
- new_parm_offset = a.parm_offset;
- }
- else if (known_le (parm_offset, a.parm_offset))
- {
- aoffset_adj = (a.parm_offset - parm_offset)
- << LOG2_BITS_PER_UNIT;
- offset_adj = 0;
- }
- else
+ if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
return false;
}
}
/* See if we can merge ranges. */
if (range_info_useful_p ())
{
- poly_int64 offset1 = offset + offset_adj;
- poly_int64 aoffset1 = a.offset + aoffset_adj;
-
/* In this case we have containment that should be
handled earlier. */
gcc_checking_assert (a.range_info_useful_p ());
@@ -255,46 +244,207 @@ struct GTY(()) modref_access_node
return false;
if (known_le (offset1, aoffset1))
{
- if (!known_size_p (max_size))
- {
- update (new_parm_offset, offset1, size, max_size,
- record_adjustments);
- return true;
- }
- else if (known_ge (offset1 + max_size, aoffset1))
+ if (!known_size_p (max_size)
+ || known_ge (offset1 + max_size, aoffset1))
{
- poly_int64 new_max_size = max_size;
- if (known_le (max_size, a.max_size + aoffset1 - offset1))
- new_max_size = a.max_size + aoffset1 - offset1;
- update (new_parm_offset, offset1, size, new_max_size,
- record_adjustments);
+ update2 (new_parm_offset, offset1, size, max_size,
+ aoffset1, a.size, a.max_size,
+ record_adjustments);
return true;
}
}
else if (known_le (aoffset1, offset1))
{
- if (!known_size_p (a.max_size))
+ if (!known_size_p (a.max_size)
+ || known_ge (aoffset1 + a.max_size, offset1))
{
- update (new_parm_offset, aoffset1, size, a.max_size,
- record_adjustments);
- return true;
- }
- else if (known_ge (aoffset1 + a.max_size, offset1))
- {
- poly_int64 new_max_size = a.max_size;
- if (known_le (a.max_size, max_size + offset1 - aoffset1))
- new_max_size = max_size + offset1 - aoffset1;
- update (new_parm_offset, aoffset1, size, new_max_size,
- record_adjustments);
+ update2 (new_parm_offset, offset1, size, max_size,
+ aoffset1, a.size, a.max_size,
+ record_adjustments);
return true;
}
}
return false;
}
- update (new_parm_offset, offset + offset_adj,
+ update (new_parm_offset, offset1,
size, max_size, record_adjustments);
return true;
}
+ /* Return true if A1 and B1 can be merged with lower informatoin
+ less than A2 and B2.
+ Assume that no containment or lossless merging is possible. */
+ static bool closer_pair_p (const modref_access_node &a1,
+ const modref_access_node &b1,
+ const modref_access_node &a2,
+ const modref_access_node &b2)
+ {
+ /* Merging different parm indexes comes to complete loss
+ of range info. */
+ if (a1.parm_index != b1.parm_index)
+ return false;
+ if (a2.parm_index != b2.parm_index)
+ return true;
+ /* If parm is known and parm indexes are the same we should
+ already have containment. */
+ gcc_checking_assert (a1.parm_offset_known && b1.parm_offset_known);
+ gcc_checking_assert (a2.parm_offset_known && b2.parm_offset_known);
+
+ /* First normalize offsets for parm offsets. */
+ poly_int64 new_parm_offset, offseta1, offsetb1, offseta2, offsetb2;
+ if (!a1.combined_offsets (b1, &new_parm_offset, &offseta1, &offsetb1)
+ || !a2.combined_offsets (b2, &new_parm_offset, &offseta2, &offsetb2))
+ gcc_unreachable ();
+
+
+ /* Now compute distnace of the intervals. */
+ poly_int64 dist1, dist2;
+ if (known_le (offseta1, offsetb1))
+ {
+ if (!known_size_p (a1.max_size))
+ dist1 = 0;
+ else
+ dist1 = offsetb1 - offseta1 - a1.max_size;
+ }
+ else
+ {
+ if (!known_size_p (b1.max_size))
+ dist1 = 0;
+ else
+ dist1 = offseta1 - offsetb1 - b1.max_size;
+ }
+ if (known_le (offseta2, offsetb2))
+ {
+ if (!known_size_p (a2.max_size))
+ dist2 = 0;
+ else
+ dist2 = offsetb2 - offseta2 - a2.max_size;
+ }
+ else
+ {
+ if (!known_size_p (b2.max_size))
+ dist2 = 0;
+ else
+ dist2 = offseta2 - offsetb2 - b2.max_size;
+ }
+ /* It may happen that intervals overlap in case size
+ is different. Preffer the overlap to non-overlap. */
+ if (known_lt (dist1, 0) && known_ge (dist2, 0))
+ return true;
+ if (known_lt (dist2, 0) && known_ge (dist1, 0))
+ return false;
+ if (known_lt (dist1, 0))
+ /* If both overlaps minimize overlap. */
+ return known_le (dist2, dist1);
+ else
+ /* If both are disjoint look for smaller distance. */
+ return known_le (dist1, dist2);
+ }
+
+ /* Merge in access A while losing precision. */
+ void forced_merge (const modref_access_node &a, bool record_adjustments)
+ {
+ if (parm_index != a.parm_index)
+ {
+ gcc_checking_assert (parm_index != -1);
+ parm_index = -1;
+ return;
+ }
+
+ /* We assume that containment and lossless merging
+ was tested earlier. */
+ gcc_checking_assert (!contains (a) && !a.contains (*this)
+ && !merge (a, record_adjustments));
+ gcc_checking_assert (parm_offset_known && a.parm_offset_known);
+
+ poly_int64 new_parm_offset, offset1, aoffset1;
+ if (!combined_offsets (a, &new_parm_offset, &offset1, &aoffset1))
+ {
+ parm_offset_known = false;
+ return;
+ }
+ gcc_checking_assert (range_info_useful_p ()
+ && a.range_info_useful_p ());
+ if (record_adjustments)
+ adjustments += a.adjustments;
+ update2 (new_parm_offset,
+ offset1, size, max_size,
+ aoffset1, a.size, a.max_size,
+ record_adjustments);
+ }
+private:
+ /* Merge two ranges both starting at parm_offset1 and update THIS
+ with result. */
+ void update2 (poly_int64 parm_offset1,
+ poly_int64 offset1, poly_int64 size1, poly_int64 max_size1,
+ poly_int64 offset2, poly_int64 size2, poly_int64 max_size2,
+ bool record_adjustments)
+ {
+ poly_int64 new_size = size1;
+
+ if (!known_size_p (size2)
+ || known_le (size2, size1))
+ new_size = size2;
+ else
+ gcc_checking_assert (known_le (size1, size2));
+
+ if (known_le (offset1, offset2))
+ ;
+ else if (known_le (offset2, offset1))
+ {
+ std::swap (offset1, offset2);
+ std::swap (max_size1, max_size2);
+ }
+ else
+ gcc_unreachable ();
+
+ poly_int64 new_max_size;
+
+ if (!known_size_p (max_size1))
+ new_max_size = max_size1;
+ else if (!known_size_p (max_size2))
+ new_max_size = max_size2;
+ else
+ {
+ new_max_size = max_size2 + offset2 - offset1;
+ if (known_le (new_max_size, max_size1))
+ new_max_size = max_size1;
+ }
+
+ update (parm_offset1, offset1,
+ new_size, new_max_size, record_adjustments);
+ }
+ /* Given access nodes THIS and A, return true if they
+ can be done with common parm_offsets. In this case
+ return parm offset in new_parm_offset, new_offset
+ which is start of range in THIS and new_aoffset that
+ is start of range in A. */
+ bool combined_offsets (const modref_access_node &a,
+ poly_int64 *new_parm_offset,
+ poly_int64 *new_offset,
+ poly_int64 *new_aoffset) const
+ {
+ gcc_checking_assert (parm_offset_known && a.parm_offset_known);
+ if (known_le (a.parm_offset, parm_offset))
+ {
+ *new_offset = offset
+ + ((parm_offset - a.parm_offset)
+ << LOG2_BITS_PER_UNIT);
+ *new_aoffset = a.offset;
+ *new_parm_offset = a.parm_offset;
+ return true;
+ }
+ else if (known_le (parm_offset, a.parm_offset))
+ {
+ *new_aoffset = a.offset
+ + ((a.parm_offset - parm_offset)
+ << LOG2_BITS_PER_UNIT);
+ *new_offset = offset;
+ *new_parm_offset = parm_offset;
+ return true;
+ }
+ else
+ return false;
+ }
};
/* Access node specifying no useful info. */
@@ -348,7 +498,7 @@ struct GTY((user)) modref_ref_node
return false;
/* Otherwise, insert a node for the ref of the access under the base. */
- size_t i;
+ size_t i, j;
modref_access_node *a2;
if (flag_checking)
@@ -390,11 +540,64 @@ struct GTY((user)) modref_ref_node
all accesses and bail out. */
if (accesses && accesses->length () >= max_accesses)
{
- if (dump_file)
+ if (max_accesses < 2)
+ {
+ collapse ();
+ if (dump_file)
+ fprintf (dump_file,
+ "--param param=modref-max-accesses limit reached;"
+ " collapsing\n");
+ return true;
+ }
+ /* Find least harmful merge and perform it. */
+ int best1 = -1, best2 = -1;
+ FOR_EACH_VEC_SAFE_ELT (accesses, i, a2)
+ {
+ for (j = i + 1; j < accesses->length (); j++)
+ if (best1 < 0
+ || modref_access_node::closer_pair_p
+ (*a2, (*accesses)[j],
+ (*accesses)[best1],
+ best2 < 0 ? a : (*accesses)[best2]))
+ {
+ best1 = i;
+ best2 = j;
+ }
+ if (modref_access_node::closer_pair_p
+ (*a2, a,
+ (*accesses)[best1],
+ best2 < 0 ? a : (*accesses)[best2]))
+ {
+ best1 = i;
+ best2 = -1;
+ }
+ }
+ (*accesses)[best1].forced_merge (best2 < 0 ? a : (*accesses)[best2],
+ record_adjustments);
+ /* Check that merging indeed merged ranges. */
+ gcc_checking_assert ((*accesses)[best1].contains
+ (best2 < 0 ? a : (*accesses)[best2]));
+ if (!(*accesses)[best1].useful_p ())
+ {
+ collapse ();
+ if (dump_file)
+ fprintf (dump_file,
+ "--param param=modref-max-accesses limit reached;"
+ " collapsing\n");
+ return true;
+ }
+ if (dump_file && best2 >= 0)
fprintf (dump_file,
- "--param param=modref-max-accesses limit reached\n");
- collapse ();
- return true;
+ "--param param=modref-max-accesses limit reached;"
+ " merging %i and %i\n", best1, best2);
+ else if (dump_file)
+ fprintf (dump_file,
+ "--param param=modref-max-accesses limit reached;"
+ " merging with %i\n", best1);
+ try_merge_with (best1);
+ if (best2 >= 0)
+ insert_access (a, max_accesses, record_adjustments);
+ return 1;
}
a.adjustments = 0;
vec_safe_push (accesses, a);
@@ -418,6 +621,7 @@ private:
found = true;
if (!found && n->merge (*a, false))
found = restart = true;
+ gcc_checking_assert (found || !a->merge (*n, false));
if (found)
{
accesses->unordered_remove (i);
@@ -808,6 +1012,31 @@ struct GTY((user)) modref_tree
return NULL;
}
+ /* Return true if tree contains access to global memory. */
+ bool global_access_p ()
+ {
+ size_t i, j, k;
+ modref_base_node <T> *base_node;
+ modref_ref_node <T> *ref_node;
+ modref_access_node *access_node;
+ if (every_base)
+ return true;
+ FOR_EACH_VEC_SAFE_ELT (bases, i, base_node)
+ {
+ if (base_node->every_ref)
+ return true;
+ FOR_EACH_VEC_SAFE_ELT (base_node->refs, j, ref_node)
+ {
+ if (ref_node->every_access)
+ return true;
+ FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node)
+ if (access_node->parm_index < 0)
+ return true;
+ }
+ }
+ return false;
+ }
+
/* Return ggc allocated instance. We explicitly call destructors via
ggc_delete and do not want finalizers to be registered and
called at the garbage collection time. */
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index 6e7788e..0bbec8d 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3. If not see
#include "ssa-iterators.h"
#include "stringpool.h"
#include "tree-ssanames.h"
+#include "attribs.h"
namespace {
@@ -280,17 +281,6 @@ modref_summary::~modref_summary ()
ggc_delete (stores);
}
-/* All flags that are implied by the ECF_CONST functions. */
-const int implicit_const_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
- | EAF_NODIRECTESCAPE | EAF_NOREAD;
-/* All flags that are implied by the ECF_PURE function. */
-const int implicit_pure_eaf_flags = EAF_NOCLOBBER | EAF_NOESCAPE
- | EAF_NODIRECTESCAPE;
-/* All flags implied when we know we can ignore stores (i.e. when handling
- call to noreturn). */
-const int ignore_stores_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
- | EAF_NODIRECTESCAPE;
-
/* Remove all flags from EAF_FLAGS that are implied by ECF_FLAGS and not
useful to track. If returns_void is true moreover clear
EAF_NOT_RETURNED. */
@@ -305,10 +295,6 @@ remove_useless_eaf_flags (int eaf_flags, int ecf_flags, bool returns_void)
eaf_flags &= ~implicit_pure_eaf_flags;
else if ((ecf_flags & ECF_NORETURN) || returns_void)
eaf_flags &= ~EAF_NOT_RETURNED;
- /* Only NOCLOBBER or DIRECT flags alone are not useful (see comments
- in tree-ssa-alias.c). Give up earlier. */
- if ((eaf_flags & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
- return 0;
return eaf_flags;
}
@@ -345,6 +331,26 @@ modref_summary::useful_p (int ecf_flags, bool check_flags)
return stores && !stores->every_base;
}
+/* Return true if global memory is read
+ (that is loads summary contains global memory access). */
+bool
+modref_summary::global_memory_read_p ()
+{
+ if (!loads)
+ return true;
+ return loads->global_access_p ();
+}
+
+/* Return true if global memory is written. */
+bool
+modref_summary::global_memory_written_p ()
+{
+ if (!stores)
+ return true;
+ return stores->global_access_p ();
+}
+
+
/* Single function summary used for LTO. */
typedef modref_tree <tree> modref_records_lto;
@@ -2016,7 +2022,8 @@ analyze_function (function *f, bool ipa)
DECL_PURE_P (current_function_decl) ? " (pure)" : "");
/* Don't analyze this function if it's compiled with -fno-strict-aliasing. */
- if (!flag_ipa_modref)
+ if (!flag_ipa_modref
+ || lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)))
return;
/* Compute no-LTO summaries when local optimization is going to happen. */
@@ -2125,7 +2132,8 @@ analyze_function (function *f, bool ipa)
FOR_EACH_BB_FN (bb, f)
{
gimple_stmt_iterator si;
- for (si = gsi_after_labels (bb); !gsi_end_p (si); gsi_next (&si))
+ for (si = gsi_start_nondebug_after_labels_bb (bb);
+ !gsi_end_p (si); gsi_next_nondebug (&si))
{
if (!analyze_stmt (summary, summary_lto,
gsi_stmt (si), ipa, &recursive_calls)
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index 540fdea..5afa3aa 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -37,10 +37,23 @@ struct GTY(()) modref_summary
~modref_summary ();
void dump (FILE *);
bool useful_p (int ecf_flags, bool check_flags = true);
+ bool global_memory_read_p ();
+ bool global_memory_written_p ();
};
modref_summary *get_modref_function_summary (cgraph_node *func);
void ipa_modref_c_finalize ();
void ipa_merge_modref_summary_after_inlining (cgraph_edge *e);
+/* All flags that are implied by the ECF_CONST functions. */
+static const int implicit_const_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
+ | EAF_NODIRECTESCAPE | EAF_NOREAD;
+/* All flags that are implied by the ECF_PURE function. */
+static const int implicit_pure_eaf_flags = EAF_NOCLOBBER | EAF_NOESCAPE
+ | EAF_NODIRECTESCAPE;
+/* All flags implied when we know we can ignore stores (i.e. when handling
+ call to noreturn). */
+static const int ignore_stores_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
+ | EAF_NODIRECTESCAPE;
+
#endif
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 1c69d97..443f21c 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -4428,19 +4428,33 @@ ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
dst_jf->value.constant.rdesc = NULL;
else if (src->caller == dst->caller)
{
- struct ipa_ref *ref;
- symtab_node *n = symtab_node_for_jfunc (src_jf);
- gcc_checking_assert (n);
- ref = src->caller->find_reference (n, src->call_stmt,
- src->lto_stmt_uid);
- gcc_checking_assert (ref);
- dst->caller->clone_reference (ref, ref->stmt);
-
- struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
- dst_rdesc->cs = dst;
- dst_rdesc->refcount = src_rdesc->refcount;
- dst_rdesc->next_duplicate = NULL;
- dst_jf->value.constant.rdesc = dst_rdesc;
+ /* Creation of a speculative edge. If the source edge is the one
+ grabbing a reference, we must create a new (duplicate)
+ reference description. Otherwise they refer to the same
+ description corresponding to a reference taken in a function
+ src->caller is inlined to. In that case we just must
+ increment the refcount. */
+ if (src_rdesc->cs == src)
+ {
+ symtab_node *n = symtab_node_for_jfunc (src_jf);
+ gcc_checking_assert (n);
+ ipa_ref *ref
+ = src->caller->find_reference (n, src->call_stmt,
+ src->lto_stmt_uid);
+ gcc_checking_assert (ref);
+ dst->caller->clone_reference (ref, ref->stmt);
+
+ ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
+ dst_rdesc->cs = dst;
+ dst_rdesc->refcount = src_rdesc->refcount;
+ dst_rdesc->next_duplicate = NULL;
+ dst_jf->value.constant.rdesc = dst_rdesc;
+ }
+ else
+ {
+ src_rdesc->refcount++;
+ dst_jf->value.constant.rdesc = src_rdesc;
+ }
}
else if (src_rdesc->cs == src)
{
diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
index 965e246..8803659 100644
--- a/gcc/ipa-sra.c
+++ b/gcc/ipa-sra.c
@@ -1005,15 +1005,17 @@ ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
if (gimple_assign_single_p (stmt))
{
tree rhs = gimple_assign_rhs1 (stmt);
- while (handled_component_p (rhs))
- rhs = TREE_OPERAND (rhs, 0);
- if (TREE_CODE (rhs) == MEM_REF
- && TREE_OPERAND (rhs, 0) == name
- && integer_zerop (TREE_OPERAND (rhs, 1))
- && types_compatible_p (TREE_TYPE (rhs),
- TREE_TYPE (TREE_TYPE (name)))
- && !TREE_THIS_VOLATILE (rhs))
- uses_ok++;
+ if (!TREE_THIS_VOLATILE (rhs))
+ {
+ while (handled_component_p (rhs))
+ rhs = TREE_OPERAND (rhs, 0);
+ if (TREE_CODE (rhs) == MEM_REF
+ && TREE_OPERAND (rhs, 0) == name
+ && integer_zerop (TREE_OPERAND (rhs, 1))
+ && types_compatible_p (TREE_TYPE (rhs),
+ TREE_TYPE (TREE_TYPE (name))))
+ uses_ok++;
+ }
}
else if (is_gimple_call (stmt))
{
@@ -1047,15 +1049,17 @@ ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
continue;
}
- while (handled_component_p (arg))
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (arg) == MEM_REF
- && TREE_OPERAND (arg, 0) == name
- && integer_zerop (TREE_OPERAND (arg, 1))
- && types_compatible_p (TREE_TYPE (arg),
- TREE_TYPE (TREE_TYPE (name)))
- && !TREE_THIS_VOLATILE (arg))
- uses_ok++;
+ if (!TREE_THIS_VOLATILE (arg))
+ {
+ while (handled_component_p (arg))
+ arg = TREE_OPERAND (arg, 0);
+ if (TREE_CODE (arg) == MEM_REF
+ && TREE_OPERAND (arg, 0) == name
+ && integer_zerop (TREE_OPERAND (arg, 1))
+ && types_compatible_p (TREE_TYPE (arg),
+ TREE_TYPE (TREE_TYPE (name))))
+ uses_ok++;
+ }
}
}
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 4212065..2a30efc 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -629,7 +629,7 @@ ior_hard_reg_conflicts (ira_allocno_t a, const_hard_reg_set set)
bool
ira_conflict_vector_profitable_p (ira_object_t obj, int num)
{
- int nw;
+ int nbytes;
int max = OBJECT_MAX (obj);
int min = OBJECT_MIN (obj);
@@ -638,9 +638,14 @@ ira_conflict_vector_profitable_p (ira_object_t obj, int num)
in allocation. */
return false;
- nw = (max - min + IRA_INT_BITS) / IRA_INT_BITS;
- return (2 * sizeof (ira_object_t) * (num + 1)
- < 3 * nw * sizeof (IRA_INT_TYPE));
+ nbytes = (max - min) / 8 + 1;
+ STATIC_ASSERT (sizeof (ira_object_t) <= 8);
+ /* Don't use sizeof (ira_object_t), use constant 8. Size of ira_object_t (a
+ pointer) is different on 32-bit and 64-bit targets. Usage sizeof
+ (ira_object_t) can result in different code generation by GCC built as 32-
+ and 64-bit program. In any case the profitability is just an estimation
+ and border cases are rare. */
+ return (2 * 8 /* sizeof (ira_object_t) */ * (num + 1) < 3 * nbytes);
}
/* Allocates and initialize the conflict vector of OBJ for NUM
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index c7379f3..334fd39 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,11 @@
+2021-09-10 Petter Tomner <tomner@kth.se>
+
+ * jit-playback.c: Moved global var processing to after loc handling.
+ Setting TYPE_NAME for fundamental types.
+ Using common functions for finalizing globals.
+ * jit-playback.h: New method init_types().
+ Changed get_tree_node_for_type() to method.
+
2021-08-19 Iain Sandoe <iain@sandoe.co.uk>
* docs/examples/tut04-toyvm/toyvm.c: Include jit-dejagnu.h.
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 79ac525..59399de 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -165,7 +165,8 @@ gt_ggc_mx ()
/* Given an enum gcc_jit_types value, get a "tree" type. */
-static tree
+tree
+playback::context::
get_tree_node_for_type (enum gcc_jit_types type_)
{
switch (type_)
@@ -192,11 +193,7 @@ get_tree_node_for_type (enum gcc_jit_types type_)
return short_unsigned_type_node;
case GCC_JIT_TYPE_CONST_CHAR_PTR:
- {
- tree const_char = build_qualified_type (char_type_node,
- TYPE_QUAL_CONST);
- return build_pointer_type (const_char);
- }
+ return m_const_char_ptr;
case GCC_JIT_TYPE_INT:
return integer_type_node;
@@ -579,10 +576,6 @@ playback::lvalue *
playback::context::
global_finalize_lvalue (tree inner)
{
- varpool_node::get_create (inner);
-
- varpool_node::finalize_decl (inner);
-
m_globals.safe_push (inner);
return new lvalue (this, inner);
@@ -2952,9 +2945,7 @@ replay ()
{
JIT_LOG_SCOPE (get_logger ());
- m_const_char_ptr
- = build_pointer_type (build_qualified_type (char_type_node,
- TYPE_QUAL_CONST));
+ init_types ();
/* Replay the recorded events: */
timevar_push (TV_JIT_REPLAY);
@@ -2984,10 +2975,17 @@ replay ()
{
int i;
function *func;
-
+ tree global;
/* No GC can happen yet; process the cached source locations. */
handle_locations ();
+ /* Finalize globals. See how FORTRAN 95 does it in gfc_be_parse_file()
+ for a simple reference. */
+ FOR_EACH_VEC_ELT (m_globals, i, global)
+ rest_of_decl_compilation (global, true, true);
+
+ wrapup_global_declarations (m_globals.address(), m_globals.length());
+
/* We've now created tree nodes for the stmts in the various blocks
in each function, but we haven't built each function's single stmt
list yet. Do so now. */
@@ -3081,6 +3079,50 @@ location_comparator (const void *lhs, const void *rhs)
return loc_lhs->get_column_num () - loc_rhs->get_column_num ();
}
+/* Initialize the NAME_TYPE of the primitive types as well as some
+ others. */
+void
+playback::context::
+init_types ()
+{
+ /* See lto_init() in lto-lang.c or void visit (TypeBasic *t) in D's types.cc
+ for reference. If TYPE_NAME is not set, debug info will not contain types */
+#define NAME_TYPE(t,n) \
+if (t) \
+ TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL, \
+ get_identifier (n), t)
+
+ NAME_TYPE (integer_type_node, "int");
+ NAME_TYPE (char_type_node, "char");
+ NAME_TYPE (long_integer_type_node, "long int");
+ NAME_TYPE (unsigned_type_node, "unsigned int");
+ NAME_TYPE (long_unsigned_type_node, "long unsigned int");
+ NAME_TYPE (long_long_integer_type_node, "long long int");
+ NAME_TYPE (long_long_unsigned_type_node, "long long unsigned int");
+ NAME_TYPE (short_integer_type_node, "short int");
+ NAME_TYPE (short_unsigned_type_node, "short unsigned int");
+ if (signed_char_type_node != char_type_node)
+ NAME_TYPE (signed_char_type_node, "signed char");
+ if (unsigned_char_type_node != char_type_node)
+ NAME_TYPE (unsigned_char_type_node, "unsigned char");
+ NAME_TYPE (float_type_node, "float");
+ NAME_TYPE (double_type_node, "double");
+ NAME_TYPE (long_double_type_node, "long double");
+ NAME_TYPE (void_type_node, "void");
+ NAME_TYPE (boolean_type_node, "bool");
+ NAME_TYPE (complex_float_type_node, "complex float");
+ NAME_TYPE (complex_double_type_node, "complex double");
+ NAME_TYPE (complex_long_double_type_node, "complex long double");
+
+ m_const_char_ptr = build_pointer_type(
+ build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+ NAME_TYPE (m_const_char_ptr, "char");
+ NAME_TYPE (size_type_node, "size_t");
+ NAME_TYPE (fileptr_type_node, "FILE");
+#undef NAME_TYPE
+}
+
/* Our API allows locations to be created in arbitrary orders, but the
linemap API requires locations to be created in ascending order
as if we were tokenizing files.
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 825a3e1..f670c9e 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -271,8 +271,13 @@ private:
source_file *
get_source_file (const char *filename);
+ tree
+ get_tree_node_for_type (enum gcc_jit_types type_);
+
void handle_locations ();
+ void init_types ();
+
const char * get_path_c_file () const;
const char * get_path_s_file () const;
const char * get_path_so_file () const;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index a56080b..8f75125 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1276,7 +1276,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
sclass = dclass = NO_REGS;
if (REG_P (dreg))
dclass = get_reg_class (REGNO (dreg));
- gcc_assert (dclass < LIM_REG_CLASSES);
+ gcc_assert (dclass < LIM_REG_CLASSES && dclass >= NO_REGS);
if (dclass == ALL_REGS)
/* ALL_REGS is used for new pseudos created by transformations
like reload of SUBREG_REG (see function
@@ -1288,7 +1288,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
return false;
if (REG_P (sreg))
sclass = get_reg_class (REGNO (sreg));
- gcc_assert (sclass < LIM_REG_CLASSES);
+ gcc_assert (sclass < LIM_REG_CLASSES && sclass >= NO_REGS);
if (sclass == ALL_REGS)
/* See comments above. */
return false;
@@ -5799,11 +5799,12 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
part of a multi-word register. In that case, just use the reg_rtx
mode. Do the same also if the biggest mode was larger than a register
or we can not compare the modes. Otherwise, limit the size to that of
- the biggest access in the function. */
+ the biggest access in the function or to the natural mode at least. */
if (mode == VOIDmode
|| !ordered_p (GET_MODE_PRECISION (mode),
GET_MODE_PRECISION (reg_rtx_mode))
- || paradoxical_subreg_p (mode, reg_rtx_mode))
+ || paradoxical_subreg_p (mode, reg_rtx_mode)
+ || maybe_gt (GET_MODE_PRECISION (reg_rtx_mode), GET_MODE_PRECISION (mode)))
{
original_reg = regno_reg_rtx[hard_regno];
mode = reg_rtx_mode;
diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c
index b5f4916..c40a13c 100644
--- a/gcc/lto-compress.c
+++ b/gcc/lto-compress.c
@@ -250,7 +250,6 @@ lto_compression_zlib (struct lto_compression_stream *stream)
const size_t outbuf_length = Z_BUFFER_LENGTH;
unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
z_stream out_stream;
- size_t compressed_bytes = 0;
int status;
gcc_assert (stream->is_compression);
@@ -282,7 +281,6 @@ lto_compression_zlib (struct lto_compression_stream *stream)
stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
lto_stats.num_compressed_il_bytes += out_bytes;
- compressed_bytes += out_bytes;
cursor += in_bytes;
remaining -= in_bytes;
@@ -342,7 +340,6 @@ lto_uncompression_zlib (struct lto_compression_stream *stream)
size_t remaining = stream->bytes;
const size_t outbuf_length = Z_BUFFER_LENGTH;
unsigned char *outbuf = (unsigned char *) xmalloc (outbuf_length);
- size_t uncompressed_bytes = 0;
gcc_assert (!stream->is_compression);
timevar_push (TV_IPA_LTO_DECOMPRESS);
@@ -378,7 +375,6 @@ lto_uncompression_zlib (struct lto_compression_stream *stream)
stream->callback ((const char *) outbuf, out_bytes, stream->opaque);
lto_stats.num_uncompressed_il_bytes += out_bytes;
- uncompressed_bytes += out_bytes;
cursor += in_bytes;
remaining -= in_bytes;
diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c
index 9496b3c..7b2ad74 100644
--- a/gcc/lto-opts.c
+++ b/gcc/lto-opts.c
@@ -70,17 +70,17 @@ lto_write_options (void)
obstack_init (&temporary_obstack);
- if (!global_options_set.x_flag_openmp
+ if (!OPTION_SET_P (flag_openmp)
&& !global_options.x_flag_openmp)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
"-fno-openmp");
- if (!global_options_set.x_flag_openacc
+ if (!OPTION_SET_P (flag_openacc)
&& !global_options.x_flag_openacc)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
"-fno-openacc");
/* Append PIC/PIE mode because its default depends on target and it is
subject of merging in lto-wrapper. */
- if (!global_options_set.x_flag_pic && !global_options_set.x_flag_pie)
+ if (!OPTION_SET_P (flag_pic) && !OPTION_SET_P (flag_pie))
{
append_to_collect_gcc_options (&temporary_obstack, &first_p,
global_options.x_flag_pic == 2
@@ -94,7 +94,7 @@ lto_write_options (void)
: "-fno-pie");
}
- if (!global_options_set.x_flag_cf_protection)
+ if (!OPTION_SET_P (flag_cf_protection))
{
append_to_collect_gcc_options (
&temporary_obstack, &first_p,
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index a26d488..643d927 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1271,7 +1271,10 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
hstate.add_flag (DECL_PACKED (t));
hstate.add_flag (DECL_NONADDRESSABLE_P (t));
hstate.add_flag (DECL_PADDING_P (t));
- hstate.add_flag (DECL_FIELD_ABI_IGNORED (t));
+ if (DECL_BIT_FIELD (t))
+ hstate.add_flag (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (t));
+ else
+ hstate.add_flag (DECL_FIELD_ABI_IGNORED (t));
hstate.add_int (DECL_OFFSET_ALIGN (t));
}
else if (code == VAR_DECL)
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index aae48af..7b9e488 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -1983,7 +1983,9 @@ cont:
output_name = XOBFINISH (&env_obstack, char *);
/* Adjust the dumpbase if the linker output file was seen. */
- int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX));
+ int dumpbase_len = (strlen (dumppfx)
+ + sizeof (DUMPBASE_SUFFIX)
+ + sizeof (".ltrans"));
char *dumpbase = (char *) xmalloc (dumpbase_len + 1);
snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i);
argv_ptr[0] = dumpbase;
@@ -2009,9 +2011,11 @@ cont:
}
else
{
- char argsuffix[sizeof (DUMPBASE_SUFFIX) + 1];
+ char argsuffix[sizeof (DUMPBASE_SUFFIX)
+ + sizeof (".ltrans_args") + 1];
if (save_temps)
- snprintf (argsuffix, sizeof (DUMPBASE_SUFFIX),
+ snprintf (argsuffix,
+ sizeof (DUMPBASE_SUFFIX) + sizeof (".ltrans_args"),
"ltrans%u.ltrans_args", i);
fork_execute (new_argv[0], CONST_CAST (char **, new_argv),
true, save_temps ? argsuffix : NULL);
@@ -2125,23 +2129,7 @@ main (int argc, char *argv[])
if (atexit (lto_wrapper_cleanup) != 0)
fatal_error (input_location, "%<atexit%> failed");
- if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- signal (SIGINT, fatal_signal);
-#ifdef SIGHUP
- if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, fatal_signal);
-#endif
- if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
- signal (SIGTERM, fatal_signal);
-#ifdef SIGPIPE
- if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
- signal (SIGPIPE, fatal_signal);
-#endif
-#ifdef SIGCHLD
- /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
- receive the signal. A different setting is inheritable */
- signal (SIGCHLD, SIG_DFL);
-#endif
+ setup_signals ();
/* We may be called with all the arguments stored in some file and
passed with @file. Expand them into argv before processing. */
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 301e5f4..1aea3f8 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,19 @@
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * lto-lang.c (lto_init_options_struct): Set also
+ x_flag_default_complex_method.
+
+2021-09-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102024
+ * lto-common.c (compare_tree_sccs_1): Also compare
+ DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD values.
+
+2021-09-02 liuhongt <hongtao.liu@intel.com>
+
+ * lto-lang.c (lto_type_for_mode): Return float16_type_node
+ when mode == TYPE_MODE (float16_type_node).
+
2021-05-31 Martin Liska <mliska@suse.cz>
* lto-common.c (compare_tree_sccs_1): Compare
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index bfe52a2..3eba431 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1187,6 +1187,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
compare_values (DECL_NONADDRESSABLE_P);
compare_values (DECL_PADDING_P);
compare_values (DECL_FIELD_ABI_IGNORED);
+ compare_values (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD);
compare_values (DECL_OFFSET_ALIGN);
}
else if (code == VAR_DECL)
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index c13c7e4..a014e58 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -813,6 +813,7 @@ lto_init_options_struct (struct gcc_options *opts)
safe choice. This will pessimize Fortran code with LTO unless
people specify a complex method manually or use -ffast-math. */
opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
}
/* Handle command-line option SCODE. If the option takes an argument, it is
@@ -992,6 +993,9 @@ lto_type_for_mode (machine_mode mode, int unsigned_p)
return unsigned_p ? unsigned_intTI_type_node : intTI_type_node;
#endif
+ if (float16_type_node && mode == TYPE_MODE (float16_type_node))
+ return float16_type_node;
+
if (mode == TYPE_MODE (float_type_node))
return float_type_node;
diff --git a/gcc/match.pd b/gcc/match.pd
index f421c74..3ff15bc 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -78,6 +78,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (CEIL)
DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+/* Unary operations and their associated IFN_COND_* function. */
+(define_operator_list UNCOND_UNARY
+ negate)
+(define_operator_list COND_UNARY
+ IFN_COND_NEG)
+
/* Binary operations and their associated IFN_COND_* function. */
(define_operator_list UNCOND_BINARY
plus minus
@@ -1481,6 +1487,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (!FIXED_POINT_TYPE_P (type))
(plus @0 (negate @1))))
+/* Other simplifications of negation (c.f. fold_negate_expr_1). */
+(simplify
+ (negate (mult:c@0 @1 negate_expr_p@2))
+ (if (! TYPE_UNSIGNED (type)
+ && ! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (mult @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 @1 negate_expr_p@2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 negate_expr_p@1 @2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv (negate @1) @2)))
+
+/* Fold -((int)x >> (prec - 1)) into (unsigned)x >> (prec - 1). */
+(simplify
+ (negate (convert? (rshift @0 INTEGER_CST@1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && wi::to_wide (@1) == element_precision (type) - 1)
+ (with { tree stype = TREE_TYPE (@0);
+ tree ntype = TYPE_UNSIGNED (stype) ? signed_type_for (stype)
+ : unsigned_type_for (stype); }
+ (convert (rshift:ntype (convert:ntype @0) @1)))))
+
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
For bitwise binary operations apply operand conversions to the
@@ -2063,6 +2099,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (ptr_difference_const (@0, @1, &diff))
{ build_int_cst_type (type, diff); }))))
+/* (&a+b) - (&a[1] + c) -> sizeof(a[0]) + (b - c) */
+(simplify
+ (pointer_diff (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @2, &diff))
+ (plus { build_int_cst_type (type, diff); } (convert (minus @1 @3))))))
+
+/* (&a+b) !=/== (&a[1] + c) -> sizeof(a[0]) + b !=/== c */
+(for neeq (ne eq)
+ (simplify
+ (neeq (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
+ (with { poly_int64 diff; tree inner_type = TREE_TYPE (@1);}
+ (if (ptr_difference_const (@0, @2, &diff))
+ (neeq (plus { build_int_cst_type (inner_type, diff); } @1) @3)))))
+
/* Canonicalize (T *)(ptr - ptr-cst) to &MEM[ptr + -ptr-cst]. */
(simplify
(convert (pointer_diff @0 INTEGER_CST@1))
@@ -3386,13 +3437,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cmp @0 @2)))))
/* Both signed and unsigned lshift produce the same result, so use
- the form that minimizes the number of conversions. */
+ the form that minimizes the number of conversions. Postpone this
+ transformation until after shifts by zero have been folded. */
(simplify
(convert (lshift:s@0 (convert:s@1 @2) INTEGER_CST@3))
(if (INTEGRAL_TYPE_P (type)
&& tree_nop_conversion_p (type, TREE_TYPE (@0))
&& INTEGRAL_TYPE_P (TREE_TYPE (@2))
- && TYPE_PRECISION (TREE_TYPE (@2)) <= TYPE_PRECISION (type))
+ && TYPE_PRECISION (TREE_TYPE (@2)) <= TYPE_PRECISION (type)
+ && !integer_zerop (@3))
(lshift (convert @2) @3)))
/* Simplifications of conversions. */
@@ -3902,15 +3955,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* a ? 1 : 0 -> a if 0 and 1 are integral types. */
(if (integer_onep (@1))
(convert (convert:boolean_type_node @0)))
- /* a ? -1 : 0 -> -a. */
- (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
- (negate (convert (convert:boolean_type_node @0))))
/* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
(if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
(with {
tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
}
- (lshift (convert (convert:boolean_type_node @0)) { shift; })))))
+ (lshift (convert (convert:boolean_type_node @0)) { shift; })))
+ /* a ? -1 : 0 -> -a. No need to check the TYPE_PRECISION not being 1
+ here as the powerof2cst case above will handle that case correctly. */
+ (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
+ (negate (convert (convert:boolean_type_node @0))))))
(if (integer_zerop (@1))
(with {
tree booltrue = constant_boolean_node (true, boolean_type_node);
@@ -3919,16 +3973,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* a ? 0 : 1 -> !a. */
(if (integer_onep (@2))
(convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))
- /* a ? -1 : 0 -> -(!a). */
- (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
- (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
/* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */
- (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2))
+ (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2)
+ && TYPE_PRECISION (type) != 1)
(with {
tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
}
(lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))
- { shift; }))))))))
+ { shift; })))
+ /* a ? -1 : 0 -> -(!a). No need to check the TYPE_PRECISION not being 1
+ here as the powerof2cst case above will handle that case correctly. */
+ (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
+ (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
+ )
+ )
+ )
+ )
+)
#endif
/* Simplification moved from fold_cond_expr_with_comparison. It may also
@@ -4465,9 +4526,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* a CMP (-0) -> a CMP 0 */
(if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
(cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
+ /* (-0) CMP b -> 0 CMP b. */
+ (if (TREE_CODE (@0) == REAL_CST
+ && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@0)))
+ (cmp { build_real (TREE_TYPE (@0), dconst0); } @1))
/* x != NaN is always true, other ops are always false. */
(if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
- && ! HONOR_SNANS (@1))
+ && !tree_expr_signaling_nan_p (@1)
+ && !tree_expr_maybe_signaling_nan_p (@0))
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+ /* NaN != y is always true, other ops are always false. */
+ (if (TREE_CODE (@0) == REAL_CST
+ && REAL_VALUE_ISNAN (TREE_REAL_CST (@0))
+ && !tree_expr_signaling_nan_p (@0)
+ && !tree_expr_signaling_nan_p (@1))
{ constant_boolean_node (cmp == NE_EXPR, type); })
/* Fold comparisons against infinity. */
(if (REAL_VALUE_ISINF (TREE_REAL_CST (@1))
@@ -5587,6 +5659,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
(cmp (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
+/* Demote operands of IFN_{ADD,SUB,MUL}_OVERFLOW. */
+(for ovf (IFN_ADD_OVERFLOW IFN_SUB_OVERFLOW IFN_MUL_OVERFLOW)
+ (simplify
+ (ovf (convert@2 @0) @1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
+ (ovf @0 @1)))
+ (simplify
+ (ovf @1 (convert@2 @0))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
+ (ovf @1 @0))))
+
/* Simplification of math builtins. These rules must all be optimizations
as well as IL simplifications. If there is a possibility that the new
form could be a pessimization, the rule should go in the canonicalization
@@ -6116,6 +6205,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(froms (convert float_value_p@0))
(convert (tos @0)))))
+#if GIMPLE
+(match float16_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == float16_type_node)))
+(for froms (BUILT_IN_TRUNCL BUILT_IN_TRUNC BUILT_IN_TRUNCF
+ BUILT_IN_FLOORL BUILT_IN_FLOOR BUILT_IN_FLOORF
+ BUILT_IN_CEILL BUILT_IN_CEIL BUILT_IN_CEILF
+ BUILT_IN_ROUNDEVENL BUILT_IN_ROUNDEVEN BUILT_IN_ROUNDEVENF
+ BUILT_IN_ROUNDL BUILT_IN_ROUND BUILT_IN_ROUNDF
+ BUILT_IN_NEARBYINTL BUILT_IN_NEARBYINT BUILT_IN_NEARBYINTF
+ BUILT_IN_RINTL BUILT_IN_RINT BUILT_IN_RINTF)
+ tos (IFN_TRUNC IFN_TRUNC IFN_TRUNC
+ IFN_FLOOR IFN_FLOOR IFN_FLOOR
+ IFN_CEIL IFN_CEIL IFN_CEIL
+ IFN_ROUNDEVEN IFN_ROUNDEVEN IFN_ROUNDEVEN
+ IFN_ROUND IFN_ROUND IFN_ROUND
+ IFN_NEARBYINT IFN_NEARBYINT IFN_NEARBYINT
+ IFN_RINT IFN_RINT IFN_RINT)
+ /* (_Float16) round ((doube) x) -> __built_in_roundf16 (x), etc.,
+ if x is a _Float16. */
+ (simplify
+ (convert (froms (convert float16_value_p@0)))
+ (if (optimize
+ && types_match (type, TREE_TYPE (@0))
+ && direct_internal_fn_supported_p (as_internal_fn (tos),
+ type, OPTIMIZE_FOR_BOTH))
+ (tos @0))))
+#endif
+
(for froms (XFLOORL XCEILL XROUNDL XRINTL)
tos (XFLOOR XCEIL XROUND XRINT)
/* llfloorl(extend(x)) -> llfloor(x), etc., if x is a double. */
@@ -6963,6 +7081,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
false, prec)); })
{ build_zero_cst (TREE_TYPE (@0)); }))))))))
+#if GIMPLE
+
+/* Simplify:
+ a = op a1
+ r = cond ? a : b
+ --> r = .COND_FN (cond, a, b)
+and,
+ a = op a1
+ r = cond ? b : a
+ --> r = .COND_FN (~cond, b, a). */
+
+(for uncond_op (UNCOND_UNARY)
+ cond_op (COND_UNARY)
+ (simplify
+ (vec_cond @0 (view_convert? (uncond_op@3 @1)) @2)
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op @0 @1 @2))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (uncond_op@3 @2)))
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op (bit_not @0) @2 @1)))))
+
/* Simplify:
a = a1 op a2
@@ -6981,20 +7125,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
conditional internal functions must support the same comparisons
inside and outside a VEC_COND_EXPR. */
-#if GIMPLE
(for uncond_op (UNCOND_BINARY)
cond_op (COND_BINARY)
(simplify
(vec_cond @0 (view_convert? (uncond_op@4 @1 @2)) @3)
(with { tree op_type = TREE_TYPE (@4); }
(if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
- && element_precision (type) == element_precision (op_type))
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
(view_convert (cond_op @0 @1 @2 (view_convert:op_type @3))))))
(simplify
(vec_cond @0 @1 (view_convert? (uncond_op@4 @2 @3)))
(with { tree op_type = TREE_TYPE (@4); }
(if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
- && element_precision (type) == element_precision (op_type))
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
(view_convert (cond_op (bit_not @0) @2 @3 (view_convert:op_type @1)))))))
/* Same for ternary operations. */
@@ -7004,13 +7147,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(vec_cond @0 (view_convert? (uncond_op@5 @1 @2 @3)) @4)
(with { tree op_type = TREE_TYPE (@5); }
(if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
- && element_precision (type) == element_precision (op_type))
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
(view_convert (cond_op @0 @1 @2 @3 (view_convert:op_type @4))))))
(simplify
(vec_cond @0 @1 (view_convert? (uncond_op@5 @2 @3 @4)))
(with { tree op_type = TREE_TYPE (@5); }
(if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
- && element_precision (type) == element_precision (op_type))
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
(view_convert (cond_op (bit_not @0) @2 @3 @4
(view_convert:op_type @1)))))))
#endif
@@ -7044,6 +7187,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& element_precision (type) == element_precision (op_type))
(view_convert (cond_op @2 @3 @4 @5 (view_convert:op_type @1)))))))
+/* Detect simplication for a conditional reduction where
+
+ a = mask1 ? b : 0
+ c = mask2 ? d + a : d
+
+ is turned into
+
+ c = mask1 && mask2 ? d + b : d. */
+(simplify
+ (IFN_COND_ADD @0 @1 (vec_cond @2 @3 integer_zerop) @1)
+ (IFN_COND_ADD (bit_and @0 @2) @1 @3 @1))
+
/* For pointers @0 and @2 and nonnegative constant offset @1, look for
expressions like:
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index e2d452f..853ce09 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,43 @@
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * objc-next-runtime-abi-01.c: Add missing include.
+ * objc-next-runtime-abi-02.c: Likewise.
+
+2021-10-08 Martin Liska <mliska@suse.cz>
+
+ * objc-next-runtime-abi-01.c: Use new macro
+ OPTION_SET_P.
+ * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init): Likewise.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/101718
+ * objc-next-runtime-abi-02.c (build_v2_build_objc_method_call):
+ Revise for cases where scalar objects use an sret parameter.
+ (next_runtime_abi_02_build_objc_method_call): Likwise.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_add_property_declaration): Register unavailable
+ attribute.
+ (maybe_make_artificial_property_decl): Set available.
+ (objc_maybe_build_component_ref): Generalise to the method prototype
+ to count availability.
+ (objc_build_class_component_ref): Likewise.
+ (build_private_template): Likewise.
+ (objc_decl_method_attributes): Handle unavailable attribute.
+ (lookup_method_in_hash_lists): Amend comments.
+ (objc_finish_message_expr): Handle unavailability in addition to
+ deprecation.
+ (start_class): Likewise.
+ (finish_class): Likewise.
+ (lookup_protocol): Likewise.
+ (objc_declare_protocol): Likewise.
+ (start_protocol): Register unavailable attribute.
+ (really_start_method): Likewise.
+ (objc_gimplify_property_ref): Emit error on encountering an
+ unavailable entity (and a warning for a deprecated one).
+
2021-08-19 Iain Sandoe <iain@sandoe.co.uk>
* objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 6e4fb62..9baa46d 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1302,6 +1302,7 @@ objc_add_property_declaration (location_t location, tree decl,
TREE_TYPE (property_decl) = p_type;
DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
+ TREE_UNAVAILABLE (property_decl) = TREE_UNAVAILABLE (decl);
/* Add property-specific information. */
PROPERTY_NAME (property_decl) = DECL_NAME (decl);
@@ -1439,6 +1440,7 @@ maybe_make_artificial_property_decl (tree interface, tree implementation,
TREE_TYPE (property_decl) = type;
DECL_SOURCE_LOCATION (property_decl) = input_location;
TREE_DEPRECATED (property_decl) = 0;
+ TREE_UNAVAILABLE (property_decl) = 0;
DECL_ARTIFICIAL (property_decl) = 1;
/* Add property-specific information. Note that one of
@@ -1717,7 +1719,7 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
{
tree expression;
tree getter_call;
- tree deprecated_method_prototype = NULL_TREE;
+ tree method_prototype_avail = NULL_TREE;
/* We have an additional nasty problem here; if this
PROPERTY_REF needs to become a 'getter', then the conversion
@@ -1751,10 +1753,10 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
is deprecated, but record the fact that the getter is
deprecated by setting PROPERTY_REF_DEPRECATED_GETTER to
the method prototype. */
- &deprecated_method_prototype);
+ &method_prototype_avail);
expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call,
- deprecated_method_prototype);
+ method_prototype_avail);
SET_EXPR_LOCATION (expression, input_location);
TREE_SIDE_EFFECTS (expression) = 1;
@@ -1804,7 +1806,9 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
}
else
{
- if (TREE_DEPRECATED (rtype))
+ if (TREE_UNAVAILABLE (rtype))
+ error ("class %qE is unavailable", class_name);
+ else if (TREE_DEPRECATED (rtype))
warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", class_name);
}
@@ -1816,17 +1820,17 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
{
tree expression;
tree getter_call;
- tree deprecated_method_prototype = NULL_TREE;
+ tree method_prototype_avail = NULL_TREE;
if (PROPERTY_HAS_NO_GETTER (x))
getter_call = NULL_TREE;
else
getter_call = objc_finish_message_expr
(object, PROPERTY_GETTER_NAME (x), NULL_TREE,
- &deprecated_method_prototype);
+ &method_prototype_avail);
expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call,
- deprecated_method_prototype);
+ method_prototype_avail);
SET_EXPR_LOCATION (expression, input_location);
TREE_SIDE_EFFECTS (expression) = 1;
@@ -4598,6 +4602,8 @@ build_private_template (tree klass)
/* Copy the attributes from the class to the type. */
if (TREE_DEPRECATED (klass))
TREE_DEPRECATED (record) = 1;
+ if (TREE_UNAVAILABLE (klass))
+ TREE_UNAVAILABLE (record) = 1;
}
}
@@ -5023,6 +5029,7 @@ objc_decl_method_attributes (tree *node, tree attributes, int flags)
tree name = TREE_PURPOSE (attribute);
if (is_attribute_p ("deprecated", name)
+ || is_attribute_p ("unavailable", name)
|| is_attribute_p ("sentinel", name)
|| is_attribute_p ("noreturn", name))
{
@@ -5488,9 +5495,9 @@ lookup_method_in_hash_lists (tree sel_name, int is_class)
C++ template functions, it is called from 'build_expr_from_tree'
(in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.
- If the DEPRECATED_METHOD_PROTOTYPE argument is NULL, then we warn
+ If the method_prototype_avail argument is NULL, then we warn
if the method being used is deprecated. If it is not NULL, instead
- of deprecating, we set *DEPRECATED_METHOD_PROTOTYPE to the method
+ of deprecating, we set *method_prototype_avail to the method
prototype that was used and is deprecated. This is useful for
getter calls that are always generated when compiling dot-syntax
expressions, even if they may not be used. In that case, we don't
@@ -5499,7 +5506,7 @@ lookup_method_in_hash_lists (tree sel_name, int is_class)
used. */
tree
objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
- tree *deprecated_method_prototype)
+ tree *method_prototype_avail)
{
tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
tree retval, class_tree;
@@ -5811,10 +5818,17 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
In practice this makes sense since casting an object to 'id'
is often used precisely to turn off warnings associated with
the object being of a particular class. */
- if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE)
+ if (TREE_UNAVAILABLE (method_prototype) && rtype != NULL_TREE)
{
- if (deprecated_method_prototype)
- *deprecated_method_prototype = method_prototype;
+ if (method_prototype_avail)
+ *method_prototype_avail = method_prototype;
+ else
+ error_unavailable_use (method_prototype, NULL_TREE);
+ }
+ else if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE)
+ {
+ if (method_prototype_avail)
+ *method_prototype_avail = method_prototype;
else
warn_deprecated_use (method_prototype, NULL_TREE);
}
@@ -6986,7 +7000,9 @@ start_class (enum tree_code code, tree class_name, tree super_name,
}
else
{
- if (TREE_DEPRECATED (super_interface))
+ if (TREE_UNAVAILABLE (super_interface))
+ error ("class %qE is not available", super);
+ else if (TREE_DEPRECATED (super_interface))
warning (OPT_Wdeprecated_declarations, "class %qE is deprecated",
super);
super_name = super;
@@ -7096,7 +7112,9 @@ start_class (enum tree_code code, tree class_name, tree super_name,
/* TODO: Document what the objc_exception attribute is/does. */
/* We handle the 'deprecated', 'visibility' and (undocumented)
'objc_exception' attributes. */
- if (is_attribute_p ("deprecated", name))
+ if (is_attribute_p ("unavailable", name))
+ TREE_UNAVAILABLE (klass) = 1;
+ else if (is_attribute_p ("deprecated", name))
TREE_DEPRECATED (klass) = 1;
else if (is_attribute_p ("objc_exception", name))
CLASS_HAS_EXCEPTION_ATTR (klass) = 1;
@@ -7127,7 +7145,9 @@ start_class (enum tree_code code, tree class_name, tree super_name,
}
else
{
- if (TREE_DEPRECATED (class_category_is_assoc_with))
+ if (TREE_UNAVAILABLE (class_category_is_assoc_with))
+ error ("class %qE is unavailable", class_name);
+ else if (TREE_DEPRECATED (class_category_is_assoc_with))
warning (OPT_Wdeprecated_declarations, "class %qE is deprecated",
class_name);
@@ -8154,6 +8174,7 @@ finish_class (tree klass)
else
objc_add_method (objc_interface_context, getter_decl, false, false);
TREE_DEPRECATED (getter_decl) = TREE_DEPRECATED (x);
+ TREE_UNAVAILABLE (getter_decl) = TREE_UNAVAILABLE (x);
METHOD_PROPERTY_CONTEXT (getter_decl) = x;
}
@@ -8198,6 +8219,7 @@ finish_class (tree klass)
else
objc_add_method (objc_interface_context, setter_decl, false, false);
TREE_DEPRECATED (setter_decl) = TREE_DEPRECATED (x);
+ TREE_UNAVAILABLE (setter_decl) = TREE_UNAVAILABLE (x);
METHOD_PROPERTY_CONTEXT (setter_decl) = x;
}
}
@@ -8251,7 +8273,9 @@ lookup_protocol (tree ident, bool warn_if_deprecated, bool definition_required)
for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
if (ident == PROTOCOL_NAME (chain))
{
- if (warn_if_deprecated && TREE_DEPRECATED (chain))
+ if (TREE_UNAVAILABLE (chain))
+ error ("protocol %qE is unavailable", PROTOCOL_NAME (chain));
+ else if (warn_if_deprecated && TREE_DEPRECATED (chain))
{
/* It would be nice to use warn_deprecated_use() here, but
we are using TREE_CHAIN (which is supposed to be the
@@ -8276,6 +8300,7 @@ void
objc_declare_protocol (tree name, tree attributes)
{
bool deprecated = false;
+ bool unavailable = false;
#ifdef OBJCPLUS
if (current_namespace != global_namespace) {
@@ -8294,6 +8319,8 @@ objc_declare_protocol (tree name, tree attributes)
if (is_attribute_p ("deprecated", name))
deprecated = true;
+ else if (is_attribute_p ("unavailable", name))
+ unavailable = true;
else
warning (OPT_Wattributes, "%qE attribute directive ignored", name);
}
@@ -8318,6 +8345,8 @@ objc_declare_protocol (tree name, tree attributes)
TYPE_ATTRIBUTES (protocol) = attributes;
if (deprecated)
TREE_DEPRECATED (protocol) = 1;
+ if (unavailable)
+ TREE_UNAVAILABLE (protocol) = 1;
}
}
}
@@ -8327,6 +8356,7 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes)
{
tree protocol;
bool deprecated = false;
+ bool unavailable = false;
#ifdef OBJCPLUS
if (current_namespace != global_namespace) {
@@ -8345,6 +8375,8 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes)
if (is_attribute_p ("deprecated", name))
deprecated = true;
+ else if (is_attribute_p ("unavailable", name))
+ unavailable = true;
else
warning (OPT_Wattributes, "%qE attribute directive ignored", name);
}
@@ -8384,6 +8416,8 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes)
TYPE_ATTRIBUTES (protocol) = attributes;
if (deprecated)
TREE_DEPRECATED (protocol) = 1;
+ if (unavailable)
+ TREE_UNAVAILABLE (protocol) = 1;
}
return protocol;
@@ -8913,6 +8947,8 @@ really_start_method (tree method,
warnings are produced), but just in case. */
if (TREE_DEPRECATED (proto))
TREE_DEPRECATED (method) = 1;
+ if (TREE_UNAVAILABLE (proto))
+ TREE_UNAVAILABLE (method) = 1;
/* If the method in the @interface was marked as
'noreturn', mark the function implementing the method
@@ -9644,12 +9680,17 @@ objc_gimplify_property_ref (tree *expr_p)
return;
}
+ /* FIXME, this should be a label indicating availability in general. */
if (PROPERTY_REF_DEPRECATED_GETTER (*expr_p))
{
- /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype
+ if (TREE_UNAVAILABLE (PROPERTY_REF_DEPRECATED_GETTER (*expr_p)))
+ error_unavailable_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p),
+ NULL_TREE);
+ else
+ /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype
that is deprecated. */
- warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p),
- NULL_TREE);
+ warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p),
+ NULL_TREE);
}
call_exp = getter;
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 183fc01..12f8bdc 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "c-family/c-objc.h"
#include "objc-act.h"
+#include "opts.h"
/* When building Objective-C++, we are not linking against the C
front-end and so need to replicate the C tree-construction
@@ -259,7 +260,7 @@ static void next_runtime_01_initialize (void)
#ifdef OBJCPLUS
/* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
default. */
- if (!global_options_set.x_flag_objc_call_cxx_cdtors)
+ if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
global_options.x_flag_objc_call_cxx_cdtors = 1;
#endif
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index ce831fc..7ca0fd7 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "tree-iterator.h"
+#include "opts.h"
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
@@ -255,7 +256,7 @@ objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
}
/* NeXT ABI 2 is intended to default to checking for nil receivers. */
- if (! global_options_set.x_flag_objc_nilcheck)
+ if (! OPTION_SET_P (flag_objc_nilcheck))
flag_objc_nilcheck = 1;
rthooks->initialize = next_runtime_02_initialize;
@@ -366,7 +367,7 @@ static void next_runtime_02_initialize (void)
#ifdef OBJCPLUS
/* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
default. */
- if (!global_options_set.x_flag_objc_call_cxx_cdtors)
+ if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
global_options.x_flag_objc_call_cxx_cdtors = 1;
#endif
@@ -1739,15 +1740,16 @@ build_v2_build_objc_method_call (int super, tree method_prototype,
/* Param list + 2 slots for object and selector. */
vec_alloc (parms, nparm + 2);
- /* If we are returning a struct in memory, and the address
- of that memory location is passed as a hidden first
- argument, then change which messenger entry point this
- expr will call. NB: Note that sender_cast remains
- unchanged (it already has a struct return type). */
- if (!targetm.calls.struct_value_rtx (0, 0)
- && (TREE_CODE (ret_type) == RECORD_TYPE
- || TREE_CODE (ret_type) == UNION_TYPE)
- && targetm.calls.return_in_memory (ret_type, 0))
+ /* If we are returning an item that must be returned in memory, and the
+ target ABI does this by an invisible pointer provided as the first arg,
+ we need to adjust the message signature to include this. The second
+ part of this excludes targets that provide some alternate scheme for
+ structure returns. */
+ if (ret_type && !VOID_TYPE_P (ret_type)
+ && targetm.calls.return_in_memory (ret_type, 0)
+ && !(targetm.calls.struct_value_rtx (0, 0)
+ && (TREE_CODE (ret_type) == RECORD_TYPE
+ || TREE_CODE (ret_type) == UNION_TYPE)))
{
if (super)
sender = umsg_id_super2_stret_fixup_decl;
@@ -1849,10 +1851,12 @@ next_runtime_abi_02_build_objc_method_call (location_t loc,
? TREE_VALUE (TREE_TYPE (method_prototype))
: objc_object_type;
- if (!targetm.calls.struct_value_rtx (0, 0)
- && (TREE_CODE (ret_type) == RECORD_TYPE
- || TREE_CODE (ret_type) == UNION_TYPE)
- && targetm.calls.return_in_memory (ret_type, 0))
+ /* See comment for the fixup version above. */
+ if (ret_type && !VOID_TYPE_P (ret_type)
+ && targetm.calls.return_in_memory (ret_type, 0)
+ && !(targetm.calls.struct_value_rtx (0, 0)
+ && (TREE_CODE (ret_type) == RECORD_TYPE
+ || TREE_CODE (ret_type) == UNION_TYPE)))
{
if (super)
message_func_decl = umsg_id_super2_stret_fixup_decl;
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 5d6187b..c5d402c 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,8 @@
+2021-10-11 Eric Gallager <egallager@gcc.gnu.org>
+
+ PR objc++/56604
+ * Make-lang.in: Add obj-c++.srcman: line.
+
2021-06-08 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Make-lang.in (cc1objplus-checksum.c): Check previous
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 0f890d8..d7cafe8 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -129,6 +129,7 @@ obj-c++.install-pdf:
obj-c++.html:
obj-c++.install-html:
obj-c++.srcinfo:
+obj-c++.srcman:
obj-c++.srcextra:
obj-c++.man:
obj-c++.install-plugin:
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 66c64f5..9715ef5 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "tree-eh.h"
+#include "opts.h"
/* OMP region information. Every parallel and workshare
directive is enclosed between two markers, the OMP_* directive
@@ -4232,9 +4233,8 @@ expand_omp_for_generic (struct omp_region *region,
&& !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
{
tree d = OMP_CLAUSE_DECL (c);
- bool is_ref = omp_is_reference (d);
tree t = d, a, dest;
- if (is_ref)
+ if (omp_privatize_by_reference (t))
t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
tree type = TREE_TYPE (t);
if (POINTER_TYPE_P (type))
@@ -5236,9 +5236,8 @@ expand_omp_for_static_nochunk (struct omp_region *region,
&& !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
{
tree d = OMP_CLAUSE_DECL (c);
- bool is_ref = omp_is_reference (d);
tree t = d, a, dest;
- if (is_ref)
+ if (omp_privatize_by_reference (t))
t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
if (itercnt == NULL_TREE)
{
@@ -5952,9 +5951,8 @@ expand_omp_for_static_chunk (struct omp_region *region,
&& !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
{
tree d = OMP_CLAUSE_DECL (c);
- bool is_ref = omp_is_reference (d);
tree t = d, a, dest;
- if (is_ref)
+ if (omp_privatize_by_reference (t))
t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
tree type = TREE_TYPE (t);
if (POINTER_TYPE_P (type))
@@ -6963,7 +6961,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
/* If not -fno-tree-loop-vectorize, hint that we want to vectorize
the loop. */
if ((flag_tree_loop_vectorize
- || !global_options_set.x_flag_tree_loop_vectorize)
+ || !OPTION_SET_P (flag_tree_loop_vectorize))
&& flag_tree_loop_optimize
&& loop->safelen > 1)
{
@@ -8436,11 +8434,17 @@ expand_omp_single (struct omp_region *region)
exit_bb = region->exit;
si = gsi_last_nondebug_bb (entry_bb);
- gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
- || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SCOPE);
+ enum gimple_code code = gimple_code (gsi_stmt (si));
+ gcc_assert (code == GIMPLE_OMP_SINGLE || code == GIMPLE_OMP_SCOPE);
gsi_remove (&si, true);
single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+ if (exit_bb == NULL)
+ {
+ gcc_assert (code == GIMPLE_OMP_SCOPE);
+ return;
+ }
+
si = gsi_last_nondebug_bb (exit_bb);
if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
{
@@ -8490,22 +8494,58 @@ expand_omp_synch (struct omp_region *region)
}
}
+/* Translate enum omp_memory_order to enum memmodel for the embedded
+ fail clause in there. */
+
+static enum memmodel
+omp_memory_order_to_fail_memmodel (enum omp_memory_order mo)
+{
+ switch (mo & OMP_FAIL_MEMORY_ORDER_MASK)
+ {
+ case OMP_FAIL_MEMORY_ORDER_UNSPECIFIED:
+ switch (mo & OMP_MEMORY_ORDER_MASK)
+ {
+ case OMP_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
+ case OMP_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
+ case OMP_MEMORY_ORDER_RELEASE: return MEMMODEL_RELAXED;
+ case OMP_MEMORY_ORDER_ACQ_REL: return MEMMODEL_ACQUIRE;
+ case OMP_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
+ default: break;
+ }
+ gcc_unreachable ();
+ case OMP_FAIL_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
+ case OMP_FAIL_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
+ case OMP_FAIL_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
+ default: gcc_unreachable ();
+ }
+}
+
/* Translate enum omp_memory_order to enum memmodel. The two enums
are using different numbers so that OMP_MEMORY_ORDER_UNSPECIFIED
- is 0. */
+ is 0 and omp_memory_order has the fail mode encoded in it too. */
static enum memmodel
omp_memory_order_to_memmodel (enum omp_memory_order mo)
{
- switch (mo)
- {
- case OMP_MEMORY_ORDER_RELAXED: return MEMMODEL_RELAXED;
- case OMP_MEMORY_ORDER_ACQUIRE: return MEMMODEL_ACQUIRE;
- case OMP_MEMORY_ORDER_RELEASE: return MEMMODEL_RELEASE;
- case OMP_MEMORY_ORDER_ACQ_REL: return MEMMODEL_ACQ_REL;
- case OMP_MEMORY_ORDER_SEQ_CST: return MEMMODEL_SEQ_CST;
+ enum memmodel ret, fail_ret;
+ switch (mo & OMP_MEMORY_ORDER_MASK)
+ {
+ case OMP_MEMORY_ORDER_RELAXED: ret = MEMMODEL_RELAXED; break;
+ case OMP_MEMORY_ORDER_ACQUIRE: ret = MEMMODEL_ACQUIRE; break;
+ case OMP_MEMORY_ORDER_RELEASE: ret = MEMMODEL_RELEASE; break;
+ case OMP_MEMORY_ORDER_ACQ_REL: ret = MEMMODEL_ACQ_REL; break;
+ case OMP_MEMORY_ORDER_SEQ_CST: ret = MEMMODEL_SEQ_CST; break;
default: gcc_unreachable ();
}
+ /* If we drop the -Winvalid-memory-model warning for C++17 P0418R2,
+ we can just return ret here unconditionally. Otherwise, work around
+ it here and make sure fail memmodel is not stronger. */
+ if ((mo & OMP_FAIL_MEMORY_ORDER_MASK) == OMP_FAIL_MEMORY_ORDER_UNSPECIFIED)
+ return ret;
+ fail_ret = omp_memory_order_to_fail_memmodel (mo);
+ if (fail_ret > ret)
+ return fail_ret;
+ return ret;
}
/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
@@ -8785,6 +8825,261 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
return true;
}
+/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
+ compare and exchange as an ATOMIC_COMPARE_EXCHANGE internal function.
+ Returns false if the expression is not of the proper form. */
+
+static bool
+expand_omp_atomic_cas (basic_block load_bb, tree addr,
+ tree loaded_val, tree stored_val, int index)
+{
+ /* We expect to find the following sequences:
+
+ load_bb:
+ GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
+
+ store_bb:
+ val = tmp == e ? d : tmp;
+ GIMPLE_OMP_ATOMIC_STORE (val)
+
+ or in store_bb instead:
+ tmp2 = tmp == e;
+ val = tmp2 ? d : tmp;
+ GIMPLE_OMP_ATOMIC_STORE (val)
+
+ or:
+ tmp3 = VIEW_CONVERT_EXPR<integral_type>(tmp);
+ val = e == tmp3 ? d : tmp;
+ GIMPLE_OMP_ATOMIC_STORE (val)
+
+ etc. */
+
+
+ basic_block store_bb = single_succ (load_bb);
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (store_bb);
+ gimple *store_stmt = gsi_stmt (gsi);
+ if (!store_stmt || gimple_code (store_stmt) != GIMPLE_OMP_ATOMIC_STORE)
+ return false;
+ gsi_prev_nondebug (&gsi);
+ if (gsi_end_p (gsi))
+ return false;
+ gimple *condexpr_stmt = gsi_stmt (gsi);
+ if (!is_gimple_assign (condexpr_stmt)
+ || gimple_assign_rhs_code (condexpr_stmt) != COND_EXPR)
+ return false;
+ if (!operand_equal_p (gimple_assign_lhs (condexpr_stmt), stored_val, 0))
+ return false;
+ gimple *cond_stmt = NULL;
+ gimple *vce_stmt = NULL;
+ gsi_prev_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ {
+ cond_stmt = gsi_stmt (gsi);
+ if (!is_gimple_assign (cond_stmt))
+ return false;
+ if (gimple_assign_rhs_code (cond_stmt) == EQ_EXPR)
+ {
+ gsi_prev_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ {
+ vce_stmt = gsi_stmt (gsi);
+ if (!is_gimple_assign (vce_stmt)
+ || gimple_assign_rhs_code (vce_stmt) != VIEW_CONVERT_EXPR)
+ return false;
+ }
+ }
+ else if (gimple_assign_rhs_code (cond_stmt) == VIEW_CONVERT_EXPR)
+ std::swap (vce_stmt, cond_stmt);
+ else
+ return false;
+ if (vce_stmt)
+ {
+ tree vce_rhs = gimple_assign_rhs1 (vce_stmt);
+ if (TREE_CODE (vce_rhs) != VIEW_CONVERT_EXPR
+ || !operand_equal_p (TREE_OPERAND (vce_rhs, 0), loaded_val))
+ return false;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (vce_rhs))
+ || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (loaded_val))
+ || !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vce_rhs)),
+ TYPE_SIZE (TREE_TYPE (loaded_val))))
+ return false;
+ gsi_prev_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ return false;
+ }
+ }
+ tree cond = gimple_assign_rhs1 (condexpr_stmt);
+ tree cond_op1, cond_op2;
+ if (cond_stmt)
+ {
+ if (!operand_equal_p (cond, gimple_assign_lhs (cond_stmt)))
+ return false;
+ cond_op1 = gimple_assign_rhs1 (cond_stmt);
+ cond_op2 = gimple_assign_rhs2 (cond_stmt);
+ }
+ else if (TREE_CODE (cond) != EQ_EXPR && TREE_CODE (cond) != NE_EXPR)
+ return false;
+ else
+ {
+ cond_op1 = TREE_OPERAND (cond, 0);
+ cond_op2 = TREE_OPERAND (cond, 1);
+ }
+ tree d;
+ if (TREE_CODE (cond) == NE_EXPR)
+ {
+ if (!operand_equal_p (gimple_assign_rhs2 (condexpr_stmt), loaded_val))
+ return false;
+ d = gimple_assign_rhs3 (condexpr_stmt);
+ }
+ else if (!operand_equal_p (gimple_assign_rhs3 (condexpr_stmt), loaded_val))
+ return false;
+ else
+ d = gimple_assign_rhs2 (condexpr_stmt);
+ tree e = vce_stmt ? gimple_assign_lhs (vce_stmt) : loaded_val;
+ if (operand_equal_p (e, cond_op1))
+ e = cond_op2;
+ else if (operand_equal_p (e, cond_op2))
+ e = cond_op1;
+ else
+ return false;
+
+ location_t loc = gimple_location (store_stmt);
+ gimple *load_stmt = last_stmt (load_bb);
+ bool need_new = gimple_omp_atomic_need_value_p (store_stmt);
+ bool need_old = gimple_omp_atomic_need_value_p (load_stmt);
+ bool weak = gimple_omp_atomic_weak_p (load_stmt);
+ enum omp_memory_order omo = gimple_omp_atomic_memory_order (load_stmt);
+ tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
+ tree fmo = build_int_cst (NULL, omp_memory_order_to_fail_memmodel (omo));
+ gcc_checking_assert (!need_old || !need_new);
+
+ enum built_in_function fncode
+ = (enum built_in_function) ((int) BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+ + index + 1);
+ tree cmpxchg = builtin_decl_explicit (fncode);
+ if (cmpxchg == NULL_TREE)
+ return false;
+ tree itype = TREE_TYPE (TREE_TYPE (cmpxchg));
+
+ if (!can_compare_and_swap_p (TYPE_MODE (itype), true)
+ || !can_atomic_load_p (TYPE_MODE (itype)))
+ return false;
+
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
+ if (SCALAR_FLOAT_TYPE_P (type) && !vce_stmt)
+ return false;
+
+ gsi = gsi_for_stmt (store_stmt);
+ if (!useless_type_conversion_p (itype, TREE_TYPE (e)))
+ {
+ tree ne = create_tmp_reg (itype);
+ gimple *g = gimple_build_assign (ne, NOP_EXPR, e);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ e = ne;
+ }
+ if (!useless_type_conversion_p (itype, TREE_TYPE (d)))
+ {
+ tree nd = create_tmp_reg (itype);
+ enum tree_code code;
+ if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (d)))
+ {
+ code = VIEW_CONVERT_EXPR;
+ d = build1 (VIEW_CONVERT_EXPR, itype, d);
+ }
+ else
+ code = NOP_EXPR;
+ gimple *g = gimple_build_assign (nd, code, d);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ d = nd;
+ }
+
+ tree ctype = build_complex_type (itype);
+ int flag = int_size_in_bytes (itype) + (weak ? 256 : 0);
+ gimple *g
+ = gimple_build_call_internal (IFN_ATOMIC_COMPARE_EXCHANGE, 6, addr, e, d,
+ build_int_cst (integer_type_node, flag),
+ mo, fmo);
+ tree cres = create_tmp_reg (ctype);
+ gimple_call_set_lhs (g, cres);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ if (cond_stmt || need_old || need_new)
+ {
+ tree im = create_tmp_reg (itype);
+ g = gimple_build_assign (im, IMAGPART_EXPR,
+ build1 (IMAGPART_EXPR, itype, cres));
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ tree re = NULL_TREE;
+ if (need_old || need_new)
+ {
+ re = create_tmp_reg (itype);
+ g = gimple_build_assign (re, REALPART_EXPR,
+ build1 (REALPART_EXPR, itype, cres));
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+
+ if (cond_stmt)
+ {
+ g = gimple_build_assign (gimple_assign_lhs (cond_stmt),
+ NOP_EXPR, im);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ else if (need_new)
+ {
+ g = gimple_build_assign (create_tmp_reg (itype), COND_EXPR,
+ build2 (NE_EXPR, boolean_type_node,
+ im, build_zero_cst (itype)),
+ d, re);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ re = gimple_assign_lhs (g);
+ }
+
+ if (need_old || need_new)
+ {
+ tree v = need_old ? loaded_val : stored_val;
+ enum tree_code code;
+ if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (v)))
+ {
+ code = VIEW_CONVERT_EXPR;
+ re = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (v), re);
+ }
+ else if (!useless_type_conversion_p (TREE_TYPE (v), itype))
+ code = NOP_EXPR;
+ else
+ code = TREE_CODE (re);
+ g = gimple_build_assign (v, code, re);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ }
+
+ gsi_remove (&gsi, true);
+ gsi = gsi_for_stmt (load_stmt);
+ gsi_remove (&gsi, true);
+ gsi = gsi_for_stmt (condexpr_stmt);
+ gsi_remove (&gsi, true);
+ if (cond_stmt)
+ {
+ gsi = gsi_for_stmt (cond_stmt);
+ gsi_remove (&gsi, true);
+ }
+ if (vce_stmt)
+ {
+ gsi = gsi_for_stmt (vce_stmt);
+ gsi_remove (&gsi, true);
+ }
+
+ return true;
+}
+
/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
oldval = *addr;
@@ -8810,8 +9105,6 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
edge e;
enum built_in_function fncode;
- /* ??? We need a non-pointer interface to __atomic_compare_exchange in
- order to use the RELAXED memory model effectively. */
fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+ index + 1);
cmpxchg = builtin_decl_explicit (fncode);
@@ -8828,6 +9121,10 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
/* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
si = gsi_last_nondebug_bb (load_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
+ location_t loc = gimple_location (gsi_stmt (si));
+ enum omp_memory_order omo = gimple_omp_atomic_memory_order (gsi_stmt (si));
+ tree mo = build_int_cst (NULL, omp_memory_order_to_memmodel (omo));
+ tree fmo = build_int_cst (NULL, omp_memory_order_to_fail_memmodel (omo));
/* For floating-point values, we'll need to view-convert them to integers
so that we can perform the atomic compare and swap. Simplify the
@@ -8924,7 +9221,15 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
GSI_SAME_STMT);
/* Build the compare&swap statement. */
- new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
+ tree ctype = build_complex_type (itype);
+ int flag = int_size_in_bytes (itype);
+ new_storedi = build_call_expr_internal_loc (loc, IFN_ATOMIC_COMPARE_EXCHANGE,
+ ctype, 6, iaddr, loadedi,
+ storedi,
+ build_int_cst (integer_type_node,
+ flag),
+ mo, fmo);
+ new_storedi = build1 (REALPART_EXPR, itype, new_storedi);
new_storedi = force_gimple_operand_gsi (&si,
fold_convert (TREE_TYPE (loadedi),
new_storedi),
@@ -9102,6 +9407,13 @@ expand_omp_atomic (struct omp_region *region)
loaded_val, stored_val, index))
return;
+ /* When possible, use ATOMIC_COMPARE_EXCHANGE ifn without a loop. */
+ if (store_bb == single_succ (load_bb)
+ && !gimple_in_ssa_p (cfun)
+ && expand_omp_atomic_cas (load_bb, addr, loaded_val, stored_val,
+ index))
+ return;
+
/* If we don't have specialized __sync builtins, try and implement
as a compare and swap loop. */
if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
@@ -9613,6 +9925,8 @@ expand_omp_target (struct omp_region *region)
{
device = OMP_CLAUSE_DEVICE_ID (c);
device_loc = OMP_CLAUSE_LOCATION (c);
+ if (OMP_CLAUSE_DEVICE_ANCESTOR (c))
+ sorry_at (device_loc, "%<ancestor%> not yet supported");
}
else
{
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index b46a537..4452755 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "data-streamer.h"
#include "streamer-hooks.h"
+#include "opts.h"
enum omp_requires omp_requires_mask;
@@ -79,10 +80,11 @@ omp_check_optional_argument (tree decl, bool for_present_check)
return lang_hooks.decls.omp_check_optional_argument (decl, for_present_check);
}
-/* Return true if DECL is a reference type. */
+/* True if OpenMP should privatize what this DECL points to rather
+ than the DECL itself. */
bool
-omp_is_reference (tree decl)
+omp_privatize_by_reference (tree decl)
{
return lang_hooks.decls.omp_privatize_by_reference (decl);
}
@@ -192,6 +194,7 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
== GF_OMP_FOR_KIND_DISTRIBUTE;
bool taskloop = gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_TASKLOOP;
+ bool order_reproducible = false;
tree iterv, countv;
fd->for_stmt = for_stmt;
@@ -276,10 +279,25 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
&& !OMP_CLAUSE__SCANTEMP__CONTROL (t))
fd->have_nonctrl_scantemp = true;
break;
+ case OMP_CLAUSE_ORDER:
+ /* FIXME: For OpenMP 5.2 this should change to
+ if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
+ (with the exception of loop construct but that lowers to
+ no schedule/dist_schedule clauses currently). */
+ if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
+ order_reproducible = true;
default:
break;
}
+ /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
+ we have either the option to expensively remember at runtime how we've
+ distributed work from first loop and reuse that in following loops with
+ the same number of iterations and schedule, or just force static schedule.
+ OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
+ users can't observe it easily anyway. */
+ if (order_reproducible)
+ fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
if (fd->collapse > 1 || fd->tiling)
fd->loops = loops;
else
@@ -935,7 +953,7 @@ omp_max_vf (void)
|| optimize_debug
|| !flag_tree_loop_optimize
|| (!flag_tree_loop_vectorize
- && global_options_set.x_flag_tree_loop_vectorize))
+ && OPTION_SET_P (flag_tree_loop_vectorize)))
return 1;
auto_vector_modes modes;
@@ -1077,6 +1095,146 @@ omp_maybe_offloaded (void)
return false;
}
+
+/* Diagnose errors in an OpenMP context selector, return CTX if
+ it is correct or error_mark_node otherwise. */
+
+tree
+omp_check_context_selector (location_t loc, tree ctx)
+{
+ /* Each trait-set-selector-name can only be specified once.
+ There are just 4 set names. */
+ for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+ for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
+ if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+ {
+ error_at (loc, "selector set %qs specified more than once",
+ IDENTIFIER_POINTER (TREE_PURPOSE (t1)));
+ return error_mark_node;
+ }
+ for (tree t = ctx; t; t = TREE_CHAIN (t))
+ {
+ /* Each trait-selector-name can only be specified once. */
+ if (list_length (TREE_VALUE (t)) < 5)
+ {
+ for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
+ for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
+ if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+ {
+ error_at (loc,
+ "selector %qs specified more than once in set %qs",
+ IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
+ IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ hash_set<tree> pset;
+ for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
+ if (pset.add (TREE_PURPOSE (t1)))
+ {
+ error_at (loc,
+ "selector %qs specified more than once in set %qs",
+ IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
+ IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+ return error_mark_node;
+ }
+ }
+
+ static const char *const kind[] = {
+ "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
+ static const char *const vendor[] = {
+ "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
+ "llvm", "nvidia", "pgi", "ti", "unknown", NULL };
+ static const char *const extension[] = { NULL };
+ static const char *const atomic_default_mem_order[] = {
+ "seq_cst", "relaxed", "acq_rel", NULL };
+ struct known_properties { const char *set; const char *selector;
+ const char *const *props; };
+ known_properties props[] = {
+ { "device", "kind", kind },
+ { "implementation", "vendor", vendor },
+ { "implementation", "extension", extension },
+ { "implementation", "atomic_default_mem_order",
+ atomic_default_mem_order } };
+ for (tree t1 = TREE_VALUE (t); t1; t1 = TREE_CHAIN (t1))
+ for (unsigned i = 0; i < ARRAY_SIZE (props); i++)
+ if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
+ props[i].selector)
+ && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t)),
+ props[i].set))
+ for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+ for (unsigned j = 0; ; j++)
+ {
+ if (props[i].props[j] == NULL)
+ {
+ if (TREE_PURPOSE (t2)
+ && !strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+ " score"))
+ break;
+ if (props[i].props == atomic_default_mem_order)
+ {
+ error_at (loc,
+ "incorrect property %qs of %qs selector",
+ IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+ "atomic_default_mem_order");
+ return error_mark_node;
+ }
+ else if (TREE_PURPOSE (t2))
+ warning_at (loc, 0,
+ "unknown property %qs of %qs selector",
+ IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+ props[i].selector);
+ else
+ warning_at (loc, 0,
+ "unknown property %qE of %qs selector",
+ TREE_VALUE (t2), props[i].selector);
+ break;
+ }
+ else if (TREE_PURPOSE (t2) == NULL_TREE)
+ {
+ const char *str = TREE_STRING_POINTER (TREE_VALUE (t2));
+ if (!strcmp (str, props[i].props[j])
+ && ((size_t) TREE_STRING_LENGTH (TREE_VALUE (t2))
+ == strlen (str) + (lang_GNU_Fortran () ? 0 : 1)))
+ break;
+ }
+ else if (!strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+ props[i].props[j]))
+ break;
+ }
+ }
+ return ctx;
+}
+
+
+/* Register VARIANT as variant of some base function marked with
+ #pragma omp declare variant. CONSTRUCT is corresponding construct
+ selector set. */
+
+void
+omp_mark_declare_variant (location_t loc, tree variant, tree construct)
+{
+ tree attr = lookup_attribute ("omp declare variant variant",
+ DECL_ATTRIBUTES (variant));
+ if (attr == NULL_TREE)
+ {
+ attr = tree_cons (get_identifier ("omp declare variant variant"),
+ unshare_expr (construct),
+ DECL_ATTRIBUTES (variant));
+ DECL_ATTRIBUTES (variant) = attr;
+ return;
+ }
+ if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
+ || (construct != NULL_TREE
+ && omp_context_selector_set_compare ("construct", TREE_VALUE (attr),
+ construct)))
+ error_at (loc, "%qD used as a variant with incompatible %<construct%> "
+ "selector sets", variant);
+}
+
+
/* Return a name from PROP, a property in selectors accepting
name lists. */
@@ -1088,7 +1246,8 @@ omp_context_name_list_prop (tree prop)
else
{
const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
- if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
+ if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop))
+ == strlen (ret) + (lang_GNU_Fortran () ? 0 : 1))
return ret;
return NULL;
}
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 5c3e0f0..8fe744c 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -93,7 +93,7 @@ struct omp_for_data
extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
extern bool omp_is_allocatable_or_ptr (tree decl);
extern tree omp_check_optional_argument (tree decl, bool for_present_check);
-extern bool omp_is_reference (tree decl);
+extern bool omp_privatize_by_reference (tree decl);
extern void omp_adjust_for_condition (location_t loc, enum tree_code *cond_code,
tree *n2, tree v, tree step);
extern tree omp_get_for_step_from_incr (location_t loc, tree incr);
@@ -104,6 +104,9 @@ extern tree find_combined_omp_for (tree *, int *, void *);
extern poly_uint64 omp_max_vf (void);
extern int omp_max_simt_vf (void);
extern int omp_constructor_traits_to_codes (tree, enum tree_code *);
+extern tree omp_check_context_selector (location_t loc, tree ctx);
+extern void omp_mark_declare_variant (location_t loc, tree variant,
+ tree construct);
extern int omp_context_selector_matches (tree);
extern int omp_context_selector_set_compare (const char *, tree, tree);
extern tree omp_get_context_selector (tree, const char *, const char *);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index a0b41af..057b7ae 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -736,7 +736,7 @@ build_outer_var_ref (tree var, omp_context *ctx,
}
else if (outer)
x = lookup_decl (var, outer);
- else if (omp_is_reference (var))
+ else if (omp_privatize_by_reference (var))
/* This can happen with orphaned constructs. If var is reference, it is
possible it is shared and as such valid. */
x = var;
@@ -759,7 +759,7 @@ build_outer_var_ref (tree var, omp_context *ctx,
}
}
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
x = build_simple_mem_ref (x);
return x;
@@ -824,7 +824,8 @@ 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 & (32 | 3)) == 1 && omp_is_reference (var))
+ else if ((mask & (32 | 3)) == 1
+ && omp_privatize_by_reference (var))
type = TREE_TYPE (type);
field = build_decl (DECL_SOURCE_LOCATION (var),
@@ -1160,14 +1161,17 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
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))))
+ || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
{
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);
+ tree val = integer_zero_node;
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
+ val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
+ ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
}
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
@@ -1217,7 +1221,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
|| TREE_ADDRESSABLE (decl)
|| by_ref
- || omp_is_reference (decl))
+ || omp_privatize_by_reference (decl))
{
by_ref = use_pointer_for_field (decl, ctx);
install_var_field (decl, by_ref, 3, ctx);
@@ -1368,7 +1372,10 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
&& is_gimple_omp_offloaded (ctx->stmt))
{
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
- install_var_field (decl, !omp_is_reference (decl), 3, ctx);
+ {
+ by_ref = !omp_privatize_by_reference (decl);
+ install_var_field (decl, by_ref, 3, ctx);
+ }
else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
install_var_field (decl, true, 3, ctx);
else
@@ -1396,7 +1403,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
by_ref = use_pointer_for_field (decl, NULL);
if (is_task_ctx (ctx)
- && (global || by_ref || omp_is_reference (decl)))
+ && (global || by_ref || omp_privatize_by_reference (decl)))
{
if (ctx->allocate_map
&& ctx->allocate_map->get (decl))
@@ -1420,7 +1427,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (lang_hooks.decls.omp_array_data (decl, true))
install_var_field (decl, false, 19, ctx);
else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
- && !omp_is_reference (decl)
+ && !omp_privatize_by_reference (decl)
&& !omp_is_allocatable_or_ptr (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
install_var_field (decl, true, 11, ctx);
@@ -3114,6 +3121,16 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
&& gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
{
+ c = omp_find_clause (gimple_omp_target_clauses (ctx->stmt),
+ OMP_CLAUSE_DEVICE);
+ if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
+ {
+ error_at (gimple_location (stmt),
+ "OpenMP constructs are not allowed in target region "
+ "with %<ancestor%>");
+ return false;
+ }
+
if (gimple_code (stmt) == GIMPLE_OMP_TEAMS && !ctx->teams_nested_p)
ctx->teams_nested_p = true;
else
@@ -3904,8 +3921,12 @@ omp_runtime_api_call (const_tree fndecl)
{
/* This array has 3 sections. First omp_* calls that don't
have any suffixes. */
- "omp_alloc",
- "omp_free",
+ "aligned_alloc",
+ "aligned_calloc",
+ "alloc",
+ "calloc",
+ "free",
+ "realloc",
"target_alloc",
"target_associate_ptr",
"target_disassociate_ptr",
@@ -3932,6 +3953,7 @@ omp_runtime_api_call (const_tree fndecl)
"get_level",
"get_max_active_levels",
"get_max_task_priority",
+ "get_max_teams",
"get_max_threads",
"get_nested",
"get_num_devices",
@@ -3944,6 +3966,7 @@ omp_runtime_api_call (const_tree fndecl)
"get_proc_bind",
"get_supported_active_levels",
"get_team_num",
+ "get_teams_thread_limit",
"get_thread_limit",
"get_thread_num",
"get_wtick",
@@ -3977,8 +4000,10 @@ omp_runtime_api_call (const_tree fndecl)
"set_dynamic",
"set_max_active_levels",
"set_nested",
+ "set_num_teams",
"set_num_threads",
- "set_schedule"
+ "set_schedule",
+ "set_teams_thread_limit"
};
int mode = 0;
@@ -4063,6 +4088,17 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
"OpenMP runtime API call %qD in a region with "
"%<order(concurrent)%> clause", fndecl);
}
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
+ && (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_REGION))
+ {
+ tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt);
+ tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE);
+ if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
+ error_at (gimple_location (stmt),
+ "OpenMP runtime API call %qD in a region with "
+ "%<device(ancestor)%> clause", fndecl);
+ }
}
}
}
@@ -4694,12 +4730,18 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
allocator = *allocatorp;
if (allocator == NULL_TREE)
return false;
- if (!is_ref && omp_is_reference (var))
+ if (!is_ref && omp_privatize_by_reference (var))
{
allocator = NULL_TREE;
return false;
}
+ unsigned HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node, allocator);
@@ -4714,21 +4756,21 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
if (TYPE_P (new_var))
{
ptr_type = build_pointer_type (new_var);
- align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var));
+ ialign = MAX (ialign, 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)));
+ ialign = MAX (ialign, 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));
+ ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
if (sz == NULL_TREE)
sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
}
+ align = build_int_cst (size_type_node, ialign);
if (TREE_CODE (sz) != INTEGER_CST)
{
tree szvar = create_tmp_var (size_type_node);
@@ -4792,7 +4834,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
case OMP_CLAUSE_LASTPRIVATE:
if (is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
- else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
{
tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
@@ -4804,7 +4846,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
|| is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
- else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
{
tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
@@ -4966,7 +5008,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
original address, it is always the address of the
global variable itself. */
if (!DECL_P (var)
- || omp_is_reference (var)
+ || omp_privatize_by_reference (var)
|| !is_global_var
(maybe_lookup_decl_in_outer_ctx (var, ctx)))
{
@@ -5407,10 +5449,10 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
tree ref = build_outer_var_ref (var, ctx);
/* For ref build_outer_var_ref already performs this. */
if (TREE_CODE (d) == INDIRECT_REF)
- gcc_assert (omp_is_reference (var));
+ gcc_assert (omp_privatize_by_reference (var));
else if (TREE_CODE (d) == ADDR_EXPR)
ref = build_fold_addr_expr (ref);
- else if (omp_is_reference (var))
+ else if (omp_privatize_by_reference (var))
ref = build_fold_addr_expr (ref);
ref = fold_convert_loc (clause_loc, ptype, ref);
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
@@ -5557,7 +5599,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bool by_ref = use_pointer_for_field (var, ctx);
x = build_receiver_ref (var, by_ref, ctx);
}
- if (!omp_is_reference (var))
+ if (!omp_privatize_by_reference (var))
x = build_fold_addr_expr (x);
x = fold_convert (ptr_type_node, x);
unsigned cnt = task_reduction_cnt - 1;
@@ -5573,7 +5615,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
else if (pass == 3)
{
tree type = TREE_TYPE (new_var);
- if (!omp_is_reference (var))
+ if (!omp_privatize_by_reference (var))
type = build_pointer_type (type);
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
{
@@ -5601,7 +5643,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
x = fold_convert (type, x);
tree t;
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gimplify_assign (new_var, x, ilist);
t = new_var;
@@ -5662,7 +5704,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimplify_assign (ptr, x, ilist);
}
}
- else if (omp_is_reference (var)
+ else if (omp_privatize_by_reference (var)
&& (c_kind != OMP_CLAUSE_FIRSTPRIVATE
|| !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)))
{
@@ -5682,6 +5724,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -5827,11 +5871,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|| (gimple_omp_for_index (ctx->stmt, 0)
!= new_var)))
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
- || omp_is_reference (var))
+ || omp_privatize_by_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
tree new_vard = TREE_OPERAND (new_var, 0);
@@ -5917,7 +5961,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
break;
}
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
tree new_vard = TREE_OPERAND (new_var, 0);
@@ -5987,7 +6031,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
case OMP_CLAUSE_FIRSTPRIVATE:
if (is_task_ctx (ctx))
{
- if ((omp_is_reference (var)
+ if ((omp_privatize_by_reference (var)
&& !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c))
|| is_variable_sized (var))
goto do_dtor;
@@ -6000,6 +6044,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -6014,7 +6060,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
}
if (OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)
- && omp_is_reference (var))
+ && omp_privatize_by_reference (var))
{
x = build_outer_var_ref (var, ctx);
gcc_assert (TREE_CODE (x) == MEM_REF
@@ -6059,7 +6105,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (OMP_CLAUSE_LINEAR_ARRAY (c))
{
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
tree new_vard = TREE_OPERAND (new_var, 0);
@@ -6096,11 +6142,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
|| TREE_ADDRESSABLE (new_var)
- || omp_is_reference (var))
+ || omp_privatize_by_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
tree new_vard = TREE_OPERAND (new_var, 0);
@@ -6137,7 +6183,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimplify_and_add (x, &llist[1]);
break;
}
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
tree new_vard = TREE_OPERAND (new_var, 0);
@@ -6220,14 +6266,14 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
NULL_TREE);
x = build_outer_var_ref (var, ctx);
- if (omp_is_reference (var)
+ if (omp_privatize_by_reference (var)
&& !useless_type_conversion_p (ptype, TREE_TYPE (x)))
x = build_fold_addr_expr_loc (clause_loc, x);
}
SET_DECL_VALUE_EXPR (placeholder, x);
DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
tree new_vard = new_var;
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
new_vard = TREE_OPERAND (new_var, 0);
@@ -6387,7 +6433,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
for it because it is undesirable if SIMD arrays are used.
But if they aren't used, we need to emit the deferred
initialization now. */
- else if (omp_is_reference (var) && is_simd)
+ else if (omp_privatize_by_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
tree lab2 = NULL_TREE;
@@ -6582,7 +6628,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bool is_truth_op
= (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
tree new_vard = new_var;
- if (is_simd && omp_is_reference (var))
+ if (is_simd && omp_privatize_by_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
new_vard = TREE_OPERAND (new_var, 0);
@@ -6653,7 +6699,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
lower_private_allocate (var, new_var, allocator,
allocate_ptr, ilist, ctx,
false, NULL_TREE);
- if (omp_is_reference (var) && is_simd)
+ if (omp_privatize_by_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_INSCAN (c))
@@ -7254,7 +7300,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
}
if (!x)
x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
gimplify_and_add (x, this_stmt_list);
@@ -7400,7 +7446,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
&& maybe_lookup_field (orig, outer) && !is_private)
{
ref_to_res = build_receiver_ref (orig, false, outer);
- if (omp_is_reference (orig))
+ if (omp_privatize_by_reference (orig))
ref_to_res = build_simple_mem_ref (ref_to_res);
tree type = TREE_TYPE (var);
@@ -7430,7 +7476,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
if (!ref_to_res)
ref_to_res = integer_zero_node;
- if (omp_is_reference (orig))
+ if (omp_privatize_by_reference (orig))
{
tree type = TREE_TYPE (var);
const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
@@ -7610,7 +7656,8 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
}
}
new_var = lookup_decl (var, ctx);
- if (var == OMP_CLAUSE_DECL (c) && omp_is_reference (var))
+ if (var == OMP_CLAUSE_DECL (c)
+ && omp_privatize_by_reference (var))
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
ref = build_outer_var_ref (var, ctx, ccode);
code = OMP_CLAUSE_REDUCTION_CODE (c);
@@ -7679,7 +7726,8 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
if (TREE_CODE (d) == INDIRECT_REF)
{
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
- gcc_assert (omp_is_reference (var) && var == orig_var);
+ gcc_assert (omp_privatize_by_reference (var)
+ && var == orig_var);
}
else if (TREE_CODE (d) == ADDR_EXPR)
{
@@ -7692,7 +7740,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
else
{
gcc_assert (orig_var == var);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
ref = build_fold_addr_expr (ref);
}
if (DECL_P (v))
@@ -7778,7 +7826,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
{
tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
- if (omp_is_reference (var)
+ if (omp_privatize_by_reference (var)
&& !useless_type_conversion_p (TREE_TYPE (placeholder),
TREE_TYPE (ref)))
ref = build_fold_addr_expr_loc (clause_loc, ref);
@@ -7864,7 +7912,7 @@ lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
ref);
ref = build_fold_indirect_ref_loc (clause_loc, ref);
}
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
ref = build_simple_mem_ref_loc (clause_loc, ref);
@@ -8017,7 +8065,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
break;
case OMP_CLAUSE_LASTPRIVATE:
- if (by_ref || omp_is_reference (val))
+ if (by_ref || omp_privatize_by_reference (val))
{
if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
continue;
@@ -8039,7 +8087,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
if (is_task_ctx (ctx))
by_ref = use_pointer_for_field (val, ctx);
else
- do_out = !(by_ref || omp_is_reference (val));
+ do_out = !(by_ref || omp_privatize_by_reference (val));
}
else
by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
@@ -8913,7 +8961,7 @@ omp_task_reduction_iterate (int pass, enum tree_code code,
}
else
{
- if (omp_is_reference (*decl))
+ if (omp_privatize_by_reference (*decl))
*type = TREE_TYPE (*type);
if (pass != (!TREE_CONSTANT (TYPE_SIZE_UNIT (*type))))
continue;
@@ -9201,7 +9249,7 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
else
{
t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
- if (!omp_is_reference (decl))
+ if (!omp_privatize_by_reference (decl))
t = build_fold_addr_expr (t);
}
t = fold_convert (pointer_sized_int_node, t);
@@ -9284,7 +9332,8 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
build_simple_mem_ref (ptr), field, NULL_TREE);
enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
- if (TREE_CODE (decl) != MEM_REF && omp_is_reference (decl))
+ if (TREE_CODE (decl) != MEM_REF
+ && omp_privatize_by_reference (decl))
ref = build_simple_mem_ref (ref);
/* reduction(-:var) sums up the partial results, so it acts
identically to reduction(+:var). */
@@ -9400,7 +9449,7 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
gimple_seq_add_stmt (end, g);
gimple_seq_add_stmt (end, gimple_build_label (lab5));
}
- if (omp_is_reference (decl)
+ if (omp_privatize_by_reference (decl)
&& !useless_type_conversion_p (TREE_TYPE (placeholder),
TREE_TYPE (ref)))
ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
@@ -9414,7 +9463,7 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
gcc_assert (d);
if (DECL_HAS_VALUE_EXPR_P (d))
oldv = DECL_VALUE_EXPR (d);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
tree v = fold_convert (TREE_TYPE (d),
build_fold_addr_expr (new_var));
@@ -9986,7 +10035,7 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx)
tree var4 = NULL_TREE;
tree lane0 = NULL_TREE;
tree new_vard = new_var;
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
val = new_var;
@@ -10853,7 +10902,7 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
tree new_var = lookup_decl (var, ctx);
tree var3 = NULL_TREE;
tree new_vard = new_var;
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
@@ -12026,7 +12075,8 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
sf = *tcctx.cb.decl_map->get (sf);
src = build_simple_mem_ref_loc (loc, sarg);
src = omp_build_component_ref (src, sf);
- if (use_pointer_for_field (decl, NULL) || omp_is_reference (decl))
+ if (use_pointer_for_field (decl, NULL)
+ || omp_privatize_by_reference (decl))
src = build_simple_mem_ref_loc (loc, src);
}
else
@@ -12041,6 +12091,12 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
if (tree *allocatorp = ctx->allocate_map->get (decl))
{
tree allocator = *allocatorp;
+ HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
{
n = splay_tree_lookup (ctx->sfield_map,
@@ -12054,7 +12110,8 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
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));
+ MAX (ialign,
+ 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);
@@ -12646,7 +12703,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
{
gcc_assert (is_gimple_omp_oacc (ctx->stmt));
- if (omp_is_reference (new_var)
+ if (omp_privatize_by_reference (new_var)
&& (TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE
|| DECL_BY_REFERENCE (var)))
{
@@ -12684,7 +12741,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
map_cnt++;
var = OMP_CLAUSE_DECL (c);
- if (!omp_is_reference (var)
+ if (!omp_privatize_by_reference (var)
&& !is_gimple_reg_type (TREE_TYPE (var)))
{
tree new_var = lookup_decl (var, ctx);
@@ -12751,7 +12808,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
}
else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
- && !omp_is_reference (var)
+ && !omp_privatize_by_reference (var)
&& !omp_is_allocatable_or_ptr (var)
&& !lang_hooks.decls.omp_array_data (var, true))
|| TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
@@ -12974,7 +13031,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
{
gcc_assert (is_gimple_omp_oacc (ctx->stmt));
- if (!omp_is_reference (var))
+ if (!omp_privatize_by_reference (var))
{
if (is_gimple_reg (var)
&& OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
@@ -13137,7 +13194,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (is_gimple_omp_oacc (ctx->stmt))
goto oacc_firstprivate_map;
ovar = OMP_CLAUSE_DECL (c);
- if (omp_is_reference (ovar))
+ if (omp_privatize_by_reference (ovar))
talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
else
talign = DECL_ALIGN_UNIT (ovar);
@@ -13145,7 +13202,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
x = build_sender_ref (ovar, ctx);
tkind = GOMP_MAP_FIRSTPRIVATE;
type = TREE_TYPE (ovar);
- if (omp_is_reference (ovar))
+ if (omp_privatize_by_reference (ovar))
type = TREE_TYPE (type);
if ((INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) <= POINTER_SIZE)
@@ -13153,7 +13210,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
tkind = GOMP_MAP_FIRSTPRIVATE_INT;
tree t = var;
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
t = build_simple_mem_ref (var);
else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
suppress_warning (var);
@@ -13162,7 +13219,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
t = fold_convert (TREE_TYPE (x), t);
gimplify_assign (x, t, &ilist);
}
- else if (omp_is_reference (var))
+ else if (omp_privatize_by_reference (var))
gimplify_assign (x, var, &ilist);
else if (is_gimple_reg (var))
{
@@ -13181,7 +13238,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
s = size_int (0);
- else if (omp_is_reference (ovar))
+ else if (omp_privatize_by_reference (ovar))
s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
else
s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
@@ -13236,13 +13293,13 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (lang_hooks.decls.omp_array_data (ovar, true))
var = lang_hooks.decls.omp_array_data (ovar, false);
else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
- && !omp_is_reference (ovar)
+ && !omp_privatize_by_reference (ovar)
&& !omp_is_allocatable_or_ptr (ovar))
|| TREE_CODE (type) == ARRAY_TYPE)
var = build_fold_addr_expr (var);
else
{
- if (omp_is_reference (ovar)
+ if (omp_privatize_by_reference (ovar)
|| omp_check_optional_argument (ovar, false)
|| omp_is_allocatable_or_ptr (ovar))
{
@@ -13251,7 +13308,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
&& TREE_CODE (type) != ARRAY_TYPE
&& ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
&& !omp_is_allocatable_or_ptr (ovar))
- || (omp_is_reference (ovar)
+ || (omp_privatize_by_reference (ovar)
&& omp_is_allocatable_or_ptr (ovar))))
var = build_simple_mem_ref (var);
var = fold_convert (TREE_TYPE (x), var);
@@ -13366,13 +13423,13 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (is_gimple_omp_oacc (ctx->stmt))
break;
var = OMP_CLAUSE_DECL (c);
- if (omp_is_reference (var)
+ if (omp_privatize_by_reference (var)
|| is_gimple_reg_type (TREE_TYPE (var)))
{
tree new_var = lookup_decl (var, ctx);
tree type;
type = TREE_TYPE (var);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
type = TREE_TYPE (type);
if ((INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) <= POINTER_SIZE)
@@ -13384,7 +13441,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
x = fold_convert (type, x);
gimplify_expr (&x, &new_body, NULL, is_gimple_val,
fb_rvalue);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
tree v = create_tmp_var_raw (type, get_name (var));
gimple_add_tmp_var (v);
@@ -13398,7 +13455,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
else
{
- x = build_receiver_ref (var, !omp_is_reference (var), ctx);
+ bool by_ref = !omp_privatize_by_reference (var);
+ x = build_receiver_ref (var, by_ref, ctx);
gimplify_expr (&x, &new_body, NULL, is_gimple_val,
fb_rvalue);
gimple_seq_add_stmt (&new_body,
@@ -13422,7 +13480,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (is_gimple_omp_oacc (ctx->stmt))
break;
var = OMP_CLAUSE_DECL (c);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
tree new_var = lookup_decl (var, ctx);
@@ -13465,7 +13523,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (is_array_data)
{
- bool is_ref = omp_is_reference (var);
+ bool is_ref = omp_privatize_by_reference (var);
do_optional_check = true;
/* First, we copy the descriptor data from the host; then
we update its data to point to the target address. */
@@ -13509,7 +13567,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_build_assign (new_var, x));
}
else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
- && !omp_is_reference (var)
+ && !omp_privatize_by_reference (var)
&& !omp_is_allocatable_or_ptr (var))
|| TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
{
@@ -13526,13 +13584,13 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
tree type = TREE_TYPE (var);
new_var = lookup_decl (var, ctx);
- if (omp_is_reference (var))
+ if (omp_privatize_by_reference (var))
{
type = TREE_TYPE (type);
if (POINTER_TYPE_P (type)
&& TREE_CODE (type) != ARRAY_TYPE
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
- || (omp_is_reference (var)
+ || (omp_privatize_by_reference (var)
&& omp_is_allocatable_or_ptr (var))))
{
tree v = create_tmp_var_raw (type, get_name (var));
@@ -13650,7 +13708,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
offset));
}
else
- is_ref = omp_is_reference (var);
+ is_ref = omp_privatize_by_reference (var);
if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
is_ref = false;
bool ref_to_array = false;
@@ -13730,7 +13788,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_stmt (&new_body,
gimple_build_assign (new_pvar, x));
}
- else if (omp_is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
+ else if (omp_privatize_by_reference (var)
+ && !is_gimple_omp_oacc (ctx->stmt))
{
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
tree new_var = lookup_decl (var, ctx);
diff --git a/gcc/omp-oacc-neuter-broadcast.cc b/gcc/omp-oacc-neuter-broadcast.cc
index d48627a..e43338f 100644
--- a/gcc/omp-oacc-neuter-broadcast.cc
+++ b/gcc/omp-oacc-neuter-broadcast.cc
@@ -53,6 +53,8 @@
#include "tree-cfg.h"
#include "omp-offload.h"
#include "attribs.h"
+#include "targhooks.h"
+#include "diagnostic-core.h"
/* Loop structure of the function. The entire function is described as
a NULL loop. */
@@ -767,16 +769,19 @@ static void
find_local_vars_to_propagate (parallel_g *par, unsigned outer_mask,
hash_set<tree> *partitioned_var_uses,
hash_set<tree> *gang_private_vars,
+ bitmap writes_gang_private,
vec<propagation_set *> *prop_set)
{
unsigned mask = outer_mask | par->mask;
if (par->inner)
find_local_vars_to_propagate (par->inner, mask, partitioned_var_uses,
- gang_private_vars, prop_set);
+ gang_private_vars, writes_gang_private,
+ prop_set);
if (par->next)
find_local_vars_to_propagate (par->next, outer_mask, partitioned_var_uses,
- gang_private_vars, prop_set);
+ gang_private_vars, writes_gang_private,
+ prop_set);
if (!(mask & GOMP_DIM_MASK (GOMP_DIM_WORKER)))
{
@@ -797,8 +802,7 @@ find_local_vars_to_propagate (parallel_g *par, unsigned outer_mask,
if (!VAR_P (var)
|| is_global_var (var)
|| AGGREGATE_TYPE_P (TREE_TYPE (var))
- || !partitioned_var_uses->contains (var)
- || gang_private_vars->contains (var))
+ || !partitioned_var_uses->contains (var))
continue;
if (stmt_may_clobber_ref_p (stmt, var))
@@ -812,6 +816,14 @@ find_local_vars_to_propagate (parallel_g *par, unsigned outer_mask,
fprintf (dump_file, "\n");
}
+ if (gang_private_vars->contains (var))
+ {
+ /* If we write a gang-private variable, we want a
+ barrier at the end of the block. */
+ bitmap_set_bit (writes_gang_private, block->index);
+ continue;
+ }
+
if (!(*prop_set)[block->index])
(*prop_set)[block->index] = new propagation_set;
@@ -923,14 +935,6 @@ worker_single_simple (basic_block from, basic_block to,
}
}
}
-
- gsi = gsi_start_bb (skip_block);
-
- decl = builtin_decl_explicit (BUILT_IN_GOACC_BARRIER);
- gimple *acc_bar = gimple_build_call (decl, 0);
-
- gsi_insert_before (&gsi, acc_bar, GSI_SAME_STMT);
- update_stmt (acc_bar);
}
/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
@@ -968,6 +972,8 @@ build_receiver_ref (tree var, tree receiver_decl, field_map_t *fields)
static tree
build_sender_ref (tree var, tree sender_decl, field_map_t *fields)
{
+ if (POINTER_TYPE_P (TREE_TYPE (sender_decl)))
+ sender_decl = build_simple_mem_ref (sender_decl);
tree field = *fields->get (var);
return oacc_build_component_ref (sender_decl, field);
}
@@ -1005,7 +1011,9 @@ static void
worker_single_copy (basic_block from, basic_block to,
hash_set<tree> *def_escapes_block,
hash_set<tree> *worker_partitioned_uses,
- tree record_type, record_field_map_t *record_field_map)
+ tree record_type, record_field_map_t *record_field_map,
+ unsigned HOST_WIDE_INT placement,
+ bool isolate_broadcasts, bool has_gang_private_write)
{
/* If we only have virtual defs, we'll have no record type, but we still want
to emit single_copy_start and (particularly) single_copy_end to act as
@@ -1016,10 +1024,12 @@ worker_single_copy (basic_block from, basic_block to,
tree sender_decl
= targetm.goacc.create_worker_broadcast_record (record_type, true,
- ".oacc_worker_o");
+ ".oacc_worker_o",
+ placement);
tree receiver_decl
= targetm.goacc.create_worker_broadcast_record (record_type, false,
- ".oacc_worker_i");
+ ".oacc_worker_i",
+ placement);
gimple_stmt_iterator gsi = gsi_last_bb (to);
if (EDGE_COUNT (to->succs) > 1)
@@ -1033,12 +1043,23 @@ worker_single_copy (basic_block from, basic_block to,
tree lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
- gimple *call = gimple_build_call (decl, 1,
- build_fold_addr_expr (sender_decl));
+ gimple *call
+ = gimple_build_call (decl, 1,
+ POINTER_TYPE_P (TREE_TYPE (sender_decl))
+ ? sender_decl : build_fold_addr_expr (sender_decl));
gimple_call_set_lhs (call, lhs);
gsi_insert_before (&start, call, GSI_NEW_STMT);
update_stmt (call);
+ /* The shared-memory range for this block overflowed. Add a barrier before
+ the GOACC_single_copy_start call. */
+ if (isolate_broadcasts)
+ {
+ decl = builtin_decl_explicit (BUILT_IN_GOACC_BARRIER);
+ gimple *acc_bar = gimple_build_call (decl, 0);
+ gsi_insert_before (&start, acc_bar, GSI_SAME_STMT);
+ }
+
tree conv_tmp = make_ssa_name (TREE_TYPE (receiver_decl));
gimple *conv = gimple_build_assign (conv_tmp,
@@ -1075,14 +1096,19 @@ worker_single_copy (basic_block from, basic_block to,
edge ef = make_edge (from, barrier_block, EDGE_FALSE_VALUE);
ef->probability = et->probability.invert ();
- decl = builtin_decl_explicit (BUILT_IN_GOACC_BARRIER);
- gimple *acc_bar = gimple_build_call (decl, 0);
-
gimple_stmt_iterator bar_gsi = gsi_start_bb (barrier_block);
- gsi_insert_before (&bar_gsi, acc_bar, GSI_NEW_STMT);
-
cond = gimple_build_cond (NE_EXPR, recv_tmp, zero_ptr, NULL_TREE, NULL_TREE);
- gsi_insert_after (&bar_gsi, cond, GSI_NEW_STMT);
+
+ if (record_type != char_type_node || has_gang_private_write)
+ {
+ decl = builtin_decl_explicit (BUILT_IN_GOACC_BARRIER);
+ gimple *acc_bar = gimple_build_call (decl, 0);
+
+ gsi_insert_before (&bar_gsi, acc_bar, GSI_NEW_STMT);
+ gsi_insert_after (&bar_gsi, cond, GSI_NEW_STMT);
+ }
+ else
+ gsi_insert_before (&bar_gsi, cond, GSI_NEW_STMT);
edge et2 = split_block (barrier_block, cond);
et2->flags &= ~EDGE_FALLTHRU;
@@ -1206,13 +1232,26 @@ worker_single_copy (basic_block from, basic_block to,
}
}
+ /* The shared-memory range for this block overflowed. Add a barrier at the
+ end. */
+ if (isolate_broadcasts)
+ {
+ gsi = gsi_start_bb (exit_block);
+ decl = builtin_decl_explicit (BUILT_IN_GOACC_BARRIER);
+ gimple *acc_bar = gimple_build_call (decl, 0);
+ gsi_insert_before (&gsi, acc_bar, GSI_SAME_STMT);
+ }
+
/* It's possible for the ET->DEST block (the work done by the active thread)
to finish with a control-flow insn, e.g. a UNIQUE function call. Split
the block and add SENDER_SEQ in the latter part to avoid having control
flow in the middle of a BB. */
decl = builtin_decl_explicit (BUILT_IN_GOACC_SINGLE_COPY_END);
- call = gimple_build_call (decl, 1, build_fold_addr_expr (sender_decl));
+ call = gimple_build_call (decl, 1,
+ POINTER_TYPE_P (TREE_TYPE (sender_decl))
+ ? sender_decl
+ : build_fold_addr_expr (sender_decl));
gimple_seq_add_stmt (&sender_seq, call);
gsi = gsi_last_bb (body);
@@ -1222,12 +1261,17 @@ worker_single_copy (basic_block from, basic_block to,
gsi_insert_seq_after (&gsi, sender_seq, GSI_CONTINUE_LINKING);
}
+typedef hash_map<basic_block, std::pair<unsigned HOST_WIDE_INT, bool> >
+ blk_offset_map_t;
+
static void
neuter_worker_single (parallel_g *par, unsigned outer_mask,
bitmap worker_single, bitmap vector_single,
vec<propagation_set *> *prop_set,
hash_set<tree> *partitioned_var_uses,
- record_field_map_t *record_field_map)
+ record_field_map_t *record_field_map,
+ blk_offset_map_t *blk_offset_map,
+ bitmap writes_gang_private)
{
unsigned mask = outer_mask | par->mask;
@@ -1313,12 +1357,72 @@ neuter_worker_single (parallel_g *par, unsigned outer_mask,
(*prop_set)[block->index] = 0;
}
- tree record_type = (tree) block->aux;
+ bool only_marker_fns = true;
+ bool join_block = false;
+
+ for (gimple_stmt_iterator gsi = gsi_start_bb (block);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) == GIMPLE_CALL
+ && gimple_call_internal_p (stmt, IFN_UNIQUE))
+ {
+ enum ifn_unique_kind k = ((enum ifn_unique_kind)
+ TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
+ if (k != IFN_UNIQUE_OACC_PRIVATE
+ && k != IFN_UNIQUE_OACC_JOIN
+ && k != IFN_UNIQUE_OACC_FORK
+ && k != IFN_UNIQUE_OACC_HEAD_MARK
+ && k != IFN_UNIQUE_OACC_TAIL_MARK)
+ only_marker_fns = false;
+ else if (k == IFN_UNIQUE_OACC_JOIN)
+ /* The JOIN marker is special in that it *cannot* be
+ predicated for worker zero, because it may be lowered
+ to a barrier instruction and all workers must typically
+ execute that barrier. We shouldn't be doing any
+ broadcasts from the join block anyway. */
+ join_block = true;
+ }
+ else if (gimple_code (stmt) == GIMPLE_CALL
+ && gimple_call_internal_p (stmt, IFN_GOACC_LOOP))
+ /* Empty. */;
+ else if (gimple_nop_p (stmt))
+ /* Empty. */;
+ else
+ only_marker_fns = false;
+ }
+
+ /* We can skip predicating this block for worker zero if the only
+ thing it contains is marker functions that will be removed in the
+ oaccdevlow pass anyway.
+ Don't do this if the block has (any) phi nodes, because those
+ might define SSA names that need broadcasting.
+ TODO: We might be able to skip transforming blocks that only
+ contain some other trivial statements too. */
+ if (only_marker_fns && !phi_nodes (block))
+ continue;
+
+ gcc_assert (!join_block);
if (has_defs)
- worker_single_copy (block, block, &def_escapes_block,
- &worker_partitioned_uses, record_type,
- record_field_map);
+ {
+ tree record_type = (tree) block->aux;
+ std::pair<unsigned HOST_WIDE_INT, bool> *off_rngalloc
+ = blk_offset_map->get (block);
+ gcc_assert (!record_type || off_rngalloc);
+ unsigned HOST_WIDE_INT offset
+ = off_rngalloc ? off_rngalloc->first : 0;
+ bool range_allocated
+ = off_rngalloc ? off_rngalloc->second : true;
+ bool has_gang_private_write
+ = bitmap_bit_p (writes_gang_private, block->index);
+ worker_single_copy (block, block, &def_escapes_block,
+ &worker_partitioned_uses, record_type,
+ record_field_map,
+ offset, !range_allocated,
+ has_gang_private_write);
+ }
else
worker_single_simple (block, block, &def_escapes_block);
}
@@ -1354,14 +1458,159 @@ neuter_worker_single (parallel_g *par, unsigned outer_mask,
if (par->inner)
neuter_worker_single (par->inner, mask, worker_single, vector_single,
- prop_set, partitioned_var_uses, record_field_map);
+ prop_set, partitioned_var_uses, record_field_map,
+ blk_offset_map, writes_gang_private);
if (par->next)
neuter_worker_single (par->next, outer_mask, worker_single, vector_single,
- prop_set, partitioned_var_uses, record_field_map);
+ prop_set, partitioned_var_uses, record_field_map,
+ blk_offset_map, writes_gang_private);
+}
+
+static void
+dfs_broadcast_reachable_1 (basic_block bb, sbitmap reachable)
+{
+ if (bb->flags & BB_VISITED)
+ return;
+
+ bb->flags |= BB_VISITED;
+
+ if (bb->succs)
+ {
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ basic_block dest = e->dest;
+ if (dest->aux)
+ bitmap_set_bit (reachable, dest->index);
+ else
+ dfs_broadcast_reachable_1 (dest, reachable);
+ }
+ }
+}
+
+typedef std::pair<int, tree> idx_decl_pair_t;
+
+typedef auto_vec<splay_tree> used_range_vec_t;
+
+static int
+sort_size_descending (const void *a, const void *b)
+{
+ const idx_decl_pair_t *pa = (const idx_decl_pair_t *) a;
+ const idx_decl_pair_t *pb = (const idx_decl_pair_t *) b;
+ unsigned HOST_WIDE_INT asize = tree_to_uhwi (TYPE_SIZE_UNIT (pa->second));
+ unsigned HOST_WIDE_INT bsize = tree_to_uhwi (TYPE_SIZE_UNIT (pb->second));
+ return bsize - asize;
}
+class addr_range
+{
+public:
+ addr_range (unsigned HOST_WIDE_INT addr_lo, unsigned HOST_WIDE_INT addr_hi)
+ : lo (addr_lo), hi (addr_hi)
+ { }
+ addr_range (const addr_range &ar) : lo (ar.lo), hi (ar.hi)
+ { }
+ addr_range () : lo (0), hi (0)
+ { }
+
+ bool invalid () { return lo == 0 && hi == 0; }
+
+ unsigned HOST_WIDE_INT lo;
+ unsigned HOST_WIDE_INT hi;
+};
+
static int
-execute_omp_oacc_neuter_broadcast ()
+splay_tree_compare_addr_range (splay_tree_key a, splay_tree_key b)
+{
+ addr_range *ar = (addr_range *) a;
+ addr_range *br = (addr_range *) b;
+ if (ar->lo == br->lo && ar->hi == br->hi)
+ return 0;
+ if (ar->hi <= br->lo)
+ return -1;
+ else if (ar->lo >= br->hi)
+ return 1;
+ return 0;
+}
+
+static void
+splay_tree_free_key (splay_tree_key k)
+{
+ addr_range *ar = (addr_range *) k;
+ delete ar;
+}
+
+static addr_range
+first_fit_range (splay_tree s, unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT align, addr_range *bounds)
+{
+ splay_tree_node min = splay_tree_min (s);
+ if (min)
+ {
+ splay_tree_node next;
+ while ((next = splay_tree_successor (s, min->key)))
+ {
+ unsigned HOST_WIDE_INT lo = ((addr_range *) min->key)->hi;
+ unsigned HOST_WIDE_INT hi = ((addr_range *) next->key)->lo;
+ unsigned HOST_WIDE_INT base = (lo + align - 1) & ~(align - 1);
+ if (base + size <= hi)
+ return addr_range (base, base + size);
+ min = next;
+ }
+
+ unsigned HOST_WIDE_INT base = ((addr_range *)min->key)->hi;
+ base = (base + align - 1) & ~(align - 1);
+ if (base + size <= bounds->hi)
+ return addr_range (base, base + size);
+ else
+ return addr_range ();
+ }
+ else
+ {
+ unsigned HOST_WIDE_INT lo = bounds->lo;
+ lo = (lo + align - 1) & ~(align - 1);
+ if (lo + size <= bounds->hi)
+ return addr_range (lo, lo + size);
+ else
+ return addr_range ();
+ }
+}
+
+static int
+merge_ranges_1 (splay_tree_node n, void *ptr)
+{
+ splay_tree accum = (splay_tree) ptr;
+ addr_range ar = *(addr_range *) n->key;
+
+ splay_tree_node old = splay_tree_lookup (accum, n->key);
+
+ /* We might have an overlap. Create a new range covering the
+ overlapping parts. */
+ if (old)
+ {
+ addr_range *old_ar = (addr_range *) old->key;
+ ar.lo = MIN (old_ar->lo, ar.lo);
+ ar.hi = MAX (old_ar->hi, ar.hi);
+ splay_tree_remove (accum, old->key);
+ }
+
+ addr_range *new_ar = new addr_range (ar);
+
+ splay_tree_insert (accum, (splay_tree_key) new_ar, n->value);
+
+ return 0;
+}
+
+static void
+merge_ranges (splay_tree accum, splay_tree sp)
+{
+ splay_tree_foreach (sp, merge_ranges_1, (void *) accum);
+}
+
+static void
+oacc_do_neutering (unsigned HOST_WIDE_INT bounds_lo,
+ unsigned HOST_WIDE_INT bounds_hi)
{
bb_stmt_map_t bb_stmt_map;
auto_bitmap worker_single, vector_single;
@@ -1378,18 +1627,17 @@ execute_omp_oacc_neuter_broadcast ()
/* If this is a routine, calculate MASK as if the outer levels are already
partitioned. */
- tree attr = oacc_get_fn_attrib (current_function_decl);
- if (attr)
- {
- tree dims = TREE_VALUE (attr);
- unsigned ix;
- for (ix = 0; ix != GOMP_DIM_MAX; ix++, dims = TREE_CHAIN (dims))
- {
- tree allowed = TREE_PURPOSE (dims);
- if (allowed && integer_zerop (allowed))
- mask |= GOMP_DIM_MASK (ix);
- }
- }
+ {
+ tree attr = oacc_get_fn_attrib (current_function_decl);
+ tree dims = TREE_VALUE (attr);
+ unsigned ix;
+ for (ix = 0; ix != GOMP_DIM_MAX; ix++, dims = TREE_CHAIN (dims))
+ {
+ tree allowed = TREE_PURPOSE (dims);
+ if (allowed && integer_zerop (allowed))
+ mask |= GOMP_DIM_MASK (ix);
+ }
+ }
parallel_g *par = omp_sese_discover_pars (&bb_stmt_map);
populate_single_mode_bitmaps (par, worker_single, vector_single, mask, 0);
@@ -1406,11 +1654,13 @@ execute_omp_oacc_neuter_broadcast ()
hash_set<tree> partitioned_var_uses;
hash_set<tree> gang_private_vars;
+ auto_bitmap writes_gang_private;
find_gang_private_vars (&gang_private_vars);
find_partitioned_var_uses (par, mask, &partitioned_var_uses);
find_local_vars_to_propagate (par, mask, &partitioned_var_uses,
- &gang_private_vars, &prop_set);
+ &gang_private_vars, writes_gang_private,
+ &prop_set);
record_field_map_t record_field_map;
@@ -1451,8 +1701,122 @@ execute_omp_oacc_neuter_broadcast ()
}
}
+ sbitmap *reachable
+ = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
+ last_basic_block_for_fn (cfun));
+
+ bitmap_vector_clear (reachable, last_basic_block_for_fn (cfun));
+
+ auto_vec<std::pair<int, tree> > priority;
+
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ if (bb->aux)
+ {
+ tree record_type = (tree) bb->aux;
+
+ basic_block bb2;
+ FOR_ALL_BB_FN (bb2, cfun)
+ bb2->flags &= ~BB_VISITED;
+
+ priority.safe_push (std::make_pair (bb->index, record_type));
+ dfs_broadcast_reachable_1 (bb, reachable[bb->index]);
+ }
+ }
+
+ sbitmap *inverted
+ = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
+ last_basic_block_for_fn (cfun));
+
+ bitmap_vector_clear (inverted, last_basic_block_for_fn (cfun));
+
+ for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
+ {
+ sbitmap_iterator bi;
+ unsigned int j;
+ EXECUTE_IF_SET_IN_BITMAP (reachable[i], 0, j, bi)
+ bitmap_set_bit (inverted[j], i);
+ }
+
+ for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
+ bitmap_ior (reachable[i], reachable[i], inverted[i]);
+
+ sbitmap_vector_free (inverted);
+
+ used_range_vec_t used_ranges;
+
+ used_ranges.safe_grow_cleared (last_basic_block_for_fn (cfun));
+
+ blk_offset_map_t blk_offset_map;
+
+ addr_range worker_shm_bounds (bounds_lo, bounds_hi);
+
+ priority.qsort (sort_size_descending);
+ for (unsigned int i = 0; i < priority.length (); i++)
+ {
+ idx_decl_pair_t p = priority[i];
+ int blkno = p.first;
+ tree record_type = p.second;
+ HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE_UNIT (record_type));
+ HOST_WIDE_INT align = TYPE_ALIGN_UNIT (record_type);
+
+ splay_tree conflicts = splay_tree_new (splay_tree_compare_addr_range,
+ splay_tree_free_key, NULL);
+
+ if (!used_ranges[blkno])
+ used_ranges[blkno] = splay_tree_new (splay_tree_compare_addr_range,
+ splay_tree_free_key, NULL);
+ else
+ merge_ranges (conflicts, used_ranges[blkno]);
+
+ sbitmap_iterator bi;
+ unsigned int j;
+ EXECUTE_IF_SET_IN_BITMAP (reachable[blkno], 0, j, bi)
+ if (used_ranges[j])
+ merge_ranges (conflicts, used_ranges[j]);
+
+ addr_range ar
+ = first_fit_range (conflicts, size, align, &worker_shm_bounds);
+
+ splay_tree_delete (conflicts);
+
+ if (ar.invalid ())
+ {
+ unsigned HOST_WIDE_INT base
+ = (bounds_lo + align - 1) & ~(align - 1);
+ if (base + size > bounds_hi)
+ error_at (UNKNOWN_LOCATION, "shared-memory region overflow");
+ std::pair<unsigned HOST_WIDE_INT, bool> base_inrng
+ = std::make_pair (base, false);
+ blk_offset_map.put (BASIC_BLOCK_FOR_FN (cfun, blkno), base_inrng);
+ }
+ else
+ {
+ splay_tree_node old = splay_tree_lookup (used_ranges[blkno],
+ (splay_tree_key) &ar);
+ if (old)
+ {
+ fprintf (stderr, "trying to map [%d..%d] but [%d..%d] is "
+ "already mapped in block %d\n", (int) ar.lo,
+ (int) ar.hi, (int) ((addr_range *) old->key)->lo,
+ (int) ((addr_range *) old->key)->hi, blkno);
+ abort ();
+ }
+
+ addr_range *arp = new addr_range (ar);
+ splay_tree_insert (used_ranges[blkno], (splay_tree_key) arp,
+ (splay_tree_value) blkno);
+ std::pair<unsigned HOST_WIDE_INT, bool> base_inrng
+ = std::make_pair (ar.lo, true);
+ blk_offset_map.put (BASIC_BLOCK_FOR_FN (cfun, blkno), base_inrng);
+ }
+ }
+
+ sbitmap_vector_free (reachable);
+
neuter_worker_single (par, mask, worker_single, vector_single, &prop_set,
- &partitioned_var_uses, &record_field_map);
+ &partitioned_var_uses, &record_field_map,
+ &blk_offset_map, writes_gang_private);
for (auto it : record_field_map)
delete it.second;
@@ -1479,6 +1843,107 @@ execute_omp_oacc_neuter_broadcast ()
fprintf (dump_file, "\n\nAfter neutering:\n\n");
dump_function_to_file (current_function_decl, dump_file, dump_flags);
}
+}
+
+static int
+execute_omp_oacc_neuter_broadcast ()
+{
+ unsigned HOST_WIDE_INT reduction_size[GOMP_DIM_MAX];
+ unsigned HOST_WIDE_INT private_size[GOMP_DIM_MAX];
+
+ for (unsigned i = 0; i < GOMP_DIM_MAX; i++)
+ {
+ reduction_size[i] = 0;
+ private_size[i] = 0;
+ }
+
+ /* Calculate shared memory size required for reduction variables and
+ gang-private memory for this offloaded function. */
+ basic_block bb;
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (!is_gimple_call (stmt))
+ continue;
+ gcall *call = as_a <gcall *> (stmt);
+ if (!gimple_call_internal_p (call))
+ continue;
+ enum internal_fn ifn_code = gimple_call_internal_fn (call);
+ switch (ifn_code)
+ {
+ default: break;
+ case IFN_GOACC_REDUCTION:
+ if (integer_minus_onep (gimple_call_arg (call, 3)))
+ continue;
+ else
+ {
+ unsigned code = TREE_INT_CST_LOW (gimple_call_arg (call, 0));
+ /* Only count reduction variables once: the choice to pick
+ the setup call is fairly arbitrary. */
+ if (code == IFN_GOACC_REDUCTION_SETUP)
+ {
+ int level = TREE_INT_CST_LOW (gimple_call_arg (call, 3));
+ tree var = gimple_call_arg (call, 2);
+ tree offset = gimple_call_arg (call, 5);
+ tree var_type = TREE_TYPE (var);
+ unsigned HOST_WIDE_INT limit
+ = (tree_to_uhwi (offset)
+ + tree_to_uhwi (TYPE_SIZE_UNIT (var_type)));
+ reduction_size[level]
+ = MAX (reduction_size[level], limit);
+ }
+ }
+ break;
+ case IFN_UNIQUE:
+ {
+ enum ifn_unique_kind kind
+ = ((enum ifn_unique_kind)
+ TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
+
+ if (kind == IFN_UNIQUE_OACC_PRIVATE)
+ {
+ HOST_WIDE_INT level
+ = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
+ if (level == -1)
+ break;
+ for (unsigned i = 3;
+ i < gimple_call_num_args (call);
+ i++)
+ {
+ tree arg = gimple_call_arg (call, i);
+ gcc_assert (TREE_CODE (arg) == ADDR_EXPR);
+ tree decl = TREE_OPERAND (arg, 0);
+ unsigned HOST_WIDE_INT align = DECL_ALIGN_UNIT (decl);
+ private_size[level] = ((private_size[level] + align - 1)
+ & ~(align - 1));
+ unsigned HOST_WIDE_INT decl_size
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (decl)));
+ private_size[level] += decl_size;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ int dims[GOMP_DIM_MAX];
+ for (unsigned i = 0; i < GOMP_DIM_MAX; i++)
+ dims[i] = oacc_get_fn_dim_size (current_function_decl, i);
+
+ /* Find bounds of shared-memory buffer space we can use. */
+ unsigned HOST_WIDE_INT bounds_lo = 0, bounds_hi = 0;
+ if (targetm.goacc.shared_mem_layout)
+ targetm.goacc.shared_mem_layout (&bounds_lo, &bounds_hi, dims,
+ private_size, reduction_size);
+
+ /* Perform worker partitioning unless we know 'num_workers(1)'. */
+ if (dims[GOMP_DIM_WORKER] != 1)
+ oacc_do_neutering (bounds_lo, bounds_hi);
return 0;
}
@@ -1506,11 +1971,21 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *)
+ virtual bool gate (function *fun)
{
- return (flag_openacc
- && targetm.goacc.create_worker_broadcast_record);
- };
+ if (!flag_openacc)
+ return false;
+
+ if (!targetm.goacc.create_worker_broadcast_record)
+ return false;
+
+ /* Only relevant for OpenACC offloaded functions. */
+ tree attr = oacc_get_fn_attrib (fun->decl);
+ if (!attr)
+ return false;
+
+ return true;
+ }
virtual unsigned int execute (function *)
{
diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c
index d881426..833f7dd 100644
--- a/gcc/omp-offload.c
+++ b/gcc/omp-offload.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "context.h"
#include "convert.h"
+#include "opts.h"
/* Describe the OpenACC looping structure of a function. The entire
function is held in a 'NULL' loop. */
@@ -633,7 +634,7 @@ oacc_xform_loop (gcall *call)
/* If not -fno-tree-loop-vectorize, hint that we want to vectorize
the loop. */
&& (flag_tree_loop_vectorize
- || !global_options_set.x_flag_tree_loop_vectorize))
+ || !OPTION_SET_P (flag_tree_loop_vectorize)))
{
basic_block bb = gsi_bb (gsi);
class loop *parent = bb->loop_father;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index ebed78f..019bbb6 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5488,20 +5488,21 @@ expand_fix (rtx to, rtx from, int unsignedp)
if (icode != CODE_FOR_nothing)
{
rtx_insn *last = get_last_insn ();
+ rtx from1 = from;
if (fmode != GET_MODE (from))
- from = convert_to_mode (fmode, from, 0);
+ from1 = convert_to_mode (fmode, from, 0);
if (must_trunc)
{
- rtx temp = gen_reg_rtx (GET_MODE (from));
- from = expand_unop (GET_MODE (from), ftrunc_optab, from,
- temp, 0);
+ rtx temp = gen_reg_rtx (GET_MODE (from1));
+ from1 = expand_unop (GET_MODE (from1), ftrunc_optab, from1,
+ temp, 0);
}
if (imode != GET_MODE (to))
target = gen_reg_rtx (imode);
- if (maybe_emit_unop_insn (icode, target, from,
+ if (maybe_emit_unop_insn (icode, target, from1,
doing_unsigned ? UNSIGNED_FIX : FIX))
{
if (target != to)
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 201b8aa..b889ad2 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -245,6 +245,7 @@ OPTAB_D (cond_fma_optab, "cond_fma$a")
OPTAB_D (cond_fms_optab, "cond_fms$a")
OPTAB_D (cond_fnma_optab, "cond_fnma$a")
OPTAB_D (cond_fnms_optab, "cond_fnms$a")
+OPTAB_D (cond_neg_optab, "cond_neg$a")
OPTAB_D (cmov_optab, "cmov$a6")
OPTAB_D (cstore_optab, "cstore$a4")
OPTAB_D (ctrap_optab, "ctrap$a4")
@@ -267,6 +268,7 @@ OPTAB_D (cpymem_optab, "cpymem$a")
OPTAB_D (movmem_optab, "movmem$a")
OPTAB_D (setmem_optab, "setmem$a")
OPTAB_D (strlen_optab, "strlen$a")
+OPTAB_D (rawmemchr_optab, "rawmemchr$a")
OPTAB_DC(fma_optab, "fma$a4", FMA)
OPTAB_D (fms_optab, "fms$a4")
diff --git a/gcc/opts.c b/gcc/opts.c
index e050155..65fe192 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -135,6 +135,14 @@ btf_debuginfo_p ()
return (write_symbols & BTF_DEBUG);
}
+/* Return TRUE iff BTF with CO-RE debug info is enabled. */
+
+bool
+btf_with_core_debuginfo_p ()
+{
+ return (write_symbols & BTF_WITH_CORE_DEBUG);
+}
+
/* Return TRUE iff CTF debug info is enabled. */
bool
@@ -561,6 +569,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fthread_jumps, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },
@@ -572,6 +581,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fvar_tracking, NULL, 1 },
/* -O1 (and not -Og) optimizations. */
{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 },
@@ -621,12 +631,12 @@ static const struct default_options default_options_table[] =
#endif
{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 },
- { OPT_LEVELS_2_PLUS, OPT_fthread_jumps, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
- { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
+ { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL,
+ VECT_COST_MODEL_VERY_CHEAP },
{ OPT_LEVELS_2_PLUS, OPT_finline_functions, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
@@ -638,6 +648,8 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL,
REORDER_BLOCKS_ALGORITHM_STC },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_ftree_loop_vectorize, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_ftree_slp_vectorize, NULL, 1 },
#ifdef INSN_SCHEDULING
/* Only run the pre-regalloc scheduling pass if optimizing for speed. */
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
@@ -655,9 +667,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 },
- { OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
- { OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },
{ OPT_LEVELS_3_PLUS, OPT_fversion_loops_for_strides, NULL, 1 },
@@ -1312,17 +1322,33 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
opts->x_flag_live_patching,
loc);
- /* Unrolling all loops implies that standard loop unrolling must also
- be done. */
- if (opts->x_flag_unroll_all_loops)
- opts->x_flag_unroll_loops = 1;
-
/* Allow cunroll to grow size accordingly. */
if (!opts_set->x_flag_cunroll_grow_size)
opts->x_flag_cunroll_grow_size
= (opts->x_flag_unroll_loops
|| opts->x_flag_peel_loops
|| opts->x_optimize >= 3);
+
+ /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
+ if (opts->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = 0;
+ else if (opts_set->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
+
+ /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
+ if (opts->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = 1;
+ else if (opts_set->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
+
+ /* Use -fvect-cost-model=cheap instead of -fvect-cost-mode=very-cheap
+ by default with explicit -ftree-{loop,slp}-vectorize. */
+ if (opts->x_optimize == 2
+ && (opts_set->x_flag_tree_loop_vectorize
+ || opts_set->x_flag_tree_vectorize))
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model,
+ VECT_COST_MODEL_CHEAP);
+
}
#define LEFT_COLUMN 27
diff --git a/gcc/opts.h b/gcc/opts.h
index bafc790..f5bc9a3 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -500,4 +500,8 @@ extern char *gen_producer_string (const char *language_string,
} \
while (false)
+/* Return true if OPTION is set by user in global options. */
+
+#define OPTION_SET_P(OPTION) global_options_set.x_ ## OPTION
+
#endif
diff --git a/gcc/output.h b/gcc/output.h
index 73ca454..8f6f153 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -365,44 +365,53 @@ extern void default_function_switched_text_sections (FILE *, tree, bool);
extern void no_asm_to_stream (FILE *);
/* Flags controlling properties of a section. */
-#define SECTION_ENTSIZE 0x000ff /* entity size in section */
-#define SECTION_CODE 0x00100 /* contains code */
-#define SECTION_WRITE 0x00200 /* data is writable */
-#define SECTION_DEBUG 0x00400 /* contains debug data */
-#define SECTION_LINKONCE 0x00800 /* is linkonce */
-#define SECTION_SMALL 0x01000 /* contains "small data" */
-#define SECTION_BSS 0x02000 /* contains zeros only */
-#define SECTION_FORGET 0x04000 /* forget that we've entered the section */
-#define SECTION_MERGE 0x08000 /* contains mergeable data */
-#define SECTION_STRINGS 0x10000 /* contains zero terminated strings without
- embedded zeros */
-#define SECTION_OVERRIDE 0x20000 /* allow override of default flags */
-#define SECTION_TLS 0x40000 /* contains thread-local storage */
-#define SECTION_NOTYPE 0x80000 /* don't output @progbits */
-#define SECTION_DECLARED 0x100000 /* section has been used */
-#define SECTION_STYLE_MASK 0x600000 /* bits used for SECTION_STYLE */
-#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_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. */
-#define SECTION_UNNAMED 0x000000
-
-/* This SECTION_STYLE is used for named sections that we can switch
- to using a general section directive. */
-#define SECTION_NAMED 0x200000
-
-/* This SECTION_STYLE is used for sections that we cannot switch to at
- all. The choice of section is implied by the directive that we use
- to declare the object. */
-#define SECTION_NOSWITCH 0x400000
+enum section_flag
+{
+ /* This SECTION_STYLE is used for unnamed sections that we can switch
+ to using a special assembler directive. */
+ SECTION_UNNAMED = 0,
+
+ SECTION_ENTSIZE = (1UL << 8) - 1, /* entity size in section */
+ SECTION_CODE = 1UL << 8, /* contains code */
+ SECTION_WRITE = 1UL << 9, /* data is writable */
+
+ SECTION_DEBUG = 1UL << 10, /* contains debug data */
+ SECTION_LINKONCE = 1UL << 11, /* is linkonce */
+ SECTION_SMALL = 1UL << 12, /* contains "small data" */
+ SECTION_BSS = 1UL << 13, /* contains zeros only */
+ SECTION_MERGE = 1UL << 14, /* contains mergeable data */
+ SECTION_STRINGS = 1UL << 15, /* contains zero terminated strings
+ without embedded zeros */
+ SECTION_OVERRIDE = 1UL << 16, /* allow override of default flags */
+ SECTION_TLS = 1UL << 17, /* contains thread-local storage */
+ SECTION_NOTYPE = 1UL << 18, /* don't output @progbits */
+ SECTION_DECLARED = 1UL << 19, /* section has been used */
+
+ /* This SECTION_STYLE is used for named sections that we can switch
+ to using a general section directive. */
+ SECTION_NAMED = 1UL << 20,
+
+ /* This SECTION_STYLE is used for sections that we cannot switch to at
+ all. The choice of section is implied by the directive that we use
+ to declare the object. */
+ SECTION_NOSWITCH = 1UL << 21,
+
+ /* bits used for SECTION_STYLE */
+ SECTION_STYLE_MASK = SECTION_NAMED | SECTION_NOSWITCH,
+
+ SECTION_COMMON = 1UL << 22, /* contains common data */
+ SECTION_RELRO = 1UL << 23, /* data is readonly after
+ relocation processing */
+ SECTION_EXCLUDE = 1UL << 24, /* discarded by the linker */
+ SECTION_RETAIN = 1UL << 25, /* retained by the linker. */
+ SECTION_LINK_ORDER = 1UL << 26, /* section needs link-order. */
+
+ /* NB: The maximum SECTION_MACH_DEP is (1UL << 28) since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+ SECTION_MACH_DEP = 1UL << 27,
+
+ /* subsequent bits reserved for target */
+};
/* A helper function for default_elf_select_section and
default_elf_unique_section. Categorizes the DECL. */
diff --git a/gcc/params.opt b/gcc/params.opt
index 3a701e2..06a6fdc 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -130,6 +130,10 @@ Maximal estimated growth of function body caused by early inlining of single cal
Common Joined UInteger Var(param_evrp_sparse_threshold) Init(800) Optimization Param
Maximum number of basic blocks before EVRP uses a sparse cache.
+-param=evrp-switch-limit=
+Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
+Maximum number of outgoing edges in a switch before EVRP will not process it.
+
-param=evrp-mode=
Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
--param=evrp-mode=[legacy|ranger|legacy-first|ranger-first|trace|gori|cache|tracegori|debug] Specifies the mode Early VRP should operate in.
@@ -169,10 +173,6 @@ Common Joined UInteger Var(param_ranger_logical_depth) Init(6) IntegerRange(1, 9
Maximum depth of logical expression evaluation ranger will look through when
evaluating outgoing edge ranges.
--param=fsm-maximum-phi-arguments=
-Common Joined UInteger Var(param_fsm_maximum_phi_arguments) Init(100) IntegerRange(1, 999999) Param Optimization
-Maximum number of arguments a PHI may have before the FSM threader will not try to thread through its block.
-
-param=fsm-scale-path-blocks=
Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization
Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements.
@@ -269,6 +269,10 @@ Maximum depth of recursive cloning for self-recursive function.
Common Joined UInteger Var(param_ipa_cp_min_recursive_probability) Init(2) Param Optimization
Recursive cloning only when the probability of call being executed exceeds the parameter.
+-param=ipa-cp-recursive-freq-factor=
+Common Joined UInteger Var(param_ipa_cp_recursive_freq_factor) Init(6) Param Optimization
+When propagating IPA-CP effect estimates, multiply frequencies of recursive edges that that bring back an unchanged value by this factor.
+
-param=ipa-cp-recursion-penalty=
Common Joined UInteger Var(param_ipa_cp_recursion_penalty) Init(40) IntegerRange(0, 100) Param Optimization
Percentage penalty the recursive functions will receive when they are evaluated for cloning.
@@ -361,6 +365,22 @@ The maximum code size growth ratio when expanding into a jump table (in percent)
Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
The size of L1 cache line.
+-param=destructive-interference-size=
+Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
+The minimum recommended offset between two concurrently-accessed objects to
+avoid additional performance degradation due to contention introduced by the
+implementation. Typically the L1 cache line size, but can be larger to
+accommodate a variety of target processors with different cache line sizes.
+C++17 code might use this value in structure layout, but is strongly
+discouraged from doing so in public ABIs.
+
+-param=constructive-interference-size=
+Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
+The maximum recommended size of contiguous memory occupied by two objects
+accessed with temporal locality by concurrent threads. Typically the L1 cache
+line size, but can be smaller to accommodate a variety of target processors with
+different cache line sizes.
+
-param=l1-cache-size=
Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
The size of L1 cache.
@@ -513,18 +533,10 @@ The maximum number of nested indirect inlining performed by early inliner.
Common Joined UInteger Var(param_max_fields_for_field_sensitive) Param
Maximum number of fields in a structure before pointer analysis treats the structure as a single variable.
--param=max-fsm-thread-length=
-Common Joined UInteger Var(param_max_fsm_thread_length) Init(10) IntegerRange(1, 999999) Param Optimization
-Maximum number of basic blocks on a finite state automaton jump thread path.
-
-param=max-fsm-thread-path-insns=
Common Joined UInteger Var(param_max_fsm_thread_path_insns) Init(100) IntegerRange(1, 999999) Param Optimization
Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path.
--param=max-fsm-thread-paths=
-Common Joined UInteger Var(param_max_fsm_thread_paths) Init(50) IntegerRange(1, 999999) Param Optimization
-Maximum number of new jump thread paths to create for a finite state automaton.
-
-param=max-gcse-insertion-ratio=
Common Joined UInteger Var(param_max_gcse_insertion_ratio) Init(20) Param Optimization
The maximum ratio of insertions to deletions of expressions in GCSE.
diff --git a/gcc/passes.def b/gcc/passes.def
index d7a1f8c..c11c237 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -212,6 +212,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_vrp, true /* warn_array_bounds_p */);
+ NEXT_PASS (pass_vrp_threader);
NEXT_PASS (pass_dse);
NEXT_PASS (pass_dce);
/* pass_stdarg is always run and at this point we execute
@@ -242,7 +243,7 @@ along with GCC; see the file COPYING3. If not see
/* Identify paths that should never be executed in a conforming
program and isolate those paths. */
NEXT_PASS (pass_isolate_erroneous_paths);
- NEXT_PASS (pass_reassoc, true /* insert_powi_p */);
+ NEXT_PASS (pass_reassoc, true /* early_p */);
NEXT_PASS (pass_dce);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt, false /* early_p */);
@@ -325,7 +326,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_lower_switch);
NEXT_PASS (pass_cse_reciprocals);
- NEXT_PASS (pass_reassoc, false /* insert_powi_p */);
+ NEXT_PASS (pass_reassoc, false /* early_p */);
NEXT_PASS (pass_strength_reduction);
NEXT_PASS (pass_split_paths);
NEXT_PASS (pass_tracer);
@@ -337,6 +338,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_strlen);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */);
+ NEXT_PASS (pass_vrp_threader);
/* Threading can leave many const/copy propagations in the IL.
Clean them up. Instead of just copy_prop, we use ccp to
compute alignment and nonzero bits. */
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 3400b40..f4b1163 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2021-08-30 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
2021-07-31 Joseph Myers <joseph@codesourcery.com>
* fr.po: Update.
diff --git a/gcc/po/sv.po b/gcc/po/sv.po
index 281fb51..b972390 100644
--- a/gcc/po/sv.po
+++ b/gcc/po/sv.po
@@ -28,7 +28,7 @@ msgstr ""
"Project-Id-Version: gcc 11.2.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2021-07-26 15:21+0000\n"
-"PO-Revision-Date: 2021-07-28 21:12+0200\n"
+"PO-Revision-Date: 2021-08-30 11:58+0200\n"
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@@ -12962,7 +12962,7 @@ msgstr "Aktivera instruktioner som skyddar mot returorienterade programattacker.
#: config/rs6000/rs6000.opt:641
#, no-c-format
msgid "Generate code that will run in privileged state."
-msgstr "Generera kod som kommer köra i priviligerat tillstånd."
+msgstr "Generera kod som kommer köra i priviligierat tillstånd."
#: config/rs6000/sysv4.opt:24
#, no-c-format
@@ -60513,7 +60513,7 @@ msgstr "%qs-argumentet till inbyggd %qs vid %L är inte ett giltigt dimensionsin
#: fortran/check.c:5704
#, gcc-internal-format
msgid "%qs argument of %qs intrinsic at %L must have length at least 1"
-msgstr "%qs-argumentet till inbyggd %qs vid %L måste åtminstone längden 1"
+msgstr "%qs-argumentet till inbyggd %qs vid %L måste åtminstone ha längden 1"
#: fortran/check.c:5968
#, gcc-internal-format, gfc-internal-format
diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc
index ba8f8a9..910f452 100644
--- a/gcc/pointer-query.cc
+++ b/gcc/pointer-query.cc
@@ -34,10 +34,14 @@
#include "stringpool.h"
#include "attribs.h"
#include "gimple-fold.h"
+#include "gimple-ssa.h"
#include "intl.h"
#include "attr-fnspec.h"
#include "gimple-range.h"
#include "pointer-query.h"
+#include "tree-pretty-print.h"
+#include "tree-ssanames.h"
+#include "target.h"
static bool compute_objsize_r (tree, int, access_ref *, ssa_name_limit_t &,
pointer_query *);
@@ -307,7 +311,7 @@ get_size_range (range_query *query, tree exp, gimple *stmt, tree range[2],
enum value_range_kind range_type;
if (!query)
- query = get_global_range_query ();
+ query = get_range_query (cfun);
if (integral)
{
@@ -628,7 +632,7 @@ access_ref::phi () const
return NULL;
gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
- if (gimple_code (def_stmt) != GIMPLE_PHI)
+ if (!def_stmt || gimple_code (def_stmt) != GIMPLE_PHI)
return NULL;
return as_a <gphi *> (def_stmt);
@@ -1038,6 +1042,9 @@ access_ref::inform_access (access_mode mode) const
if (TREE_CODE (ref) == SSA_NAME)
{
gimple *stmt = SSA_NAME_DEF_STMT (ref);
+ if (!stmt)
+ return;
+
if (is_gimple_call (stmt))
{
loc = gimple_location (stmt);
@@ -1081,6 +1088,34 @@ access_ref::inform_access (access_mode mode) const
else if (gimple_nop_p (stmt))
/* Handle DECL_PARM below. */
ref = SSA_NAME_VAR (ref);
+ else if (is_gimple_assign (stmt)
+ && (gimple_assign_rhs_code (stmt) == MIN_EXPR
+ || gimple_assign_rhs_code (stmt) == MAX_EXPR))
+ {
+ /* MIN or MAX_EXPR here implies a reference to a known object
+ and either an unknown or distinct one (the latter being
+ the result of an invalid relational expression). Determine
+ the identity of the former and point to it in the note.
+ TODO: Consider merging with PHI handling. */
+ access_ref arg_ref[2];
+ tree arg = gimple_assign_rhs1 (stmt);
+ compute_objsize (arg, /* ostype = */ 1 , &arg_ref[0]);
+ arg = gimple_assign_rhs2 (stmt);
+ compute_objsize (arg, /* ostype = */ 1 , &arg_ref[1]);
+
+ /* Use the argument that references a known object with more
+ space remaining. */
+ const bool idx
+ = (!arg_ref[0].ref || !arg_ref[0].base0
+ || (arg_ref[0].base0 && arg_ref[1].base0
+ && (arg_ref[0].size_remaining ()
+ < arg_ref[1].size_remaining ())));
+
+ arg_ref[idx].offrng[0] = offrng[0];
+ arg_ref[idx].offrng[1] = offrng[1];
+ arg_ref[idx].inform_access (mode);
+ return;
+ }
}
if (DECL_P (ref))
@@ -1339,7 +1374,7 @@ pointer_query::put_ref (tree ptr, const access_ref &ref, int ostype /* = 1 */)
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];
+ access_ref &cache_ref = var_cache->access_refs[cache_idx];
if (cache_ref.ref)
{
gcc_checking_assert (cache_ref.ref == ref.ref);
@@ -1360,16 +1395,115 @@ pointer_query::flush_cache ()
var_cache->access_refs.release ();
}
+/* Dump statistics and, optionally, cache contents to DUMP_FILE. */
+
+void
+pointer_query::dump (FILE *dump_file, bool contents /* = false */)
+{
+ unsigned nused = 0, nrefs = 0;
+ unsigned nidxs = var_cache->indices.length ();
+ for (unsigned i = 0; i != nidxs; ++i)
+ {
+ unsigned ari = var_cache->indices[i];
+ if (!ari)
+ continue;
+
+ ++nused;
+
+ const access_ref &aref = var_cache->access_refs[ari];
+ if (!aref.ref)
+ continue;
+
+ ++nrefs;
+ }
+
+ fprintf (dump_file, "pointer_query counters:\n"
+ " index cache size: %u\n"
+ " index entries: %u\n"
+ " access cache size: %u\n"
+ " access entries: %u\n"
+ " hits: %u\n"
+ " misses: %u\n"
+ " failures: %u\n"
+ " max_depth: %u\n",
+ nidxs, nused,
+ var_cache->access_refs.length (), nrefs,
+ hits, misses, failures, max_depth);
+
+ if (!contents || !nidxs)
+ return;
+
+ fputs ("\npointer_query cache contents:\n", dump_file);
+
+ for (unsigned i = 0; i != nidxs; ++i)
+ {
+ unsigned ari = var_cache->indices[i];
+ if (!ari)
+ continue;
+
+ const access_ref &aref = var_cache->access_refs[ari];
+ if (!aref.ref)
+ continue;
+
+ /* The level-1 cache index corresponds to the SSA_NAME_VERSION
+ shifted left by one and ORed with the Object Size Type in
+ the lowest bit. Print the two separately. */
+ unsigned ver = i >> 1;
+ unsigned ost = i & 1;
+
+ fprintf (dump_file, " %u.%u[%u]: ", ver, ost, ari);
+ if (tree name = ssa_name (ver))
+ {
+ print_generic_expr (dump_file, name);
+ fputs (" = ", dump_file);
+ }
+ else
+ fprintf (dump_file, " _%u = ", ver);
+
+ if (gphi *phi = aref.phi ())
+ {
+ fputs ("PHI <", dump_file);
+ unsigned nargs = gimple_phi_num_args (phi);
+ for (unsigned i = 0; i != nargs; ++i)
+ {
+ tree arg = gimple_phi_arg_def (phi, i);
+ print_generic_expr (dump_file, arg);
+ if (i + 1 < nargs)
+ fputs (", ", dump_file);
+ }
+ fputc ('>', dump_file);
+ }
+ else
+ print_generic_expr (dump_file, aref.ref);
+
+ if (aref.offrng[0] != aref.offrng[1])
+ fprintf (dump_file, " + [%lli, %lli]",
+ (long long) aref.offrng[0].to_shwi (),
+ (long long) aref.offrng[1].to_shwi ());
+ else if (aref.offrng[0] != 0)
+ fprintf (dump_file, " %c %lli",
+ aref.offrng[0] < 0 ? '-' : '+',
+ (long long) aref.offrng[0].to_shwi ());
+
+ fputc ('\n', dump_file);
+ }
+
+ fputc ('\n', dump_file);
+}
+
/* A helper of compute_objsize_r() to determine the size from an assignment
- statement STMT with the RHS of either MIN_EXPR or MAX_EXPR. */
+ statement STMT with the RHS of either MIN_EXPR or MAX_EXPR. On success
+ set PREF->REF to the operand with more or less space remaining,
+ respectively, if both refer to the same (sub)object, or to PTR if they
+ might not, and return true. Otherwise, if the identity of neither
+ operand can be determined, return false. */
static bool
-handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
+handle_min_max_size (tree ptr, 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);
+ const gimple *stmt = SSA_NAME_DEF_STMT (ptr);
+ const tree_code code = gimple_assign_rhs_code (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
@@ -1377,7 +1511,8 @@ handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
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))
+ tree arg1 = gimple_assign_rhs1 (stmt);
+ if (!compute_objsize_r (arg1, ostype, &aref[0], snlim, qry))
{
aref[0].base0 = false;
aref[0].offrng[0] = aref[0].offrng[1] = 0;
@@ -1385,8 +1520,8 @@ handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
aref[0].set_max_size_range ();
}
- ptr = gimple_assign_rhs2 (stmt);
- if (!compute_objsize_r (ptr, ostype, &aref[1], snlim, qry))
+ tree arg2 = gimple_assign_rhs2 (stmt);
+ if (!compute_objsize_r (arg2, ostype, &aref[1], snlim, qry))
{
aref[1].base0 = false;
aref[1].offrng[0] = aref[1].offrng[1] = 0;
@@ -1415,6 +1550,13 @@ handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
*pref = aref[i1];
else
*pref = aref[i0];
+
+ if (aref[i0].ref != aref[i1].ref)
+ /* If the operands don't refer to the same (sub)object set
+ PREF->REF to the SSA_NAME from which STMT was obtained
+ so that both can be identified in a diagnostic. */
+ pref->ref = ptr;
+
return true;
}
@@ -1435,6 +1577,10 @@ handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
pref->offrng[0] = aref[i0].offrng[0];
pref->offrng[1] = aref[i0].offrng[1];
}
+
+ /* Replace PTR->REF with the SSA_NAME to indicate the expression
+ might not refer to the same (sub)object. */
+ pref->ref = ptr;
return true;
}
@@ -1724,13 +1870,24 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
if (code == INTEGER_CST)
{
/* Pointer constants other than null are most likely the result
- of erroneous null pointer addition/subtraction. Set size to
- zero. For null pointers, set size to the maximum for now
- since those may be the result of jump threading. */
+ of erroneous null pointer addition/subtraction. Unless zero
+ is a valid address set size to zero. For null pointers, set
+ size to the maximum for now since those may be the result of
+ jump threading. */
if (integer_zerop (ptr))
pref->set_max_size_range ();
+ else if (POINTER_TYPE_P (TREE_TYPE (ptr)))
+ {
+ tree deref_type = TREE_TYPE (TREE_TYPE (ptr));
+ addr_space_t as = TYPE_ADDR_SPACE (deref_type);
+ if (targetm.addr_space.zero_address_valid (as))
+ pref->set_max_size_range ();
+ else
+ pref->sizrng[0] = pref->sizrng[1] = 0;
+ }
else
pref->sizrng[0] = pref->sizrng[1] = 0;
+
pref->ref = ptr;
return true;
@@ -1782,8 +1939,14 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
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. */
+ to and return success.
+ FIXME: BNDRNG is determined by each access and so it doesn't
+ belong in access_ref. Until the design is changed, keep it
+ unchanged here. */
+ const offset_int bndrng[2] = { pref->bndrng[0], pref->bndrng[1] };
*pref = *cache_ref;
+ pref->bndrng[0] = bndrng[0];
+ pref->bndrng[1] = bndrng[1];
return true;
}
}
@@ -1901,8 +2064,9 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
if (code == MAX_EXPR || code == MIN_EXPR)
{
- if (!handle_min_max_size (stmt, ostype, pref, snlim, qry))
+ if (!handle_min_max_size (ptr, ostype, pref, snlim, qry))
return false;
+
qry->put_ref (ptr, *pref);
return true;
}
@@ -1928,13 +2092,18 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
pref->add_offset (orng[0], orng[1]);
else
pref->add_max_offset ();
+
qry->put_ref (ptr, *pref);
return true;
}
- if (code == ADDR_EXPR
- || code == SSA_NAME)
- return compute_objsize_r (rhs, ostype, pref, snlim, qry);
+ if (code == ADDR_EXPR || code == SSA_NAME)
+ {
+ if (!compute_objsize_r (rhs, ostype, pref, snlim, qry))
+ return false;
+ qry->put_ref (ptr, *pref);
+ return true;
+ }
/* (This could also be an assignment from a nonlocal pointer.) Save
PTR to mention in diagnostics but otherwise treat it as a pointer
diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h
index eb7e90d..3c8172c 100644
--- a/gcc/pointer-query.h
+++ b/gcc/pointer-query.h
@@ -186,6 +186,9 @@ public:
/* Flush the cache. */
void flush_cache ();
+ /* Dump statistics and optionally cache contents to DUMP_FILE. */
+ void dump (FILE *, bool = false);
+
/* A Ranger instance. May be null to use global ranges. */
range_query *rvals;
/* Cache of SSA_NAMEs. May be null to disable caching. */
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index f47f9e4..94e7b70 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -324,10 +324,10 @@ struct poly_result<T1, T2, 2>
routine can take the address of RES rather than the address of
a temporary.
- The dummy comparison against a null C * is just a way of checking
+ The dummy self-comparison against C * is just a way of checking
that C gives the right type. */
#define POLY_SET_COEFF(C, RES, I, VALUE) \
- ((void) (&(RES).coeffs[0] == (C *) 0), \
+ ((void) (&(RES).coeffs[0] == (C *) (void *) &(RES).coeffs[0]), \
wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
? (void) ((RES).coeffs[I] = VALUE) \
: (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
diff --git a/gcc/predict.c b/gcc/predict.c
index d9c7249..68b1113 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -4481,6 +4481,43 @@ force_edge_cold (edge e, bool impossible)
}
}
+/* Change E's probability to NEW_E_PROB, redistributing the probabilities
+ of other outgoing edges proportionally.
+
+ Note that this function does not change the profile counts of any
+ basic blocks. The caller must do that instead, using whatever
+ information it has about the region that needs updating. */
+
+void
+change_edge_frequency (edge e, profile_probability new_e_prob)
+{
+ profile_probability old_e_prob = e->probability;
+ profile_probability old_other_prob = old_e_prob.invert ();
+ profile_probability new_other_prob = new_e_prob.invert ();
+
+ e->probability = new_e_prob;
+ profile_probability cumulative_prob = new_e_prob;
+
+ unsigned int num_other = EDGE_COUNT (e->src->succs) - 1;
+ edge other_e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (other_e, ei, e->src->succs)
+ if (other_e != e)
+ {
+ num_other -= 1;
+ if (num_other == 0)
+ /* Ensure that the probabilities add up to 1 without
+ rounding error. */
+ other_e->probability = cumulative_prob.invert ();
+ else
+ {
+ other_e->probability /= old_other_prob;
+ other_e->probability *= new_other_prob;
+ cumulative_prob += other_e->probability;
+ }
+ }
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/predict.h b/gcc/predict.h
index 8860caf..4df51bd 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -100,6 +100,7 @@ extern void rebuild_frequencies (void);
extern void report_predictor_hitrates (void);
extern void force_edge_cold (edge, bool);
extern void propagate_unlikely_bbs_forward (void);
+extern void change_edge_frequency (edge, profile_probability);
extern void add_reg_br_prob_note (rtx_insn *, profile_probability);
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 8ad0dcf..d1fbd04 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -364,6 +364,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
fputs (code == CALL_EXPR ? " must-tail-call" : " static", file);
if (TREE_DEPRECATED (node))
fputs (" deprecated", file);
+ if (TREE_UNAVAILABLE (node))
+ fputs (" unavailable", file);
if (TREE_VISITED (node))
fputs (" visited", file);
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 56eccf4..bbf2924 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1372,13 +1372,14 @@ operator_minus::wi_fold (irange &r, tree type,
}
// Check to see if the relation REL between OP1 and OP2 has any effect on the
-// LHS of the expression. If so, apply it to LHS_RANGE.
+// LHS of the expression. If so, apply it to LHS_RANGE. This is a helper
+// function for both MINUS_EXPR and POINTER_DIFF_EXPR.
-bool
-operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
- const irange &op1_range ATTRIBUTE_UNUSED,
- const irange &op2_range ATTRIBUTE_UNUSED,
- relation_kind rel) const
+static bool
+minus_op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &op1_range ATTRIBUTE_UNUSED,
+ const irange &op2_range ATTRIBUTE_UNUSED,
+ relation_kind rel)
{
if (rel == VREL_NONE)
return false;
@@ -1441,6 +1442,16 @@ operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
}
bool
+operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &op1_range,
+ const irange &op2_range,
+ relation_kind rel) const
+{
+ return minus_op1_op2_relation_effect (lhs_range, type, op1_range, op2_range,
+ rel);
+}
+
+bool
operator_minus::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
@@ -1459,6 +1470,26 @@ operator_minus::op2_range (irange &r, tree type,
}
+class operator_pointer_diff : public range_operator
+{
+ virtual bool op1_op2_relation_effect (irange &lhs_range,
+ tree type,
+ const irange &op1_range,
+ const irange &op2_range,
+ relation_kind rel) const;
+} op_pointer_diff;
+
+bool
+operator_pointer_diff::op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &op1_range,
+ const irange &op2_range,
+ relation_kind rel) const
+{
+ return minus_op1_op2_relation_effect (lhs_range, type, op1_range, op2_range,
+ rel);
+}
+
+
class operator_min : public range_operator
{
public:
@@ -2047,6 +2078,12 @@ operator_lshift::op1_range (irange &r,
relation_kind rel ATTRIBUTE_UNUSED) const
{
tree shift_amount;
+
+ if (!lhs.contains_p (build_zero_cst (type)))
+ r.set_nonzero (type);
+ else
+ r.set_varying (type);
+
if (op2.singleton_p (&shift_amount))
{
wide_int shift = wi::to_wide (shift_amount);
@@ -2058,21 +2095,22 @@ operator_lshift::op1_range (irange &r,
return false;
if (shift == 0)
{
- r = lhs;
+ r.intersect (lhs);
return true;
}
// Work completely in unsigned mode to start.
tree utype = type;
+ int_range_max tmp_range;
if (TYPE_SIGN (type) == SIGNED)
{
int_range_max tmp = lhs;
utype = unsigned_type_for (type);
range_cast (tmp, utype);
- op_rshift.fold_range (r, utype, tmp, op2);
+ op_rshift.fold_range (tmp_range, utype, tmp, op2);
}
else
- op_rshift.fold_range (r, utype, lhs, op2);
+ op_rshift.fold_range (tmp_range, utype, lhs, op2);
// Start with ranges which can produce the LHS by right shifting the
// result by the shift amount.
@@ -2088,16 +2126,19 @@ operator_lshift::op1_range (irange &r,
unsigned low_bits = TYPE_PRECISION (utype)
- TREE_INT_CST_LOW (shift_amount);
wide_int up_mask = wi::mask (low_bits, true, TYPE_PRECISION (utype));
- wide_int new_ub = wi::bit_or (up_mask, r.upper_bound ());
- wide_int new_lb = wi::set_bit (r.lower_bound (), low_bits);
+ wide_int new_ub = wi::bit_or (up_mask, tmp_range.upper_bound ());
+ wide_int new_lb = wi::set_bit (tmp_range.lower_bound (), low_bits);
int_range<2> fill_range (utype, new_lb, new_ub);
- r.union_ (fill_range);
+ tmp_range.union_ (fill_range);
if (utype != type)
- range_cast (r, type);
+ range_cast (tmp_range, type);
+
+ r.intersect (tmp_range);
return true;
}
- return false;
+
+ return !r.varying_p ();
}
bool
@@ -4017,7 +4058,8 @@ integral_table::integral_table ()
set (PAREN_EXPR, op_identity);
set (OBJ_TYPE_REF, op_identity);
set (IMAGPART_EXPR, op_unknown);
- set (POINTER_DIFF_EXPR, op_unknown);
+ set (REALPART_EXPR, op_unknown);
+ set (POINTER_DIFF_EXPR, op_pointer_diff);
set (ABS_EXPR, op_abs);
set (ABSU_EXPR, op_absu);
set (NEGATE_EXPR, op_negate);
diff --git a/gcc/read-md.c b/gcc/read-md.c
index bb419e0..8fda401 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -902,7 +902,8 @@ void
md_reader::handle_enum (file_location loc, bool md_p)
{
char *enum_name, *value_name;
- struct md_name name;
+ unsigned int cur_value;
+ struct md_name name, value;
struct enum_type *def;
struct enum_value *ev;
void **slot;
@@ -928,6 +929,7 @@ md_reader::handle_enum (file_location loc, bool md_p)
*slot = def;
}
+ cur_value = def->num_values;
require_char_ws ('[');
while ((c = read_skip_spaces ()) != ']')
@@ -937,8 +939,18 @@ md_reader::handle_enum (file_location loc, bool md_p)
error_at (loc, "unterminated construct");
exit (1);
}
- unread_char (c);
- read_name (&name);
+ if (c == '(')
+ {
+ read_name (&name);
+ read_name (&value);
+ require_char_ws (')');
+ cur_value = atoi (value.string);
+ }
+ else
+ {
+ unread_char (c);
+ read_name (&name);
+ }
ev = XNEW (struct enum_value);
ev->next = 0;
@@ -954,11 +966,12 @@ md_reader::handle_enum (file_location loc, bool md_p)
ev->name = value_name;
}
ev->def = add_constant (get_md_constants (), value_name,
- md_decimal_string (def->num_values), def);
+ md_decimal_string (cur_value), def);
*def->tail_ptr = ev;
def->tail_ptr = &ev->next;
def->num_values++;
+ cur_value++;
}
}
diff --git a/gcc/real.c b/gcc/real.c
index 555cf44..8c7a47a 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -3150,9 +3150,10 @@ encode_ieee_double (const struct real_format *fmt, long *buf,
const REAL_VALUE_TYPE *r)
{
unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
+ unsigned long sign = r->sign;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- image_hi = r->sign << 31;
+ image_hi = sign << 31;
image_lo = 0;
if (HOST_BITS_PER_LONG == 64)
@@ -3938,10 +3939,11 @@ encode_ieee_quad (const struct real_format *fmt, long *buf,
const REAL_VALUE_TYPE *r)
{
unsigned long image3, image2, image1, image0, exp;
+ unsigned long sign = r->sign;
bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
REAL_VALUE_TYPE u;
- image3 = r->sign << 31;
+ image3 = sign << 31;
image2 = 0;
image1 = 0;
image0 = 0;
diff --git a/gcc/rtl.def b/gcc/rtl.def
index c80144b..5710a2e 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -467,6 +467,11 @@ DEF_RTL_EXPR(SS_MULT, "ss_mult", "ee", RTX_COMM_ARITH)
/* Multiplication with unsigned saturation */
DEF_RTL_EXPR(US_MULT, "us_mult", "ee", RTX_COMM_ARITH)
+/* Signed high-part multiplication. */
+DEF_RTL_EXPR(SMUL_HIGHPART, "smul_highpart", "ee", RTX_COMM_ARITH)
+/* Unsigned high-part multiplication. */
+DEF_RTL_EXPR(UMUL_HIGHPART, "umul_highpart", "ee", RTX_COMM_ARITH)
+
/* Operand 0 divided by operand 1. */
DEF_RTL_EXPR(DIV, "div", "ee", RTX_BIN_ARITH)
/* Division with signed saturation */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index c81e27e..2bb18fb 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1249,7 +1249,8 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
than HOST_BITS_PER_WIDE_INT. */
if (HWI_COMPUTABLE_MODE_P (mode)
&& COMPARISON_P (op)
- && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0)
+ && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
+ && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)))
{
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
@@ -1511,12 +1512,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_SIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_SIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 1);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Sign-extending a sign-extended subreg. */
+ return simplify_gen_unary (SIGN_EXTEND, mode,
+ subreg, subreg_mode);
}
/* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
@@ -1630,12 +1647,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_UNSIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_UNSIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 0);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Zero-extending a zero-extended subreg. */
+ return simplify_gen_unary (ZERO_EXTEND, mode,
+ subreg, subreg_mode);
}
/* Extending a widening multiplication should be canonicalized to
@@ -1993,6 +2026,20 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
result = wide_int::from (op0, width, SIGNED);
break;
+ case SS_NEG:
+ if (wi::only_sign_bit_p (op0))
+ result = wi::max_value (GET_MODE_PRECISION (imode), SIGNED);
+ else
+ result = wi::neg (op0);
+ break;
+
+ case SS_ABS:
+ if (wi::only_sign_bit_p (op0))
+ result = wi::max_value (GET_MODE_PRECISION (imode), SIGNED);
+ else
+ result = wi::abs (op0);
+ break;
+
case SQRT:
default:
return 0;
@@ -4109,11 +4156,36 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
case US_PLUS:
case SS_MINUS:
case US_MINUS:
+ /* Simplify x +/- 0 to x, if possible. */
+ if (trueop1 == CONST0_RTX (mode))
+ return op0;
+ return 0;
+
case SS_MULT:
case US_MULT:
+ /* Simplify x * 0 to 0, if possible. */
+ if (trueop1 == CONST0_RTX (mode)
+ && !side_effects_p (op0))
+ return op1;
+
+ /* Simplify x * 1 to x, if possible. */
+ if (trueop1 == CONST1_RTX (mode))
+ return op0;
+ return 0;
+
+ case SMUL_HIGHPART:
+ case UMUL_HIGHPART:
+ /* Simplify x * 0 to 0, if possible. */
+ if (trueop1 == CONST0_RTX (mode)
+ && !side_effects_p (op0))
+ return op1;
+ return 0;
+
case SS_DIV:
case US_DIV:
- /* ??? There are simplifications that can be done. */
+ /* Simplify x / 1 to x, if possible. */
+ if (trueop1 == CONST1_RTX (mode))
+ return op0;
return 0;
case VEC_SERIES:
@@ -4554,7 +4626,8 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
if (GET_CODE (trueop0) == VEC_SELECT
&& GET_CODE (trueop1) == VEC_SELECT
&& rtx_equal_p (XEXP (trueop0, 0), XEXP (trueop1, 0))
- && GET_MODE (XEXP (trueop0, 0)) == mode)
+ && GET_MODE_INNER (GET_MODE (XEXP (trueop0, 0)))
+ == GET_MODE_INNER(mode))
{
rtx par0 = XEXP (trueop0, 1);
rtx par1 = XEXP (trueop1, 1);
@@ -4978,6 +5051,51 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
}
break;
}
+
+ case SS_PLUS:
+ result = wi::add (pop0, pop1, SIGNED, &overflow);
+ clamp_signed_saturation:
+ if (overflow == wi::OVF_OVERFLOW)
+ result = wi::max_value (GET_MODE_PRECISION (int_mode), SIGNED);
+ else if (overflow == wi::OVF_UNDERFLOW)
+ result = wi::min_value (GET_MODE_PRECISION (int_mode), SIGNED);
+ else if (overflow != wi::OVF_NONE)
+ return NULL_RTX;
+ break;
+
+ case US_PLUS:
+ result = wi::add (pop0, pop1, UNSIGNED, &overflow);
+ clamp_unsigned_saturation:
+ if (overflow != wi::OVF_NONE)
+ result = wi::max_value (GET_MODE_PRECISION (int_mode), UNSIGNED);
+ break;
+
+ case SS_MINUS:
+ result = wi::sub (pop0, pop1, SIGNED, &overflow);
+ goto clamp_signed_saturation;
+
+ case US_MINUS:
+ result = wi::sub (pop0, pop1, UNSIGNED, &overflow);
+ if (overflow != wi::OVF_NONE)
+ result = wi::min_value (GET_MODE_PRECISION (int_mode), UNSIGNED);
+ break;
+
+ case SS_MULT:
+ result = wi::mul (pop0, pop1, SIGNED, &overflow);
+ goto clamp_signed_saturation;
+
+ case US_MULT:
+ result = wi::mul (pop0, pop1, UNSIGNED, &overflow);
+ goto clamp_unsigned_saturation;
+
+ case SMUL_HIGHPART:
+ result = wi::mul_high (pop0, pop1, SIGNED);
+ break;
+
+ case UMUL_HIGHPART:
+ result = wi::mul_high (pop0, pop1, UNSIGNED);
+ break;
+
default:
return NULL_RTX;
}
diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index 6c0fbdd..aa8a772 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -191,7 +191,7 @@ public:
template<typename Arg, bool (*f)(const T &, Arg)>
void traverse (Arg a) const
{
- m_map.traverse <f> (a);
+ m_map.template traverse <f> (a);
}
/* Getter for summary callgraph node pointer. If a summary for a node
@@ -690,7 +690,7 @@ public:
template<typename Arg, bool (*f)(const T &, Arg)>
void traverse (Arg a) const
{
- m_map.traverse <f> (a);
+ m_map.template traverse <f> (a);
}
/* Getter for summary callgraph edge pointer.
diff --git a/gcc/target.def b/gcc/target.def
index b302042..b9bc7fd 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1750,7 +1750,17 @@ of REC to place the new variable in shared GPU memory.\n\
\n\
Presence of this target hook indicates that middle end neutering/broadcasting\n\
be used.",
-tree, (tree rec, bool sender, const char *name),
+tree, (tree rec, bool sender, const char *name, unsigned HOST_WIDE_INT offset),
+NULL)
+
+DEFHOOK
+(shared_mem_layout,
+"Lay out a fixed shared-memory region on the target. The LO and HI\n\
+arguments should be set to a range of addresses that can be used for worker\n\
+broadcasting. The dimensions, reduction size and gang-private size\n\
+arguments are for the current offload region.",
+void, (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, int[],
+ unsigned HOST_WIDE_INT[], unsigned HOST_WIDE_INT[]),
NULL)
HOOK_VECTOR_END (goacc)
@@ -6211,18 +6221,21 @@ DEFHOOK
"Return a value, with the same meaning as the C99 macro\n\
@code{FLT_EVAL_METHOD} that describes which excess precision should be\n\
applied. @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\n\
-@code{EXCESS_PRECISION_TYPE_FAST}, or\n\
-@code{EXCESS_PRECISION_TYPE_STANDARD}. For\n\
+@code{EXCESS_PRECISION_TYPE_FAST},\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, or\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}. For\n\
@code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\n\
precision and range operations will be implictly evaluated in regardless\n\
of the excess precision explicitly added. For\n\
-@code{EXCESS_PRECISION_TYPE_STANDARD} and\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, \n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}, and\n\
@code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\n\
explicit excess precision that should be added depending on the\n\
value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.\n\
Note that unpredictable explicit excess precision does not make sense,\n\
so a target should never return @code{FLT_EVAL_METHOD_UNPREDICTABLE}\n\
-when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD} or\n\
+when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD},\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16} or\n\
@code{EXCESS_PRECISION_TYPE_FAST}.",
enum flt_eval_method, (enum excess_precision_type type),
default_excess_precision)
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index c9b5208..812bbe3 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2200,7 +2200,7 @@ pch_option_mismatch (const char *option)
/* Default version of pch_valid_p. */
const char *
-default_pch_valid_p (const void *data_p, size_t len)
+default_pch_valid_p (const void *data_p, size_t len ATTRIBUTE_UNUSED)
{
struct cl_option_state state;
const char *data = (const char *)data_p;
@@ -2221,7 +2221,6 @@ default_pch_valid_p (const void *data_p, size_t len)
memcpy (&tf, data, sizeof (target_flags));
data += sizeof (target_flags);
- len -= sizeof (target_flags);
r = targetm.check_pch_target_flags (tf);
if (r != NULL)
return r;
@@ -2233,7 +2232,6 @@ default_pch_valid_p (const void *data_p, size_t len)
if (memcmp (data, state.data, state.size) != 0)
return pch_option_mismatch (cl_options[i].opt_text);
data += state.size;
- len -= state.size;
}
return NULL;
@@ -2453,12 +2451,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
if (predictable_p)
{
- if (global_options_set.x_param_max_rtl_if_conversion_predictable_cost)
+ if (OPTION_SET_P (param_max_rtl_if_conversion_predictable_cost))
return param_max_rtl_if_conversion_predictable_cost;
}
else
{
- if (global_options_set.x_param_max_rtl_if_conversion_unpredictable_cost)
+ if (OPTION_SET_P (param_max_rtl_if_conversion_unpredictable_cost))
return param_max_rtl_if_conversion_unpredictable_cost;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9d28b02..2876c7a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,3390 @@
+2021-10-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/51851
+ PR c++/101402
+ PR c++/102033
+ PR c++/102034
+ PR c++/102039
+ PR c++/102044
+ * g++.dg/template/fnspec2.C: New test.
+ * g++.dg/template/parm-cv1.C: New test.
+ * g++.dg/template/parm-cv2.C: New test.
+ * g++.dg/template/parm-cv3.C: New test.
+
+2021-10-15 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102685
+ * gfortran.dg/derived_constructor_char_1.f90: Fix invalid code.
+ * gfortran.dg/pr70931.f90: Likewise.
+ * gfortran.dg/transfer_simplify_2.f90: Likewise.
+ * gfortran.dg/pr102685.f90: New test.
+
+2021-10-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/pr102736.c: Make sign explicit.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ * lib/prune.exp: Prune STABS obsoletion message.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ PR c/102763
+ * gcc.dg/gimplefe-error-12.c: New testcase.
+
+2021-10-15 Richard Biener <rguenther@suse.de>
+
+ PR ipa/102762
+ * gcc.dg/torture/pr102762.c: New testcase.
+
+2021-10-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin_shuffle-1.c: New test.
+ * gcc.target/i386/avx512fp16-pr101846.c: Ditto.
+ * gcc.target/i386/avx512fp16-pr94680.c: Ditto.
+
+2021-10-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-v4hf-concat.c: New test.
+
+2021-10-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1a.c: Add scan for
+ vblendmps.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1a.c: Add -mno-avx512vl.
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c: Likewise.
+
+2021-10-15 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/ext/vla22.C: Don't expect a narrowing error.
+ * g++.dg/cpp0x/constexpr-inst1.C: New test.
+
+2021-10-15 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr102738.c: Add target int128.
+
+2021-10-14 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/format/c11-dfp-printf-1.c,
+ gcc.dg/format/c11-dfp-scanf-1.c, gcc.dg/format/c2x-dfp-printf-1.c,
+ gcc.dg/format/c2x-dfp-scanf-1.c: New tests.
+
+2021-10-14 Raphael Moreira Zinsly <rzinsly@linux.ibm.com>
+
+ * gcc.target/powerpc/unwind-backchain.c: New test.
+
+2021-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102717
+ * gfortran.dg/reshape_shape_2.f90: New test.
+
+2021-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102716
+ * gfortran.dg/shape_10.f90: New test.
+
+2021-10-14 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/102738
+ * gcc.dg/pr102738.c: New.
+
+2021-10-14 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * gfortran.dg/gomp/declare-variant-1.f90: New test.
+ * gfortran.dg/gomp/declare-variant-10.f90: New test.
+ * gfortran.dg/gomp/declare-variant-11.f90: New test.
+ * gfortran.dg/gomp/declare-variant-12.f90: New test.
+ * gfortran.dg/gomp/declare-variant-13.f90: New test.
+ * gfortran.dg/gomp/declare-variant-14.f90: New test.
+ * gfortran.dg/gomp/declare-variant-15.f90: New test.
+ * gfortran.dg/gomp/declare-variant-16.f90: New test.
+ * gfortran.dg/gomp/declare-variant-17.f90: New test.
+ * gfortran.dg/gomp/declare-variant-18.f90: New test.
+ * gfortran.dg/gomp/declare-variant-19.f90: New test.
+ * gfortran.dg/gomp/declare-variant-2.f90: New test.
+ * gfortran.dg/gomp/declare-variant-2a.f90: New test.
+ * gfortran.dg/gomp/declare-variant-3.f90: New test.
+ * gfortran.dg/gomp/declare-variant-4.f90: New test.
+ * gfortran.dg/gomp/declare-variant-5.f90: New test.
+ * gfortran.dg/gomp/declare-variant-6.f90: New test.
+ * gfortran.dg/gomp/declare-variant-7.f90: New test.
+ * gfortran.dg/gomp/declare-variant-8.f90: New test.
+ * gfortran.dg/gomp/declare-variant-9.f90: New test.
+
+2021-10-14 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/mips/msa-insert-split.c: Turn off vectorizer.
+
+2021-10-14 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/sve/pred-cond-reduc.c: New test.
+
+2021-10-14 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.dg/tree-ssa/predcom-3.c: Disable vectorizer.
+
+2021-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102736
+ * gcc.dg/tree-ssa/pr102736.c: New test.
+
+2021-10-14 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add new mask3 builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c: Add scanning for
+ mask/mask3 intrinsic.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1c.c: New test for
+ -mavx512vl.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1c.c: Ditto.
+
+2021-10-14 liuhongt <hongtao.liu@intel.com>
+
+ * g++.dg/warn/Wuninitialized-13.C: Add -fno-tree-vectorize.
+
+2021-10-13 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102630
+ * gcc.target/i386/addr-space-2.c: Add -Wall.
+ * gcc.target/i386/addr-space-3.c: New test.
+
+2021-10-13 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ * gcc.target/arm/mve/mve.exp: Make it test main directory.
+ * gcc.target/arm/mve/mve_load_memory_modes.c: New test.
+ * gcc.target/arm/mve/mve_store_memory_modes.c: New test.
+
+2021-10-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102659
+ * gcc.dg/torture/pr69760.c: Adjust the testcase.
+ * gcc.target/i386/avx2-vect-mask-store-move1.c: Expect to move
+ the conversions to unsigned as well.
+
+2021-10-13 Richard Biener <rguenther@suse.de>
+
+ PR ipa/102714
+ * gcc.dg/ipa/pr102714.c: New testcase.
+
+2021-10-13 Kewen Lin <linkw@linux.ibm.com>
+
+ PR testsuite/102658
+ * gcc.target/powerpc/dform-1.c: Adjust as vectorization enabled at O2.
+ * gcc.target/powerpc/dform-2.c: Likewise.
+ * gcc.target/powerpc/pr80510-2.c: Likewise.
+
+2021-10-12 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/format/c11-printf-1.c, gcc.dg/format/c11-scanf-1.c,
+ gcc.dg/format/c2x-printf-1.c, gcc.dg/format/c2x-scanf-1.c,
+ gcc.dg/format/ext-9.c, gcc.dg/format/ext-10.c: New tests.
+
+2021-10-12 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/101985
+ * gcc.target/powerpc/pr101985-1.c: New.
+ * gcc.target/powerpc/pr101985-2.c: New.
+
+2021-10-12 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/85730
+ PR target/82524
+ * gcc.target/i386/pr85730.c: New test.
+
+2021-10-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102696
+ * g++.dg/vect/pr102696.cc: New testcase.
+
+2021-10-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102572
+ * g++.dg/vect/pr102572.cc: New testcase.
+
+2021-10-12 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/sve/pred-not-gen-1.c: New test.
+ * gcc.target/aarch64/sve/pred-not-gen-2.c: New test.
+ * gcc.target/aarch64/sve/pred-not-gen-3.c: New test.
+ * gcc.target/aarch64/sve/pred-not-gen-4.c: New test.
+
+2021-10-12 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102541
+ * gfortran.dg/assumed_rank_24.f90: New test.
+
+2021-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/gomp/simd-2.c: Remove option -fvect-cost-model=cheap.
+ * gcc.dg/gomp/simd-3.c: Likewise.
+
+2021-10-12 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr102483.c: New test.
+ * gcc.target/i386/pr102483-2.c: New test.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * gcc.target/powerpc/pr78102.c: Fix dg-require-effective-target.
+ * gcc.target/powerpc/sse4_1-packusdw.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmaxsb.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmaxsd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmaxud.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmaxuw.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pminsb.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pminsd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pminud.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pminuw.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovsxbd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovsxbw.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovsxwd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxbd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxbq.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxbw.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxdq.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxwd.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmovzxwq.c: Likewise.
+ * gcc.target/powerpc/sse4_1-pmulld.c: Likewise.
+ * gcc.target/powerpc/sse4_2-pcmpgtq.c: Likewise.
+ * gcc.target/powerpc/sse4_1-phminposuw.c: Use correct
+ dg-require-effective-target.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * gcc.target/powerpc/pr78102.c: Copy from gcc.target/i386,
+ adjust dg directives to suit.
+ * gcc.target/powerpc/sse4_1-packusdw.c: Same.
+ * gcc.target/powerpc/sse4_1-pcmpeqq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmuldq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmulld.c: Same.
+ * gcc.target/powerpc/sse4_2-pcmpgtq.c: Same.
+ * gcc.target/powerpc/sse4_2-check.h: Copy from gcc.target/i386,
+ tweak to suit.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * gcc.target/powerpc/sse4_1-pmovsxbd.c: Copy from gcc.target/i386,
+ adjust dg directives to suit.
+ * gcc.target/powerpc/sse4_1-pmovsxbq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovsxbw.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovsxdq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovsxwd.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovsxwq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxbd.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxbq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxbw.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxdq.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxwd.c: Same.
+ * gcc.target/powerpc/sse4_1-pmovzxwq.c: Same.
+
+2021-10-12 Paul A. Clarke <pc@us.ibm.com>
+
+ * gcc.target/powerpc/sse4_1-pmaxsb.c: Copy from gcc.target/i386.
+ * gcc.target/powerpc/sse4_1-pmaxsd.c: Same.
+ * gcc.target/powerpc/sse4_1-pmaxud.c: Same.
+ * gcc.target/powerpc/sse4_1-pmaxuw.c: Same.
+ * gcc.target/powerpc/sse4_1-pminsb.c: Same.
+ * gcc.target/powerpc/sse4_1-pminsd.c: Same.
+ * gcc.target/powerpc/sse4_1-pminud.c: Same.
+ * gcc.target/powerpc/sse4_1-pminuw.c: Same.
+
+2021-10-11 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/torture/ssa-pta-fn-1.c: Fix template; add noipa.
+ * gcc.dg/tree-ssa/pta-callused.c: Fix template.
+
+2021-10-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102643
+ * g++.dg/cpp2a/class-deduction-alias11.C: New test.
+
+2021-10-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/101480
+ * g++.dg/torture/pr10148.C: New testcase.
+
+2021-10-11 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * gcc.target/s390/rawmemchr-1.c: New test.
+
+2021-10-11 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * gcc.dg/tree-ssa/ldist-rawmemchr-1.c: New test.
+ * gcc.dg/tree-ssa/ldist-rawmemchr-2.c: New test.
+ * gcc.dg/tree-ssa/ldist-strlen-1.c: New test.
+ * gcc.dg/tree-ssa/ldist-strlen-2.c: New test.
+ * gcc.dg/tree-ssa/ldist-strlen-3.c: New test.
+
+2021-10-11 Kito Cheng <kito.cheng@sifive.com>
+
+ PR target/100316
+ * gcc.c-torture/compile/pr100316.c: New.
+
+2021-10-11 liuhongt <hongtao.liu@intel.com>
+
+ PR middle-end/102669
+ * gnat.dg/unroll1.adb: Add -fno-tree-vectorize.
+
+2021-10-10 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/99348
+ PR fortran/102521
+ * gfortran.dg/parameter_array_init_8.f90: New test.
+
+2021-10-10 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/102622
+ * gcc.c-torture/execute/bitfld-10.c: New test.
+
+2021-10-09 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/65454
+ * gfortran.dg/interface_operator_3.f90: New test.
+
+2021-10-09 Kewen Lin <linkw@linux.ibm.com>
+
+ * c-c++-common/Wstringop-overflow-2.c: Add missing comment.
+ * gcc.dg/Warray-bounds-51.c: Likewise.
+ * gcc.dg/Warray-parameter-3.c: Likewise.
+ * gcc.dg/Wstringop-overflow-14.c: Likewise.
+ * gcc.dg/Wstringop-overflow-21.c: Likewise.
+ * gcc.dg/Wstringop-overflow-76.c: Likewise.
+
+2021-10-09 liuhongt <hongtao.liu@intel.com>
+
+ * g++.dg/tree-ssa/pr94403.C: Add -fno-tree-vectorize
+ * gcc.dg/optimize-bswapsi-5.c: Ditto.
+ * gcc.dg/optimize-bswapsi-6.c: Ditto.
+ * gcc.dg/Warray-bounds-51.c: Add additional option
+ -mtune=generic for target x86/i?86
+ * gcc.dg/Wstringop-overflow-14.c: Ditto.
+
+2021-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/sections1.c (foo): Don't expect errors on
+ multiple statements in between section directive(s). Add testcases
+ for invalid no statements in between section directive(s).
+ * gcc.dg/gomp/sections-2.c (foo): Don't expect errors on
+ multiple statements in between section directive(s).
+ * g++.dg/gomp/sections-2.C (foo): Likewise.
+ * g++.dg/gomp/attrs-6.C (foo): Add testcases for multiple
+ statements in between section directive(s).
+ (bar): Add testcases for multiple statements in between scan
+ directive.
+ * g++.dg/gomp/attrs-7.C (bar): Adjust expected error recovery.
+
+2021-10-09 liuhongt <hongtao.liu@intel.com>
+
+ * g++.target/i386/pr102639.C: New test.
+
+2021-10-08 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/54753
+ * gfortran.dg/c-interop/c535c-1.f90: Rewrite and expand.
+ * gfortran.dg/c-interop/c535c-2.f90: Remove xfails.
+ * gfortran.dg/c-interop/c535c-3.f90: Likewise.
+ * gfortran.dg/c-interop/c535c-4.f90: Likewise.
+ * gfortran.dg/PR94110.f90: Extend to cover class types.
+
+2021-10-08 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/102627
+ * gcc.target/i386/pr102627.c: New test.
+
+2021-10-08 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/pr102385.c: New test.
+
+2021-10-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102640
+ * c-c++-common/gomp/pr102640.c: New test.
+
+2021-10-08 Roger Sayle <roger@nextmovesoftware.com>
+
+ * gcc.target/i386/sse2-mmx-paddsb-2.c: Test for -128 or 128.
+ * gcc.target/i386/sse2-mmx-paddusb-2.c: Test for -1 or 255.
+ * gcc.target/i386/sse2-mmx-psubsb-2.c: Test for -128 or 128.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr102464.c: New test.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/mmx-reduce-op-1.c: New test.
+ * gcc.target/i386/mmx-reduce-op-2.c: New test.
+
+2021-10-08 liuhongt <hongtao.liu@intel.com>
+
+ * c-c++-common/Wstringop-overflow-2.c: Adjust testcase.
+ * g++.dg/tree-ssa/pr81408.C: Ditto.
+ * g++.dg/warn/Wuninitialized-13.C: Ditto.
+ * gcc.dg/Warray-bounds-51.c: Ditto.
+ * gcc.dg/Warray-parameter-3.c: Ditto.
+ * gcc.dg/Wstringop-overflow-14.c: Ditto.
+ * gcc.dg/Wstringop-overflow-21.c: Ditto.
+ * gcc.dg/Wstringop-overflow-68.c: Ditto.
+ * gcc.dg/Wstringop-overflow-76.c: Ditto.
+ * gcc.dg/gomp/pr46032-2.c: Ditto.
+ * gcc.dg/gomp/pr46032-3.c: Ditto.
+ * gcc.dg/gomp/simd-2.c: Ditto.
+ * gcc.dg/gomp/simd-3.c: Ditto.
+ * gcc.dg/graphite/fuse-1.c: Ditto.
+ * gcc.dg/pr67089-6.c: Ditto.
+ * gcc.dg/pr82929-2.c: Ditto.
+ * gcc.dg/pr82929.c: Ditto.
+ * gcc.dg/store_merging_1.c: Ditto.
+ * gcc.dg/store_merging_11.c: Ditto.
+ * gcc.dg/store_merging_13.c: Ditto.
+ * gcc.dg/store_merging_15.c: Ditto.
+ * gcc.dg/store_merging_16.c: Ditto.
+ * gcc.dg/store_merging_19.c: Ditto.
+ * gcc.dg/store_merging_24.c: Ditto.
+ * gcc.dg/store_merging_25.c: Ditto.
+ * gcc.dg/store_merging_28.c: Ditto.
+ * gcc.dg/store_merging_30.c: Ditto.
+ * gcc.dg/store_merging_5.c: Ditto.
+ * gcc.dg/store_merging_7.c: Ditto.
+ * gcc.dg/store_merging_8.c: Ditto.
+ * gcc.dg/strlenopt-85.c: Ditto.
+ * gcc.dg/tree-ssa/dump-6.c: Ditto.
+ * gcc.dg/tree-ssa/pr19210-1.c: Ditto.
+ * gcc.dg/tree-ssa/pr47059.c: Ditto.
+ * gcc.dg/tree-ssa/pr86017.c: Ditto.
+ * gcc.dg/tree-ssa/pr91482.c: Ditto.
+ * gcc.dg/tree-ssa/predcom-1.c: Ditto.
+ * gcc.dg/tree-ssa/predcom-dse-3.c: Ditto.
+ * gcc.dg/tree-ssa/prefetch-3.c: Ditto.
+ * gcc.dg/tree-ssa/prefetch-6.c: Ditto.
+ * gcc.dg/tree-ssa/prefetch-8.c: Ditto.
+ * gcc.dg/tree-ssa/prefetch-9.c: Ditto.
+ * gcc.dg/tree-ssa/ssa-dse-18.c: Ditto.
+ * gcc.dg/tree-ssa/ssa-dse-19.c: Ditto.
+ * gcc.dg/uninit-40.c: Ditto.
+ * gcc.dg/unroll-7.c: Ditto.
+ * gcc.misc-tests/help.exp: Ditto.
+ * gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c: Ditto.
+ * gcc.target/i386/pr34012.c: Ditto.
+ * gcc.target/i386/pr49781-1.c: Ditto.
+ * gcc.target/i386/pr95798-1.c: Ditto.
+ * gcc.target/i386/pr95798-2.c: Ditto.
+ * gfortran.dg/pr77498.f: Ditto.
+
+2021-10-07 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/61355
+ * g++.old-deja/g++.pt/nontype5.C: Adjust.
+ * g++.dg/template/param6.C: New test.
+
+2021-10-07 Roger Sayle <roger@nextmovesoftware.com>
+
+ * gcc.target/i386/sse2-mmx-paddsb-2.c: New test case.
+ * gcc.target/i386/sse2-mmx-paddusb-2.c: New test case.
+ * gcc.target/i386/sse2-mmx-psubsb-2.c: New test case.
+ * gcc.target/i386/sse2-mmx-psubusb-2.c: New test case.
+
+2021-10-07 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99904
+ * g++.dg/cpp2a/concepts-ttp4.C: New test.
+
+2021-10-07 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/102482
+ * g++.dg/warn/Winit-list5.C: New test.
+
+2021-10-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/torture/pr102581.C: New test.
+
+2021-10-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102615
+ * g++.dg/cpp23/charlit-encoding1.C: New testcase for C++23 P2316R2.
+
+2021-10-07 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-47.c: New testcase.
+
+2021-10-06 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/spaceship-synth8a.C: New test.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102612
+ * g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202110L rather
+ than 201907L.
+ * g++.dg/cpp23/constexpr-nonlit1.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit2.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit3.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit4.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit5.C: New test.
+ * g++.dg/cpp23/constexpr-nonlit6.C: New test.
+ * g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for
+ c++20_down.
+ * g++.dg/cpp1y/constexpr-label.C: Likewise.
+ * g++.dg/cpp1y/constexpr-neg1.C: Likewise.
+ * g++.dg/cpp2a/constexpr-try5.C: Likewise. Adjust some expected
+ wording.
+ * g++.dg/cpp2a/constexpr-dtor3.C: Likewise.
+ * g++.dg/cpp2a/consteval3.C: Likewise. Add effective target c++20
+ and remove dg-options.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/cpp/gnu11-elifdef-1.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-2.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-3.c: New test.
+ * gcc.dg/cpp/gnu11-elifdef-4.c: New test.
+ * g++.dg/cpp/elifdef-1.C: New test.
+ * g++.dg/cpp/elifdef-2.C: New test.
+ * g++.dg/cpp/elifdef-3.C: New test.
+ * g++.dg/cpp/elifdef-4.C: New test.
+ * g++.dg/cpp/elifdef-5.C: New test.
+ * g++.dg/cpp/elifdef-6.C: New test.
+ * g++.dg/cpp/elifdef-7.C: New test.
+
+2021-10-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/attr_deprecated-2.f90: New test.
+
+2021-10-06 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/98712
+ PR c++/102490
+ * g++.dg/cpp2a/spaceship-synth8.C (std::strong_ordering): Provide
+ more complete definition.
+ (std::strong_ordering::less, std::strong_ordering::equal,
+ std::strong_ordering::greater): Define.
+ * g++.dg/cpp2a/spaceship-synth12.C: New test.
+ * g++.dg/cpp2a/spaceship-synth13.C: New test.
+ * g++.dg/cpp2a/spaceship-synth14.C: New test.
+ * g++.dg/cpp2a/spaceship-eq11.C: New test.
+ * g++.dg/cpp2a/spaceship-eq12.C: New test.
+ * g++.dg/cpp2a/spaceship-eq13.C: New test.
+
+2021-10-05 qing zhao <qing.zhao@oracle.com>
+
+ PR middle-end/102359
+ * g++.dg/pr102359_1.C: New test.
+ * g++.dg/pr102359_2.C: New test.
+
+2021-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102548
+ * g++.target/i386/pr102548.C: New test.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102547
+ * g++.dg/cpp0x/variadic-partial2.C: New test.
+ * g++.dg/cpp0x/variadic-partial2a.C: New test.
+
+2021-10-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-thread-valid.c: New test.
+
+2021-10-05 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/s390/pr80725.c: Ensure computed goto is used on
+ a pointer type.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR c/102605
+ * gcc.dg/gimplefe-46.c: New testcase.
+
+2021-10-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98930
+ * g++.dg/cpp1z/nontype4.C: New test.
+ * g++.dg/cpp1z/nontype4a.C: New test.
+
+2021-10-05 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/pr43711.f90: Add dg-error + dg-prune-output,
+ remove dg-excess-errors to change XFAIL to PASS.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ PR middle-end/102285
+ * gcc.target/aarch64/sve/pr102587-1.c: Add -march=armv8.3-a+sve.
+ * gcc.target/aarch64/sve/pr102587-2.c: Likewise.
+
+2021-10-05 Richard Biener <rguenther@suse.de>
+
+ * gfortran.dg/predict-2.f90: Adjust to avoid redundant
+ inner loop preheader checking code.
+
+2021-10-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-c++-common/Warray-compare-1.c: New test.
+ * c-c++-common/Warray-compare-2.c: New test.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/auto-init-hardreg-1.c: New testcase.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ * c-c++-common/pr102285.c: New testcase.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102570
+ * gcc.dg/tree-ssa/ssa-fre-96.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-pre-33.c: Likewise.
+
+2021-10-04 Aldy Hernandez <aldyh@redhat.com>
+
+ * g++.dg/Walloca2.C: New test.
+
+2021-10-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102587
+ * gcc.target/aarch64/sve/pr102587-1.c: New testcase.
+ * gcc.target/aarch64/sve/pr102587-2.c: Likewise.
+
+2021-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/54753
+ * gfortran.dg/assumed_rank_23.f90: New file.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101765
+ * g++.dg/coroutines/pr101765.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99710
+ * g++.dg/coroutines/pr99710.C: New test.
+
+2021-10-03 John Eivind Helset <jehelset@gmail.com>
+
+ PR c++/100673
+ * g++.dg/coroutines/pr100673.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/101133
+ * g++.dg/coroutines/pr101133.C: New test.
+
+2021-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/99575
+ * g++.dg/coroutines/pr99575.C: New test.
+
+2021-10-02 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/pr102563.c: New test.
+
+2021-10-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c (DECLARE_ARGS):
+ Use unsigned long long for x86-64.
+
+2021-10-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102546
+ * gcc.dg/tree-ssa/pr102546.c: New file.
+
+2021-10-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/102103
+ * g++.dg/cpp0x/constexpr-array-ptr10.C: Suppress a valid warning.
+ * g++.dg/warn/Wreturn-local-addr-6.C: Correct a cast.
+ * gcc.dg/Waddress.c: Expect a warning.
+ * c-c++-common/Waddress-3.c: New test.
+ * c-c++-common/Waddress-4.c: New test.
+ * g++.dg/warn/Waddress-5.C: New test.
+ * g++.dg/warn/Waddress-6.C: New test.
+ * g++.dg/warn/pr101219.C: Expect a warning.
+ * gcc.dg/Waddress-3.c: New test.
+
+2021-10-01 H.J. Lu <hjl.tools@gmail.com>
+
+ * c-c++-common/tsan/atomic_stack.c: Don't expect print out from
+ __tsan_atomic32_fetch_add.
+
+2021-10-01 qingzhe huang <nickhuang99@hotmail.com>
+
+ PR c++/101783
+ * g++.dg/parse/pr101783.C: New test.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR sanitizer/102515
+ * c-c++-common/ubsan/div-by-zero-3.c: Use
+ -fsanitize=signed-integer-overflow instead of
+ -fsanitize=integer-divide-by-zero.
+ * c-c++-common/ubsan/div-by-zero-5.c: Likewise.
+ * c-c++-common/ubsan/div-by-zero-4.c: Likewise. Add
+ -fsanitize-undefined-trap-on-error.
+ * c-c++-common/ubsan/float-div-by-zero-2.c: New test.
+ * c-c++-common/ubsan/overflow-div-1.c: New test.
+ * c-c++-common/ubsan/overflow-div-2.c: New test.
+ * c-c++-common/ubsan/overflow-div-3.c: New test.
+
+2021-10-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cpymem-size.c: Adjust scan for ilp32.
+
+2021-10-01 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.dg/vect/bb-slp-pr97709.c: Fix for computed goto
+ pointers.
+
+2021-10-01 Martin Liska <mliska@suse.cz>
+
+ * gcc.target/i386/avx512er-vrsqrt28ps-3.c: Disable fast math.
+ * gcc.target/i386/avx512er-vrsqrt28ps-5.c: Likewise.
+ * gcc.target/i386/attr-optimize.c: New test.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.dg/gomp/order-5.f90: Adjust scan-tree-dump-times regexps.
+
+2021-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102496
+ * g++.dg/tls/pr102496-1.C: New test.
+ * g++.dg/tls/pr102496-2.C: New test.
+
+2021-10-01 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102518
+ * gcc.dg/torture/pr102518.c: New testcase.
+
+2021-09-30 David Edelsohn <dje.gcc@gmail.com>
+
+ * gfortran.dg/c-interop/cf-descriptor-5-c.c: Include alloca.h.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102535
+ * g++.dg/ext/is_trivially_constructible7.C: New test.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/ext/is_constructible6.C: New test.
+
+2021-09-30 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95567
+ * g++.dg/cpp2a/spaceship-virtual1.C: New test.
+
+2021-09-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * gfortran.dg/pr102458b.f90: New test.
+
+2021-09-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89954
+ * gcc.target/i386/pr89954.c: New test.
+
+2021-09-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/71703
+ PR fortran/84007
+ * gfortran.dg/c-interop/c535b-1.f90: Remove wrong comment.
+ * gfortran.dg/unlimited_polymorphic_1.f03: Extend.
+ * gfortran.dg/unlimited_polymorphic_32.f90: New test.
+
+2021-09-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102476
+ * gdc.dg/pr102476.d: New test.
+
+2021-09-30 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/102509
+ * gcc.c-torture/compile/attr-complex-method.c: Skip if LTO is
+ used.
+ * gcc.c-torture/compile/attr-complex-method-2.c: Likewise.
+
+2021-09-29 Aldy Hernandez <aldyh@redhat.com>
+
+ PR testsuite/102501
+ * gcc.dg/tree-ssa/pr66752-3.c: Adjust.
+ * gcc.dg/tree-ssa/pr77445-2.c: Adjust.
+
+2021-09-29 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102520
+ * gfortran.dg/pr102520.f90: New test.
+
+2021-09-29 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.c-torture/compile/920831-1.c: Fix computed goto types.
+ * gcc.c-torture/compile/pr27863.c: Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/102517
+ * gcc.dg/pr78408-1.c: Make S not power-of-two size.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.target/i386/vect-alignment-peeling-1.c: New testcase.
+ * gcc.target/i386/vect-alignment-peeling-2.c: Likewise.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cpymem-size.c: New test.
+
+2021-09-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/memset-corner-cases-2.c: New test.
+ * gcc.target/aarch64/memset-strict-align-1.c: Adjust.
+
+2021-09-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102504
+ * c-c++-common/gomp/scope-4.c: New test.
+
+2021-09-29 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.c-torture/compile/920826-1.c: Fix computed goto.
+ * gcc.c-torture/compile/pr27863.c: Likewise.
+ * gcc.c-torture/compile/pr70190.c: Likewise.
+ * gcc.dg/torture/pr89135.c: Likewise.
+ * gcc.dg/torture/pr90071.c: Likewise.
+ * gcc.dg/vect/bb-slp-pr97709.c: Likewise.
+
+2021-09-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/out-of-bounds-1.c: Make memcpied size not power-of-two.
+
+2021-09-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99909
+ * g++.dg/cpp2a/concepts-ttp3.C: New test.
+
+2021-09-28 Andrew Pinski <apinski@marvell.com>
+
+ PR c/32122
+ * gcc.dg/comp-goto-5.c: New test.
+ * gcc.dg/comp-goto-6.c: New test.
+
+2021-09-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/102454
+ * g++.dg/coroutines/pr102454.C: New test.
+
+2021-09-28 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.dg/tree-ssa/reassoc-46.c: New test.
+ * gcc.dg/tree-ssa/reassoc-46.h: Common code for new tests.
+ * gcc.dg/tree-ssa/reassoc-47.c: New test.
+ * gcc.dg/tree-ssa/reassoc-48.c: New test.
+ * gcc.dg/tree-ssa/reassoc-49.c: New test.
+ * gcc.dg/tree-ssa/reassoc-50.c: New test.
+ * gcc.dg/tree-ssa/reassoc-51.c: New test.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/auto-init-uninit-1.c: Adjust.
+ * gcc.dg/auto-init-uninit-15.c: Same.
+ * gcc.dg/guality/example.c: Same.
+ * gcc.dg/loop-8.c: Same.
+ * gcc.dg/strlenopt-40.c: Same.
+ * gcc.dg/tree-ssa/pr18133-2.c: Same.
+ * gcc.dg/tree-ssa/pr18134.c: Same.
+ * gcc.dg/uninit-1.c: Same.
+ * gcc.dg/uninit-pr44547.c: Same.
+ * gcc.dg/uninit-pr59970.c: Same.
+
+2021-09-28 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/assumed_rank_22_aux.c: Adjust messages printed.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102498
+ * gcc.target/i386/pr102498.c: New test.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/99793
+ * gcc.dg/tree-ssa/pr99793.c: New testcase.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/100112
+ * gcc.dg/tree-ssa/ssa-fre-95.c: New testcase.
+
+2021-09-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102492
+ * g++.dg/gomp/simd-3.C: New test.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/102511
+ * gcc.dg/pr102511.c: New test.
+ * gcc.dg/tree-ssa/ssa-dom-thread-14.c: Adjust.
+
+2021-09-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/102230
+ * gcc.target/i386/avx512fp16-floatvnhf.c: Remove xfail.
+ * gcc.target/i386/avx512fp16-trunc-extendvnhf.c: Ditto.
+ * gcc.target/i386/avx512fp16-truncvnhf.c: Ditto.
+ * gcc.target/i386/avx512fp16-64-32-vecop-1.c: New test.
+ * gcc.target/i386/avx512fp16-64-32-vecop-2.c: Ditto.
+ * gcc.target/i386/pr102230.c: Ditto.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.target/i386/vect-pr97352.c: Pass -mno-avx2 -mno-avx512f.
+
+2021-09-28 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102500
+ * gfortran.dg/include_15.f90: Add 'dg-prune-output' to prune
+ -Wmissing-include-dirs output printed or not depending on
+ how the testsuite is run.
+
+2021-09-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-pr65935.c: Prefer 128bit vectorization
+ on x86.
+
+2021-09-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/auto-init-uninit-1.c: Add -fthread-jumps.
+ * gcc.dg/auto-init-uninit-15.c: Same.
+ * gcc.dg/guality/example.c: Same.
+ * gcc.dg/loop-8.c: Same.
+ * gcc.dg/strlenopt-40.c: Same.
+ * gcc.dg/tree-ssa/pr18133-2.c: Same.
+ * gcc.dg/tree-ssa/pr18134.c: Same.
+ * gcc.dg/uninit-1.c: Same.
+ * gcc.dg/uninit-pr44547.c: Same.
+ * gcc.dg/uninit-pr59970.c: Same.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/vect-rebuild.c: Adjust testcases.
+ * gcc.target/i386/avx512f-vect-rebuild.c: New test.
+
+2021-09-28 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-reduce-op-2.c: New test.
+ * gcc.target/i386/avx512fp16-reduce-op-3.c: New test.
+
+2021-09-27 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102479
+ * g++.dg/cpp1z/class-deduction12.C: Also test alias CTAD in the
+ same way.
+ * g++.dg/cpp1z/class-deduction99.C: New test.
+
+2021-09-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/torture/pr55107.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-1.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-2.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-3.c: Adjust.
+ * gcc.dg/tree-ssa/phi_on_compare-4.c: Adjust.
+ * gcc.dg/tree-ssa/pr21559.c: Adjust.
+ * gcc.dg/tree-ssa/pr59597.c: Adjust.
+ * gcc.dg/tree-ssa/pr61839_1.c: Adjust.
+ * gcc.dg/tree-ssa/pr61839_3.c: Adjust.
+ * gcc.dg/tree-ssa/pr71437.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-11.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-16.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-2a.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-thread-14.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-vrp-thread-1.c: Adjust.
+ * gcc.dg/tree-ssa/vrp106.c: Adjust.
+ * gcc.dg/tree-ssa/vrp55.c: Adjust.
+
+2021-09-27 Martin Liska <mliska@suse.cz>
+
+ * gcc.c-torture/compile/attr-complex-method-2.c: New test.
+ * gcc.c-torture/compile/attr-complex-method.c: New test.
+
+2021-09-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/94070
+ * gfortran.dg/c-interop/cf-out-descriptor-6.f90: Remove xfail.
+ * gfortran.dg/c-interop/size.f90: Remove xfail.
+ * gfortran.dg/intrinsic_size_3.f90: Update scan-tree-dump-times.
+ * gfortran.dg/transpose_optimization_2.f90: Likewise.
+ * gfortran.dg/size_optional_dim_1.f90: Add scan-tree-dump-not.
+ * gfortran.dg/assumed_rank_22.f90: New test.
+ * gfortran.dg/assumed_rank_22_aux.c: New test.
+
+2021-09-27 Andrew Pinski <apinski@marvell.com>
+
+ PR c/94726
+ * gcc.dg/pr94726.c: New test.
+
+2021-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97351
+ PR tree-optimization/97352
+ PR tree-optimization/82426
+ * gcc.target/i386/vect-pr82426.c: New testcase.
+ * gcc.target/i386/vect-pr97352.c: Likewise.
+
+2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ Revert:
+ 2021-09-27 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * gcc.target/i386/sse2-pr101059.c: New test.
+ * gcc.target/i386/sse3-pr101059.c: New test.
+
+2021-09-26 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/101334
+ * gfortran.dg/associated_assumed_rank.f90: New test.
+
+2021-09-25 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.target/pru/regio-as-pointer.c: New negative test.
+ * gcc.target/pru/regio-as-pointer-2.c: New negative test.
+ * gcc.target/pru/regio-decl-2.c: New negative test.
+ * gcc.target/pru/regio-decl-3.c: New negative test.
+ * gcc.target/pru/regio-decl-4.c: New negative test.
+ * gcc.target/pru/regio-decl.c: New negative test.
+ * gcc.target/pru/regio-di.c: New negative test.
+ * gcc.target/pru/regio-hi.c: New negative test.
+ * gcc.target/pru/regio-qi.c: New negative test.
+ * gcc.target/pru/regio.c: New test.
+ * gcc.target/pru/regio.h: New helper header.
+
+2021-09-24 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102458
+ * gfortran.dg/pr102458.f90: New test.
+
+2021-09-24 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101333
+ * gfortran.dg/c-interop/c407c-1.f90: Remove xfails.
+
+2021-09-24 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98216
+ PR c++/91292
+ * g++.dg/cpp2a/nontype-float2.C: New test.
+
+2021-09-24 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * gfortran.dg/include_9.f90: Add dg-prune-output.
+ * gfortran.dg/include_23.f90: New test.
+ * gfortran.dg/include_24.f90: New test.
+
+2021-09-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/20030714-2.c: Adjust.
+ * gcc.dg/tree-ssa/pr66752-3.c: Adjust.
+ * gcc.dg/tree-ssa/pr77445-2.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.
+ * gcc.dg/vect/bb-slp-16.c: Adjust.
+
+2021-09-24 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c: New test.
+ * gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c: Ditto.
+ * gcc.target/i386/cond_op_fma__Float16-1.c: Ditto.
+ * gcc.target/i386/cond_op_fma__Float16-2.c: Ditto.
+ * gcc.target/i386/cond_op_maxmin__Float16-1.c: Ditto.
+ * gcc.target/i386/cond_op_maxmin__Float16-2.c: Ditto.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101320
+ * gfortran.dg/c-interop/c516.f90: Remove xfails. Add more
+ tests.
+
+2021-09-23 Michel Morin <mimomorin@gmail.com>
+
+ PR c++/77565
+ * g++.dg/spellcheck-pr77565.C: New test.
+
+2021-09-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr102463.c: New.
+
+2021-09-23 Harald Anlauf <anlauf@gmx.de>
+ Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/93834
+ * gfortran.dg/coarray/coarray_allocated.f90: New test.
+
+2021-09-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/102024
+ * g++.target/powerpc/pr102024.C: New.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * g++.target/i386/avx512fp16-vcondmn-vec.C: New test.
+ * g++.target/i386/avx512fp16-vcondmn-minmax.C: Ditto.
+ * gcc.target/i386/avx512fp16-vcondmn-loop-1.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcondmn-loop-2.c: Ditto.
+ * gcc.target/i386/avx512fp16-vec_cmpmn.c: Ditto.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-trunc-extendvnhf.c: New test.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-floatvnhf.c: New test.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-trunchf.c: New test.
+ * gcc.target/i386/avx512fp16-truncvnhf.c: Ditto.
+
+2021-09-23 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-minmax-1.c: New test.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-fma-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-fma-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-fma-vectorize-1.c: New test.
+
+2021-09-23 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-round-1.c: Add new testcase.
+
+2021-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102413
+ * g++.dg/gomp/attrs-14.C: New test.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101319
+ * gfortran.dg/c-interop/assumed-type-dummy.f90: Remove xfail.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR fortran/101334
+ * gfortran.dg/c-interop/c535b-2.f90: Remove xfails.
+ * gfortran.dg/c-interop/c535b-3.f90: Likewise.
+
+2021-09-23 Sandra Loosemore <sandra@codesourcery.com>
+
+ * gfortran.dg/assumed_rank_18.f90 (g): Wrap call to h in
+ select rank.
+ * gfortran.dg/assumed_type_10.f90 (test_array): Likewise for
+ call to test_lib.
+ * gfortran.dg/assumed_type_11.f90 (test_array): Likewise.
+
+2021-09-22 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/55534
+ * gfortran.dg/include_14.f90: Add -J testcase and update dg-output.
+ * gfortran.dg/include_15.f90: Likewise.
+ * gfortran.dg/include_16.f90: Likewise.
+ * gfortran.dg/include_17.f90: Likewise.
+ * gfortran.dg/include_18.f90: Likewise.
+ * gfortran.dg/include_19.f90: Likewise.
+
+2021-09-22 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/fold-negate-1.c: New test case.
+
+2021-09-22 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/auto-init-2.c: Replace ia32 with { ! lp64 }.
+ * gcc.target/i386/auto-init-3.c (dg-options): Add -msse.
+ (dg-additional-options): Add -mfpmath=387 for ia32.
+ Replace lp64 with { ! ia32 }. Add a space after ia32.
+ * gcc.target/i386/auto-init-4.c: Replace lp64 with { ! ia32 }.
+ * gcc.target/i386/auto-init-5.c: Likewise.
+ * gcc.target/i386/auto-init-padding-3.c: Likewise.
+ * gcc.target/i386/auto-init-padding-7.c: Likewise.
+ * gcc.target/i386/auto-init-padding-8.c: Likewise.
+ * gcc.target/i386/auto-init-padding-9.c: Likewise.
+
+2021-09-22 Patrick Palka <ppalka@redhat.com>
+
+ DR 2446
+ PR c++/102412
+ * g++.dg/cpp2a/concepts-nondep2.C: New test.
+ * g++.dg/cpp2a/concepts-nondep3.C: New test.
+
+2021-09-22 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR tree-optimization/102087
+ * gcc.dg/pr102087.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-14.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-conjugation-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-conjugation-1.c: New test.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-reduce-op-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-reduce-op-1.c: Ditto.
+
+2021-09-22 dianhong xu <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx512fp16-13.c: New test.
+
+2021-09-22 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/pr102222.c: New test.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/102415
+ * c-c++-common/gomp/scope-3.c: New test.
+
+2021-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/allocate-6.c: New test.
+ * c-c++-common/gomp/allocate-7.c: New test.
+ * g++.dg/gomp/allocate-4.C: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512vl-pr95046.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr92658-avx512f.c: Refine testcase.
+ * gcc.target/i386/pr92658-avx512vl.c: Adjust scan-assembler,
+ only v2di->v2qi truncate is not supported, v4di->v4qi should
+ be supported.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-fpcompare-1.c: New test.
+ * gcc.target/i386/avx512fp16-builtin-fpcompare-2.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-round-1.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-builtin-sqrt-1.c: New test.
+ * gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c: New test.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-complex-constraints.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h
+ (init_src): Adjust init value.
+ (NET_CMASK): New net mask for complex input.
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfcmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1b.c: Ditto.
+
+2021-09-22 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-22 Barrett Adair <barrettellisadair@gmail.com>
+
+ * g++.dg/cpp0x/constexpr-52830.C: Remove unwanted dg-ice.
+ * g++.dg/template/canon-type-15.C: New test.
+ * g++.dg/template/canon-type-16.C: New test.
+ * g++.dg/template/canon-type-17.C: New test.
+ * g++.dg/template/canon-type-18.C: New test.
+ * g++.dg/template/dependent-name15.C: New regression test.
+ * g++.dg/template/dependent-name16.C: New regression test.
+
+2021-09-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102421
+ * g++.dg/vect/pr102421.cc: New testcase.
+
+2021-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * lib/target-supports.exp (no_fsanitize_address): Add missing bits.
+ * gcc.dg/uninit-pr93100.c: Skip if no_fsanitize_address.
+ * gcc.dg/pr91441.c: Likewise.
+ * gcc.dg/pr96260.c: Likewise.
+ * gcc.dg/pr96307.c: Likewise.
+ * g++.dg/warn/uninit-pr93100.C: Likewise.
+ * gnat.dg/asan1.adb: Likewise.
+ * gcc.dg/Wstringop-overflow-70.c: Adjust for SPARC.
+ * g++.dg/abi/anon4.C: Likewise.
+
+2021-09-21 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/include_6.f90: Change dg-error to
+ dg-warning and update pattern.
+ * gfortran.dg/include_14.f90: New test.
+ * gfortran.dg/include_15.f90: New test.
+ * gfortran.dg/include_16.f90: New test.
+ * gfortran.dg/include_17.f90: New test.
+ * gfortran.dg/include_18.f90: New test.
+ * gfortran.dg/include_19.f90: New test.
+ * gfortran.dg/include_20.f90: New test.
+ * gfortran.dg/include_21.f90: New test.
+
+2021-09-21 wangpc <pc.wang@linux.alibaba.com>
+
+ * g++.target/aarch64/sve/static-var-in-template.C: New test.
+
+2021-09-20 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/tree-ssa/evrp-ignore.c: New.
+
+2021-09-20 Matthias Kretz <m.kretz@gsi.de>
+
+ * gcc.dg/associative-math-1.c: New test.
+ * gcc.dg/associative-math-2.c: New test.
+ * gcc.dg/no-signed-zeros-1.c: New test.
+ * gcc.dg/no-signed-zeros-2.c: New test.
+ * gcc.dg/no-trapping-math-1.c: New test.
+ * gcc.dg/no-trapping-math-2.c: New test.
+ * gcc.dg/reciprocal-math-1.c: New test.
+ * gcc.dg/reciprocal-math-2.c: New test.
+ * gcc.dg/rounding-math-1.c: New test.
+ * gcc.dg/rounding-math-2.c: New test.
+
+2021-09-20 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/order-5.f90: New test.
+ * gfortran.dg/gomp/order-6.f90: New test.
+ * gfortran.dg/gomp/order-7.f90: New test.
+ * gfortran.dg/gomp/order-8.f90: New test.
+ * gfortran.dg/gomp/order-9.f90: New test.
+
+2021-09-20 Christophe Lyon <christophe.lyon@foss.st.com>
+ Torbjörn SVENSSON <torbjorn.svensson@st.com>
+
+ * lib/prune.exp (prune_gcc_output): Remove .exe suffix from
+ toolchain executables names.
+
+2021-09-20 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gcc.dg/plugin/diagnostic-test-string-literals-1.c: Adjust
+ expected error diagnostics.
+
+2021-09-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/65206
+ * gcc.dg/torture/20210916.c: New testcase.
+ * gcc.dg/vect/pr65206.c: Likewise.
+
+2021-09-19 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102403
+ * gcc.dg/uninit-pr102403.c: New test.
+ * gcc.dg/uninit-pr102403-c2.c: New test.
+
+2021-09-19 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102243
+ * g++.dg/warn/Wplacement-new-size-10.C: New test.
+
+2021-09-19 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gfortran.dg/goacc/privatization-1-compute.f90: Make test names
+ unique.
+ * gfortran.dg/goacc/routine-external-level-of-parallelism-2.f:
+ Likewise.
+
+2021-09-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * jit.dg/jit.exp (fixed_local_execute): Amend the match and
+ exit conditions to cater for more platforms.
+
+2021-09-19 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR middle-end/88173
+ * c-c++-common/pr57371-4.c: Tweak/correct test case for QNaNs.
+ * g++.dg/pr88173-1.C: New test case.
+ * g++.dg/pr88173-2.C: New test case.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/order-1.c (f2): Add tests for distribute
+ with order clause.
+ (f3): Remove.
+ * c-c++-common/gomp/order-2.c: Don't expect error for distribute
+ with order clause.
+ * c-c++-common/gomp/order-5.c: New test.
+ * c-c++-common/gomp/order-6.c: New test.
+ * c-c++-common/gomp/clause-dups-1.c (f1): Add tests for
+ duplicated order clause.
+ (f9): New function.
+ * c-c++-common/gomp/clauses-1.c (baz, bar): Don't mix copyin and
+ order(concurrent) clauses on the same composite construct combined
+ with distribute, instead split it into two tests, one without
+ copyin and one without order(concurrent). Add order(concurrent)
+ clauses to {,{,target} teams} distribute.
+ * g++.dg/gomp/attrs-1.C (baz, bar): Likewise.
+ * g++.dg/gomp/attrs-2.C (baz, bar): Likewise.
+
+2021-09-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/default-2.c: New test.
+ * c-c++-common/gomp/default-3.c: New test.
+ * g++.dg/gomp/default-1.C: New test.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfmaddXXXsh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfmaddXXXsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubXXXsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubXXXsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmaddXXXsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmaddXXXsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmsubXXXsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmsubXXXsh-1b.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-18 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/avx512fp16-xorsign-1.c: New test.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-neg-1a.c: New test.
+ * gcc.target/i386/avx512fp16-neg-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-scalar-bitwise-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-scalar-bitwise-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vector-bitwise-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vector-bitwise-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-neg-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-neg-1b.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfmaddXXXph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfmaddXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmaddXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmaddXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmsubXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfnmsubXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmsubXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmsubXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1b.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test fot new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfmaddsubXXXph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfmaddsubXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubaddXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfmsubaddXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1b.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-18 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-broadcast-1.c: New test.
+ * gcc.target/i386/avx512fp16-broadcast-2.c: New test.
+
+2021-09-18 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/template/dtor5.C: Adjust expected error.
+ * g++.dg/cpp23/lookup2.C: New test.
+ * g++.dg/template/dtor11.C: New test.
+
+2021-09-17 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102366
+ * gfortran.dg/pr102366.f90: New test.
+
+2021-09-17 qing zhao <qing.zhao@oracle.com>
+
+ * gcc.target/i386/auto-init-1.c: Restrict the testing only for
+ -march=x86-64 and -mtune=generic. Add -fno-stack-protector.
+ * gcc.target/i386/auto-init-2.c: Restrict the testing only for
+ -march=x86-64 and -mtune=generic -msse.
+ * gcc.target/i386/auto-init-3.c: Likewise.
+ * gcc.target/i386/auto-init-4.c: Likewise.
+ * gcc.target/i386/auto-init-5.c: Different pattern match for lp64 and
+ ia32.
+ * gcc.target/i386/auto-init-6.c: Restrict the testing only for
+ -march=x86-64 and -mtune-generic -msse. Add -fno-stack-protector.
+ * gcc.target/i386/auto-init-7.c: Likewise.
+ * gcc.target/i386/auto-init-8.c: Restrict the testing only for
+ -march=x86-64 and -mtune=generic -msse..
+ * gcc.target/i386/auto-init-padding-1.c: Likewise.
+ * gcc.target/i386/auto-init-padding-10.c: Likewise.
+ * gcc.target/i386/auto-init-padding-11.c: Likewise.
+ * gcc.target/i386/auto-init-padding-12.c: Likewise.
+ * gcc.target/i386/auto-init-padding-2.c: Likewise.
+ * gcc.target/i386/auto-init-padding-3.c: Restrict the testing only for
+ -march=x86-64. Different pattern match for lp64 and ia32.
+ * gcc.target/i386/auto-init-padding-4.c: Restrict the testing only for
+ -march=x86-64 and -mtune-generic -msse.
+ * gcc.target/i386/auto-init-padding-5.c: Likewise.
+ * gcc.target/i386/auto-init-padding-6.c: Likewise.
+ * gcc.target/i386/auto-init-padding-7.c: Restrict the testing only for
+ -march=x86-64 and -mtune-generic -msse. Add -fno-stack-protector.
+ * gcc.target/i386/auto-init-padding-8.c: Likewise.
+ * gcc.target/i386/auto-init-padding-9.c: Restrict the testing only for
+ -march=x86-64. Different pattern match for lp64 and ia32.
+
+2021-09-17 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/102200
+ * gcc.dg/Wstringop-overflow-62.c: Adjust text of an expected note.
+ * gcc.dg/Warray-bounds-89.c: New test.
+ * gcc.dg/Wstringop-overflow-74.c: New test.
+ * gcc.dg/Wstringop-overflow-75.c: New test.
+ * gcc.dg/Wstringop-overflow-76.c: New test.
+
+2021-09-17 Sandra Loosemore <sandra@codesourcery.com>
+
+ * gfortran.dg/PR100914.c: Do not include quadmath.h. Use
+ _Float128 _Complex instead of __complex128.
+ * gfortran.dg/PR100914.f90: Add -Wno-pedantic to suppress error
+ about use of _Float128.
+ * gfortran.dg/c-interop/typecodes-array-float128-c.c: Use
+ _Float128 instead of __float128.
+ * gfortran.dg/c-interop/typecodes-sanity-c.c: Likewise.
+ * gfortran.dg/c-interop/typecodes-scalar-float128-c.c: Likewise.
+ * lib/target-supports.exp
+ (check_effective_target_fortran_real_c_float128): Update comments.
+
+2021-09-17 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR c/102245
+ * gcc.dg/Wint-in-bool-context-4.c: New test case.
+
+2021-09-17 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/atomic-18.c: Expect same diagnostics in C++ as in
+ C.
+ * c-c++-common/gomp/atomic-25.c: Drop c effective target.
+ * c-c++-common/gomp/atomic-26.c: Likewise.
+ * c-c++-common/gomp/atomic-27.c: Likewise.
+ * c-c++-common/gomp/atomic-28.c: Likewise.
+ * c-c++-common/gomp/atomic-29.c: Likewise.
+ * c-c++-common/gomp/atomic-30.c: Likewise. Adjust expected diagnostics
+ for C++ when it differs from C.
+ (foo): Change return type from double to void.
+ * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics wording.
+ * g++.dg/gomp/atomic-20.C: New test.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/avx-covert-1.c: New file.
+ * gcc.target/i386/avx-fp-covert-1.c: Likewise.
+ * gcc.target/i386/avx-int-covert-1.c: Likewise.
+ * gcc.target/i386/sse-covert-1.c: Likewise.
+ * gcc.target/i386/sse-fp-covert-1.c: Likewise.
+ * gcc.target/i386/sse-int-covert-1.c: Likewise.
+
+2021-09-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101900
+ * gcc.target/i386/pr101900-1.c: New test.
+ * gcc.target/i386/pr101900-2.c: Likewise.
+ * gcc.target/i386/pr101900-3.c: Likewise.
+
+2021-09-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/20210917-1.c: New test.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-typecast-1.c: New test.
+ * gcc.target/i386/avx512fp16-typecast-2.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-typecast-1.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-typecast-2.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vcvtsd2sh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvtsd2sh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2sd-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2sd-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2ss-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2ss-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtss2sh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtss2sh-1b.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h (V512): Add DF contents.
+ (src3f): New.
+ * gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvtpd2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2pd-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2pd-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2psx-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2psx-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtps2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtps2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtpd2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2pd-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2pd-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2psx-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtps2ph-1b.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vcvttsh2si-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvttsh2si-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2si64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2si64-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2usi-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2usi64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttsh2usi64-1b.c: Ditto.
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vcvttph2dq-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvttph2dq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2qq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2qq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2udq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2udq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2uqq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2uw-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2uw-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2w-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvttph2w-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2dq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2qq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2qq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2udq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2uqq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2uqq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2uw-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvttph2w-1b.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h (V512): Add int32
+ component.
+ * gcc.target/i386/avx512fp16-vcvtsh2si-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvtsh2si-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2si64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2si64-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2usi-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2usi64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsh2usi64-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsi2sh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsi2sh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsi2sh64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtsi2sh64-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtusi2sh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtusi2sh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtusi2sh64-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtusi2sh64-1b.c: Ditto.
+
+2021-09-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-16 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/98486
+ * g++.dg/cpp2a/concepts-var-templ1.C: New test.
+ * g++.dg/cpp2a/concepts-var-templ1a.C: New test.
+ * g++.dg/cpp2a/concepts-var-templ1b.C: New test.
+
+2021-09-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102287
+ * gfortran.dg/intent_out_14.f90: New test.
+
+2021-09-16 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102360
+ * g++.dg/pr102360.C: New testcase.
+
+2021-09-16 Richard Earnshaw <rearnsha@arm.com>
+
+ * g++.dg/eh/arm-vfp-unwind.C: Support single-precision.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ PR middle-end/102080
+ * gcc.target/i386/pr102080.c: New test.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vcvtdq2ph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvtdq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtqq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtudq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtudq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtuqq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtuw2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtuw2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtw2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtw2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtdq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtdq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtqq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtudq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtudq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtuw2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtuw2ph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtw2ph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtw2ph-1b.c: Ditto.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h (V512): Add QI
+ components.
+ * gcc.target/i386/avx512fp16-vcvtph2dq-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcvtph2dq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2qq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2qq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2udq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2udq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2uqq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2uw-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2uw-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2w-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcvtph2w-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2dq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2qq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2udq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uqq-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uw-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcvtph2w-1b.c: Ditto.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-16 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vmovsh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vmovsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-2a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-2b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-3a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-3b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-4a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmovw-4b.c: Ditto.
+
+2021-09-15 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101904
+ * g++.dg/ext/conv2.C: New test.
+ * g++.dg/template/conv17.C: Extend test.
+
+2021-09-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/88578
+ PR c++/102295
+ * g++.dg/ext/flexary39.C: New test.
+ * g++.dg/ext/flexary40.C: New test.
+
+2021-09-15 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102050
+ * g++.dg/cpp0x/initlist125.C: New test.
+ * g++.dg/cpp0x/initlist126.C: New test.
+
+2021-09-15 Alexandre Oliva <oliva@adacore.com>
+
+ * gnat.dg/zcur_attr.adb, gnat.dg/zcur_attr.ads: New.
+
+2021-09-15 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr102327-1.c: New test.
+ * gcc.target/i386/pr102327-2.c: New test.
+ * gcc.target/i386/avx512fp16-1c.c: Adjust testcase.
+
+2021-09-15 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx-1.c: Adjust builtin macros.
+ * gcc.target/i386/sse-13.c: Likewise.
+ * gcc.target/i386/sse-23.c: Likewise.
+
+2021-09-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102318
+ * gcc.dg/vect/pr102318.c: New testcase.
+
+2021-09-15 Hongtao Liu <hongtao.liu@intel.com>
+ Peter Cordes <peter@cordes.ca>
+
+ PR target/91103
+ * gcc.target/i386/pr91103-1.c: Add extract tests.
+ * gcc.target/i386/pr91103-2.c: Ditto.
+
+2021-09-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/unexpected-end.f90: Add OpenACC 'host_data'
+ testing.
+
+2021-09-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/48396
+ * g++.dg/rtti/undeclared1.C: New test.
+
+2021-09-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102311
+ * gfortran.dg/entry_25.f90: New test.
+
+2021-09-14 Peter Bergner <bergner@linux.ibm.com>
+
+ * gcc.target/powerpc/mma-builtin-6.c: Add second call to xxsetacc
+ built-in. Update instruction counts.
+
+2021-09-14 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102163
+ * g++.dg/cpp0x/constexpr-empty17.C: New test.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102295
+ * g++.target/i386/pr102295.C: New test.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/102305
+ * g++.dg/cpp0x/pr102305.C: New test.
+
+2021-09-14 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/102313
+ * gfortran.dg/goacc/unexpected-end.f90: New test.
+ * gfortran.dg/gomp/unexpected-end.f90: New test.
+
+2021-09-14 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/gcov/gcov.py: Fix failing pytests as gcov.json.gz
+ filename was changed in b777f228b481ae881a7fbb09de367a053740932c.
+
+2021-09-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/enum_rep2.adb: New test.
+
+2021-09-14 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/atomic-29.c: Add -march=pentium
+ dg-additional-options for ia32. Use sync_long_long effective target
+ instead of sync_int_long.
+ * lib/target-supports.exp (check_effective_target_sync_long_long): Fix
+ a syntax error.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h (V512):
+ Add xmm component.
+ * gcc.target/i386/avx512fp16-vfpclassph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vfpclassph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfpclasssh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vfpclasssh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetexpph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetexpph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetexpsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetexpsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetmantph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetmantph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetmantsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vgetmantsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfpclassph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vfpclassph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vgetexpph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vgetexpph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vgetmantph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vgetmantph-1b.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h (_ROUND_CUR): New macro.
+ * gcc.target/i386/avx512fp16-vreduceph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vreduceph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vreducesh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vreducesh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrndscaleph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrndscaleph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrndscalesh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrndscalesh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vreduceph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vreduceph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrndscaleph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrndscaleph-1b.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vrcpph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vrcpph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrcpsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrcpsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vscalefph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vscalefph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vscalefsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vscalefsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrcpph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrcpph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vscalefph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vscalefph-1b.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vrsqrtph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vrsqrtph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrsqrtsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vrsqrtsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsqrtph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsqrtph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsqrtsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsqrtsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vrsqrtph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vsqrtph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vsqrtph-1b.c: Ditto.
+
+2021-09-14 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-13 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/82314
+ * gfortran.dg/pr82314.f90: New test.
+
+2021-09-13 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/85130
+ * gfortran.dg/substr_6.f90: Revert commit r8-7574, adding again
+ test that was erroneously considered as illegal.
+
+2021-09-13 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/warn/Winterference.H: New file.
+ * g++.dg/warn/Winterference.C: New test.
+ * g++.target/aarch64/interference.C: New test.
+ * g++.target/arm/interference.C: New test.
+ * g++.target/i386/interference.C: New test.
+ * g++.dg/warn/Winterference-2.C: New file.
+
+2021-09-13 Martin Liska <mliska@suse.cz>
+ H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101696
+ * g++.target/i386/mv30.C: New test.
+ * gcc.target/i386/mvc16.c: New test.
+ * gcc.target/i386/builtin_target.c (CHECK___builtin_cpu_supports):
+ New.
+
+2021-09-13 Andrew Pinski <apinski@marvell.com>
+
+ PR target/95969
+ * gcc.target/aarch64/lane-bound-1.c: New test.
+ * gcc.target/aarch64/lane-bound-2.c: New test.
+
+2021-09-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/102252
+ * g++.target/aarch64/sve/pr102252.C: New test.
+
+2021-09-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/pr21417.c: Adjust for FSM removal.
+ * gcc.dg/tree-ssa/pr66752-3.c: Same.
+ * gcc.dg/tree-ssa/pr68198.c: Same.
+ * gcc.dg/tree-ssa/pr69196-1.c: Same.
+ * gcc.dg/tree-ssa/pr70232.c: Same.
+ * gcc.dg/tree-ssa/pr77445.c: Same.
+ * gcc.dg/tree-ssa/ranger-threader-4.c: Same.
+ * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Same.
+ * gcc.dg/tree-ssa/ssa-dom-thread-6.c: Same.
+ * gcc.dg/tree-ssa/ssa-thread-12.c: Same.
+ * gcc.dg/tree-ssa/ssa-thread-13.c: Same.
+
+2021-09-13 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101764
+ * g++.dg/cpp1z/constexpr-if35.C: New test.
+
+2021-09-13 Martin Liska <mliska@suse.cz>
+
+ PR c++/101331
+ * g++.dg/pr101331.C: New test.
+
+2021-09-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust for aarch64.
+
+2021-09-13 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/101935
+ * g++.target/i386/pr80566-1.C: Add
+ -mtune-ctrl=avx256_store_by_pieces.
+ * gcc.target/i386/pr100865-4a.c: Likewise.
+ * gcc.target/i386/pr100865-10a.c: Likewise.
+ * gcc.target/i386/pr90773-20.c: Likewise.
+ * gcc.target/i386/pr90773-21.c: Likewise.
+ * gcc.target/i386/pr90773-22.c: Likewise.
+ * gcc.target/i386/pr90773-23.c: Likewise.
+ * g++.target/i386/pr80566-2.C: Add
+ -mtune-ctrl=avx256_move_by_pieces.
+ * gcc.target/i386/eh_return-1.c: Likewise.
+ * gcc.target/i386/pr90773-26.c: Likewise.
+ * gcc.target/i386/pieces-memcpy-12.c: Replace -mtune=haswell
+ with -mtune-ctrl=avx256_move_by_pieces.
+ * gcc.target/i386/pieces-memcpy-15.c: Likewise.
+ * gcc.target/i386/pieces-memset-2.c: Replace -mtune=haswell
+ with -mtune-ctrl=avx256_store_by_pieces.
+ * gcc.target/i386/pieces-memset-5.c: Likewise.
+ * gcc.target/i386/pieces-memset-11.c: Likewise.
+ * gcc.target/i386/pieces-memset-14.c: Likewise.
+ * gcc.target/i386/pieces-memset-20.c: Likewise.
+ * gcc.target/i386/pieces-memset-23.c: Likewise.
+ * gcc.target/i386/pieces-memset-29.c: Likewise.
+ * gcc.target/i386/pieces-memset-30.c: Likewise.
+ * gcc.target/i386/pieces-memset-33.c: Likewise.
+ * gcc.target/i386/pieces-memset-34.c: Likewise.
+ * gcc.target/i386/pieces-memset-44.c: Likewise.
+ * gcc.target/i386/pieces-memset-37.c: Replace -mtune=generic
+ with -mtune-ctrl=avx256_store_by_pieces.
+
+2021-09-12 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102185
+ * gdc.dg/pr102185.d: New test.
+
+2021-09-11 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/auto-init-1.c: Enable test only on ilp32 or lp64
+ targets, expect different long and pointer sizes between ilp32 and
+ lp64.
+ * c-c++-common/auto-init-2.c: Likewise.
+ * c-c++-common/auto-init-3.c: Expect one of the common long double
+ sizes (8/12/16 bytes) instead of hardcoding 16 bytes.
+ * c-c++-common/auto-init-4.c: Likewise.
+ * c-c++-common/auto-init-5.c: Expect one of the common
+ _Complex long double sizes (16/24/32 bytes) instead of hardcoding 32
+ bytes.
+ * c-c++-common/auto-init-6.c: Likewise.
+ * c-c++-common/auto-init-padding-1.c: Enable test only on ilp32 or lp64
+ targets.
+ (struct test_small_hole): Change type of four to unsigned long long
+ and add aligned attribute.
+
+2021-09-10 Petter Tomner <tomner@kth.se>
+
+ * jit.dg/test-error-array-bounds.c: Array is not unsigned
+ * jit.dg/jit.exp: Helper function
+ * jit.dg/test-debuginfo.c: New testcase
+
+2021-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/atomic-17.c (foo): Add tests for atomic read,
+ write or update with acq_rel clause and atomic update with acquire clause.
+ * c-c++-common/gomp/atomic-18.c (foo): Adjust expected diagnostics
+ wording, remove tests moved to atomic-17.c.
+ * c-c++-common/gomp/atomic-21.c: Expect only 2 omp atomic release and
+ 2 omp atomic acq_rel directives instead of 4 omp atomic release.
+ * c-c++-common/gomp/atomic-25.c: New test.
+ * c-c++-common/gomp/atomic-26.c: New test.
+ * c-c++-common/gomp/atomic-27.c: New test.
+ * c-c++-common/gomp/atomic-28.c: New test.
+ * c-c++-common/gomp/atomic-29.c: New test.
+ * c-c++-common/gomp/atomic-30.c: New test.
+ * c-c++-common/goacc-gomp/atomic.c: Expect 1 omp atomic release and
+ 1 omp atomic_acq_rel instead of 2 omp atomic release directives.
+ * gcc.dg/gomp/atomic-5.c: Adjust expected error diagnostic wording.
+ * g++.dg/gomp/atomic-18.C:Expect 4 omp atomic release and
+ 1 omp atomic_acq_rel instead of 5 omp atomic release directives.
+
+2021-09-10 Aldy Hernandez <aldyh@redhat.com>
+ Michael Matz <matz@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Adjust for disabling of
+ threading through latches.
+ * gcc.dg/tree-ssa/ssa-dom-thread-6.c: Same.
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Same.
+
+2021-09-10 David Faust <david.faust@oracle.com>
+
+ * gcc.target/bpf/alu-1.c: New test.
+ * gcc.target/bpf/jmp-1.c: New test.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102273
+ * gcc.dg/pr102273.c: New testcase.
+
+2021-09-10 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/auto-init-padding-2.c: Fix 'dg-do run' syntax.
+ * c-c++-common/auto-init-padding-3.c: Likewise.
+
+2021-09-10 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/102269
+ * gcc.dg/pr102269.c: New testcase.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h
+ (check_results_mask): New check_function.
+ * gcc.target/i386/avx512fp16-vcmpph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vcmpph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcmpsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcmpsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcomish-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcomish-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vcomish-1c.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcmpph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vcmpph-1b.c: Ditto.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vmaxph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vmaxph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmaxsh-1.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmaxsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vminph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vminph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vminsh-1.c: Ditto.
+ * gcc.target/i386/avx512fp16-vminsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vmaxph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vmaxph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vminph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vminph-1b.c: Ditto.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-vaddsh-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vaddsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vdivsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vdivsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmulsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmulsh-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsubsh-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsubsh-1b.c: Ditto.
+ * gcc.target/i386/pr54855-11.c: Ditto.
+
+2021-09-10 Liu, Hongtao <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add test for new builtins.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-10 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/vect-float16-1.c: New test.
+ * gcc.target/i386/vect-float16-10.c: Ditto.
+ * gcc.target/i386/vect-float16-11.c: Ditto.
+ * gcc.target/i386/vect-float16-12.c: Ditto.
+ * gcc.target/i386/vect-float16-2.c: Ditto.
+ * gcc.target/i386/vect-float16-3.c: Ditto.
+ * gcc.target/i386/vect-float16-4.c: Ditto.
+ * gcc.target/i386/vect-float16-5.c: Ditto.
+ * gcc.target/i386/vect-float16-6.c: Ditto.
+ * gcc.target/i386/vect-float16-7.c: Ditto.
+ * gcc.target/i386/vect-float16-8.c: Ditto.
+ * gcc.target/i386/vect-float16-9.c: Ditto.
+
+2021-09-10 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512dq-abs-copysign-1.c: Adjust testcase.
+ * gcc.target/i386/avx512vl-abs-copysign-1.c: Adjust testcase.
+
+2021-09-09 qing zhao <qing.zhao@oracle.com>
+
+ * c-c++-common/auto-init-1.c: New test.
+ * c-c++-common/auto-init-10.c: New test.
+ * c-c++-common/auto-init-11.c: New test.
+ * c-c++-common/auto-init-12.c: New test.
+ * c-c++-common/auto-init-13.c: New test.
+ * c-c++-common/auto-init-14.c: New test.
+ * c-c++-common/auto-init-15.c: New test.
+ * c-c++-common/auto-init-16.c: New test.
+ * c-c++-common/auto-init-2.c: New test.
+ * c-c++-common/auto-init-3.c: New test.
+ * c-c++-common/auto-init-4.c: New test.
+ * c-c++-common/auto-init-5.c: New test.
+ * c-c++-common/auto-init-6.c: New test.
+ * c-c++-common/auto-init-7.c: New test.
+ * c-c++-common/auto-init-8.c: New test.
+ * c-c++-common/auto-init-9.c: New test.
+ * c-c++-common/auto-init-esra.c: New test.
+ * c-c++-common/auto-init-padding-1.c: New test.
+ * c-c++-common/auto-init-padding-2.c: New test.
+ * c-c++-common/auto-init-padding-3.c: New test.
+ * g++.dg/auto-init-uninit-pred-1_a.C: New test.
+ * g++.dg/auto-init-uninit-pred-2_a.C: New test.
+ * g++.dg/auto-init-uninit-pred-3_a.C: New test.
+ * g++.dg/auto-init-uninit-pred-4.C: New test.
+ * gcc.dg/auto-init-sra-1.c: New test.
+ * gcc.dg/auto-init-sra-2.c: New test.
+ * gcc.dg/auto-init-uninit-1.c: New test.
+ * gcc.dg/auto-init-uninit-12.c: New test.
+ * gcc.dg/auto-init-uninit-13.c: New test.
+ * gcc.dg/auto-init-uninit-14.c: New test.
+ * gcc.dg/auto-init-uninit-15.c: New test.
+ * gcc.dg/auto-init-uninit-16.c: New test.
+ * gcc.dg/auto-init-uninit-17.c: New test.
+ * gcc.dg/auto-init-uninit-18.c: New test.
+ * gcc.dg/auto-init-uninit-19.c: New test.
+ * gcc.dg/auto-init-uninit-2.c: New test.
+ * gcc.dg/auto-init-uninit-20.c: New test.
+ * gcc.dg/auto-init-uninit-21.c: New test.
+ * gcc.dg/auto-init-uninit-22.c: New test.
+ * gcc.dg/auto-init-uninit-23.c: New test.
+ * gcc.dg/auto-init-uninit-24.c: New test.
+ * gcc.dg/auto-init-uninit-25.c: New test.
+ * gcc.dg/auto-init-uninit-26.c: New test.
+ * gcc.dg/auto-init-uninit-3.c: New test.
+ * gcc.dg/auto-init-uninit-34.c: New test.
+ * gcc.dg/auto-init-uninit-36.c: New test.
+ * gcc.dg/auto-init-uninit-37.c: New test.
+ * gcc.dg/auto-init-uninit-4.c: New test.
+ * gcc.dg/auto-init-uninit-5.c: New test.
+ * gcc.dg/auto-init-uninit-6.c: New test.
+ * gcc.dg/auto-init-uninit-8.c: New test.
+ * gcc.dg/auto-init-uninit-9.c: New test.
+ * gcc.dg/auto-init-uninit-A.c: New test.
+ * gcc.dg/auto-init-uninit-B.c: New test.
+ * gcc.dg/auto-init-uninit-C.c: New test.
+ * gcc.dg/auto-init-uninit-H.c: New test.
+ * gcc.dg/auto-init-uninit-I.c: New test.
+ * gcc.target/aarch64/auto-init-1.c: New test.
+ * gcc.target/aarch64/auto-init-2.c: New test.
+ * gcc.target/aarch64/auto-init-3.c: New test.
+ * gcc.target/aarch64/auto-init-4.c: New test.
+ * gcc.target/aarch64/auto-init-5.c: New test.
+ * gcc.target/aarch64/auto-init-6.c: New test.
+ * gcc.target/aarch64/auto-init-7.c: New test.
+ * gcc.target/aarch64/auto-init-8.c: New test.
+ * gcc.target/aarch64/auto-init-padding-1.c: New test.
+ * gcc.target/aarch64/auto-init-padding-10.c: New test.
+ * gcc.target/aarch64/auto-init-padding-11.c: New test.
+ * gcc.target/aarch64/auto-init-padding-12.c: New test.
+ * gcc.target/aarch64/auto-init-padding-2.c: New test.
+ * gcc.target/aarch64/auto-init-padding-3.c: New test.
+ * gcc.target/aarch64/auto-init-padding-4.c: New test.
+ * gcc.target/aarch64/auto-init-padding-5.c: New test.
+ * gcc.target/aarch64/auto-init-padding-6.c: New test.
+ * gcc.target/aarch64/auto-init-padding-7.c: New test.
+ * gcc.target/aarch64/auto-init-padding-8.c: New test.
+ * gcc.target/aarch64/auto-init-padding-9.c: New test.
+ * gcc.target/i386/auto-init-1.c: New test.
+ * gcc.target/i386/auto-init-2.c: New test.
+ * gcc.target/i386/auto-init-21.c: New test.
+ * gcc.target/i386/auto-init-22.c: New test.
+ * gcc.target/i386/auto-init-23.c: New test.
+ * gcc.target/i386/auto-init-24.c: New test.
+ * gcc.target/i386/auto-init-3.c: New test.
+ * gcc.target/i386/auto-init-4.c: New test.
+ * gcc.target/i386/auto-init-5.c: New test.
+ * gcc.target/i386/auto-init-6.c: New test.
+ * gcc.target/i386/auto-init-7.c: New test.
+ * gcc.target/i386/auto-init-8.c: New test.
+ * gcc.target/i386/auto-init-padding-1.c: New test.
+ * gcc.target/i386/auto-init-padding-10.c: New test.
+ * gcc.target/i386/auto-init-padding-11.c: New test.
+ * gcc.target/i386/auto-init-padding-12.c: New test.
+ * gcc.target/i386/auto-init-padding-2.c: New test.
+ * gcc.target/i386/auto-init-padding-3.c: New test.
+ * gcc.target/i386/auto-init-padding-4.c: New test.
+ * gcc.target/i386/auto-init-padding-5.c: New test.
+ * gcc.target/i386/auto-init-padding-6.c: New test.
+ * gcc.target/i386/auto-init-padding-7.c: New test.
+ * gcc.target/i386/auto-init-padding-8.c: New test.
+ * gcc.target/i386/auto-init-padding-9.c: New test.
+
+2021-09-09 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98490
+ * gfortran.dg/bounds_check_23.f90: New test.
+
+2021-09-09 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/x86_64/abi/avx512fp16/args.h: Replace long with
+ long long.
+ (XMM_T): Rename _long to _longlong and _ulong to _ulonglong.
+ (X87_T): Rename _ulong to _ulonglong.
+ * gcc.target/x86_64/abi/avx512fp16/defines.h (TYPE_SIZE_LONG):
+ Define to 4 if __ILP32__ is defined.
+ (TYPE_SIZE_POINTER): Likewise.
+ (TYPE_ALIGN_LONG): Likewise.
+ (TYPE_ALIGN_POINTER): Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
+ (main): Skip test for long if __ILP32__ is defined.
+ * gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
+ (do_test): Replace _long with _longlong.
+ * gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c:
+ (check_300): Replace _ulong with _ulonglong.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/args.h: Replace long
+ with long long.
+ (YMM_T): Rename _long to _longlong and _ulong to _ulonglong.
+ (X87_T): Rename _ulong to _ulonglong.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/args.h: Replace long
+ with long long.
+ (ZMM_T): Rename _long to _longlong and _ulong to _ulonglong.
+ (X87_T): Rename _ulong to _ulonglong.
+
+2021-09-09 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-lim-17.c: New testcase.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512fp16-helper.h: New header file for
+ FP16 runtime test.
+ * gcc.target/i386/avx512fp16-vaddph-1a.c: New test.
+ * gcc.target/i386/avx512fp16-vaddph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vdivph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vdivph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmulph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vmulph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsubph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-vsubph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vaddph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vaddph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vdivph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vdivph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vmulph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vmulph-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vsubph-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16vl-vsubph-1b.c: Ditto.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add -mavx512vl and test for new intrinsics.
+ * gcc.target/i386/avx-2.c: Add -mavx512vl.
+ * gcc.target/i386/avx512fp16-11a.c: New test.
+ * gcc.target/i386/avx512fp16-11b.c: Ditto.
+ * gcc.target/i386/avx512vlfp16-11a.c: Ditto.
+ * gcc.target/i386/avx512vlfp16-11b.c: Ditto.
+ * gcc.target/i386/sse-13.c: Add test for new builtins.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c: Add test for new intrinsics.
+ * gcc.target/i386/sse-22.c: Ditto.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/101059
+ * gcc.target/i386/sse2-pr101059.c: New test.
+ * gcc.target/i386/sse3-pr101059.c: New test.
+
+2021-09-09 liuhongt <hongtao.liu@intel.com>
+
+ PR target/91103
+ * gcc.target/i386/pr91103-1.c: New test.
+ * gcc.target/i386/pr91103-2.c: New test.
+
+2021-09-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102225
+ * gcc.dg/analyzer/realloc-1.c (test_10): New.
+ * gcc.dg/analyzer/torture/pr102225.c: New test.
+
+2021-09-08 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/array-quals-1.c: Allow .sdata section in more cases.
+
+2021-09-08 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/tree-ssa/pr89430-1.c, gcc.dg/tree-ssa/pr89430-2.c,
+ gcc.dg/tree-ssa/pr89430-3.c, gcc.dg/tree-ssa/pr89430-4.c,
+ gcc.dg/tree-ssa/pr89430-5.c, gcc.dg/tree-ssa/pr89430-6.c,
+ gcc.dg/tree-ssa/pr89430-7-comp-ref.c,
+ gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c,
+ gcc.dg/tree-ssa/pr99473-1.c: Use -ftree-cselim.
+
+2021-09-08 Jakub Jelinek <jakub@redhat.com>
+ liuhongt <hongtao.liu@intel.com>
+
+ PR target/89984
+ * gcc.target/i386/avx-pr102224.c: Fix up PR number.
+ * gcc.dg/pr89984.c: New test.
+ * gcc.target/i386/avx-pr89984.c: New test.
+
+2021-09-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/102224
+ * gcc.dg/pr102224.c: New test.
+ * gcc.target/i386/avx-pr102224.c: New test.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp:
+ New file.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/args.h: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c:
+ Likewise.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp:
+ New exp file.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/args.h: New header.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S: New.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c:
+ New test.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c: Likewise.
+
+2021-09-08 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp: New exp
+ file for abi test.
+ * gcc.target/x86_64/abi/avx512fp16/args.h: New header file for abi test.
+ * gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/defines.h: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/macros.h: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/asm-support.S: New asm for abi check.
+ * gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c:
+ New test.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c:
+ Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c: Likewise.
+ * gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c: Likewise.
+
+2021-09-08 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/avx512fp16-vararg-1.c: New test.
+ * gcc.target/i386/avx512fp16-vararg-2.c: Ditto.
+ * gcc.target/i386/avx512fp16-vararg-3.c: Ditto.
+ * gcc.target/i386/avx512fp16-vararg-4.c: Ditto.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/m512-check.h: Add union128h, union256h, union512h.
+ * gcc.target/i386/avx512fp16-10a.c: New test.
+ * gcc.target/i386/avx512fp16-10b.c: Ditto.
+ * gcc.target/i386/avx512fp16-1a.c: Ditto.
+ * gcc.target/i386/avx512fp16-1b.c: Ditto.
+ * gcc.target/i386/avx512fp16-1c.c: Ditto.
+ * gcc.target/i386/avx512fp16-1d.c: Ditto.
+ * gcc.target/i386/avx512fp16-1e.c: Ditto.
+ * gcc.target/i386/avx512fp16-2a.c: Ditto.
+ * gcc.target/i386/avx512fp16-2b.c: Ditto.
+ * gcc.target/i386/avx512fp16-2c.c: Ditto.
+ * gcc.target/i386/avx512fp16-3a.c: Ditto.
+ * gcc.target/i386/avx512fp16-3b.c: Ditto.
+ * gcc.target/i386/avx512fp16-3c.c: Ditto.
+ * gcc.target/i386/avx512fp16-4.c: Ditto.
+ * gcc.target/i386/avx512fp16-5.c: Ditto.
+ * gcc.target/i386/avx512fp16-6.c: Ditto.
+ * gcc.target/i386/avx512fp16-7.c: Ditto.
+ * gcc.target/i386/avx512fp16-8.c: Ditto.
+ * gcc.target/i386/avx512fp16-9a.c: Ditto.
+ * gcc.target/i386/avx512fp16-9b.c: Ditto.
+ * gcc.target/i386/pr54855-13.c: Ditto.
+ * gcc.target/i386/avx512fp16-vec_set_var.c: Ditto.
+
+2021-09-08 Guo, Xuepeng <xuepeng.guo@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+ Liu Hongtao <hongtao.liu@intel.com>
+ Wang Hongyu <hongyu.wang@intel.com>
+ Xu Dianhong <dianhong.xu@intel.com>
+
+ * gcc.target/i386/avx-1.c: Add -mavx512fp16 in dg-options.
+ * gcc.target/i386/avx-2.c: Ditto.
+ * gcc.target/i386/avx512-check.h: Check cpuid for AVX512FP16.
+ * gcc.target/i386/funcspec-56.inc: Add new target attribute check.
+ * gcc.target/i386/sse-13.c: Add -mavx512fp16.
+ * gcc.target/i386/sse-14.c: Ditto.
+ * gcc.target/i386/sse-22.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * lib/target-supports.exp: (check_effective_target_avx512fp16): New.
+ * g++.target/i386/float16-1.C: New test.
+ * g++.target/i386/float16-2.C: Ditto.
+ * g++.target/i386/float16-3.C: Ditto.
+ * gcc.target/i386/avx512fp16-12a.c: Ditto.
+ * gcc.target/i386/avx512fp16-12b.c: Ditto.
+ * gcc.target/i386/float16-3a.c: Ditto.
+ * gcc.target/i386/float16-3b.c: Ditto.
+ * gcc.target/i386/float16-4a.c: Ditto.
+ * gcc.target/i386/float16-4b.c: Ditto.
+ * gcc.target/i386/pr54855-12.c: Ditto.
+ * g++.dg/other/i386-2.C: Ditto.
+ * g++.dg/other/i386-3.C: Ditto.
+
+2021-09-08 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/float16-6.c: New test.
+ * gcc.target/i386/float16-7.c: New test.
+
+2021-09-07 David Faust <david.faust@oracle.com>
+
+ * gcc.target/bpf/core-attr-1.c: New test.
+ * gcc.target/bpf/core-attr-2.c: Likewise.
+ * gcc.target/bpf/core-attr-3.c: Likewise.
+ * gcc.target/bpf/core-attr-4.c: Likewise
+ * gcc.target/bpf/core-builtin-1.c: Likewise
+ * gcc.target/bpf/core-builtin-2.c: Likewise.
+ * gcc.target/bpf/core-builtin-3.c: Likewise.
+ * gcc.target/bpf/core-section-1.c: Likewise.
+
+2021-09-07 Hans-Peter Nilsson <hp@axis.com>
+
+ * gcc.dg/no_profile_instrument_function-attr-2.c: Fix
+ typo in last change.
+
+2021-09-07 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/101327
+ * gfortran.dg/pr101327.f90: New test.
+
+2021-09-07 Indu Bhagat <indu.bhagat@oracle.com>
+
+ * gcc.target/bpf/core-lto-1.c: New test.
+
+2021-09-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/100495
+ * g++.dg/cpp2a/constexpr-new21.C: New test.
+
+2021-09-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/85819
+ * gcc.target/i386/pr85819-1a.c: New test.
+ * gcc.target/i386/pr85819-1b.c: Likewise.
+ * gcc.target/i386/pr85819-2a.c: Likewise.
+ * gcc.target/i386/pr85819-2b.c: Likewise.
+ * gcc.target/i386/pr85819-2c.c: Likewise.
+ * gcc.target/i386/pr85819-3.c: Likewise.
+
+2021-09-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102226
+ * g++.dg/vect/pr102226.cc: New testcase.
+
+2021-09-07 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-c++-common/gomp/flush-1.c: Add test case for 'seq_cst'.
+ * c-c++-common/gomp/flush-2.c: Add test case for 'seq_cst'.
+ * g++.dg/gomp/attrs-1.C: Adapt test to handle all flush clauses.
+ * g++.dg/gomp/attrs-2.C: Adapt test to handle all flush clauses.
+ * gfortran.dg/gomp/flush-1.f90: Add test case for 'seq_cst'.
+ * gfortran.dg/gomp/flush-2.f90: Add test case for 'seq_cst'.
+
+2021-09-07 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/80223
+ * gcc.dg/no_profile_instrument_function-attr-2.c: New test.
+
+2021-09-07 Xionghu Luo <luoxhu@linux.ibm.com>
+
+ PR target/97142
+ * gcc.target/powerpc/pr97142.c: New test.
+
+2021-09-06 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/89984
+ * gcc.target/i386/pr89984-1.c: New test.
+ * gcc.target/i386/pr89984-2.c: Likewise.
+ * gcc.target/i386/xorsign-avx.c: Likewise.
+
+2021-09-06 liuhongt <hongtao.liu@intel.com>
+
+ PR middle-end/102182
+ * gcc.target/i386/pr101282.c: New test.
+
+2021-09-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102207
+ * gcc.dg/pr102207.c: New test.
+
+2021-09-06 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/63184
+ * c-c++-common/pr19807-2.c: Enable for all targets and remove the xfail.
+ * c-c++-common/pr19807-3.c: Likewise.
+
+2021-09-03 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/101904
+ * g++.dg/template/conv17.C: New test.
+
+2021-09-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/bind_c_char_6.f90: Update dg-error.
+ * gfortran.dg/bind_c_char_7.f90: Likewise.
+ * gfortran.dg/bind_c_char_8.f90: Likewise.
+ * gfortran.dg/iso_c_binding_char_1.f90: Likewise.
+ * gfortran.dg/pr32599.f03: Likewise.
+ * gfortran.dg/bind_c_char_9.f90: Comment testcase bits which are
+ implementable but not valid F2018.
+ * gfortran.dg/bind_c_contiguous.f90: New test.
+
+2021-09-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102166
+ * g++.target/i386/pr102166.C: New test.
+
+2021-09-02 Sandra Loosemore <sandra@codesourcery.com>
+ José Rui Faustino de Sousa <jrfsousa@gmail.com>
+
+ PR fortran/100911
+ PR fortran/100915
+ PR fortran/100916
+ * gfortran.dg/PR100911.c: New file.
+ * gfortran.dg/PR100911.f90: New file.
+ * gfortran.dg/PR100914.c: New file.
+ * gfortran.dg/PR100914.f90: New file.
+ * gfortran.dg/PR100915.c: New file.
+ * gfortran.dg/PR100915.f90: New file.
+
+2021-09-02 Sandra Loosemore <sandra@codesourcery.com>
+
+ * gfortran.dg/c-interop/allocatable-dummy-c.c: New file.
+ * gfortran.dg/c-interop/allocatable-dummy.f90: New file.
+ * gfortran.dg/c-interop/allocatable-optional-pointer.f90: New file.
+ * gfortran.dg/c-interop/allocate-c.c: New file.
+ * gfortran.dg/c-interop/allocate-errors-c.c: New file.
+ * gfortran.dg/c-interop/allocate-errors.f90: New file.
+ * gfortran.dg/c-interop/allocate.f90: New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-1.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-2.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-3.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-4.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-5.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-6.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-7.f90:
+ New file.
+ * gfortran.dg/c-interop/argument-association-assumed-rank-8.f90:
+ New file.
+ * gfortran.dg/c-interop/assumed-type-dummy.f90: New file.
+ * gfortran.dg/c-interop/c-interop.exp: New file.
+ * gfortran.dg/c-interop/c1255-1.f90: New file.
+ * gfortran.dg/c-interop/c1255-2.f90: New file.
+ * gfortran.dg/c-interop/c1255a.f90: New file.
+ * gfortran.dg/c-interop/c407a-1.f90: New file.
+ * gfortran.dg/c-interop/c407a-2.f90: New file.
+ * gfortran.dg/c-interop/c407b-1.f90: New file.
+ * gfortran.dg/c-interop/c407b-2.f90: New file.
+ * gfortran.dg/c-interop/c407c-1.f90: New file.
+ * gfortran.dg/c-interop/c516.f90: New file.
+ * gfortran.dg/c-interop/c524a.f90: New file.
+ * gfortran.dg/c-interop/c535a-1.f90: New file.
+ * gfortran.dg/c-interop/c535a-2.f90: New file.
+ * gfortran.dg/c-interop/c535b-1.f90: New file.
+ * gfortran.dg/c-interop/c535b-2.f90: New file.
+ * gfortran.dg/c-interop/c535b-3.f90: New file.
+ * gfortran.dg/c-interop/c535c-1.f90: New file.
+ * gfortran.dg/c-interop/c535c-2.f90: New file.
+ * gfortran.dg/c-interop/c535c-3.f90: New file.
+ * gfortran.dg/c-interop/c535c-4.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-1-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-1.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-2-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-2.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-3-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-3.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-4-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-4.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-5-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-5.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-6-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-6.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-7-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-7.f90: New file.
+ * gfortran.dg/c-interop/cf-descriptor-8-c.c: New file.
+ * gfortran.dg/c-interop/cf-descriptor-8.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-1-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-1.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-2-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-2.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-3-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-3.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-4-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-4.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-5-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-5.f90: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-6-c.c: New file.
+ * gfortran.dg/c-interop/cf-out-descriptor-6.f90: New file.
+ * gfortran.dg/c-interop/contiguous-1-c.c: New file.
+ * gfortran.dg/c-interop/contiguous-1.f90: New file.
+ * gfortran.dg/c-interop/contiguous-2-c.c: New file.
+ * gfortran.dg/c-interop/contiguous-2.f90: New file.
+ * gfortran.dg/c-interop/contiguous-3-c.c: New file.
+ * gfortran.dg/c-interop/contiguous-3.f90: New file.
+ * gfortran.dg/c-interop/deferred-character-1.f90: New file.
+ * gfortran.dg/c-interop/deferred-character-2.f90: New file.
+ * gfortran.dg/c-interop/dump-descriptors.c: New file.
+ * gfortran.dg/c-interop/dump-descriptors.h: New file.
+ * gfortran.dg/c-interop/establish-c.c: New file.
+ * gfortran.dg/c-interop/establish-errors-c.c: New file.
+ * gfortran.dg/c-interop/establish-errors.f90: New file.
+ * gfortran.dg/c-interop/establish.f90: New file.
+ * gfortran.dg/c-interop/explicit-interface.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-1-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-1.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-2-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-2.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-3-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-3.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-4-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-4.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-5-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-5.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-6-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-6.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-7-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-7.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-8-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-8.f90: New file.
+ * gfortran.dg/c-interop/fc-descriptor-9-c.c: New file.
+ * gfortran.dg/c-interop/fc-descriptor-9.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-1-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-1.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-2-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-2.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-3-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-3.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-4-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-4.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-5-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-5.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-6-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-6.f90: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-7-c.c: New file.
+ * gfortran.dg/c-interop/fc-out-descriptor-7.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-1.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-2.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-3.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-4.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-5.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-6.f90: New file.
+ * gfortran.dg/c-interop/ff-descriptor-7.f90: New file.
+ * gfortran.dg/c-interop/note-5-3.f90: New file.
+ * gfortran.dg/c-interop/note-5-4-c.c: New file.
+ * gfortran.dg/c-interop/note-5-4.f90: New file.
+ * gfortran.dg/c-interop/optional-c.c: New file.
+ * gfortran.dg/c-interop/optional.f90: New file.
+ * gfortran.dg/c-interop/rank-class.f90: New file.
+ * gfortran.dg/c-interop/rank.f90: New file.
+ * gfortran.dg/c-interop/removed-restrictions-1.f90: New file.
+ * gfortran.dg/c-interop/removed-restrictions-2.f90: New file.
+ * gfortran.dg/c-interop/removed-restrictions-3.f90: New file.
+ * gfortran.dg/c-interop/removed-restrictions-4.f90: New file.
+ * gfortran.dg/c-interop/section-1-c.c: New file.
+ * gfortran.dg/c-interop/section-1.f90: New file.
+ * gfortran.dg/c-interop/section-1p.f90: New file.
+ * gfortran.dg/c-interop/section-2-c.c: New file.
+ * gfortran.dg/c-interop/section-2.f90: New file.
+ * gfortran.dg/c-interop/section-2p.f90: New file.
+ * gfortran.dg/c-interop/section-3-c.c: New file.
+ * gfortran.dg/c-interop/section-3.f90: New file.
+ * gfortran.dg/c-interop/section-3p.f90: New file.
+ * gfortran.dg/c-interop/section-4-c.c: New file.
+ * gfortran.dg/c-interop/section-4.f90: New file.
+ * gfortran.dg/c-interop/section-errors-c.c: New file.
+ * gfortran.dg/c-interop/section-errors.f90: New file.
+ * gfortran.dg/c-interop/select-c.c: New file.
+ * gfortran.dg/c-interop/select-errors-c.c: New file.
+ * gfortran.dg/c-interop/select-errors.f90: New file.
+ * gfortran.dg/c-interop/select.f90: New file.
+ * gfortran.dg/c-interop/setpointer-c.c: New file.
+ * gfortran.dg/c-interop/setpointer-errors-c.c: New file.
+ * gfortran.dg/c-interop/setpointer-errors.f90: New file.
+ * gfortran.dg/c-interop/setpointer.f90: New file.
+ * gfortran.dg/c-interop/shape.f90: New file.
+ * gfortran.dg/c-interop/size.f90: New file.
+ * gfortran.dg/c-interop/tkr.f90: New file.
+ * gfortran.dg/c-interop/typecodes-array-basic-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-array-basic.f90: New file.
+ * gfortran.dg/c-interop/typecodes-array-char-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-array-char.f90: New file.
+ * gfortran.dg/c-interop/typecodes-array-float128-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-array-float128.f90: New file.
+ * gfortran.dg/c-interop/typecodes-array-int128-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-array-int128.f90: New file.
+ * gfortran.dg/c-interop/typecodes-array-longdouble-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-array-longdouble.f90: New file.
+ * gfortran.dg/c-interop/typecodes-sanity-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-sanity.f90: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-basic-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-basic.f90: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-float128-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-float128.f90: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-int128-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-int128.f90: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-longdouble-c.c: New file.
+ * gfortran.dg/c-interop/typecodes-scalar-longdouble.f90: New file.
+ * gfortran.dg/c-interop/ubound.f90: New file.
+ * lib/target-supports.exp
+ (check_effective_target_fortran_real_c_float128): New function.
+
+2021-09-02 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/17506
+ PR testsuite/37182
+ * gcc.dg/diagnostic-tree-expr-ranges-2.c: Add expected output.
+ * gcc.dg/uninit-15-O0.c: Remove xfail.
+ * gcc.dg/uninit-15.c: Same.
+
+2021-09-02 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * gfortran.dg/gomp/target-device-ancestor-4.f90: Comment out dg-final to avoid
+ UNRESOLVED.
+
+2021-09-02 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-lim-16.c: New testcase.
+
+2021-09-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/99591
+ * gcc.target/i386/pr99591.c: New test.
+ * gcc.target/i386/pr97950.c: Match or reject setb or jn?b instructions
+ together with seta or jn?a.
+
+2021-09-02 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/sse2-float16-1.c: New test.
+ * gcc.target/i386/sse2-float16-2.c: Ditto.
+ * gcc.target/i386/sse2-float16-3.c: Ditto.
+ * gcc.target/i386/float16-5.c: New test.
+
+2021-09-01 Jeff Law <jlaw@localhost.localdomain>
+
+ PR tree-optimization/102152
+ * gcc.dg/pr102152.c: New test
+
+2021-09-01 Andrew Pinski <apinski@marvell.com>
+
+ PR target/101934
+ * gcc.target/aarch64/memset-strict-align-1.c: New test.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/100977
+ * g++.dg/cpp23/normalize1.C: New test.
+ * g++.dg/cpp23/normalize2.C: New test.
+ * g++.dg/cpp23/normalize3.C: New test.
+ * g++.dg/cpp23/normalize4.C: New test.
+ * g++.dg/cpp23/normalize5.C: New test.
+ * g++.dg/cpp23/normalize6.C: New test.
+ * g++.dg/cpp23/normalize7.C: New test.
+ * g++.dg/cpp23/ucnid-1-utf8.C: New test.
+ * g++.dg/cpp23/ucnid-2-utf8.C: New test.
+ * gcc.dg/cpp/ucnid-4.c: Don't expect
+ "not valid at the start of an identifier" errors.
+ * gcc.dg/cpp/ucnid-4-utf8.c: Likewise.
+ * gcc.dg/cpp/ucnid-5-utf8.c: New test.
+
+2021-09-01 Andrew Pinski <apinski@marvell.com>
+
+ PR testsuite/51748
+ * gcc.misc-tests/linkage.exp: Add mips*-linux-* support.
+
+2021-09-01 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/Wstringop-overflow-11.c: Remove xfails.
+ * gcc.dg/Wstringop-overflow-12.c: Same.
+ * gcc.dg/Wstringop-overflow-43.c: Add xfails.
+ * gcc.dg/Wstringop-overflow-73.c: New test.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/101488
+ * c-c++-common/cpp/va-opt-3.c: Adjust expected output.
+ * c-c++-common/cpp/va-opt-7.c: New test.
+
+2021-09-01 Marek Polacek <polacek@redhat.com>
+
+ PR c++/101592
+ * g++.dg/warn/Wlogical-op-3.C: New test.
+
+2021-09-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.dg/ext/attr-unavailable-1.C: New test.
+ * g++.dg/ext/attr-unavailable-2.C: New test.
+ * g++.dg/ext/attr-unavailable-3.C: New test.
+ * g++.dg/ext/attr-unavailable-4.C: New test.
+ * g++.dg/ext/attr-unavailable-5.C: New test.
+ * g++.dg/ext/attr-unavailable-6.C: New test.
+ * g++.dg/ext/attr-unavailable-7.C: New test.
+ * g++.dg/ext/attr-unavailable-8.C: New test.
+ * g++.dg/ext/attr-unavailable-9.C: New test.
+ * gcc.dg/attr-unavailable-1.c: New test.
+ * gcc.dg/attr-unavailable-2.c: New test.
+ * gcc.dg/attr-unavailable-3.c: New test.
+ * gcc.dg/attr-unavailable-4.c: New test.
+ * gcc.dg/attr-unavailable-5.c: New test.
+ * gcc.dg/attr-unavailable-6.c: New test.
+ * obj-c++.dg/attributes/method-unavailable-1.mm: New test.
+ * obj-c++.dg/attributes/method-unavailable-2.mm: New test.
+ * obj-c++.dg/attributes/method-unavailable-3.mm: New test.
+ * obj-c++.dg/property/at-property-unavailable-1.mm: New test.
+ * obj-c++.dg/property/at-property-unavailable-2.mm: New test.
+ * obj-c++.dg/property/dotsyntax-unavailable-1.mm: New test.
+ * objc.dg/attributes/method-unavailable-1.m: New test.
+ * objc.dg/attributes/method-unavailable-2.m: New test.
+ * objc.dg/attributes/method-unavailable-3.m: New test.
+ * objc.dg/property/at-property-unavailable-1.m: New test.
+ * objc.dg/property/at-property-unavailable-2.m: New test.
+ * objc.dg/property/dotsyntax-unavailable-1.m: New test.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102124
+ * gcc.dg/torture/pr102124.c: New test.
+
+2021-09-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/93491
+ * gcc.dg/torture/pr93491.c: New testcase.
+ * gcc.dg/tree-ssa/pr88087.c: Change to valid PRE opportunity.
+
+2021-09-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102139
+ * gcc.dg/torture/pr102139.c: New testcase.
+
+2021-09-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102141
+ * gcc.dg/pr102141.c: New test.
+
+2021-09-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102149
+ * gcc.dg/torture/pr102149.c: New testcase.
+
+2021-09-01 Roger Sayle <roger@nextmovesoftware.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ PR c/79412
+ * gcc.dg/pr79412.c: New test case.
+ * gcc.dg/typedef-var-2.c: Update expeted errors.
+
+2021-08-31 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/100950
+ * gfortran.dg/pr100950.f90: Extend coverage.
+
+2021-08-31 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/12672
+ * g++.dg/cpp0x/decltype29.C: Adjust.
+ * g++.dg/template/error56.C: Adjust.
+ * g++.old-deja/g++.pt/unify6.C: Adjust.
+ * g++.dg/template/explicit-args7.C: New test.
+
+2021-08-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/92193
+ * g++.dg/diagnostic/static_assert4.C: New test.
+
+2021-08-31 Jeff Law <jlaw@localhost.localdomain>
+
+ * gcc.target/mips/mips.exp: Add tree-vrp to mips_option_group.
+ * gcc.target/mips/data-sym-multi-pool.c: Add -fno-tree-vrp.
+
+2021-08-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/101145
+ * gcc.dg/vect/pr101145.c: Use dg-additional-options with just -O3
+ instead of dg-options with -O3 -fdump-tree-vect-details.
+ * gcc.dg/vect/pr101145_1.c: Likewise.
+ * gcc.dg/vect/pr101145_2.c: Likewise.
+ * gcc.dg/vect/pr101145_3.c: Likewise.
+
+2021-08-31 Marcel Vollweiler <marcel@codesourcery.com>
+
+ * c-c++-common/gomp/target-device-1.c: New test.
+ * c-c++-common/gomp/target-device-2.c: New test.
+ * c-c++-common/gomp/target-device-ancestor-1.c: New test.
+ * c-c++-common/gomp/target-device-ancestor-2.c: New test.
+ * c-c++-common/gomp/target-device-ancestor-3.c: New test.
+ * c-c++-common/gomp/target-device-ancestor-4.c: New test.
+ * gfortran.dg/gomp/target-device-1.f90: New test.
+ * gfortran.dg/gomp/target-device-2.f90: New test.
+ * gfortran.dg/gomp/target-device-ancestor-1.f90: New test.
+ * gfortran.dg/gomp/target-device-ancestor-2.f90: New test.
+ * gfortran.dg/gomp/target-device-ancestor-3.f90: New test.
+ * gfortran.dg/gomp/target-device-ancestor-4.f90: New test.
+
+2021-08-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102142
+ * g++.dg/torture/pr102142.C: New testcase.
+
+2021-08-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102134
+ * gcc.c-torture/execute/pr102134.c: New test.
+
+2021-08-31 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gcc.target/arm/pr51534.c: Adjust test-case for soft fp targets.
+
+2021-08-31 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.dg/ipa/inline-8.c: Mark cmp and move as
+ static so they both bind local and available for
+ inlinine.
+
+2021-08-31 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-vpcmpeqb-1.c: Adjust testcase.
+ * gcc.target/i386/avx512bw-vpcmpeqw-1.c: Ditto.
+ * gcc.target/i386/avx512bw-vpcmpgtb-1.c: Ditto.
+ * gcc.target/i386/avx512bw-vpcmpgtw-1.c: Ditto.
+ * gcc.target/i386/avx512f-vpcmpeqd-1.c: Ditto.
+ * gcc.target/i386/avx512f-vpcmpeqq-1.c: Ditto.
+ * gcc.target/i386/avx512f-vpcmpgtd-1.c: Ditto.
+ * gcc.target/i386/avx512f-vpcmpgtq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpeqd-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpeqq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgtd-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgtq-1.c: Ditto.
+ * gcc.target/i386/bitwise_mask_op-1.c: Ditto.
+ * gcc.target/i386/bitwise_mask_op-2.c: Ditto.
+
+2021-08-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/99260
+ * gcc.dg/analyzer/capacity-2.c: Update for changes to realloc
+ analysis.
+ * gcc.dg/analyzer/pr99193-1.c: Likewise.
+ * gcc.dg/analyzer/pr99193-3.c: Likewise.
+ * gcc.dg/analyzer/realloc-1.c: Likewise. Add test coverage for
+ realloc of non-heap pointer, realloc from mismatching allocator,
+ and realloc on a freed pointer.
+ * gcc.dg/analyzer/realloc-2.c: New test.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/96286
+ * g++.dg/template/access2.C: Split struct A.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/101460
+ * g++.dg/template/explicit-args6.C: New test.
+
+2021-08-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102113
+ * gfortran.dg/goto_9.f90: New test.
+
+2021-08-30 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-lambda14.C: Add expected warnings.
+
+2021-08-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/101349
+ * gfortran.dg/unlimited_polymorphic_33.f90: New test.
+
+2021-08-30 Pat Haugen <pthaugen@linux.ibm.com>
+
+ * gcc.target/powerpc/fusion-p10-stst.c: New test.
+ * gcc.target/powerpc/fusion-p10-stst2.c: New test.
+
+2021-08-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/102094
+ * gdc.dg/lto/pr102094_0.d: New test.
+
+2021-08-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/analyzer/strndup-1.c: Skip for Darwin versions
+ without strndup support in libc.
+
+2021-08-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/tree-ssa/modref-9.c: New test.
+
+2021-08-28 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/87737
+ * gfortran.dg/entry_24.f90: New test.
+
+2021-08-27 Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.target/powerpc/float128-call.c: Update comments.
+
+2021-08-27 Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.target/powerpc/float128-call.c: Fix test for IEEE 128-bit
+ long double and power10.
+
+2021-08-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * lib/target-supports.exp: Exclude cctools assembler based on
+ GAS 1.38.
+
+2021-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/45178
+ * gcc.dg/tree-ssa/ssa-dce-3.c: Adjust testcase.
+
+2021-08-27 konglin1 <lingling.kong@intel.com>
+
+ PR target/101472
+ * gcc.target/i386/avx512f-pr101472.c: New test.
+ * gcc.target/i386/avx512vl-pr101472.c: New test.
+
+2021-08-27 Kewen Lin <linkw@linux.ibm.com>
+
+ * gcc.target/powerpc/dive-vectorize-1.c: New test.
+ * gcc.target/powerpc/dive-vectorize-1.h: New test.
+ * gcc.target/powerpc/dive-vectorize-2.c: New test.
+ * gcc.target/powerpc/dive-vectorize-2.h: New test.
+ * gcc.target/powerpc/dive-vectorize-run-1.c: New test.
+ * gcc.target/powerpc/dive-vectorize-run-2.c: New test.
+ * gcc.target/powerpc/p10-bifs-vectorize-1.c: New test.
+ * gcc.target/powerpc/p10-bifs-vectorize-1.h: New test.
+ * gcc.target/powerpc/p10-bifs-vectorize-run-1.c: New test.
+
+2021-08-27 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512f-vshufpd-1.c: Adjust testcase.
+ * gcc.target/i386/avx512f-vshufps-1.c: Adjust testcase.
+ * gcc.target/i386/pr43147.c: New test.
+
2021-08-26 Roger Sayle <roger@nextmovesoftware.com>
* gcc.dg/tree-ssa/ssa-ccp-41.c: New test case.
diff --git a/gcc/testsuite/c-c++-common/Waddress-3.c b/gcc/testsuite/c-c++-common/Waddress-3.c
new file mode 100644
index 0000000..9a13a44
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-3.c
@@ -0,0 +1,125 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+struct S { void *p, *a1[2], *a2[2][2]; } s, *p;
+
+extern const void *a1[2];
+extern void *a2[2][2], *ax[];
+
+void T (bool);
+
+void test_array_eq_0 (int i)
+{
+ // Verify that casts intptr_t suppress the warning.
+ T ((intptr_t)a1 == 0);
+ T ((uintptr_t)a1 == 0);
+ T (a1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1); // { dg-warning "-Waddress" }
+ // Verify that casts to other pointer types don't suppress it.
+ T ((void *)a1 == 0); // { dg-warning "-Waddress" }
+ T ((char *)a1 == 0); // { dg-warning "-Waddress" }
+ T (a1[0] == 0);
+ T (0 == (intptr_t)&a1[0]);
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (a1[i] == 0);
+ T (0 == (uintptr_t)&a1[i]);
+ T (0 == &a1[i]); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)a2 == 0);
+ T (a2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2); // { dg-warning "-Waddress" }
+ T (a2[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (a2[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[i]); // { dg-warning "-Waddress" }
+ T (a2[0][0] == 0);
+ T (0 == &a2[0][0]); // { dg-warning "-Waddress" }
+ T (&ax == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax); // { dg-warning "-Waddress" }
+ T (&ax[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == ax[0]);
+}
+
+
+void test_array_neq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((uintptr_t)a1);
+
+ T (a1); // { dg-warning "-Waddress" }
+ T ((void *)a1); // { dg-warning "-Waddress" }
+ T (&a1 != 0); // { dg-warning "-Waddress" }
+ T (a1[0]);
+ T (&a1[0] != 0); // { dg-warning "-Waddress" }
+ T (a1[i]);
+ T (&a1[i] != 0); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)a2);
+ T (a2); // { dg-warning "-Waddress" }
+ T ((void *)a2); // { dg-warning "-Waddress" }
+ T ((char *)a2); // { dg-warning "-Waddress" }
+ T (&a2 != 0); // { dg-warning "-Waddress" }
+ T (a2[0]); // { dg-warning "-Waddress" }
+ T (&a1[0] != 0); // { dg-warning "-Waddress" }
+ T (a2[i]); // { dg-warning "-Waddress" }
+ T (&a2[i] != 0); // { dg-warning "-Waddress" }
+ T (a2[0][0]);
+ T (&a2[0][0] != 0); // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)s.a1 == 0);
+ T (s.a1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1); // { dg-warning "-Waddress" }
+ T (s.a1[0] == 0);
+ T ((void*)s.a1); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (s.a1[i] == 0);
+ T (0 == &a1[i]); // { dg-warning "-Waddress" }
+
+ T ((uintptr_t)s.a2 == 0);
+ T (s.a2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2); // { dg-warning "-Waddress" }
+ T ((void *)s.a2 == 0);// { dg-warning "-Waddress" }
+ T (s.a2[0] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a1[0]); // { dg-warning "-Waddress" }
+ T (s.a2[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[i]); // { dg-warning "-Waddress" }
+ T (s.a2[0][0] == 0);
+ T (0 == &a2[0][0]); // { dg-warning "-Waddress" }
+}
+
+
+void test_member_array_neq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((uintptr_t)s.a1);
+ T (s.a1); // { dg-warning "-Waddress" }
+ T (&s.a1 != 0); // { dg-warning "-Waddress" }
+ T ((void *)&s.a1[0]); // { dg-warning "-Waddress" }
+ T (s.a1[0]);
+ T (&s.a1[0] != 0); // { dg-warning "-Waddress" }
+ T (s.a1[i]);
+ T (&s.a1[i] != 0); // { dg-warning "-Waddress" }
+
+ T ((intptr_t)s.a2);
+ T (s.a2); // { dg-warning "-Waddress" }
+ T (&s.a2 != 0); // { dg-warning "-Waddress" }
+ T (s.a2[0]); // { dg-warning "-Waddress" }
+ T (&s.a1[0] != 0); // { dg-warning "-Waddress" }
+ T (s.a2[i]); // { dg-warning "-Waddress" }
+ T (&s.a2[i] != 0); // { dg-warning "-Waddress" }
+ T (s.a2[0][0]);
+ T (&s.a2[0][0] != 0); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Waddress-4.c b/gcc/testsuite/c-c++-common/Waddress-4.c
new file mode 100644
index 0000000..489a0cd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-4.c
@@ -0,0 +1,106 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __INTPTR_TYPE__ uintptr_t;
+
+extern char *ax[], *a2[][2];
+
+void T (int);
+
+void test_ax_plus_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)(ax + 0) == 0);
+ T ((uintptr_t)(ax + 1) == 0);
+
+ T (ax + 0 == 0); // { dg-warning "-Waddress" }
+ T (&ax[0] == 0); // { dg-warning "-Waddress" }
+ T (ax - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[-1]); // { dg-warning "-Waddress" }
+ T ((void *)(&ax[0] + 2) == 0); // { dg-warning "-Waddress" }
+ T (&ax[0] + 2 == 0); // { dg-warning "-Waddress" }
+ T (ax + 3 == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[-4]); // { dg-warning "-Waddress" }
+ T (ax - i == 0); // { dg-warning "-Waddress" }
+ T (&ax[i] == 0); // { dg-warning "-Waddress" }
+ T (0 == &ax[1] + i); // { dg-warning "-Waddress" }
+}
+
+void test_a2_plus_eq_0 (int i)
+{
+ // Verify that casts to intptr_t suppress the warning.
+ T ((intptr_t)(a2 + 0) == 0);
+ T ((uintptr_t)(a2 + 1) == 0);
+
+ T (a2 + 0 == 0); // { dg-warning "-Waddress" }
+ // Verify that a cast to another pointer type doesn't suppress it.
+ T ((void*)(a2 + 0) == 0); // { dg-warning "-Waddress" }
+ T ((char*)a2 + 1 == 0); // { dg-warning "-Waddress" }
+ T (&a2[0] == 0); // { dg-warning "-Waddress" }
+ T (a2 - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[-1]); // { dg-warning "-Waddress" }
+ T (a2 + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &a2[-2]); // { dg-warning "-Waddress" }
+ T (a2 - i == 0); // { dg-warning "-Waddress" }
+ T (&a2[i] == 0); // { dg-warning "-Waddress" }
+}
+
+// Exercise a pointer.
+void test_p_plus_eq_0 (int *p, int i)
+{
+ /* P + 0 and equivalently &P[0] are invalid for a null P but they're
+ folded to p before the warning has a chance to trigger. */
+ T (p + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&p[0] == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+
+ T (p - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &p[-1]); // { dg-warning "-Waddress" }
+ T (p + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &p[-2]); // { dg-warning "-Waddress" }
+ T (p - i == 0); // { dg-warning "-Waddress" }
+ T (&p[i] == 0); // { dg-warning "-Waddress" }
+}
+
+// Exercise pointer to array.
+void test_pa_plus_eq_0 (int (*p)[], int (*p2)[][2], int i)
+{
+ // The array pointer may be null.
+ T (*p == 0);
+ /* &**P is equivalent to *P and might be the result od macro expansion.
+ Verify it doesn't cause a warning. */
+ T (&**p == 0);
+
+ /* *P + 0 is invalid but folded to *P before the warning has a chance
+ to trigger. */
+ T (*p + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+
+ T (&(*p)[0] == 0); // { dg-warning "-Waddress" }
+ T (*p - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p)[-1]); // { dg-warning "-Waddress" }
+ T (*p + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p)[-2]); // { dg-warning "-Waddress" }
+ T (*p - i == 0); // { dg-warning "-Waddress" }
+ T (&(*p)[i] == 0); // { dg-warning "-Waddress" }
+
+
+ /* Similar to the above but for a pointer to a two-dimensional array,
+ referring to the higher-level element (i.e., an array itself). */
+ T (*p2 == 0);
+ T (**p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&**p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&***p2 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&**p2 == 0);
+
+ T (*p2 + 0 == 0); // { dg-warning "-Waddress" "pr102555" { xfail *-*-* } }
+ T (&(*p2)[0] == 0); // { dg-warning "-Waddress" }
+ T (&(*p2)[0][1] == 0); // { dg-warning "-Waddress" }
+ T (*p2 - 1 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[-1]); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[1][2]); // { dg-warning "-Waddress" }
+ T (*p2 + 2 == 0); // { dg-warning "-Waddress" }
+ T (0 == &(*p2)[-2]); // { dg-warning "-Waddress" }
+ T (*p2 - i == 0); // { dg-warning "-Waddress" }
+ T (&(*p2)[i] == 0); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Warray-compare-1.c b/gcc/testsuite/c-c++-common/Warray-compare-1.c
new file mode 100644
index 0000000..922396c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-compare-1.c
@@ -0,0 +1,44 @@
+/* PR c++/97573 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool
+g ()
+{
+ bool b = arr1 == arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 != arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 > arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 >= arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 < arr2; /* { dg-warning "comparison between two arrays" } */
+ b &= arr1 <= arr2; /* { dg-warning "comparison between two arrays" } */
+#ifdef __cplusplus
+ b &= +arr1 == +arr2;
+ b &= +arr1 != +arr2;
+ b &= +arr1 > +arr2;
+ b &= +arr1 >= +arr2;
+ b &= +arr1 < +arr2;
+ b &= +arr1 <= +arr2;
+#endif
+ b &= &arr1[0] == &arr2[0];
+ b &= &arr1[0] != &arr2[0];
+ b &= &arr1[0] > &arr2[0];
+ b &= &arr1[0] >= &arr2[0];
+ b &= &arr1[0] < &arr2[0];
+ b &= &arr1[0] <= &arr2[0];
+
+ b &= arr3 == arr4; /* { dg-warning "comparison between two arrays" } */
+
+#if defined(__cplusplus) && __cplusplus > 201703L
+ auto cmp = arr1 <=> arr2; /* { dg-error "invalid operands" "" { target c++20 } } */
+#endif
+ return b;
+}
diff --git a/gcc/testsuite/c-c++-common/Warray-compare-2.c b/gcc/testsuite/c-c++-common/Warray-compare-2.c
new file mode 100644
index 0000000..b3688e6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-compare-2.c
@@ -0,0 +1,44 @@
+/* PR c++/97573 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-array-compare" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool
+g ()
+{
+ bool b = arr1 == arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 != arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 > arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 >= arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 < arr2; /* { dg-bogus "comparison between two arrays" } */
+ b &= arr1 <= arr2; /* { dg-bogus "comparison between two arrays" } */
+#ifdef __cplusplus
+ b &= +arr1 == +arr2;
+ b &= +arr1 != +arr2;
+ b &= +arr1 > +arr2;
+ b &= +arr1 >= +arr2;
+ b &= +arr1 < +arr2;
+ b &= +arr1 <= +arr2;
+#endif
+ b &= &arr1[0] == &arr2[0];
+ b &= &arr1[0] != &arr2[0];
+ b &= &arr1[0] > &arr2[0];
+ b &= &arr1[0] >= &arr2[0];
+ b &= &arr1[0] < &arr2[0];
+ b &= &arr1[0] <= &arr2[0];
+
+ b &= arr3 == arr4; /* { dg-bogus "comparison between two arrays" } */
+
+#if defined(__cplusplus) && __cplusplus > 201703L
+ auto cmp = arr1 <=> arr2; /* { dg-error "invalid operands" "" { target c++20 } } */
+#endif
+ return b;
+}
diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
index 1d79930..7d29b5f 100644
--- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
@@ -190,7 +190,7 @@ void ga1__ (void)
struct A1 a = { 1 };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
@@ -207,7 +207,7 @@ void ga1_0_ (void)
struct A1 a = { 1, { } };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
@@ -221,10 +221,10 @@ void ga1_1 (void)
a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
- struct A1 a = { 0, { 1 } };
+ struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
a.a[0] = 0;
- a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+ a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
@@ -289,7 +289,7 @@ void ga1i__ (void)
struct A1i a = { 0 };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
@@ -306,7 +306,7 @@ void ga1i_0_ (void)
struct A1 a = { 0, { } };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
@@ -320,10 +320,10 @@ void ga1i_1 (void)
a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
- struct A1 a = { 0, { 1 } };
+ struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
a.a[0] = 1;
- a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
- a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
+ a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+ a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
sink (&a);
}
diff --git a/gcc/testsuite/c-c++-common/auto-init-1.c b/gcc/testsuite/c-c++-common/auto-init-1.c
new file mode 100644
index 0000000..84ba0a9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-1.c
@@ -0,0 +1,41 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-10.c b/gcc/testsuite/c-c++-common/auto-init-10.c
new file mode 100644
index 0000000..f35205f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-10.c
@@ -0,0 +1,22 @@
+/* Verify the variable attribute "uninitialized". */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored because" "is not a variable" } */
+extern int __attribute__ ((uninitialized)) boo1; /* { dg-warning "'uninitialized' attribute ignored because 'boo1' is not a local variable" } */
+static int __attribute__ ((uninitialized)) boo2; /* { dg-warning "'uninitialized' attribute ignored because 'boo2' is not a local variable" } */
+
+
+void foo()
+{
+ short temp1;
+ long long __attribute__ ((uninitialized)) temp2[10];
+ static int __attribute__ ((uninitialized)) boo3; /* { dg-warning "'uninitialized' attribute ignored because 'boo3' is not a local variable" } */
+
+
+ bar (temp1, temp2);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-11.c b/gcc/testsuite/c-c++-common/auto-init-11.c
new file mode 100644
index 0000000..a2d6690
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-11.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-12.c b/gcc/testsuite/c-c++-common/auto-init-12.c
new file mode 100644
index 0000000..f05d743
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-12.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-13.c b/gcc/testsuite/c-c++-common/auto-init-13.c
new file mode 100644
index 0000000..b0c0365
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-13.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+ member. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct a {
+ int b;
+ int array[];
+};
+union tar {
+ struct a bar;
+ char buf;
+};
+
+int foo()
+{
+ struct a d;
+ union tar var;
+ return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-14.c b/gcc/testsuite/c-c++-common/auto-init-14.c
new file mode 100644
index 0000000..986bb19
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-14.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+ member. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct a {
+ int b;
+ int array[];
+};
+union tar {
+ struct a bar;
+ char buf;
+};
+
+int foo()
+{
+ struct a d;
+ union tar var;
+ return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-15.c b/gcc/testsuite/c-c++-common/auto-init-15.c
new file mode 100644
index 0000000..aa9d7fa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-15.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+ int x[a][a];
+ g(x);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-16.c b/gcc/testsuite/c-c++-common/auto-init-16.c
new file mode 100644
index 0000000..86493ee
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-16.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+ int x[a][a];
+ g(x);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-2.c b/gcc/testsuite/c-c++-common/auto-init-2.c
new file mode 100644
index 0000000..69768d6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-2.c
@@ -0,0 +1,41 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-3.c b/gcc/testsuite/c-c++-common/auto-init-3.c
new file mode 100644
index 0000000..062d60c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-4.c b/gcc/testsuite/c-c++-common/auto-init-4.c
new file mode 100644
index 0000000..9d8f23e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-5.c b/gcc/testsuite/c-c++-common/auto-init-5.c
new file mode 100644
index 0000000..9c98a6e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-5.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), 2, 0\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-6.c b/gcc/testsuite/c-c++-common/auto-init-6.c
new file mode 100644
index 0000000..3fe2456
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-6.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), 1, 0\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-7.c b/gcc/testsuite/c-c++-common/auto-init-7.c
new file mode 100644
index 0000000..1998696
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-7.c
@@ -0,0 +1,35 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-8.c b/gcc/testsuite/c-c++-common/auto-init-8.c
new file mode 100644
index 0000000..9778e91
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-8.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-9.c b/gcc/testsuite/c-c++-common/auto-init-9.c
new file mode 100644
index 0000000..29acb7f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-9.c
@@ -0,0 +1,20 @@
+/* Verify the variable attribute "uninitialized". */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored because" "is not a variable" } */
+extern int __attribute__ ((uninitialized)) boo1; /* { dg-warning "'uninitialized' attribute ignored because 'boo1' is not a local variable" } */
+static int __attribute__ ((uninitialized)) boo2; /* { dg-warning "'uninitialized' attribute ignored because 'boo2' is not a local variable" } */
+
+void foo()
+{
+ short temp1;
+ long long __attribute__ ((uninitialized)) temp2[10];
+ static int __attribute__ ((uninitialized)) boo3; /* { dg-warning "'uninitialized' attribute ignored because 'boo3' is not a local variable" } */
+
+ bar (temp1, temp2);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-esra.c b/gcc/testsuite/c-c++-common/auto-init-esra.c
new file mode 100644
index 0000000..77ec023
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-esra.c
@@ -0,0 +1,35 @@
+/* Verify the strength reduction adjustment for -ftrivial-auto-var-init. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrivial-auto-var-init=zero -fdump-tree-gimple -fdump-tree-esra" } */
+
+
+typedef double VECTOR[3];
+
+enum
+{
+ X = 0,
+ Y = 1,
+ Z = 2,
+ T = 3
+};
+
+void Assign_Vector(VECTOR d, VECTOR s)
+{
+ d[X] = s[X];
+ d[Y] = s[Y];
+ d[Z] = s[Z];
+}
+
+void VCross(VECTOR a, const VECTOR b, const VECTOR c)
+{
+ VECTOR tmp;
+
+ tmp[X] = b[Y] * c[Z] - b[Z] * c[Y];
+ tmp[Y] = b[Z] * c[X] - b[X] * c[Z];
+ tmp[Z] = b[X] * c[Y] - b[Y] * c[X];
+
+ Assign_Vector(a, tmp);
+}
+
+/* { dg-final { scan-tree-dump-times "tmp = .DEFERRED_INIT \\(24, 2, 0\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times ".DEFERRED_INIT \\(8, 2, 0\\)" 3 "esra" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-1.c b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
new file mode 100644
index 0000000..83db8dd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
@@ -0,0 +1,23 @@
+/* Verify the padding initialization for pattern initialization, we always emit
+ * a call to __builtin_clear_padding to initialize the paddings to zero. */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+
+struct test_small_hole {
+ int one;
+ char two;
+ /* 3 byte padding hole here. */
+ int three;
+ unsigned long long four __attribute__((aligned (8)));
+};
+
+extern void g (struct test_small_hole);
+void foo(int a)
+{
+ struct test_small_hole s;
+ g(s);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(24, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "__builtin_clear_padding" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-2.c b/gcc/testsuite/c-c++-common/auto-init-padding-2.c
new file mode 100644
index 0000000..462f5ae
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-2.c
@@ -0,0 +1,114 @@
+/* To test that the compiler can fill all the paddings to zeroes for the
+ structures when the auto variable is partially initialized, fully
+ initialized, or not initialized for -ftrivial-auto-var-init=zero. */
+/* { dg-do run } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+/* Structure with no padding. */
+struct test_packed {
+ unsigned long one;
+ unsigned long two;
+ unsigned long three;
+ unsigned long four;
+} p1;
+
+/* Simple structure with padding likely to be covered by compiler. */
+struct test_small_hole {
+ unsigned long one;
+ char two;
+ /* 3 byte padding hole here. */
+ int three;
+ unsigned long four;
+} sh1;
+
+/* Try to trigger unhandled padding in a structure. */
+struct test_aligned {
+ unsigned int internal1;
+ unsigned long long internal2;
+} __attribute__((__aligned__(64)));
+
+struct test_aligned a1;
+
+struct test_big_hole {
+ unsigned char one;
+ unsigned char two;
+ unsigned char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__((__aligned__(64)));
+
+struct test_big_hole bh1;
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+} th1;
+
+__attribute__((noipa)) void
+foo (struct test_packed *p, struct test_small_hole *sh, struct test_aligned *a,
+ struct test_big_hole *bh, struct test_trailing_hole *th)
+{
+ p->one = 1; p->two = 2; p->three = 3; p->four = 4;
+ sh->one = 11; sh->two = 12; sh->three = 13; sh->four = 14;
+ a->internal1 = 21; a->internal2 = 22;
+ bh->one = 31; bh->two = 32; bh->three = 33;
+ bh->four.internal1 = 34; bh->four.internal2 = 35;
+ th->one = 0; th->two = 0; th->three = 0; th->four = 44;
+}
+
+int main ()
+{
+ struct test_packed p2;
+ struct test_small_hole sh2;
+ struct test_aligned a2;
+ struct test_big_hole bh2;
+ struct test_trailing_hole th2;
+
+ struct test_packed p3 = {.one = 1};
+ struct test_small_hole sh3 = {.two = 12};
+ struct test_aligned a3 = {.internal1 = 21};
+ struct test_big_hole bh3 = {.one = 31};
+ struct test_trailing_hole th3 = {.three = 0};
+
+ struct test_packed p4 = {.one = 1, .two = 2, .three = 3, .four = 4};
+ struct test_small_hole sh4 = {.one = 11, .two = 12, .three = 13, .four = 14};
+ struct test_aligned a4 = {.internal1 = 21, .internal2 = 22};
+ struct test_big_hole bh4 = {.one = 31, .two = 32, .three = 33};
+ struct test_trailing_hole th4 = {.one = 0, .two = 0, .three = 0, .four = 44};
+
+ foo (&p1, &sh1, &a1, &bh1, &th1);
+ foo (&p2, &sh2, &a2, &bh2, &th2);
+ foo (&p3, &sh3, &a3, &bh3, &th3);
+ bh4.four.internal1 = 34; bh4.four.internal2 = 35;
+
+ __builtin_clear_padding (&p1);
+ __builtin_clear_padding (&sh1);
+ __builtin_clear_padding (&a1);
+ __builtin_clear_padding (&bh1);
+ __builtin_clear_padding (&th1);
+
+ if (__builtin_memcmp (&p1, &p2, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh2, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a2, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh2, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th2, sizeof (th1)))
+ __builtin_abort ();
+ if (__builtin_memcmp (&p1, &p3, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh3, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a3, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh3, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th3, sizeof (th1)))
+ __builtin_abort ();
+ if (__builtin_memcmp (&p1, &p4, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh4, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a4, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh4, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th4, sizeof (th1)))
+ __builtin_abort ();
+
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-3.c b/gcc/testsuite/c-c++-common/auto-init-padding-3.c
new file mode 100644
index 0000000..2277014
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-3.c
@@ -0,0 +1,114 @@
+/* To test that the compiler can fill all the paddings to zeroes for the
+ structures when the auto variable is partially initialized, fully
+ initialized, or not initialized for -ftrivial-auto-var-init=pattern. */
+/* { dg-do run } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+/* Structure with no padding. */
+struct test_packed {
+ unsigned long one;
+ unsigned long two;
+ unsigned long three;
+ unsigned long four;
+} p1;
+
+/* Simple structure with padding likely to be covered by compiler. */
+struct test_small_hole {
+ unsigned long one;
+ char two;
+ /* 3 byte padding hole here. */
+ int three;
+ unsigned long four;
+} sh1;
+
+/* Try to trigger unhandled padding in a structure. */
+struct test_aligned {
+ unsigned int internal1;
+ unsigned long long internal2;
+} __attribute__((__aligned__(64)));
+
+struct test_aligned a1;
+
+struct test_big_hole {
+ unsigned char one;
+ unsigned char two;
+ unsigned char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__((__aligned__(64)));
+
+struct test_big_hole bh1;
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+} th1;
+
+__attribute__((noipa)) void
+foo (struct test_packed *p, struct test_small_hole *sh, struct test_aligned *a,
+ struct test_big_hole *bh, struct test_trailing_hole *th)
+{
+ p->one = 1; p->two = 2; p->three = 3; p->four = 4;
+ sh->one = 11; sh->two = 12; sh->three = 13; sh->four = 14;
+ a->internal1 = 21; a->internal2 = 22;
+ bh->one = 31; bh->two = 32; bh->three = 33;
+ bh->four.internal1 = 34; bh->four.internal2 = 35;
+ th->one = 0; th->two = 0; th->three = 0; th->four = 44;
+}
+
+int main ()
+{
+ struct test_packed p2;
+ struct test_small_hole sh2;
+ struct test_aligned a2;
+ struct test_big_hole bh2;
+ struct test_trailing_hole th2;
+
+ struct test_packed p3 = {.one = 1};
+ struct test_small_hole sh3 = {.two = 12};
+ struct test_aligned a3 = {.internal1 = 21};
+ struct test_big_hole bh3 = {.one = 31};
+ struct test_trailing_hole th3 = {.three = 0};
+
+ struct test_packed p4 = {.one = 1, .two = 2, .three = 3, .four = 4};
+ struct test_small_hole sh4 = {.one = 11, .two = 12, .three = 13, .four = 14};
+ struct test_aligned a4 = {.internal1 = 21, .internal2 = 22};
+ struct test_big_hole bh4 = {.one = 31, .two = 32, .three = 33};
+ struct test_trailing_hole th4 = {.one = 0, .two = 0, .three = 0, .four = 44};
+
+ foo (&p1, &sh1, &a1, &bh1, &th1);
+ foo (&p2, &sh2, &a2, &bh2, &th2);
+ foo (&p3, &sh3, &a3, &bh3, &th3);
+ bh4.four.internal1 = 34; bh4.four.internal2 = 35;
+
+ __builtin_clear_padding (&p1);
+ __builtin_clear_padding (&sh1);
+ __builtin_clear_padding (&a1);
+ __builtin_clear_padding (&bh1);
+ __builtin_clear_padding (&th1);
+
+ if (__builtin_memcmp (&p1, &p2, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh2, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a2, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh2, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th2, sizeof (th1)))
+ __builtin_abort ();
+ if (__builtin_memcmp (&p1, &p3, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh3, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a3, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh3, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th3, sizeof (th1)))
+ __builtin_abort ();
+ if (__builtin_memcmp (&p1, &p4, sizeof (p1))
+ || __builtin_memcmp (&sh1, &sh4, sizeof (sh1))
+ || __builtin_memcmp (&a1, &a4, sizeof (a1))
+ || __builtin_memcmp (&bh1, &bh4, sizeof (bh1))
+ || __builtin_memcmp (&th1, &th4, sizeof (th1)))
+ __builtin_abort ();
+
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-3.c b/gcc/testsuite/c-c++-common/cpp/va-opt-3.c
index 1a5a7b2..5b4f175 100644
--- a/gcc/testsuite/c-c++-common/cpp/va-opt-3.c
+++ b/gcc/testsuite/c-c++-common/cpp/va-opt-3.c
@@ -85,10 +85,10 @@ t25 f19 (f16 (), 1);
t26 f20 (f21 (), 2);
/* { dg-final { scan-file va-opt-3.i "t26 f17 h;" } } */
t27 f22 (, x);
-/* { dg-final { scan-file va-opt-3.i "t27 123;" } } */
+/* { dg-final { scan-file va-opt-3.i "t27 1 23;" } } */
t28 f23 (, x);
-/* { dg-final { scan-file va-opt-3.i "t28 123;" } } */
+/* { dg-final { scan-file va-opt-3.i "t28 1 23;" } } */
t29 f24 (, x);
-/* { dg-final { scan-file va-opt-3.i "t29 123;" } } */
+/* { dg-final { scan-file va-opt-3.i "t29 12 3;" } } */
t30 f25 (, x);
-/* { dg-final { scan-file va-opt-3.i "t30 123;" } } */
+/* { dg-final { scan-file va-opt-3.i "t30 12 3;" } } */
diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-7.c b/gcc/testsuite/c-c++-common/cpp/va-opt-7.c
new file mode 100644
index 0000000..06cdb25
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/va-opt-7.c
@@ -0,0 +1,101 @@
+/* PR preprocessor/101488 */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu99" { target c } } */
+/* { dg-options "-std=c++2a" { target c++ } } */
+
+#define f0() n
+#define f1(x,...) a ## __VA_OPT__ (a) ## a
+#define f2(x,...) a ## __VA_OPT__ () ## a
+#define f3(x,...) a ## __VA_OPT__ (x) ## a
+#define f4(x,...) a ## __VA_OPT__ (x##x) ## a
+#define f5(x,...) a ## __VA_OPT__ (x##x 1) ## a
+#define f6(x,...) a ## __VA_OPT__ (1 x##x) ## a
+#define f7(x,...) __VA_OPT__ (f0 x ## x ) ## 1
+#define f8(x,...) __VA_OPT__ (f0 x) ## 1
+#define f9(x,...) f0 ## __VA_OPT__ (x 1) ## 1
+#define f10(x,...) f0 ## __VA_OPT__ (x ## x 1) ## 1
+#define f11(x, ...) __VA_OPT__(a x ## x) ## b
+#define f12(x, ...) a ## __VA_OPT__(x ## x b)
+#define f13(x) x ## x b
+#define ab def
+#define bc ghi
+#define abc jkl
+#define f14(x, ...) a ## __VA_OPT__(x b x) ## c
+t1 f1(,);
+/* { dg-final { scan-file va-opt-7.i "t1 aa;" } } */
+t2 f1(,1);
+/* { dg-final { scan-file va-opt-7.i "t2 aaa;" } } */
+t3 f1(2,1);
+/* { dg-final { scan-file va-opt-7.i "t3 aaa;" } } */
+t4 f2(,);
+/* { dg-final { scan-file va-opt-7.i "t4 aa;" } } */
+t5 f2(,1);
+/* { dg-final { scan-file va-opt-7.i "t5 aa;" } } */
+t6 f2(2,1);
+/* { dg-final { scan-file va-opt-7.i "t6 aa;" } } */
+t7 f3(,);
+/* { dg-final { scan-file va-opt-7.i "t7 aa;" } } */
+t8 f3(,1);
+/* { dg-final { scan-file va-opt-7.i "t8 aa;" } } */
+t9 f3(2,1);
+/* { dg-final { scan-file va-opt-7.i "t9 a2a;" } } */
+t10 f4(,);
+/* { dg-final { scan-file va-opt-7.i "t10 aa;" } } */
+t11 f4(,1);
+/* { dg-final { scan-file va-opt-7.i "t11 aa;" } } */
+t12 f4(2,1);
+/* { dg-final { scan-file va-opt-7.i "t12 a22a;" } } */
+t13 f5(,);
+/* { dg-final { scan-file va-opt-7.i "t13 aa;" } } */
+t14 f5(,1);
+/* { dg-final { scan-file va-opt-7.i "t14 a 1a;" } } */
+t15 f5(2,1);
+/* { dg-final { scan-file va-opt-7.i "t15 a22 1a;" } } */
+t16 f6(,);
+/* { dg-final { scan-file va-opt-7.i "t16 aa;" } } */
+t17 f6(,1);
+/* { dg-final { scan-file va-opt-7.i "t17 a1 a;" } } */
+t18 f6(2,1);
+/* { dg-final { scan-file va-opt-7.i "t18 a1 22a;" } } */
+t19 f7(,);
+/* { dg-final { scan-file va-opt-7.i "t19 1;" } } */
+t20 f7(,1);
+/* { dg-final { scan-file va-opt-7.i "t20 f0 1;" } } */
+t21 f7(2,1);
+/* { dg-final { scan-file va-opt-7.i "t21 f0 221;" } } */
+t22 f8(,);
+/* { dg-final { scan-file va-opt-7.i "t22 1;" } } */
+t23 f8(,1);
+/* { dg-final { scan-file va-opt-7.i "t23 f0 1;" } } */
+t24 f8(2,1);
+/* { dg-final { scan-file va-opt-7.i "t24 f0 21;" } } */
+t25 f9(,);
+/* { dg-final { scan-file va-opt-7.i "t25 f01;" } } */
+t26 f9(,1);
+/* { dg-final { scan-file va-opt-7.i "t26 f0 11;" } } */
+t27 f9(2,1);
+/* { dg-final { scan-file va-opt-7.i "t27 f02 11;" } } */
+t28 f10(,);
+/* { dg-final { scan-file va-opt-7.i "t28 f01;" } } */
+t29 f10(,1);
+/* { dg-final { scan-file va-opt-7.i "t29 f0 11;" } } */
+t30 f10(2,1);
+/* { dg-final { scan-file va-opt-7.i "t30 f022 11;" } } */
+t31 f11(,);
+/* { dg-final { scan-file va-opt-7.i "t31 b;" } } */
+t32 f11(,1);
+/* { dg-final { scan-file va-opt-7.i "t32 a b;" } } */
+t33 f11(2,1);
+/* { dg-final { scan-file va-opt-7.i "t33 a 22b;" } } */
+t34 f12(,);
+/* { dg-final { scan-file va-opt-7.i "t34 a;" } } */
+t35 f12(,1);
+/* { dg-final { scan-file va-opt-7.i "t35 a b;" } } */
+t36 f12(2,1);
+/* { dg-final { scan-file va-opt-7.i "t36 a22 b;" } } */
+t37 f14(,);
+/* { dg-final { scan-file va-opt-7.i "t37 ac;" } } */
+t38 f14(,1);
+/* { dg-final { scan-file va-opt-7.i "t38 a b c;" } } */
+t39 f14(f13(),1);
+/* { dg-final { scan-file va-opt-7.i "t39 def b ghi;" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c b/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c
index 4d18f23..e1ab03e 100644
--- a/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c
+++ b/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c
@@ -37,7 +37,8 @@ foo ()
/* { 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 acq_rel" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp atomic release" 1 "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/gomp/allocate-6.c b/gcc/testsuite/c-c++-common/gomp/allocate-6.c
new file mode 100644
index 0000000..059fd72
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-6.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 (align (sizeof (int)) : x) allocate (allocator (omp_default_mem_alloc) : y) \
+ allocate (align (8), allocator ((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 (allocator (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 (allocator ((omp_allocator_handle_t)(omp_default_mem_alloc + 0)), align (16) : z) \
+ allocate (allocator (omp_default_mem_alloc) : x, y) allocate (align (32), allocator (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 (allocator (h):x)
+ ;
+ #pragma omp single allocate (align (2 * sizeof (int)), allocator (*&h) : x) private (x)
+ ;
+ #pragma omp parallel shared (r, x, z)
+ #pragma omp single firstprivate (r) allocate (align (4) : x, r, z) private (x, z)
+ ;
+ #pragma omp for allocate (align (2 * 2 * 2) : x) private (x)
+ for (i = 0; i < 64; i++)
+ x = 1;
+ #pragma omp sections private (x) allocate (allocator (omp_low_lat_mem_alloc), align (8): x)
+ {
+ x = 1;
+ #pragma omp section
+ x = 2;
+ #pragma omp section
+ x = 3;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (__alignof (r)) : r)
+ #pragma omp task in_reduction(+:r) allocate (align (2 * sizeof (r)), allocator (omp_default_mem_alloc) : r)
+ r += bar (r, &r, 0);
+ #pragma omp teams private (x) firstprivate (y) allocate (allocator (h), align (8) : x, y)
+ bar (x, y, 0);
+ #pragma omp taskloop lastprivate (x) reduction (+:r) allocate (align (16), allocator (h) : x, r)
+ for (i = 0; i < 16; i++)
+ {
+ r += bar (0, &r, 0);
+ x = i;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (64) : r)
+ #pragma omp taskloop firstprivate (x) in_reduction (+:r) \
+ allocate (allocator (omp_default_mem_alloc), align (128) : 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 (align (16), allocator (h): x)
+ x = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-7.c b/gcc/testsuite/c-c++-common/gomp/allocate-7.c
new file mode 100644
index 0000000..d125d92
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-7.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;
+
+int bar (int *);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int i;
+ #pragma omp parallel private (x) allocate (allocator (0.0) : x) /* { dg-error "'allocate' clause allocator expression has type 'double' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (allocator (0) : x) /* { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (z) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16.0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (14) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16), align (16) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+ #pragma omp parallel private (x) allocate (allocator (omp_default_mem_alloc), allocator (omp_default_mem_alloc) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-17.c b/gcc/testsuite/c-c++-common/gomp/atomic-17.c
index d313b29..001887e 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-17.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-17.c
@@ -22,8 +22,18 @@ foo ()
v = i = i + 1;
#pragma omp atomic read acquire
v = i;
+ #pragma omp atomic acq_rel read
+ v = i;
#pragma omp atomic release,write
i = v;
+ #pragma omp atomic write,acq_rel
+ i = v;
#pragma omp atomic hint(1),update,release
f = f + 2.0;
+ #pragma omp atomic update ,acquire
+ i = i + 1;
+ #pragma omp atomic acq_rel update
+ i = i + 1;
+ #pragma omp atomic acq_rel,hint(0)
+ i = i + 1;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-18.c b/gcc/testsuite/c-c++-common/gomp/atomic-18.c
index 95fbcd1..a8ed3c7 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-18.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-18.c
@@ -8,28 +8,16 @@ foo (int j)
i = i + 1;
#pragma omp atomic seq_cst release /* { dg-error "too many memory order clauses" } */
i = i + 1;
- #pragma omp atomic read,release /* { dg-error "incompatible with 'acq_rel' or 'release' clauses" } */
+ #pragma omp atomic read,release /* { dg-error "incompatible with 'release' clause" } */
v = i;
- #pragma omp atomic acq_rel read /* { dg-error "incompatible with 'acq_rel' or 'release' clauses" } */
- v = i;
- #pragma omp atomic write acq_rel /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
- i = v;
- #pragma omp atomic acquire , write /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
+ #pragma omp atomic acquire , write /* { dg-error "incompatible with 'acquire' clause" } */
i = v;
- #pragma omp atomic update ,acquire /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
- i = i + 1;
- #pragma omp atomic acq_rel update /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
- i = i + 1;
- #pragma omp atomic acq_rel,hint(0) /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
- i = i + 1;
- #pragma omp atomic acquire /* { dg-error "incompatible with 'acq_rel' or 'acquire' clauses" } */
- i = i + 1;
- #pragma omp atomic capture hint (0) capture /* { dg-error "too many atomic clauses" } */
+ #pragma omp atomic capture hint (0) capture /* { dg-error "too many 'capture' clauses" } */
v = i = i + 1;
#pragma omp atomic hint(j + 2) /* { dg-error "constant integer expression" } */
i = i + 1;
#pragma omp atomic hint(f) /* { dg-error "integ" } */
i = i + 1;
- #pragma omp atomic foobar /* { dg-error "expected 'read', 'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" } */
+ #pragma omp atomic foobar /* { dg-error "expected 'read', 'write', 'update', 'capture', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" } */
i = i + 1; /* { dg-error "expected end of line before" "" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-21.c b/gcc/testsuite/c-c++-common/gomp/atomic-21.c
index 8d052ae..12b1237 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-21.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-21.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-additional-options "-fdump-tree-original" } */
-/* { dg-final { scan-tree-dump-times "omp atomic release" 4 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic release" 2 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp atomic acq_rel" 2 "original" } } */
/* { dg-final { scan-tree-dump-times "omp atomic read acquire" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "omp atomic capture acq_rel" 1 "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-25.c b/gcc/testsuite/c-c++-common/gomp/atomic-25.c
new file mode 100644
index 0000000..653ef18
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-25.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+
+int x, r, z;
+double d, v;
+long double ld;
+
+void
+foo (int y, double e, long double f)
+{
+ #pragma omp atomic compare update seq_cst
+ x = x > y ? y : x;
+ #pragma omp atomic compare relaxed
+ d = e > d ? e : d;
+ #pragma omp atomic compare
+ d = f < d ? f : d;
+ #pragma omp atomic compare seq_cst fail(relaxed)
+ x = 12U < x ? 12U : x;
+ #pragma omp atomic compare
+ x = x == 7 ? 24 : x;
+ #pragma omp atomic compare
+ x = x == 123UL ? 256LL : x;
+ #pragma omp atomic compare
+ ld = ld == f ? f + 5.0L : ld;
+ #pragma omp atomic compare
+ if (x == 9) { x = 5; }
+ #pragma omp atomic compare
+ if (x > 5) { x = 5; }
+ #pragma omp atomic compare
+ if (7 > x) { x = 7; }
+ #pragma omp atomic compare update capture seq_cst fail(acquire)
+ v = d = f > d ? f : d;
+ #pragma omp atomic update capture compare
+ v = x = x < 24ULL ? 24ULL : x;
+ #pragma omp atomic compare, capture, update
+ v = x = x == e ? f : x;
+ #pragma omp atomic capture compare
+ { v = d; if (d > e) { d = e; } }
+ #pragma omp atomic compare capture
+ { if (e < d) { d = e; } v = d; }
+ #pragma omp atomic compare capture
+ { y = x; if (x == 42) { x = 7; } }
+ #pragma omp atomic capture compare weak
+ { if (x == 42) { x = 7; } y = x; }
+ #pragma omp atomic capture compare fail(seq_cst)
+ if (d == 8.0) { d = 16.0; } else { v = d; }
+ #pragma omp atomic capture compare
+ { r = x == 8; if (r) { x = 24; } }
+ #pragma omp atomic compare capture
+ { r = x == y; if (r) { x = y + 6; } else { z = x; } }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-26.c b/gcc/testsuite/c-c++-common/gomp/atomic-26.c
new file mode 100644
index 0000000..b7a4a1f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-26.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+
+int x;
+double d;
+
+double
+foo (int y, double e, long double f)
+{
+ double v;
+ #pragma omp atomic compare compare /* { dg-error "too many 'compare' clauses" } */
+ x = x > y ? y : x;
+ #pragma omp atomic compare fail(seq_cst) fail(seq_cst) /* { dg-error "too many 'fail' clauses" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare,fail(seq_cst),fail(relaxed) /* { dg-error "too many 'fail' clauses" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare weak weak /* { dg-error "too many 'weak' clauses" } */
+ d = d == e ? e + 1.0 : d;
+ #pragma omp atomic read capture /* { dg-error "'capture' clause is incompatible with 'read' or 'write' clauses" } */
+ v = d;
+ #pragma omp atomic capture, write /* { dg-error "'capture' clause is incompatible with 'read' or 'write' clauses" } */
+ d = v;
+ #pragma omp atomic read compare /* { dg-error "'compare' clause is incompatible with 'read' or 'write' clauses" } */
+ v = d;
+ #pragma omp atomic compare, write /* { dg-error "'compare' clause is incompatible with 'read' or 'write' clauses" } */
+ d = v;
+ #pragma omp atomic read fail(seq_cst) /* { dg-error "'fail' clause requires 'compare' clause" } */
+ v = d;
+ #pragma omp atomic fail(relaxed), write /* { dg-error "'fail' clause requires 'compare' clause" } */
+ d = v;
+ #pragma omp atomic fail(relaxed) update /* { dg-error "'fail' clause requires 'compare' clause" } */
+ d += 3.0;
+ #pragma omp atomic fail(relaxed) /* { dg-error "'fail' clause requires 'compare' clause" } */
+ d += 3.0;
+ #pragma omp atomic capture fail(relaxed) /* { dg-error "'fail' clause requires 'compare' clause" } */
+ v = d += 3.0;
+ #pragma omp atomic read weak /* { dg-error "'weak' clause requires 'compare' clause" } */
+ v = d;
+ #pragma omp atomic weak, write /* { dg-error "'weak' clause requires 'compare' clause" } */
+ d = v;
+ #pragma omp atomic weak update /* { dg-error "'weak' clause requires 'compare' clause" } */
+ d += 3.0;
+ #pragma omp atomic weak /* { dg-error "'weak' clause requires 'compare' clause" } */
+ d += 3.0;
+ #pragma omp atomic capture weak /* { dg-error "'weak' clause requires 'compare' clause" } */
+ v = d += 3.0;
+ #pragma omp atomic compare,weak /* { dg-error "'weak' clause requires atomic equality comparison" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail /* { dg-error "expected '\\\(' before end of line" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail( /* { dg-error "expected 'seq_cst', 'acquire' or 'relaxed' before end of line" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail() /* { dg-error "expected 'seq_cst', 'acquire' or 'relaxed' before '\\\)' token" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail(foobar) /* { dg-error "expected 'seq_cst', 'acquire' or 'relaxed' before 'foobar'" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail(acq_rel) /* { dg-error "expected 'seq_cst', 'acquire' or 'relaxed' before 'acq_rel'" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail(release) /* { dg-error "expected 'seq_cst', 'acquire' or 'relaxed' before 'release'" } */
+ d = e > d ? e : d;
+ #pragma omp atomic compare fail(seq_cst /* { dg-error "expected '\\\)' before end of line" } */
+ d = e > d ? e : d;
+ return v;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-27.c b/gcc/testsuite/c-c++-common/gomp/atomic-27.c
new file mode 100644
index 0000000..8f1e7e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-27.c
@@ -0,0 +1,41 @@
+/* PR middle-end/88968 */
+/* { dg-do compile } */
+
+struct __attribute__((packed)) S {
+ unsigned int a : 16;
+ unsigned int b : 1;
+} s;
+
+void
+foo (int y, int z)
+{
+ #pragma omp atomic compare
+ s.a = s.a == y ? z : s.a;
+}
+
+int
+bar (int y, int z)
+{
+ int r;
+ #pragma omp atomic compare capture
+ { r = s.a == y; if (r) { s.a = z; } }
+ return r;
+}
+
+int
+baz (int y, int z)
+{
+ int v;
+ #pragma omp atomic compare capture
+ if (s.a == y) { s.a = z; } else { v = s.a; }
+ return v;
+}
+
+int
+qux (int y, int z)
+{
+ int v;
+ #pragma omp atomic compare capture
+ v = s.a = s.a == y ? z : s.a;
+ return v;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-28.c b/gcc/testsuite/c-c++-common/gomp/atomic-28.c
new file mode 100644
index 0000000..853ae1c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-28.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -fdump-tree-ompexp" } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 4, 5, 5\\\);" 1 "ompexp" { target sync_int_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 4, 4, 2\\\);" 1 "ompexp" { target sync_int_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 260, 5, 0\\\);" 1 "ompexp" { target sync_int_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 4, 0, 0\\\);" 1 "ompexp" { target sync_int_long } } } */
+/* { dg-final { scan-tree-dump-not "__atomic_load_4 \\\(" "ompexp" { target sync_int_long } } } */
+
+int x;
+
+void
+foo (int y, int z)
+{
+ #pragma omp atomic compare seq_cst
+ x = x == y ? z : x;
+}
+
+int
+bar (int y, int z)
+{
+ int r;
+ #pragma omp atomic compare capture acq_rel fail (acquire)
+ { r = x == y; if (r) { x = z; } }
+ return r;
+}
+
+int
+baz (int y, int z)
+{
+ int v;
+ #pragma omp atomic compare capture seq_cst fail (relaxed) weak
+ if (x == y) { x = z; } else { v = x; }
+ return v;
+}
+
+int
+qux (int y, int z)
+{
+ int v;
+ #pragma omp atomic compare capture
+ v = x = x == y ? z : x;
+ return v;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-29.c b/gcc/testsuite/c-c++-common/gomp/atomic-29.c
new file mode 100644
index 0000000..1081e43
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-29.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -fdump-tree-ompexp" } */
+/* { dg-additional-options "-march=pentium" { target ia32 } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 8, 5, 5\\\);" 1 "ompexp" { target sync_long_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 8, 4, 2\\\);" 1 "ompexp" { target sync_long_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 264, 5, 0\\\);" 1 "ompexp" { target sync_long_long } } } */
+/* { dg-final { scan-tree-dump-times "\.ATOMIC_COMPARE_EXCHANGE \\\(\[^\n\r]*, 8, 0, 0\\\);" 1 "ompexp" { target sync_long_long } } } */
+/* { dg-final { scan-tree-dump-not "__atomic_load_8 \\\(" "ompexp" { target sync_long_long } } } */
+
+double x;
+
+void
+foo (double y, double z)
+{
+ #pragma omp atomic compare seq_cst
+ x = x == y ? z : x;
+}
+
+double
+bar (double y, double z)
+{
+ int r;
+ #pragma omp atomic compare capture acq_rel fail (acquire)
+ { r = x == y; if (r) { x = z; } }
+ return r;
+}
+
+double
+baz (double y, double z)
+{
+ double v;
+ #pragma omp atomic compare capture seq_cst fail (relaxed) weak
+ if (x == y) { x = z; } else { v = x; }
+ return v;
+}
+
+double
+qux (double y, double z)
+{
+ double v;
+ #pragma omp atomic compare capture
+ v = x = x == y ? z : x;
+ return v;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-30.c b/gcc/testsuite/c-c++-common/gomp/atomic-30.c
new file mode 100644
index 0000000..37a30bb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-30.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+
+int x;
+double d, g;
+
+void
+foo (int y, double e, long double f)
+{
+ double v;
+ int r, r2 = 0;
+ #pragma omp atomic capture compare
+ v = if (d == e) { d = f; }; /* { dg-error "expected expression" } */
+ #pragma omp atomic compare
+ if; /* { dg-error "expected '\\\(' before ';' token" } */
+ #pragma omp atomic compare
+ if (d >= e) { d = e; } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
+ #pragma omp atomic compare
+ if (d <= e) { d = e; } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
+ #pragma omp atomic compare
+ if (d != e) { d = e; } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
+ #pragma omp atomic compare
+ if (d + e) { d = e; } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" } */
+ #pragma omp atomic capture compare
+ { r = d >= e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d <= e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d > e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d < e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d != e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d + e; if (r) { d = f; } } /* { dg-error "expected '==', '<' or '>' comparison in 'if' condition" "" { target c } } */
+ #pragma omp atomic capture compare /* { dg-error "invalid form of '#pragma omp atomic' before 'd'" "" { target c++ } .-1 } */
+ { r = d == e; if (r2) { d = f; } } /* { dg-error "invalid form of '#pragma omp atomic compare' before '\{' token" } */
+ #pragma omp atomic capture compare
+ if (d > e) { d = e; } /* { dg-error "expected '==' comparison in 'if' condition" } */
+ #pragma omp atomic capture compare
+ if (d < e) { d = e; } /* { dg-error "expected '==' comparison in 'if' condition" } */
+ #pragma omp atomic compare
+ if (d < e) d = e; /* { dg-error "expected '\{' before 'd'" } */
+ #pragma omp atomic compare
+ if (d == e) d = e + 1.0; /* { dg-error "expected '\{' before 'd'" } */
+ #pragma omp atomic compare
+ if (d < e) { d += e; } /* { dg-error "expected '=' before '\\\+=' token" } */
+ #pragma omp atomic compare
+ if (d < e) { d = e }; /* { dg-error "expected ';' before '\}' token" } */
+ #pragma omp atomic compare
+ if (d < e) { d = e; e = 1.0; } /* { dg-error "expected '\}' before 'e'" } */
+ #pragma omp atomic compare
+ if (e == d) { d = f; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (e == d) { g = f; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (d < e) { g = e; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (d > e) { g = e; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (d < e) { d = g; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (d > e) { d = g; }; /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare
+ if (d == e) { d = f; } else ; /* { dg-error "unexpected 'else'" } */
+ #pragma omp atomic compare capture
+ { if (d == e) { d = f; } else { v = d; } v = d; } /* { dg-error "unexpected 'else'" } */
+ #pragma omp atomic compare
+ if (d < e) { d = e; } else { v = d; } /* { dg-error "unexpected 'else'" } */
+ #pragma omp atomic compare capture
+ if (d == e) { d = f; } else v = d; /* { dg-error "expected '\{' before 'v'" } */
+ #pragma omp atomic compare capture
+ if (d == e) { d = f; } else { v += d; } /* { dg-error "expected '=' before '\\\+=' token" } */
+ #pragma omp atomic compare capture
+ if (d == e) { d = f; } else { v = e; } /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" } */
+ #pragma omp atomic compare capture
+ if (d == e) { d = f; } else { v = d }; /* { dg-error "expected ';' before '\}' token" } */
+ #pragma omp atomic compare capture
+ if (d == e) { d = f; }; /* { dg-error "expected 'else' before ';' token" } */
+ #pragma omp atomic compare
+ x++; /* { dg-error "invalid form of 'pragma omp atomic compare'" } */
+ #pragma omp atomic compare
+ x--; /* { dg-error "invalid form of 'pragma omp atomic compare'" } */
+ #pragma omp atomic compare
+ ++x; /* { dg-error "invalid form of 'pragma omp atomic compare'" } */
+ #pragma omp atomic compare
+ --x; /* { dg-error "invalid form of 'pragma omp atomic compare'" } */
+ #pragma omp atomic compare
+ x += 3; /* { dg-error "expected '=' before '\\\+=' token" } */
+ #pragma omp atomic compare
+ x -= 5; /* { dg-error "expected '=' before '-=' token" } */
+ #pragma omp atomic compare
+ x *= 2; /* { dg-error "expected '=' before '\\\*=' token" } */
+ #pragma omp atomic compare
+ x |= 5; /* { dg-error "expected '=' before '\\\|=' token" } */
+ #pragma omp atomic compare
+ x &= ~5; /* { dg-error "expected '=' before '\\\&=' token" } */
+ #pragma omp atomic compare
+ x ^= 5; /* { dg-error "expected '=' before '\\\^=' token" } */
+ #pragma omp atomic compare
+ x = x + 3; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\+' token" "" { target c++ } .-1 } */
+ x = x - 5; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before '-' token" "" { target c++ } .-1 } */
+ x = 2 * x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+ x = 5 | x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+ x = x & ~5; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\&' token" "" { target c++ } .-1 } */
+ x = x | 5; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before '\\\|' token" "" { target c++ } .-1 } */
+ x = x >= 5 ? 5 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid operator for '#pragma omp atomic' before '>=' token" "" { target c++ } .-1 } */
+ x = x <= 5 ? 5 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid operator for '#pragma omp atomic' before '<=' token" "" { target c++ } .-1 } */
+ x = x != 5 ? 7 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid operator for '#pragma omp atomic' before '!=' token" "" { target c++ } .-1 } */
+ x = 5 == x ? 7 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic' before numeric constant" "" { target c++ } .-1 } */
+ x = x == 5 ? x : 7; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ x = x == 5 ? 9 : 7; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ x = x > 5 ? 6 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ x = x < 5 ? 6 : x; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ x = x > 5 ? x : 6; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic compare /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ x = x < 5 ? x : 6; /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ #pragma omp atomic capture /* { dg-error "invalid form of '#pragma omp atomic compare' before ';' token" "" { target c++ } .-1 } */
+ r = x == 5; /* { dg-error "invalid operator for '#pragma omp atomic' before '==' token" } */
+ #pragma omp atomic capture compare
+ r = x == 5; /* { dg-error "expected '=' before '==' token" } */
+ #pragma omp atomic capture compare /* { dg-error "'#pragma omp atomic compare capture' with non-integral comparison result" } */
+ { v = x == 5; if (v) { x = 6; } }
+ #pragma omp atomic compare capture
+ { r2 = x; x = y; } /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" } */
+ #pragma omp atomic compare capture
+ { r2 = x; x = y == 7 ? 12 : y; } /* { dg-error "invalid form of '#pragma omp atomic' before ';' token" "" { target c } } */
+ /* { dg-error "invalid form of '#pragma omp atomic' before 'y'" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c b/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
index 604caf0..a17f68d 100644
--- a/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
@@ -29,6 +29,12 @@ f1 (int *p)
#pragma omp for nowait nowait /* { dg-error "too many 'nowait' clauses" } */
for (i = 0; i < 8; ++i)
f0 ();
+ #pragma omp for schedule(static) order(concurrent) order(concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+ #pragma omp for schedule(static) order(reproducible:concurrent) order(unconstrained:concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
#pragma omp simd collapse(1) collapse(1) /* { dg-error "too many 'collapse' clauses" } */
for (i = 0; i < 8; ++i)
f0 ();
@@ -207,6 +213,18 @@ f1 (int *p)
f0 ();
#pragma omp scope nowait nowait /* { dg-error "too many 'nowait' clauses" } */
;
+ #pragma omp loop bind(thread) order(concurrent) order(concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+ #pragma omp loop bind(thread) order(reproducible:concurrent) order(unconstrained:concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+ #pragma omp simd order(concurrent) order(concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+ #pragma omp simd order(reproducible:concurrent) order(unconstrained:concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
}
#pragma omp declare simd simdlen (4) simdlen (4) /* { dg-error "too many 'simdlen' clauses" } */
@@ -223,3 +241,17 @@ void f6 (int a, int b);
void f7 (int a, int b);
#pragma omp declare simd linear (a) uniform (a) /* { dg-error "'a' appears more than once in data clauses" } */
void f8 (int a, int b);
+
+#pragma omp declare target
+void
+f9 (void)
+{
+ int i;
+ #pragma omp distribute dist_schedule(static) order(concurrent) order(concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+ #pragma omp loop bind(thread) order(reproducible:concurrent) order(unconstrained:concurrent) /* { dg-error "too many 'order' clauses" } */
+ for (i = 0; i < 8; ++i)
+ f0 ();
+}
+#pragma omp end declare target
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-1.c b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
index 378c7bf..742132f 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
@@ -66,14 +66,27 @@ 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) allocate (p)
+ lastprivate (l) schedule(static, 4) copyin(t) allocate (p)
+ for (int i = 0; i < 64; i++)
+ ll++;
+ #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) 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) allocate (f)
+ safelen(8) simdlen(4) aligned(q: 32) copyin(t) allocate (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) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp distribute simd \
@@ -156,7 +169,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
;
#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) \
+ shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) order(concurrent) \
collapse(1) dist_schedule(static, 16) nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f) in_reduction(+:r2)
for (int i = 0; i < 64; i++)
;
@@ -218,7 +231,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
#pragma omp target nowait depend(inout: dd[0]) in_reduction(+:r2)
#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) allocate (omp_default_mem_alloc: f)
+ collapse(1) dist_schedule(static, 16) allocate (omp_default_mem_alloc: f) order(concurrent)
for (int i = 0; i < 64; i++)
;
#pragma omp target
@@ -249,20 +262,36 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
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) \
+ collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) copyin(t) allocate (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) allocate (f)
+ for (int i = 0; i < 64; i++)
+ ll++;
#pragma omp teams distribute parallel for simd \
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) \
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 parallel for simd \
+ 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) \
+ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) \
+ 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) \
diff --git a/gcc/testsuite/c-c++-common/gomp/default-2.c b/gcc/testsuite/c-c++-common/gomp/default-2.c
new file mode 100644
index 0000000..6378e6e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/default-2.c
@@ -0,0 +1,67 @@
+int x;
+extern int z;
+
+void
+foo (void)
+{
+ int y = 0, i;
+ static int w;
+ #pragma omp task default(firstprivate) /* { dg-message "note: enclosing 'task'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
+ }
+ #pragma omp taskloop default(firstprivate) /* { dg-message "note: enclosing 'taskloop'" } */
+ for (i = 0; i < 64; i++)
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
+ }
+ #pragma omp teams default(firstprivate) /* { dg-message "note: enclosing 'teams'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
+ }
+ #pragma omp parallel default(firstprivate) /* { dg-message "note: enclosing 'parallel'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
+ }
+ #pragma omp task default(private) /* { dg-message "note: enclosing 'task'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
+ }
+ #pragma omp taskloop default(private) /* { dg-message "note: enclosing 'taskloop'" } */
+ for (i = 0; i < 64; i++)
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
+ }
+ #pragma omp teams default(private) /* { dg-message "note: enclosing 'teams'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
+ }
+ #pragma omp parallel default(private) /* { dg-message "note: enclosing 'parallel'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
+ x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
+ z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/default-3.c b/gcc/testsuite/c-c++-common/gomp/default-3.c
new file mode 100644
index 0000000..a742a71
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/default-3.c
@@ -0,0 +1,14 @@
+void
+foo (void)
+{
+ int i;
+ #pragma omp task default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
+ ;
+ #pragma omp taskloop default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp teams default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
+ ;
+ #pragma omp parallel default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/flush-1.c b/gcc/testsuite/c-c++-common/gomp/flush-1.c
index 7c3e529..717b951 100644
--- a/gcc/testsuite/c-c++-common/gomp/flush-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/flush-1.c
@@ -1,4 +1,5 @@
/* { dg-additional-options "-fdump-tree-gimple" } */
+/* { dg-final { scan-tree-dump "foo \\(6\\);\[\n\r]* __sync_synchronize \\(\\);\[\n\r]* foo \\(6\\);" "gimple" } } */
/* { dg-final { scan-tree-dump "foo \\(4\\);\[\n\r]* __atomic_thread_fence \\(4\\);\[\n\r]* foo \\(4\\);" "gimple" } } */
/* { dg-final { scan-tree-dump "foo \\(3\\);\[\n\r]* __atomic_thread_fence \\(3\\);\[\n\r]* foo \\(3\\);" "gimple" } } */
/* { dg-final { scan-tree-dump "foo \\(2\\);\[\n\r]* __atomic_thread_fence \\(2\\);\[\n\r]* foo \\(2\\);" "gimple" } } */
@@ -37,3 +38,11 @@ f4 (void)
#pragma omp flush
foo (5);
}
+
+void
+f5 (void)
+{
+ foo (6);
+ #pragma omp flush seq_cst
+ foo (6);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/flush-2.c b/gcc/testsuite/c-c++-common/gomp/flush-2.c
index 00baa8a..30ef598 100644
--- a/gcc/testsuite/c-c++-common/gomp/flush-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/flush-2.c
@@ -8,10 +8,11 @@ foo (void)
#pragma omp flush acquire
#pragma omp flush release
#pragma omp flush acq_rel
- #pragma omp flush relaxed /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */
- #pragma omp flush seq_cst /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */
- #pragma omp flush foobar /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */
+ #pragma omp flush seq_cst
+ #pragma omp flush relaxed /* { dg-error "expected 'seq_cst', 'acq_rel', 'release' or 'acquire'" } */
+ #pragma omp flush foobar /* { dg-error "expected 'seq_cst', 'acq_rel', 'release' or 'acquire'" } */
#pragma omp flush acquire (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */
#pragma omp flush release (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */
#pragma omp flush acq_rel (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */
+ #pragma omp flush seq_cst (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */
}
diff --git a/gcc/testsuite/c-c++-common/gomp/order-1.c b/gcc/testsuite/c-c++-common/gomp/order-1.c
index da4b73d..547d061 100644
--- a/gcc/testsuite/c-c++-common/gomp/order-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/order-1.c
@@ -29,6 +29,9 @@ f2 (int *a)
#pragma omp teams distribute parallel for simd order(concurrent)
for (i = 0; i < 128; i++)
a[i]++;
+ #pragma omp teams distribute order(concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
#pragma omp teams
{
#pragma omp distribute parallel for order(concurrent)
@@ -37,17 +40,11 @@ f2 (int *a)
#pragma omp distribute parallel for simd order(concurrent)
for (i = 0; i < 128; i++)
a[i]++;
+ #pragma omp distribute order(concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
}
#pragma omp taskloop simd order (concurrent)
for (i = 0; i < 128; i++)
a[i]++;
}
-
-void
-f3 (int *a)
-{
- int i;
- #pragma omp for order(concurrent) order(concurrent) order(concurrent)
- for (i = 0; i < 128; i++)
- a[i]++;
-}
diff --git a/gcc/testsuite/c-c++-common/gomp/order-2.c b/gcc/testsuite/c-c++-common/gomp/order-2.c
index 1a9adb0..5e044dc 100644
--- a/gcc/testsuite/c-c++-common/gomp/order-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/order-2.c
@@ -24,7 +24,7 @@ f2 (int *a)
{
int i;
#pragma omp teams
- #pragma omp distribute order(concurrent) /* { dg-error "'order' is not valid for '#pragma omp distribute'" } */
+ #pragma omp distribute order(concurrent)
for (i = 0; i < 128; i++)
a[i]++;
#pragma omp taskloop order (concurrent) /* { dg-error "'order' is not valid for '#pragma omp taskloop'" } */
diff --git a/gcc/testsuite/c-c++-common/gomp/order-5.c b/gcc/testsuite/c-c++-common/gomp/order-5.c
new file mode 100644
index 0000000..17cc8b5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/order-5.c
@@ -0,0 +1,101 @@
+void
+f1 (int *a)
+{
+ int i;
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp simd order ( reproducible : concurrent )
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp for simd order(reproducible :concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+}
+
+void
+f2 (int *a)
+{
+ int i;
+ #pragma omp parallel for order(reproducible: concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp parallel for simd order (reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute parallel for order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute parallel for simd order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams
+ {
+ #pragma omp distribute parallel for order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp distribute parallel for simd order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp distribute order(reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ }
+ #pragma omp taskloop simd order (reproducible:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+}
+
+void
+f3 (int *a)
+{
+ int i;
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp simd order ( unconstrained : concurrent )
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp for simd order(unconstrained :concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+}
+
+void
+f4 (int *a)
+{
+ int i;
+ #pragma omp parallel for order(unconstrained: concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp parallel for simd order (unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute parallel for order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute parallel for simd order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams distribute order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp teams
+ {
+ #pragma omp distribute parallel for order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp distribute parallel for simd order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ #pragma omp distribute order(unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+ }
+ #pragma omp taskloop simd order (unconstrained:concurrent)
+ for (i = 0; i < 128; i++)
+ a[i]++;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/order-6.c b/gcc/testsuite/c-c++-common/gomp/order-6.c
new file mode 100644
index 0000000..2127830
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/order-6.c
@@ -0,0 +1,412 @@
+void foo (void);
+int v;
+#ifdef __cplusplus
+extern "C" {
+#endif
+int omp_get_thread_num (void);
+int omp_get_num_threads (void);
+int omp_target_is_present (const void *, int);
+int omp_get_cancellation (void);
+#ifdef __cplusplus
+}
+#endif
+
+void
+f1 (int *a)
+{
+ int i;
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
+
+void
+f2 (int *a)
+{
+ int i;
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
+
+void
+f3 (int *a)
+{
+ int i;
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel
+ foo ();
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp task /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ a[i]++;
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp taskloop /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(reproducible:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
+
+void
+f4 (int *a)
+{
+ int i;
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
+
+void
+f5 (int *a)
+{
+ int i;
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */
+ foo ();
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for simd order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
+
+void
+f6 (int *a)
+{
+ int i;
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp parallel
+ foo ();
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp simd
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ foo ();
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ v++;
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic read /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */
+ v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp task /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ a[i]++;
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp taskloop /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */
+ for (j = 0; j < 64; j++)
+ a[64 * i + j] = i + j;
+ }
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+ #pragma omp for order(unconstrained:concurrent)
+ for (i = 0; i < 64; i++)
+ a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr102640.c b/gcc/testsuite/c-c++-common/gomp/pr102640.c
new file mode 100644
index 0000000..00ebab9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr102640.c
@@ -0,0 +1,44 @@
+/* PR c++/102640 */
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple -fdump-tree-omplower" } */
+/* Verify var[123] are mapped without any copying, because they are
+ mentioned in declare target directive to clauses. */
+/* { dg-final { scan-tree-dump-not "firstprivate\\\(var\[123]\\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not ".omp_data_arr.\[0-9]*.var" "omplower" } } */
+/* { dg-final { scan-tree-dump-not ".omp_data_i->var" "omplower" } } */
+
+void
+foo (void)
+{
+ extern int var1;
+ #pragma omp declare target to (var1)
+
+ #pragma omp target
+ var1++;
+}
+
+int
+bar (int x)
+{
+ extern int var2;
+ #pragma omp declare target to (var2)
+ if (x)
+ return var2;
+ #pragma omp target
+ var2++;
+ return -1;
+}
+#pragma omp declare target to (bar)
+
+#pragma omp declare target
+int
+baz (int x)
+{
+ extern int var3;
+ if (x)
+ return var3;
+ #pragma omp target
+ var3++;
+ return -1;
+}
+#pragma omp end declare target
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-3.c b/gcc/testsuite/c-c++-common/gomp/scope-3.c
new file mode 100644
index 0000000..78bb1a3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scope-3.c
@@ -0,0 +1,21 @@
+/* PR middle-end/102415 */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+void
+foo (void)
+{
+ #pragma omp scope nowait
+ abort ();
+}
+
+void
+bar (void)
+{
+ #pragma omp scope
+ abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-4.c b/gcc/testsuite/c-c++-common/gomp/scope-4.c
new file mode 100644
index 0000000..924ae9c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scope-4.c
@@ -0,0 +1,11 @@
+/* PR middle-end/102504 */
+/* { dg-do compile } */
+
+int
+foo ()
+{
+ int r = 0;
+ #pragma omp scope reduction(+:r) /* { dg-error "reduction variable 'r' is private in outer context" } */
+ r++;
+ return r;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/sections1.c b/gcc/testsuite/c-c++-common/gomp/sections1.c
index 8c8ab91..417d205 100644
--- a/gcc/testsuite/c-c++-common/gomp/sections1.c
+++ b/gcc/testsuite/c-c++-common/gomp/sections1.c
@@ -50,7 +50,7 @@ foo ()
#pragma omp sections
{
bar (12);
- bar (13); /* { dg-error "pragma omp section" } */
+ bar (13);
#pragma omp section
bar (14);
}
@@ -63,11 +63,29 @@ foo ()
bar (15);
#pragma omp section
bar (16);
- bar (17); /* { dg-error "pragma omp section" } */
+ bar (17);
}
#pragma omp sections
{
bar (18);
#pragma omp section
} /* { dg-error "expression before" } */
+ #pragma omp sections
+ {
+ #pragma omp section
+ #pragma omp section /* { dg-error "may only be used in" } */
+ bar (19);
+ }
+ #pragma omp sections
+ {
+ bar (20);
+ #pragma omp section
+ #pragma omp section /* { dg-error "may only be used in" } */
+ bar (21);
+ }
+ #pragma omp sections
+ {
+ bar (22);
+ #pragma omp section
+ } /* { dg-error "expression before" } */
}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-1.c b/gcc/testsuite/c-c++-common/gomp/target-device-1.c
new file mode 100644
index 0000000..9822862
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+
+void
+foo (int n)
+{
+ /* Test to ensure that 'device_num' is parsed correctly in device clauses. */
+
+ #pragma omp target device (1)
+ ;
+
+ #pragma omp target device (n)
+ ;
+
+ #pragma omp target device (n + 1)
+ ;
+
+ #pragma omp target device (device_num : 1)
+ ;
+
+ #pragma omp target device (device_num : n)
+ ;
+
+ #pragma omp target device (device_num : n + 1)
+ ;
+
+ #pragma omp target device (invalid : 1) /* { dg-error "expected 'ancestor' or 'device_num'" "" { target *-*-* } } */
+ /* { dg-error "expected '\\)' before 'invalid'" "" { target c } .-1 } */
+ ;
+
+ #pragma omp target device (device_num : n, n) /* { dg-error "expected '\\)' before ','" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-2.c b/gcc/testsuite/c-c++-common/gomp/target-device-2.c
new file mode 100644
index 0000000..b711ea1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+ /* Test to ensure that device-modifier 'device_num' is parsed correctly in
+ device clauses. */
+
+void
+foo (void)
+{
+ #pragma omp target device (device_num : 42)
+ ;
+}
+
+/* { dg-final { scan-tree-dump "pragma omp target \[^\n\r)]*device\\(42\\)" "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-1.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-1.c
new file mode 100644
index 0000000..b3c1ce8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+ /* Ensure that a 'requires' directive with the 'reverse_offload' clause was
+ specified. */
+
+ #pragma omp target device (ancestor : 1) /* { dg-error "'ancestor' device modifier not preceded by 'requires' directive with 'reverse_offload' clause" } */
+ /* { dg-error "expected '\\)' before 'ancestor'" "" { target c } .-1 } */
+
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-2.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-2.c
new file mode 100644
index 0000000..cf05c50
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-2.c
@@ -0,0 +1,82 @@
+/* { dg-do compile } */
+
+#pragma omp requires reverse_offload /* { dg-message "sorry, unimplemented: 'reverse_offload' clause on 'requires' directive not supported yet" } */
+
+void
+foo (int n)
+{
+ /* The following test is marked with 'xfail' because a previous 'sorry' from
+ 'reverse_offload' suppresses the 'sorry' for 'ancestor'. */
+ #pragma omp target device (ancestor: 1) /* { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } } */
+ ;
+
+
+ /* Ensure that the integer expression in the 'device' clause for
+ device-modifier 'ancestor' evaluates to '1' in case of a constant. */
+
+ #pragma omp target device (ancestor : 1)
+ ;
+ #pragma omp target device (ancestor : 42) /* { dg-error "the 'device' clause expression must evaluate to '1'" } */
+ ;
+
+ #pragma omp target device (ancestor : n) /* { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } } */
+ ;
+ #pragma omp target device (ancestor : n + 1) /* { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } } */
+ ;
+
+
+ /* Ensure that only one 'device' clause appears on the construct. */
+
+ #pragma omp target device (17) device (42) /* { dg-error "too many 'device' clauses" } */
+ ;
+
+
+ /* Ensure that with 'ancestor' only the 'device', 'firstprivate', 'private',
+ 'defaultmap', and 'map' clauses appear on the construct. */
+
+ #pragma omp target nowait device (ancestor: 1) /* { dg-error "with 'ancestor', only the 'device', 'firstprivate', 'private', 'defaultmap', and 'map' clauses may appear on the construct" } */
+ ;
+ #pragma omp target device (ancestor: 1) nowait /* { dg-error "with 'ancestor', only the 'device', 'firstprivate', 'private', 'defaultmap', and 'map' clauses may appear on the construct" } */
+ ;
+ #pragma omp target nowait device (42)
+ ;
+ #pragma omp target nowait device (device_num: 42)
+ ;
+
+ int a = 0, b = 0, c = 0;
+ #pragma omp target device (ancestor: 1) firstprivate (a) private (b) defaultmap (none) map (c)
+ ;
+
+
+ /* Ensure that 'ancestor' is only used with 'target' constructs (not with
+ 'target data', 'target update' etc.). */
+
+ #pragma omp target data map (a) device (ancestor: 1) /* { dg-error "'device' clause with 'ancestor' is only allowed on 'target' construct" } */
+ ;
+ #pragma omp target enter data map (to: a) device (ancestor: 1) /* { dg-error "'device' clause with 'ancestor' is only allowed on 'target' construct" } */
+ #pragma omp target exit data map (from: a) device (ancestor: 1) /* { dg-error "'device' clause with 'ancestor' is only allowed on 'target' construct" } */
+ #pragma omp target update to (a) device (ancestor: 1) /* { dg-error "'device' clause with 'ancestor' is only allowed on 'target' construct" "" { target *-*-* } } */
+
+
+ /* Ensure that no OpenMP constructs appear inside target regions with
+ 'ancestor'. */
+
+ #pragma omp target device (ancestor: 1)
+ {
+ #pragma omp teams /* { dg-error "OpenMP constructs are not allowed in target region with 'ancestor'" } */
+ ;
+ }
+
+ #pragma omp target device (device_num: 1)
+ {
+ #pragma omp teams
+ ;
+ }
+
+ #pragma omp target device (1)
+ {
+ #pragma omp teams
+ ;
+ }
+
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c
new file mode 100644
index 0000000..5e3a478
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c
@@ -0,0 +1,37 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int omp_get_num_teams (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* { dg-do compile } */
+
+#pragma omp requires reverse_offload /* { dg-message "sorry, unimplemented: 'reverse_offload' clause on 'requires' directive not supported yet" } */
+
+void
+foo (void)
+{
+ /* Ensure that no calls to OpenMP API runtime routines are allowed inside the
+ corresponding target region. */
+
+ int a;
+
+ #pragma omp target device (ancestor: 1)
+ {
+ a = omp_get_num_teams (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_teams\[^\n\r]*' in a region with 'device\\(ancestor\\)' clause" } */
+ }
+
+ #pragma omp target device (device_num: 1)
+ {
+ a = omp_get_num_teams ();
+ }
+
+ #pragma omp target device (1)
+ {
+ a = omp_get_num_teams ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c
new file mode 100644
index 0000000..b4b5620
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+ /* Test to ensure that device-modifier 'ancestor' is parsed correctly in
+ device clauses. */
+
+#pragma omp requires reverse_offload /* { dg-message "sorry, unimplemented: 'reverse_offload' clause on 'requires' directive not supported yet" } */
+
+void
+foo (void)
+{
+ #pragma omp target device (ancestor: 1) /* { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } } */
+ ;
+
+}
+
+/* { dg-final { scan-tree-dump "pragma omp target \[^\n\r)]*device\\(ancestor:1\\)" "original" } } */
diff --git a/gcc/testsuite/c-c++-common/pr102285.c b/gcc/testsuite/c-c++-common/pr102285.c
new file mode 100644
index 0000000..644054b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr102285.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=zero -Wuninitialized" } */
+
+int
+qy (void)
+{
+ int tw = 4;
+ int fb[tw];
+ return fb[2]; /* { dg-warning "uninitialized" } */
+}
diff --git a/gcc/testsuite/c-c++-common/pr19807-2.c b/gcc/testsuite/c-c++-common/pr19807-2.c
index d2c0101..529b9c9 100644
--- a/gcc/testsuite/c-c++-common/pr19807-2.c
+++ b/gcc/testsuite/c-c++-common/pr19807-2.c
@@ -1,5 +1,4 @@
-/* Some targets can optimize this on RTL. */
-/* { dg-do link { target { x86_64-*-* i?86-*-* } } } */
+/* { dg-do link } */
/* { dg-options "-O -fdump-tree-optimized" } */
extern void link_error(void);
@@ -12,4 +11,4 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump-not "link_error" "optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr19807-3.c b/gcc/testsuite/c-c++-common/pr19807-3.c
index bb7f982..31c88f3 100644
--- a/gcc/testsuite/c-c++-common/pr19807-3.c
+++ b/gcc/testsuite/c-c++-common/pr19807-3.c
@@ -1,5 +1,4 @@
-/* Some targets can optimize this on RTL. */
-/* { dg-do link { target { x86_64-*-* i?86-*-* } } } */
+/* { dg-do link } */
/* { dg-options "-O -fdump-tree-optimized" } */
extern void link_error(void);
@@ -12,4 +11,4 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump-not "link_error" "optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr57371-4.c b/gcc/testsuite/c-c++-common/pr57371-4.c
index f43f7c2..d938ecd 100644
--- a/gcc/testsuite/c-c++-common/pr57371-4.c
+++ b/gcc/testsuite/c-c++-common/pr57371-4.c
@@ -13,25 +13,25 @@ void nonfinite(unsigned short x) {
{
volatile int nonfinite_1;
nonfinite_1 = (float) x > QNAN;
- /* { dg-final { scan-tree-dump "nonfinite_1 = \\(float\\)" "original" } } */
+ /* { dg-final { scan-tree-dump "nonfinite_1 = 0" "original" } } */
}
{
volatile int nonfinite_2;
nonfinite_2 = (float) x >= QNAN;
- /* { dg-final { scan-tree-dump "nonfinite_2 = \\(float\\)" "original" } } */
+ /* { dg-final { scan-tree-dump "nonfinite_2 = 0" "original" } } */
}
{
volatile int nonfinite_3;
nonfinite_3 = (float) x < QNAN;
- /* { dg-final { scan-tree-dump "nonfinite_3 = \\(float\\)" "original" } } */
+ /* { dg-final { scan-tree-dump "nonfinite_3 = 0" "original" } } */
}
{
volatile int nonfinite_4;
nonfinite_4 = (float) x <= QNAN;
- /* { dg-final { scan-tree-dump "nonfinite_4 = \\(float\\)" "original" } } */
+ /* { dg-final { scan-tree-dump "nonfinite_4 = 0" "original" } } */
}
{
diff --git a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
index 746afa7..09ac7c7 100644
--- a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
+++ b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c
@@ -31,5 +31,4 @@ int main() {
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Atomic write of size 4.*" } */
-/* { dg-output " #0 __tsan_atomic32_fetch_add.*" } */
-/* { dg-output " #1 Thread1.*" } */
+/* { dg-output " #0 Thread1.*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
index 266423a..1d51e35 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-overflow" } */
#include <limits.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
index 02162e1..ef431c9 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -Wno-overflow" } */
#define INT_MIN (-__INT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
index bb391c5..853a3dc 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fsanitize=integer-divide-by-zero" } */
+/* { dg-options "-fsanitize=signed-integer-overflow" } */
void
foo (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c
new file mode 100644
index 0000000..61d050a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=float-divide-by-zero -fno-sanitize-recover=float-divide-by-zero -fsanitize-recover=integer-divide-by-zero" } */
+
+int
+main (void)
+{
+ volatile float a = 1.3f;
+ volatile double b = 0.0;
+ volatile int c = 4;
+ volatile float res;
+
+ res = a / b;
+
+ return 0;
+}
+
+/* { dg-output "division by zero" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c
new file mode 100644
index 0000000..d781660
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -fno-sanitize-recover=undefined,float-divide-by-zero -Wno-overflow" } */
+
+#include <limits.h>
+
+int
+main (void)
+{
+ volatile int min = INT_MIN;
+ volatile int zero = 0;
+
+ INT_MIN / -1;
+ min / -1;
+ min / (10 * zero - (2 - 1));
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c
new file mode 100644
index 0000000..dfef1b0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=integer-divide-by-zero" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+ return x / y;
+}
+
+void
+handler (int i)
+{
+ if (cnt++ != 0)
+ exit (0);
+ volatile int b = foo (5, 0);
+ exit (0);
+}
+
+int
+main (void)
+{
+ struct sigaction s;
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = handler;
+ s.sa_flags = 0;
+ sigaction (SIGFPE, &s, NULL);
+ volatile int a = foo (INT_MIN, -1);
+ cnt++;
+ volatile int b = foo (5, 0);
+ return 0;
+}
+
+/* { dg-output "division of -2147483648 by -1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c
new file mode 100644
index 0000000..479dffb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+ return x / y;
+}
+
+void
+handler (int i)
+{
+ if (cnt++ != 0)
+ exit (0);
+ volatile int b = foo (INT_MIN, -1);
+ exit (0);
+}
+
+int
+main (void)
+{
+ struct sigaction s;
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = handler;
+ s.sa_flags = 0;
+ sigaction (SIGFPE, &s, NULL);
+ volatile int a = foo (42, 0);
+ cnt++;
+ volatile int b = foo (INT_MIN, -1);
+ return 0;
+}
+
+/* { dg-output "division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type 'int'" } */
diff --git a/gcc/testsuite/g++.dg/Walloca2.C b/gcc/testsuite/g++.dg/Walloca2.C
new file mode 100644
index 0000000..b6992d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/Walloca2.C
@@ -0,0 +1,6 @@
+// { dg-do compile }
+// { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2 --param ggc-min-heapsize=0 --param ggc-min-expand=0 -w" }
+// { dg-require-effective-target alloca }
+
+int a;
+char *b = static_cast<char *>(__builtin_alloca (a));
diff --git a/gcc/testsuite/g++.dg/abi/anon4.C b/gcc/testsuite/g++.dg/abi/anon4.C
index 088ba99..8200f4b 100644
--- a/gcc/testsuite/g++.dg/abi/anon4.C
+++ b/gcc/testsuite/g++.dg/abi/anon4.C
@@ -1,4 +1,5 @@
// PR c++/65209
+// { dg-additional-options "-fno-pie" { target sparc*-*-* } }
// { dg-final { scan-assembler-not "comdat" } }
// Everything involving the anonymous namespace bits should be private, not
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
new file mode 100644
index 0000000..4300223
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+#include "uninit-pred-1_a.C"
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
new file mode 100644
index 0000000..5551060
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+#include "uninit-pred-2_a.C"
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
new file mode 100644
index 0000000..d6ab4f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+#include "uninit-pred-3_a.C"
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
new file mode 100644
index 0000000..4747d28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Og -ftrivial-auto-var-init=zero" } */
+#include "uninit-pred-4.C"
diff --git a/gcc/testsuite/g++.dg/coroutines/pr100673.C b/gcc/testsuite/g++.dg/coroutines/pr100673.C
new file mode 100644
index 0000000..750ce66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr100673.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fsyntax-only -w" }
+
+// Diagnose bad coroutine awatiable type.
+
+#include<coroutine>
+
+struct coro{
+ struct not_a_template{};
+ using promise_type = coro;
+ static constexpr std::suspend_always initial_suspend()noexcept{ return {}; }
+ constexpr bool await_ready()noexcept{ return false; }
+ constexpr not_a_template await_suspend(std::coroutine_handle<>)noexcept{ return{}; }
+ constexpr void await_resume()noexcept{}
+ static coro body()
+ {
+ co_await coro{}; // { dg-error {'await_suspend' must return 'void', 'bool' or a coroutine handle} }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/coroutines/pr101133.C b/gcc/testsuite/g++.dg/coroutines/pr101133.C
new file mode 100644
index 0000000..6c6bc16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr101133.C
@@ -0,0 +1,31 @@
+#include <coroutine>
+#include <string>
+
+template<typename T>
+struct Awaiter
+{
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<>) const {}
+ T await_resume() const { return T{}; }
+};
+
+struct ReturnObject
+{
+ struct promise_type
+ {
+ ReturnObject get_return_object() { return {}; }
+ std::suspend_never initial_suspend() noexcept { return {}; }
+ std::suspend_never final_suspend() noexcept { return {}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+ReturnObject f()
+{
+ auto a1 = Awaiter<int>{};
+ auto a2 = Awaiter<std::string>{};
+
+ [[maybe_unused]] auto v1 = co_await a1; // ok
+ [[maybe_unused]] std::string v2 = co_await a2; // error
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr101765.C b/gcc/testsuite/g++.dg/coroutines/pr101765.C
new file mode 100644
index 0000000..49a49d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr101765.C
@@ -0,0 +1,45 @@
+// We cannot compile this yet, much run it - but one day it might be
+// feasible, so do the minimum for now.
+// { dg-additional-options " -fsyntax-only -Wno-vla" }
+
+#include "coro.h"
+
+// boiler-plate for tests of codegen
+#include "coro1-ret-int-yield-int.h"
+
+struct coro1
+foo (int arg) noexcept
+{
+ PRINTF ("foo arg = %d\n", arg);
+ char arr[arg]; /* { dg-message "sorry, unimplemented: variable length arrays are not yet supported in coroutines" "" { target *-*-* } } */
+ if (arg < 4)
+ co_return -6174;
+ else
+ for (int i = 0; i < arg; ++i) arr[i] = (char) i;
+ co_yield (int) arr[2];
+ co_return (int) arr[3];
+}
+
+int main ()
+{
+ PRINT ("main: create coro1");
+ struct coro1 x = foo (10);
+ PRINT ("main: got coro1 - resuming");
+ if (x.handle.done())
+ abort();
+ x.handle.resume();
+ PRINT ("main: after resume");
+ int y = x.handle.promise().get_value();
+ if ( y == -6174 )
+ {
+ PRINT ("main: saw -6174");
+ return 1;
+ }
+ else if ( y != 2 )
+ abort;
+ x.handle.resume();
+ y = x.handle.promise().get_value();
+ if ( y != 3 )
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr102454.C b/gcc/testsuite/g++.dg/coroutines/pr102454.C
new file mode 100644
index 0000000..41aeda7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr102454.C
@@ -0,0 +1,38 @@
+// { dg-additional-options "-fno-exceptions" }
+
+#include <coroutine>
+#include <string>
+
+template <typename T>
+struct looper {
+ struct promise_type {
+ auto get_return_object () { return handle_type::from_promise (*this); }
+ auto initial_suspend () { return suspend_always_prt {}; }
+ auto final_suspend () noexcept { return suspend_always_prt {}; }
+ void return_value (T);
+ void unhandled_exception ();
+ };
+
+ using handle_type = std::coroutine_handle<promise_type>;
+
+ looper (handle_type);
+
+ struct suspend_always_prt {
+ bool await_ready () noexcept;
+ void await_suspend (handle_type) noexcept;
+ void await_resume () noexcept;
+ };
+};
+
+template <typename T>
+looper<T>
+with_ctorable_state (T)
+{
+ co_return T ();
+}
+
+auto
+foo ()
+{
+ return with_ctorable_state<std::string>;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr99575.C b/gcc/testsuite/g++.dg/coroutines/pr99575.C
new file mode 100644
index 0000000..d5f86c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr99575.C
@@ -0,0 +1,35 @@
+
+#include <coroutine>
+
+class Task {
+ public:
+ struct promise_type {
+ Task get_return_object() { return Task{}; }
+ std::suspend_always initial_suspend() { return {}; }
+ std::suspend_always final_suspend() noexcept { return {}; }
+ void unhandled_exception() {}
+ void return_void() {}
+ };
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void> continuation) {}
+ void await_resume() {}
+};
+
+class NonMoveableTask {
+ public:
+ NonMoveableTask() = default;
+ NonMoveableTask(const NonMoveableTask&) = delete;
+ NonMoveableTask(NonMoveableTask&&) = delete;
+
+ NonMoveableTask& operator=(const NonMoveableTask&) = delete;
+ NonMoveableTask& operator=(NonMoveableTask&& other) = delete;
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void>) {}
+ void await_resume() {}
+};
+
+Task Foo(NonMoveableTask* task) { co_await* task; }
+
+int main() {}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr99710.C b/gcc/testsuite/g++.dg/coroutines/pr99710.C
new file mode 100644
index 0000000..e4f7116
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr99710.C
@@ -0,0 +1,25 @@
+#include <coroutine>
+
+struct task {
+ struct promise_type {
+ std::suspend_always initial_suspend();
+ std::suspend_always final_suspend() noexcept;
+ task get_return_object();
+ void return_void();
+ void unhandled_exception();
+ };
+};
+
+task
+my_coro ()
+{
+ try
+ { }
+ catch (...)
+ {
+ // [expr.await] An await-expression shall appear only in a potentially-
+ // evaluated expression within the compound-statement of a function-body
+ // outside of a handler
+ co_await std::suspend_always{}; // { dg-error "await expressions are not permitted in handlers" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-1.C b/gcc/testsuite/g++.dg/cpp/elifdef-1.C
new file mode 100644
index 0000000..f7965e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-1.C
@@ -0,0 +1,3 @@
+// { dg-do preprocess { target { ! c++23 } } }
+
+#include "../../gcc.dg/cpp/c11-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-2.C b/gcc/testsuite/g++.dg/cpp/elifdef-2.C
new file mode 100644
index 0000000..6408271
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-2.C
@@ -0,0 +1,4 @@
+// P2334R1
+// { dg-do preprocess { target c++23 } }
+
+#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-3.C b/gcc/testsuite/g++.dg/cpp/elifdef-3.C
new file mode 100644
index 0000000..d9acce0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-3.C
@@ -0,0 +1,62 @@
+// P2334R1
+// { dg-do preprocess { target c++23 } }
+
+#define A
+#undef B
+
+#elifdef A // { dg-error "#elifdef without #if" }
+#elifdef B // { dg-error "#elifdef without #if" }
+#elifndef A // { dg-error "#elifndef without #if" }
+#elifndef B // { dg-error "#elifndef without #if" }
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef A // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef B // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef A // { dg-error "#elifndef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef B // { dg-error "#elifndef after #else" }
+#endif
+
+#if 0
+#elifdef A = // { dg-error "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifdef B = // { dg-error "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifndef A = // { dg-error "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifndef B = // { dg-error "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifdef // { dg-error "no macro name given in #elifdef directive" }
+#endif
+
+#if 0
+#elifndef // { dg-error "no macro name given in #elifndef directive" }
+#endif
+
+#if 0
+#elifdef , // { dg-error "macro names must be identifiers" }
+#endif
+
+#if 0
+#elifndef , // { dg-error "macro names must be identifiers" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-4.C b/gcc/testsuite/g++.dg/cpp/elifdef-4.C
new file mode 100644
index 0000000..08edf58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-4.C
@@ -0,0 +1,5 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "" }
+
+#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-5.C b/gcc/testsuite/g++.dg/cpp/elifdef-5.C
new file mode 100644
index 0000000..f7d4007
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-5.C
@@ -0,0 +1,63 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "" }
+
+#define A
+#undef B
+
+#elifdef A // { dg-error "#elifdef without #if" }
+#elifdef B // { dg-error "#elifdef without #if" }
+#elifndef A // { dg-error "#elifndef without #if" }
+#elifndef B // { dg-error "#elifndef without #if" }
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef A // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifdef B // { dg-error "#elifdef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef A // { dg-error "#elifndef after #else" }
+#endif
+
+#if 1 // { dg-error "-:began here" }
+#else
+#elifndef B // { dg-error "#elifndef after #else" }
+#endif
+
+#if 0
+#elifdef A = // { dg-warning "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifdef B = // { dg-warning "extra tokens at end of #elifdef directive" }
+#endif
+
+#if 0
+#elifndef A = // { dg-warning "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifndef B = // { dg-warning "extra tokens at end of #elifndef directive" }
+#endif
+
+#if 0
+#elifdef // { dg-error "no macro name given in #elifdef directive" }
+#endif
+
+#if 0
+#elifndef // { dg-error "no macro name given in #elifndef directive" }
+#endif
+
+#if 0
+#elifdef , // { dg-error "macro names must be identifiers" }
+#endif
+
+#if 0
+#elifndef , // { dg-error "macro names must be identifiers" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-6.C b/gcc/testsuite/g++.dg/cpp/elifdef-6.C
new file mode 100644
index 0000000..94d2118
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-6.C
@@ -0,0 +1,65 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+
+#define A
+#undef B
+
+#if 0
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+// As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group.
+
+#if 1
+#elifdef x * y // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef ! // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp/elifdef-7.C b/gcc/testsuite/g++.dg/cpp/elifdef-7.C
new file mode 100644
index 0000000..bb9b8ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/elifdef-7.C
@@ -0,0 +1,65 @@
+// P2334R1
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A
+#undef B
+
+#if 0
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+// As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group.
+
+#if 1
+#elifdef x * y // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
+
+#if 1
+#elifndef ! // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
index eae0d8c..d6057f1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
@@ -1,7 +1,6 @@
// PR c++/52830
// { dg-do compile { target c++11 } }
// { dg-additional-options "-fchecking" }
-// { dg-ice "comptypes" }
template<bool b> struct eif { typedef void type; };
template<> struct eif<false> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
index 5224bb1..6329523 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C
@@ -85,8 +85,11 @@ extern __attribute__ ((weak)) int i;
constexpr int *p1 = &i + 1;
#pragma GCC diagnostic push
+// Suppress warning: ordered comparison of pointer with integer zero.
#pragma GCC diagnostic ignored "-Wextra"
-// Suppress warning: ordered comparison of pointer with integer zero
+// Also suppress -Waddress for comparisons of constant addresses to
+// to null.
+#pragma GCC diagnostic ignored "-Waddress"
constexpr bool b0 = p1; // { dg-error "not a constant expression" }
constexpr bool b1 = p1 == 0; // { dg-error "not a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty17.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty17.C
new file mode 100644
index 0000000..86126da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty17.C
@@ -0,0 +1,21 @@
+// PR c++/102163
+// { dg-do compile { target c++11 } }
+
+struct O {
+ constexpr O(int) { }
+};
+
+union _Variadic_union {
+ constexpr _Variadic_union(int __arg) : _M_rest(__arg) { }
+ int _M_first;
+ O _M_rest;
+};
+
+constexpr _Variadic_union u(42);
+
+struct _Variant_storage {
+ constexpr _Variant_storage() : _M_u(42) {}
+ _Variadic_union _M_u;
+};
+
+constexpr _Variant_storage w;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-inst1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-inst1.C
new file mode 100644
index 0000000..3ce513d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-inst1.C
@@ -0,0 +1,17 @@
+// Test that we don't uselessly instantiate f<A> immediately while parsing g.
+// Doing so is permitted by the standard, but has no benefit and breaks code
+// unnecessarily.
+
+// { dg-do compile { target c++11 } }
+
+// -O activates the call to maybe_constant_value in cp_fold.
+// { dg-additional-options -O }
+
+template <class T>
+constexpr int f (const T* p) { return p->i; }
+
+constexpr int g(const struct A* p) { return f(p); }
+
+struct A { int i; };
+
+// Instantiating f<A> at EOF works fine.
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C
index 51da8dd..ea97b03 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C
@@ -10,10 +10,10 @@ ft() {}
template<class F, int N>
decltype (ft<F> (F())) // { dg-error "depth" }
-ft() {}
+ft(F) {}
int main() {
- ft<struct a*, 0>(); // { dg-message "from here" }
+ ft<struct a*, 0>(0); // { dg-message "from here" }
}
// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist125.C b/gcc/testsuite/g++.dg/cpp0x/initlist125.C
new file mode 100644
index 0000000..49dee1c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist125.C
@@ -0,0 +1,12 @@
+// PR c++/102050
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+struct A {
+ A(std::initializer_list<int> = {});
+};
+
+A x{0};
+A y{1, 2, 3};
+A z;
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist126.C b/gcc/testsuite/g++.dg/cpp0x/initlist126.C
new file mode 100644
index 0000000..0a8fb99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist126.C
@@ -0,0 +1,17 @@
+// PR c++/102050
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+extern struct A a;
+
+struct A {
+ A(const A& = a);
+ A(std::initializer_list<int>) = delete;
+};
+
+void f(A);
+
+int main() {
+ f({}); // { dg-bogus "deleted" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr102305.C b/gcc/testsuite/g++.dg/cpp0x/pr102305.C
new file mode 100644
index 0000000..e63adcf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr102305.C
@@ -0,0 +1,39 @@
+// PR c++/102305
+// { dg-do compile { target c++11 } }
+
+namespace std
+{
+ 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;
+
+ typedef integral_constant<bool, true> true_type;
+ typedef integral_constant<bool, false> false_type;
+
+ template<bool __v>
+ using bool_constant = integral_constant<bool, __v>;
+
+ template<typename _Tp, typename... _Args>
+ struct is_constructible
+ : public bool_constant<__is_constructible(_Tp, _Args...)>
+ {
+ };
+}
+
+template<typename>
+struct A {
+ virtual ~A() = 0;
+};
+
+struct B {
+ virtual ~B() = 0;
+};
+
+static_assert(!std::is_constructible<A<int> >::value, "");
+static_assert(!std::is_constructible<B>::value, "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C
new file mode 100644
index 0000000..df61f26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2.C
@@ -0,0 +1,16 @@
+// PR c++/102547
+// { dg-do compile { target c++11 } }
+
+template<int... Vs>
+struct vals { };
+
+template<class V, class T>
+struct vals_client { };
+
+template<int V0, int V1, class T>
+struct vals_client<vals<V0, V1>, T> { };
+
+template<int V0, int V1>
+struct vals_client<vals<V0, V1>, void> { };
+
+template struct vals_client<vals<1, 2>, void>; //- "sorry, unimplemented..., ICE"
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C
new file mode 100644
index 0000000..e98bdbb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial2a.C
@@ -0,0 +1,22 @@
+// PR c++/102547
+// { dg-do compile { target c++11 } }
+// A version of variadic-partial2.C where partial ordering is performed
+// on function templates instead of class templates.
+
+template<int... Vs>
+struct vals { };
+
+template<class V, class T>
+void f(V, T) { };
+
+template<int V0, int V1, class T>
+void f(vals<V0, V1>, T) { };
+
+template<int V0, int V1>
+void f(vals<V0, V1>, char) { };
+
+template void f(vals<1, 2>, char); //- "sorry, unimplemented..., ICE"
+
+int main() {
+ f(vals<1, 3>{}, 'a'); //- "sorry, unimplemented..., ICE"
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
index a2d113c..4994008 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
@@ -4,6 +4,6 @@
constexpr int
f ()
{
-x: // { dg-error "label definition is not a constant expression" }
+x: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } }
return 42;
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
index 53f0f1f..8e9d1ea 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
@@ -4,12 +4,12 @@ struct A { A(); };
constexpr int f(int i) {
static int j = i; // { dg-error "static" }
- thread_local int l = i; // { dg-error "thread_local" }
- goto foo; // { dg-error "goto" }
+ thread_local int l = i; // { dg-error "thread_local" "" { target c++20_down } }
+ goto foo; // { dg-error "goto" "" { target c++20_down } }
foo:
asm("foo"); // { dg-error "asm" "" { target c++17_down } }
int k; // { dg-error "uninitialized" "" { target c++17_down } }
- A a; // { dg-error "non-literal" }
+ A a; // { dg-error "non-literal" "" { target c++20_down } }
return i;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
index a31cc15..f0d7ea0 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction12.C
@@ -15,3 +15,9 @@ A a(&i,2,B<42>());
template <class,class> class same;
template <class T> class same<T,T> {};
same<decltype(a), A<int*>> s;
+
+#if __cpp_deduction_guides >= 201907
+template <class T> using C = A<const T*>;
+
+same<decltype(C(&i, 2, B<42>())), A<const int*>> t;
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C
new file mode 100644
index 0000000..6daa4b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction99.C
@@ -0,0 +1,35 @@
+// PR c++/102479
+// { dg-do compile { target c++17 } }
+
+template<class T> struct A;
+
+template<class T>
+struct tuple {
+ tuple(T);
+
+ template<template<class> class Tmpl>
+ tuple(Tmpl<T>);
+
+ template<template<class> class Tmpl, typename A<Tmpl<char>>::type = 0>
+ tuple(Tmpl<T>);
+
+ template<template<class> class Tmpl, typename A<Tmpl<long>>::type = 0>
+ tuple(Tmpl<T>);
+};
+
+template<class T> struct B { };
+
+using ty1 = tuple<int>;
+using ty1 = decltype(tuple(0));
+using ty1 = decltype(tuple(B<int>{}));
+
+#if __cpp_deduction_guides >= 201907
+template<class T> using const_tuple = tuple<const T>;
+
+using ty2 = const_tuple<int>;
+using ty2 = decltype(const_tuple(0));
+using ty2 = decltype(const_tuple(B<const int>{}));
+
+using ty3 = const_tuple<B<int>>;
+using ty3 = decltype(const_tuple(B<int>{}));
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C
new file mode 100644
index 0000000..b1248fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C
@@ -0,0 +1,18 @@
+// PR c++/101764
+// { dg-do compile { target c++17 } }
+
+void g(...);
+
+template<class>
+auto f() {
+ return [](auto... ts) {
+ g([] { if constexpr (sizeof(ts)); }...);
+#if __cpp_concepts
+ g(requires { decltype(ts){0}; }...);
+#endif
+ };
+}
+
+int main() {
+ f<int>()('a', true);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype4.C b/gcc/testsuite/g++.dg/cpp1z/nontype4.C
new file mode 100644
index 0000000..ff476dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype4.C
@@ -0,0 +1,14 @@
+// PR c++/98930
+// { dg-do compile { target c++17 } }
+
+template<int*>
+struct A { A() { } };
+
+template<class T>
+void impl() {
+ static int i;
+ static A<&i> a;
+}
+
+template void impl<int>();
+template void impl<char>();
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype4a.C b/gcc/testsuite/g++.dg/cpp1z/nontype4a.C
new file mode 100644
index 0000000..5b74292
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype4a.C
@@ -0,0 +1,14 @@
+// PR c++/98930
+// { dg-do compile { target c++17 } }
+
+template<int*>
+struct A { };
+
+template<class T>
+auto impl() {
+ static int i;
+ return A<&i>();
+}
+
+using type = decltype(impl<int>());
+using type = decltype(impl<char>()); // { dg-error "conflicting declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C b/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C
new file mode 100644
index 0000000..736f022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/charlit-encoding1.C
@@ -0,0 +1,33 @@
+// PR c++/102615 - P2316R2 - Consistent character literal encoding
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+main ()
+{
+#if ' ' == 0x20
+ if (' ' != 0x20)
+ abort ();
+#elif ' ' == 0x40
+ if (' ' != 0x40)
+ abort ();
+#else
+ if (' ' == 0x20 || ' ' == 0x40)
+ abort ();
+#endif
+#if 'a' == 0x61
+ if ('a' != 0x61)
+ abort ();
+#elif 'a' == 0x81
+ if ('a' != 0x81)
+ abort ();
+#elif 'a' == -0x7F
+ if ('a' != -0x7F)
+ abort ();
+#else
+ if ('a' == 0x61 || 'a' == 0x81 || 'a' == -0x7F)
+ abort ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C
new file mode 100644
index 0000000..c80ea38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C
@@ -0,0 +1,68 @@
+// P2242R3
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo ()
+{
+lab: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } }
+ return 1;
+}
+
+constexpr int
+bar (int x)
+{
+ if (x)
+ goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
+ return 1;
+lab:
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ if (!x)
+ return 1;
+ static int a; // { dg-error "'a' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 }
+}
+
+constexpr int
+qux (int x)
+{
+ if (!x)
+ return 1;
+ thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 }
+}
+
+constexpr int
+garply (int x)
+{
+ if (!x)
+ return 1;
+ extern thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } }
+ return ++a;
+}
+
+struct S { S (); ~S (); int s; }; // { dg-message "'S' is not literal because:" "" { target c++20_down } }
+ // { dg-message "'S' has a non-trivial destructor" "" { target c++17_down } .-1 }
+ // { dg-message "'S' does not have 'constexpr' destructor" "" { target { c++20_only } } .-2 }
+
+constexpr int
+corge (int x)
+{
+ if (!x)
+ return 1;
+ S s; // { dg-error "variable 's' of non-literal type 'S' in 'constexpr' function only available with" "" { target c++20_down } }
+ return 0;
+}
+
+#if __cpp_constexpr >= 202110L
+static_assert (foo ());
+static_assert (bar (0));
+static_assert (baz (0));
+static_assert (qux (0));
+static_assert (garply (0));
+static_assert (corge (0));
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C
new file mode 100644
index 0000000..0f7b229
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C
@@ -0,0 +1,54 @@
+// P2242R3
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+constexpr int
+foo ()
+{
+lab:
+ return 1;
+}
+
+constexpr int
+bar (int x)
+{
+ if (x)
+ goto lab; // { dg-error "'goto' is not a constant expression" }
+ return 1;
+lab:
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ if (!x)
+ return 1;
+ static int a; // { dg-error "control passes through declaration of 'a' with static storage duration" }
+ return ++a;
+}
+
+constexpr int
+qux (int x)
+{
+ if (!x)
+ return 1;
+ thread_local int a; // { dg-error "control passes through declaration of 'a' with thread storage duration" }
+ return ++a;
+}
+
+struct S { S (); ~S (); int s; }; // { dg-message "'S::S\\\(\\\)' declared here" }
+
+constexpr int
+corge (int x)
+{
+ if (!x)
+ return 1;
+ S s; // { dg-error "call to non-'constexpr' function 'S::S\\\(\\\)'" }
+ return 0;
+}
+
+constexpr int a = bar (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int b = baz (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int c = qux (1); // { dg-message "in 'constexpr' expansion of" }
+constexpr int d = corge (1); // { dg-message "in 'constexpr' expansion of" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C
new file mode 100644
index 0000000..3b5585d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C
@@ -0,0 +1,10 @@
+// P2242R3
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo ()
+{
+ goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
+lab: // { dg-error "'goto' is not a constant expression" "" { target { c++23 } } .-1 }
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C
new file mode 100644
index 0000000..e4ed2e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C
@@ -0,0 +1,57 @@
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+int qux ();
+
+constexpr int
+foo (int x)
+{
+ switch (x)
+ {
+ static int v = qux ();
+ case 12:
+ return 1;
+ }
+ return 0;
+}
+
+constexpr int
+bar (int x)
+{
+ switch (x)
+ {
+ thread_local int v = qux ();
+ case 12:
+ return 1;
+ }
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ switch (x)
+ {
+ static const int v = qux (); // { dg-message "'v' was not initialized with a constant expression" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+corge (int x)
+{
+ switch (x)
+ {
+ const thread_local int v = qux (); // { dg-message "'v' was not initialized with a constant expression" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int a = foo (12);
+constexpr int b = bar (12);
+constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
+constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C
new file mode 100644
index 0000000..838f282
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C
@@ -0,0 +1,57 @@
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+int qux ();
+
+constexpr int
+foo (int x)
+{
+ switch (x)
+ {
+ static const int v = 6;
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+bar (int x)
+{
+ switch (x)
+ {
+ thread_local const int v = 7;
+ case 12:
+ return 7;
+ }
+ return 0;
+}
+
+constexpr int
+baz (int x)
+{
+ switch (x)
+ {
+ static int v = 6; // { dg-message "int v' is not const" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int
+corge (int x)
+{
+ switch (x)
+ {
+ thread_local int v = 6; // { dg-message "int v' is not const" }
+ case 12:
+ return v;
+ }
+ return 0;
+}
+
+constexpr int a = foo (12);
+constexpr int b = bar (12);
+constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
+constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C
new file mode 100644
index 0000000..11cb518
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C
@@ -0,0 +1,25 @@
+// P2242R3
+// { dg-do compile }
+// { dg-options "-std=c++2b" }
+
+constexpr int
+foo ()
+{
+ goto lab; // { dg-error "'goto' is not a constant expression" }
+lab:
+ return 1;
+}
+
+constexpr int
+bar ()
+{
+ static int a; // { dg-error "'a' declared 'static' in 'constexpr' context" }
+ return ++a;
+}
+
+constexpr int
+baz (int x)
+{
+ thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' context" }
+ return ++a;
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
index 7070f59..8bb3bf1 100644
--- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -134,8 +134,8 @@
#ifndef __cpp_constexpr
# error "__cpp_constexpr"
-#elif __cpp_constexpr != 201907
-# error "__cpp_constexpr != 201907"
+#elif __cpp_constexpr != 202110
+# error "__cpp_constexpr != 202110"
#endif
#ifndef __cpp_decltype_auto
diff --git a/gcc/testsuite/g++.dg/cpp23/lookup2.C b/gcc/testsuite/g++.dg/cpp23/lookup2.C
new file mode 100644
index 0000000..a16afbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/lookup2.C
@@ -0,0 +1,6 @@
+// DR 1835
+
+template <class T> void f(T t) { t.foo::bar(); }
+struct foo { void bar(); };
+struct baz : foo { };
+int main() { f(baz()); }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize1.C b/gcc/testsuite/g++.dg/cpp23/normalize1.C
new file mode 100644
index 0000000..8357ed3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize1.C
@@ -0,0 +1,66 @@
+// { dg-do preprocess { target { c++11 && { ! c++23 } } } }
+// { dg-options "" }
+
+\u00AA
+\u00B7
+\u0F43 // { dg-warning "not in NFC" }
+a\u05B8\u05B9\u05B9\u05BBb
+ a\u05BB\u05B9\u05B8\u05B9b // { dg-warning "not in NFC" }
+\u09CB
+\u09C7\u09BE // { dg-warning "not in NFC" }
+\u0B4B
+\u0B47\u0B3E // { dg-warning "not in NFC" }
+\u0BCA
+\u0BC6\u0BBE // { dg-warning "not in NFC" }
+\u0BCB
+\u0BC7\u0BBE // { dg-warning "not in NFC" }
+\u0CCA
+\u0CC6\u0CC2 // { dg-warning "not in NFC" }
+\u0D4A
+\u0D46\u0D3E // { dg-warning "not in NFC" }
+\u0D4B
+\u0D47\u0D3E // { dg-warning "not in NFC" }
+
+K
+\u212A // { dg-warning "not in NFC" }
+
+\u03AC
+\u1F71 // { dg-warning "not in NFC" }
+
+\uAC00
+\u1100\u1161 // { dg-warning "not in NFC" }
+\uAC01
+\u1100\u1161\u11A8 // { dg-warning "not in NFC" }
+\uAC00\u11A8 // { dg-warning "not in NFC" }
+
+གྷ // { dg-warning "not in NFC" }
+aָֹֹֻb
+ aָֹֹֻb // { dg-warning "not in NFC" }
+ো
+ো // { dg-warning "not in NFC" }
+ୋ
+ୋ // { dg-warning "not in NFC" }
+ொ
+ொ // { dg-warning "not in NFC" }
+ோ
+ோ // { dg-warning "not in NFC" }
+ೊ
+ೊ // { dg-warning "not in NFC" }
+ൊ
+ൊ // { dg-warning "not in NFC" }
+ോ
+ോ // { dg-warning "not in NFC" }
+
+K
+K // { dg-warning "not in NFC" }
+
+ά // { dg-warning "not in NFC" }
+
+가
+가 // { dg-warning "not in NFC" }
+각
+각 // { dg-warning "not in NFC" }
+각 // { dg-warning "not in NFC" }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize2.C b/gcc/testsuite/g++.dg/cpp23/normalize2.C
new file mode 100644
index 0000000..ad14e64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize2.C
@@ -0,0 +1,66 @@
+// { dg-do preprocess { target { c++23 } } }
+// { dg-options "" }
+
+\u00AA
+\u00B7
+\u0F43 // { dg-warning "not in NFC" }
+a\u05B8\u05B9\u05B9\u05BBb
+ a\u05BB\u05B9\u05B8\u05B9b // { dg-warning "not in NFC" }
+\u09CB
+\u09C7\u09BE // { dg-warning "not in NFC" }
+\u0B4B
+\u0B47\u0B3E // { dg-warning "not in NFC" }
+\u0BCA
+\u0BC6\u0BBE // { dg-warning "not in NFC" }
+\u0BCB
+\u0BC7\u0BBE // { dg-warning "not in NFC" }
+\u0CCA
+\u0CC6\u0CC2 // { dg-warning "not in NFC" }
+\u0D4A
+\u0D46\u0D3E // { dg-warning "not in NFC" }
+\u0D4B
+\u0D47\u0D3E // { dg-warning "not in NFC" }
+
+K
+\u212A // { dg-warning "not in NFC" }
+
+\u03AC
+\u1F71 // { dg-warning "not in NFC" }
+
+\uAC00
+\u1100\u1161 // { dg-warning "not in NFC" }
+\uAC01
+\u1100\u1161\u11A8 // { dg-warning "not in NFC" }
+\uAC00\u11A8 // { dg-warning "not in NFC" }
+
+གྷ // { dg-warning "not in NFC" }
+aָֹֹֻb
+ aָֹֹֻb // { dg-warning "not in NFC" }
+ো
+ো // { dg-warning "not in NFC" }
+ୋ
+ୋ // { dg-warning "not in NFC" }
+ொ
+ொ // { dg-warning "not in NFC" }
+ோ
+ோ // { dg-warning "not in NFC" }
+ೊ
+ೊ // { dg-warning "not in NFC" }
+ൊ
+ൊ // { dg-warning "not in NFC" }
+ോ
+ോ // { dg-warning "not in NFC" }
+
+K
+K // { dg-warning "not in NFC" }
+
+ά // { dg-warning "not in NFC" }
+
+가
+가 // { dg-warning "not in NFC" }
+각
+각 // { dg-warning "not in NFC" }
+각 // { dg-warning "not in NFC" }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize3.C b/gcc/testsuite/g++.dg/cpp23/normalize3.C
new file mode 100644
index 0000000..bf4bb3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize3.C
@@ -0,0 +1,80 @@
+// { dg-do preprocess { target { c++23 } } }
+// { dg-options "-pedantic-errors" }
+
+\u00AA
+\u00B7 // { dg-error "is not valid at the start of an identifier" }
+\u0F43 // { dg-error "not in NFC" }
+a\u05B8\u05B9\u05B9\u05BBb
+ a\u05BB\u05B9\u05B8\u05B9b // { dg-error "not in NFC" }
+\u09CB // { dg-error "is not valid at the start of an identifier" }
+\u09C7\u09BE // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0B4B // { dg-error "is not valid at the start of an identifier" }
+\u0B47\u0B3E // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0BCA // { dg-error "is not valid at the start of an identifier" }
+\u0BC6\u0BBE // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0BCB // { dg-error "is not valid at the start of an identifier" }
+\u0BC7\u0BBE // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0CCA // { dg-error "is not valid at the start of an identifier" }
+\u0CC6\u0CC2 // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0D4A // { dg-error "is not valid at the start of an identifier" }
+\u0D46\u0D3E // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+\u0D4B // { dg-error "is not valid at the start of an identifier" }
+\u0D47\u0D3E // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+
+K
+\u212A // { dg-error "not in NFC" }
+
+\u03AC
+\u1F71 // { dg-error "not in NFC" }
+
+\uAC00
+\u1100\u1161 // { dg-error "not in NFC" }
+\uAC01
+\u1100\u1161\u11A8 // { dg-error "not in NFC" }
+\uAC00\u11A8 // { dg-error "not in NFC" }
+
+· // { dg-error "is not valid at the start of an identifier" }
+གྷ // { dg-error "not in NFC" }
+aָֹֹֻb
+ aָֹֹֻb // { dg-error "not in NFC" }
+ো // { dg-error "is not valid at the start of an identifier" }
+ো // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ୋ // { dg-error "is not valid at the start of an identifier" }
+ୋ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ொ // { dg-error "is not valid at the start of an identifier" }
+ொ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ோ // { dg-error "is not valid at the start of an identifier" }
+ோ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ೊ // { dg-error "is not valid at the start of an identifier" }
+ೊ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ൊ // { dg-error "is not valid at the start of an identifier" }
+ൊ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+ോ // { dg-error "is not valid at the start of an identifier" }
+ോ // { dg-error "not in NFC" }
+ // { dg-error "is not valid at the start of an identifier" "" { target *-*-* } .-1 }
+
+K
+K // { dg-error "not in NFC" }
+
+ά // { dg-error "not in NFC" }
+
+가
+가 // { dg-error "not in NFC" }
+각
+각 // { dg-error "not in NFC" }
+각 // { dg-error "not in NFC" }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize4.C b/gcc/testsuite/g++.dg/cpp23/normalize4.C
new file mode 100644
index 0000000..9f83cd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize4.C
@@ -0,0 +1,66 @@
+// { dg-do preprocess { target { c++23 } } }
+// { dg-options "" }
+
+\u00AA
+x\u00B7
+\u0F43 // { dg-warning "not in NFC" }
+a\u05B8\u05B9\u05B9\u05BBb
+ a\u05BB\u05B9\u05B8\u05B9b // { dg-warning "not in NFC" }
+x\u09CB
+x\u09C7\u09BE // { dg-warning "not in NFC" }
+x\u0B4B
+x\u0B47\u0B3E // { dg-warning "not in NFC" }
+x\u0BCA
+x\u0BC6\u0BBE // { dg-warning "not in NFC" }
+x\u0BCB
+x\u0BC7\u0BBE // { dg-warning "not in NFC" }
+x\u0CCA
+x\u0CC6\u0CC2 // { dg-warning "not in NFC" }
+x\u0D4A
+x\u0D46\u0D3E // { dg-warning "not in NFC" }
+x\u0D4B
+x\u0D47\u0D3E // { dg-warning "not in NFC" }
+
+K
+\u212A // { dg-warning "not in NFC" }
+
+\u03AC
+\u1F71 // { dg-warning "not in NFC" }
+
+\uAC00
+\u1100\u1161 // { dg-warning "not in NFC" }
+\uAC01
+\u1100\u1161\u11A8 // { dg-warning "not in NFC" }
+\uAC00\u11A8 // { dg-warning "not in NFC" }
+
+x·
+གྷ // { dg-warning "not in NFC" }
+aָֹֹֻb
+ aָֹֹֻb // { dg-warning "not in NFC" }
+xো
+xো // { dg-warning "not in NFC" }
+xୋ
+xୋ // { dg-warning "not in NFC" }
+xொ
+xொ // { dg-warning "not in NFC" }
+xோ
+xோ // { dg-warning "not in NFC" }
+xೊ
+xೊ // { dg-warning "not in NFC" }
+xൊ
+xൊ // { dg-warning "not in NFC" }
+xോ
+xോ // { dg-warning "not in NFC" }
+
+K
+K // { dg-warning "not in NFC" }
+
+ά // { dg-warning "not in NFC" }
+
+가
+가 // { dg-warning "not in NFC" }
+각
+각 // { dg-warning "not in NFC" }
+각 // { dg-warning "not in NFC" }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize5.C b/gcc/testsuite/g++.dg/cpp23/normalize5.C
new file mode 100644
index 0000000..afe339a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize5.C
@@ -0,0 +1,66 @@
+// { dg-do preprocess { target { c++23 } } }
+// { dg-options "-pedantic-errors" }
+
+\u00AA
+x\u00B7
+\u0F43 // { dg-error "not in NFC" }
+a\u05B8\u05B9\u05B9\u05BBb
+ a\u05BB\u05B9\u05B8\u05B9b // { dg-error "not in NFC" }
+x\u09CB
+x\u09C7\u09BE // { dg-error "not in NFC" }
+x\u0B4B
+x\u0B47\u0B3E // { dg-error "not in NFC" }
+x\u0BCA
+x\u0BC6\u0BBE // { dg-error "not in NFC" }
+x\u0BCB
+x\u0BC7\u0BBE // { dg-error "not in NFC" }
+x\u0CCA
+x\u0CC6\u0CC2 // { dg-error "not in NFC" }
+x\u0D4A
+x\u0D46\u0D3E // { dg-error "not in NFC" }
+x\u0D4B
+x\u0D47\u0D3E // { dg-error "not in NFC" }
+
+K
+\u212A // { dg-error "not in NFC" }
+
+\u03AC
+\u1F71 // { dg-error "not in NFC" }
+
+\uAC00
+\u1100\u1161 // { dg-error "not in NFC" }
+\uAC01
+\u1100\u1161\u11A8 // { dg-error "not in NFC" }
+\uAC00\u11A8 // { dg-error "not in NFC" }
+
+x·
+གྷ // { dg-error "not in NFC" }
+aָֹֹֻb
+ aָֹֹֻb // { dg-error "not in NFC" }
+xো
+xো // { dg-error "not in NFC" }
+xୋ
+xୋ // { dg-error "not in NFC" }
+xொ
+xொ // { dg-error "not in NFC" }
+xோ
+xோ // { dg-error "not in NFC" }
+xೊ
+xೊ // { dg-error "not in NFC" }
+xൊ
+xൊ // { dg-error "not in NFC" }
+xോ
+xോ // { dg-error "not in NFC" }
+
+K
+K // { dg-error "not in NFC" }
+
+ά // { dg-error "not in NFC" }
+
+가
+가 // { dg-error "not in NFC" }
+각
+각 // { dg-error "not in NFC" }
+각 // { dg-error "not in NFC" }
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize6.C b/gcc/testsuite/g++.dg/cpp23/normalize6.C
new file mode 100644
index 0000000..4c2b141
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize6.C
@@ -0,0 +1,10 @@
+// P1949R7
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+constexpr int À = 1; // U+00C0
+constexpr int À = 2; // U+0041 U+0300 { dg-warning "is not in NFC" }
+constexpr int gv1 = \u00c0;
+constexpr int gv2 = A\u0300; // { dg-warning "is not in NFC" }
+static_assert(gv1 == 1, "");
+static_assert(gv2 == 2, "");
diff --git a/gcc/testsuite/g++.dg/cpp23/normalize7.C b/gcc/testsuite/g++.dg/cpp23/normalize7.C
new file mode 100644
index 0000000..f639d65
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/normalize7.C
@@ -0,0 +1,12 @@
+// P1949R7
+// { dg-do compile { target c++11 } }
+// { dg-options "-pedantic-errors" }
+
+constexpr int À = 1; // U+00C0
+constexpr int À = 2; // U+0041 U+0300 { dg-warning "is not in NFC" "" { target { ! c++23 } } }
+// { dg-error "is not in NFC" "" { target c++23 } .-1 }
+constexpr int gv1 = \u00c0;
+constexpr int gv2 = A\u0300; // { dg-warning "is not in NFC" "" { target { ! c++23 } } }
+// { dg-error "is not in NFC" "" { target c++23 } .-1 }
+static_assert(gv1 == 1, "");
+static_assert(gv2 == 2, "");
diff --git a/gcc/testsuite/g++.dg/cpp23/ucnid-1-utf8.C b/gcc/testsuite/g++.dg/cpp23/ucnid-1-utf8.C
new file mode 100644
index 0000000..61acc82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ucnid-1-utf8.C
@@ -0,0 +1,18 @@
+// P1949R7
+// { dg-do compile }
+// { dg-options "" }
+
+bool 👷 = true;
+bool 👷‍♀ = false; // { dg-error "is not valid in an identifier" }
+int ⏰ = 0; // { dg-error "is not valid in an identifier" }
+int 🕐 = 0;
+int ☠ = 0; // { dg-error "is not valid in an identifier" }
+int 💀 = 0;
+int ✋ = 0; // { dg-error "is not valid in an identifier" }
+int 👊 = 0;
+int ✈ = 0; // { dg-error "is not valid in an identifier" }
+int 🚀 = 0;
+int ☹ = 0; // { dg-error "is not valid in an identifier" }
+int 😀 = 0;
+struct E {};
+class 💩 : public E {};
diff --git a/gcc/testsuite/g++.dg/cpp23/ucnid-2-utf8.C b/gcc/testsuite/g++.dg/cpp23/ucnid-2-utf8.C
new file mode 100644
index 0000000..6c8aa6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ucnid-2-utf8.C
@@ -0,0 +1,18 @@
+// P1949R7
+// { dg-do compile }
+// { dg-options "-pedantic-errors" }
+
+bool 👷 = true; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+bool 👷‍♀ = false; // { dg-error "is not valid in an identifier" }
+int ⏰ = 0; // { dg-error "is not valid in an identifier" }
+int 🕐 = 0; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+int ☠ = 0; // { dg-error "is not valid in an identifier" }
+int 💀 = 0; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+int ✋ = 0; // { dg-error "is not valid in an identifier" }
+int 👊 = 0; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+int ✈ = 0; // { dg-error "is not valid in an identifier" }
+int 🚀 = 0; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+int ☹ = 0; // { dg-error "is not valid in an identifier" }
+int 😀 = 0; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
+struct E {};
+class 💩 : public E {}; // { dg-error "is not valid in an identifier" "" { target { c++98_only || c++23 } } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias11.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias11.C
new file mode 100644
index 0000000..87eb3e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias11.C
@@ -0,0 +1,12 @@
+// PR c++/102643
+// { dg-do compile { target c++20 } }
+
+template<class _Tp, class>
+struct vector {
+ typedef int allocator_type;
+ vector(_Tp, allocator_type = allocator_type());
+};
+
+template<class T> using vector_mm = vector<T, int>;
+
+vector_mm v(0);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda14.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda14.C
index bdc893d..02b6b6a 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda14.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda14.C
@@ -11,9 +11,9 @@ void foo() noexcept(!__is_same(T, void)) { }
template<typename U>
auto f() {
- return []<typename T>(T, bool a = requires { C<T>; }){
+ return []<typename T>(T, bool a = requires { C<T>; }){ // { dg-warning Wmissing-requires }
static_assert(requires { requires C<U> && (C<T> || C<T>); }); // { dg-error "assert" }
- static_assert(requires { C<T>; });
+ static_assert(requires { C<T>; }); // { dg-warning Wmissing-requires }
static_assert(requires { { foo<T>() } noexcept -> C; });
static_assert(!requires { typename T::blah; }); // { dg-error "assert" }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C
new file mode 100644
index 0000000..e9867f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep2.C
@@ -0,0 +1,21 @@
+// PR c++/102412
+// { dg-do link { target c++20 } }
+
+template<class T, class U> concept C = __is_same(T, U);
+
+template<class T, bool = C<int, T>> void f();
+template<> void f<int, true>() { }
+template<> void f<char, false>() { }
+
+template<bool = C<int, char>> void g();
+template<> void g<false>() { }
+
+template<bool = C<int, int>> void h();
+template<> void h<true>() { }
+
+int main() {
+ f<int>();
+ f<char>();
+ g();
+ h();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C
new file mode 100644
index 0000000..4aae287
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nondep3.C
@@ -0,0 +1,9 @@
+// DR 2446
+// { dg-do compile { target c++20 } }
+
+template <typename T> concept C = true;
+template <typename T> struct A;
+template <> struct A<bool> { using type = bool; };
+
+template <typename T>
+void f(A<decltype(C<T>)>::type); // OK, no 'typename' needed
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
new file mode 100644
index 0000000..11b6293
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
@@ -0,0 +1,11 @@
+// PR c++/99909
+// { dg-do compile { target c++20 } }
+
+template<class T> constexpr bool always_true = true;
+template<class T> concept C = always_true<T>;
+
+template<C auto> struct S;
+
+template<template<auto> class TT> void f() { }
+
+template void f<S>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C
new file mode 100644
index 0000000..cf3e71e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp4.C
@@ -0,0 +1,9 @@
+// PR c++/99904
+// { dg-do compile { target c++20 } }
+
+template<class... Ts> concept C = (Ts::value && ...);
+template<class... Ts> requires C<Ts...> struct A;
+template<class T> requires true struct B;
+template<template<class... Ts> requires C<Ts...> class TT> struct S;
+using ty1 = S<A>;
+using ty2 = S<B>; // { dg-error "constraint" } TT's constraints don't subsume B's
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C
new file mode 100644
index 0000000..80b48ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C
@@ -0,0 +1,9 @@
+// PR c++/98486
+// { dg-do compile { target c++20 } }
+
+template<class T, class U> concept C = __is_same(T, U);
+
+template<C<int>> int v;
+
+template<> int v<int>;
+template<> int v<char>; // { dg-error "match" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C
new file mode 100644
index 0000000..b12d37d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C
@@ -0,0 +1,14 @@
+// PR c++/98486
+// { dg-do compile { target c++20 } }
+
+template<class T, class U> concept C = __is_same(T, U);
+
+struct A {
+ template<C<int>> static int v;
+};
+
+template<> int A::v<int>;
+template<> int A::v<char>; // { dg-error "match" }
+
+int x = A::v<int>;
+int y = A::v<char>; // { dg-error "invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C
new file mode 100644
index 0000000..37d7f0f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C
@@ -0,0 +1,15 @@
+// PR c++/98486
+// { dg-do compile { target c++20 } }
+
+template<class T, class U> concept C = __is_same(T, U);
+
+template<class T>
+struct A {
+ template<C<T>> static int v;
+};
+
+template<> template<> int A<int>::v<int>;
+template<> template<> int A<int>::v<char>; // { dg-error "match" }
+
+int x = A<int>::v<int>;
+int y = A<int>::v<char>; // { dg-error "invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval3.C b/gcc/testsuite/g++.dg/cpp2a/consteval3.C
index 9fb1f1a..8f93164 100644
--- a/gcc/testsuite/g++.dg/cpp2a/consteval3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval3.C
@@ -1,5 +1,4 @@
-// { dg-do compile }
-// { dg-options "-std=c++2a" }
+// { dg-do compile { target c++20 } }
struct S { S () : a (0), b (1) {} int a, b; };
int f1 (); // { dg-message "previous declaration 'int f1\\(\\)'" }
@@ -57,7 +56,8 @@ template consteval float f12 (float x); // { dg-error "explicit instantiation sh
consteval int
f13 (int x)
{
- static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function" }
- thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function" }
+ static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function only available with" "" { target c++20_only } }
+ // { dg-error "'a' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function only available with" "" { target c++20_only } }
return x;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
index 7700bb7..69fe9e2 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
@@ -180,6 +180,6 @@ f7 ()
constexpr int
f8 ()
{
- T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function" }
+ T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target c++20_down } }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C
new file mode 100644
index 0000000..8231e99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C
@@ -0,0 +1,17 @@
+// PR c++/100495
+// { dg-do compile { target c++20 } }
+
+struct S {
+ constexpr virtual ~S () {}
+};
+
+constexpr bool
+foo ()
+{
+ S *p = new S ();
+ delete p;
+ return true;
+}
+
+constexpr bool x = foo ();
+static_assert (x);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
index 3b51bf7..ed5e40d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
@@ -5,14 +5,15 @@
constexpr int foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } }
- static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
- goto l; // { dg-error "'goto' in 'constexpr' function" }
+ static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l:;
return 0;
} catch (...) {
long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } }
- static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function" }
- goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l2:;
return -1;
}
@@ -20,20 +21,21 @@ try { // { dg-warning "function-try-block body of 'constexpr' function only av
constexpr int bar ()
{
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } }
- static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
- goto l; // { dg-error "'goto' in 'constexpr' function" }
+ static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 }
+ goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l:;
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } }
- static float d; // { dg-error "'d' declared 'static' in 'constexpr' function" }
+ static float d; // { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
// { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target c++17_down } .-1 }
- goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l2:;
return 0;
} catch (int) {
char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" "" { target c++17_down } }
- static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function" }
- goto l3; // { dg-error "'goto' in 'constexpr' function" }
+ static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+ goto l3; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } }
l3:;
return 1;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C b/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C
new file mode 100644
index 0000000..40b42b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-float2.C
@@ -0,0 +1,14 @@
+// PR c++/98216
+// PR c++/91292
+// { dg-do compile { target c++20 } }
+
+template<auto> void f() { }
+
+template void f<-1.0f>();
+template void f<-2.0f>();
+
+template void f<-1.0>();
+template void f<-2.0>();
+
+template void f<-1.0L>();
+template void f<-2.0L>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C
new file mode 100644
index 0000000..b71ed4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq11.C
@@ -0,0 +1,43 @@
+// PR c++/102490
+// { dg-do run { target c++20 } }
+
+struct A
+{
+ unsigned char a : 1;
+ unsigned char b : 1;
+ constexpr bool operator== (const A &) const = default;
+};
+
+struct B
+{
+ unsigned char a : 8;
+ int : 0;
+ unsigned char b : 7;
+ constexpr bool operator== (const B &) const = default;
+};
+
+struct C
+{
+ unsigned char a : 3;
+ unsigned char b : 1;
+ constexpr bool operator== (const C &) const = default;
+};
+
+void
+foo (C &x, int y)
+{
+ x.b = y;
+}
+
+int
+main ()
+{
+ A a{}, b{};
+ B c{}, d{};
+ C e{}, f{};
+ a.b = 1;
+ d.b = 1;
+ foo (e, 0);
+ foo (f, 1);
+ return a == b || c == d || e == f;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C
new file mode 100644
index 0000000..8346e7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq12.C
@@ -0,0 +1,5 @@
+// PR c++/102490
+// { dg-do run { target c++20 } }
+// { dg-options "-O2" }
+
+#include "spaceship-eq11.C"
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C
new file mode 100644
index 0000000..cb521ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq13.C
@@ -0,0 +1,22 @@
+// PR c++/98712
+// { dg-do run { target c++20 } }
+
+struct S
+{
+ int s = 0;
+ S(int s) : s(s) {}
+ bool operator==(const S&) const = default;
+};
+
+struct T : S
+{
+ T(int s) : S(s) {}
+ constexpr bool operator==(const T&) const = default;
+};
+
+int
+main()
+{
+ if (T(0) == T(1))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C
new file mode 100644
index 0000000..85b4784
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth12.C
@@ -0,0 +1,24 @@
+// PR c++/98712
+// { dg-do run { target c++20 } }
+
+#include <compare>
+
+struct S
+{
+ int s = 0;
+ S(int s) : s(s) {}
+ auto operator<=>(const S&) const = default;
+};
+
+struct T : S
+{
+ T(int s) : S(s) {}
+ constexpr auto operator<=>(const T&) const = default;
+};
+
+int
+main()
+{
+ if (T(0) >= T(1))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C
new file mode 100644
index 0000000..ab479d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth13.C
@@ -0,0 +1,29 @@
+// { dg-do compile { target c++20 } }
+
+#include <compare>
+#include <type_traits>
+
+struct E;
+struct D {
+ auto operator<=>(const D&) const = default;
+ float f;
+};
+struct E : D {
+ auto operator<=>(const E&) const = default;
+ int i;
+};
+extern E e1, e2;
+auto a = e1 <=> e2;
+static_assert (std::is_same_v <decltype (a), std::partial_ordering>);
+struct G;
+struct H {
+ constexpr auto operator<=>(const H&) const = default;
+ float f;
+};
+struct G : H {
+ constexpr auto operator<=>(const G&) const = default;
+ int i;
+};
+extern G g1, g2;
+auto c = g1 <=> g2;
+static_assert (std::is_same_v <decltype (c), std::partial_ordering>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C
new file mode 100644
index 0000000..369d3a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth14.C
@@ -0,0 +1,26 @@
+// Test virtual <=>.
+// { dg-do run { target c++20 } }
+
+#include <compare>
+
+struct E;
+struct D {
+ std::partial_ordering operator<=>(const D&) const = default;
+ virtual std::partial_ordering operator<=>(const E&) const = 0;
+ float f;
+ D(float f): f(f) {}
+};
+struct E : D {
+ std::partial_ordering operator<=>(const E&) const override = default;
+ int i;
+ E(float f, int i): D(f), i(i) {}
+};
+
+int main()
+{
+ E e1{0.0,42};
+ E e2{1.0,24};
+ auto a = e1 <=> e2;
+ if (!is_lt (e1 <=> e2))
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
index bd1c4d2..8861765 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8.C
@@ -1,7 +1,18 @@
// PR c++/94907
// { dg-do compile { target c++20 } }
-namespace std { struct strong_ordering { }; }
+namespace std { struct strong_ordering {
+ int _v;
+ constexpr strong_ordering (int v) :_v(v) {}
+ constexpr operator int (void) const { return _v; }
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+};
+constexpr strong_ordering strong_ordering::less = -1;
+constexpr strong_ordering strong_ordering::equal = 0;
+constexpr strong_ordering strong_ordering::greater = 1;
+}
struct E;
struct D {
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C
new file mode 100644
index 0000000..42a32da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth8a.C
@@ -0,0 +1,25 @@
+// PR c++/94907
+// { dg-do compile { target c++20 } }
+
+namespace std { struct strong_ordering {
+ int _v;
+ constexpr strong_ordering (int v) :_v(v) {}
+ constexpr operator int (void) const { return _v; }
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+};
+constexpr strong_ordering strong_ordering::less = -1;
+constexpr strong_ordering strong_ordering::equal = 0;
+constexpr strong_ordering strong_ordering::greater = 1;
+}
+
+struct E;
+struct D {
+ virtual std::strong_ordering operator<=>(const struct E&) const = 0;
+};
+struct E : D { // { dg-error "no match" }
+ std::strong_ordering operator<=>(const E&) const override = default; // { dg-message "default" }
+};
+
+auto x = E() <=> E(); // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C
new file mode 100644
index 0000000..8067d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-virtual1.C
@@ -0,0 +1,20 @@
+// PR c++/95567
+// { dg-do run { target c++20 } }
+
+struct B {
+ B(int i) : i(i) {}
+ virtual ~B() = default;
+
+ bool operator==(B const&) const = default;
+ int i;
+};
+
+struct D : B {
+ D(int i, int j) : B(i), j(j) {}
+ int j;
+};
+
+int main() {
+ if (B(2) != D(2, 3))
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
index f029e86..f2bcec6 100644
--- a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C
@@ -1,5 +1,7 @@
// { dg-do compile { target c++11 } }
-constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." }
+constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." "" { target c++20_down } }
+// { dg-error "40:.i. declared .thread_local. in .constexpr. context" "" { target c++23 } .-1 }
-constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." }
+constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." "" { target c++20_down } }
+// { dg-error "34:.i. declared .static. in .constexpr. context" "" { target c++23 } .-1 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert4.C b/gcc/testsuite/g++.dg/diagnostic/static_assert4.C
new file mode 100644
index 0000000..c539016
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert4.C
@@ -0,0 +1,30 @@
+// PR c++/92193
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+ struct has_foo
+ { static constexpr bool value = false; };
+
+template<typename T>
+#ifndef NO_CONSTEXPR
+ constexpr
+#endif
+ bool
+ foo(T t) noexcept(noexcept(t.foo()))
+ { return t.foo(); }
+
+template<typename T>
+ void
+ maybe_foo(T t)
+ {
+ static_assert( has_foo<T>::value, "has foo" ); // { dg-error "has foo" }
+ foo(t);
+ }
+
+struct X { };
+
+int main()
+{
+ X x;
+ maybe_foo(x);
+}
diff --git a/gcc/testsuite/g++.dg/eh/arm-vfp-unwind.C b/gcc/testsuite/g++.dg/eh/arm-vfp-unwind.C
index 62263c0..8ea25e5 100644
--- a/gcc/testsuite/g++.dg/eh/arm-vfp-unwind.C
+++ b/gcc/testsuite/g++.dg/eh/arm-vfp-unwind.C
@@ -12,7 +12,11 @@ using namespace std;
static void donkey ()
{
- asm volatile ("fcpyd d9, %P0" : : "w" (1.2345) : "d9");
+#if __ARM_FP & 8
+ asm volatile ("vmov.f64 d9, %P0" : : "w" (1.2345) : "d9");
+#else
+ asm volatile ("vmov.f32 s18, %0" : : "t" (1.2345f) : "s18");
+#endif
throw 1;
}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C
new file mode 100644
index 0000000..862651f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C
@@ -0,0 +1,113 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int INT1 __attribute__((unavailable));
+typedef INT1 INT2 __attribute__ ((__unavailable__));
+
+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable" "" } */
+typedef INT1 INT1b __attribute__ ((unavailable));
+
+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable" "" } */
+INT1a should_not_be_unavailable;
+
+INT1 f1(void) __attribute__ ((unavailable));
+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable" "" } */
+
+INT2 f3(void) __attribute__ ((__unavailable__));
+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable" "" } */
+int f5(INT2 x); /* { dg-error "'INT2' is unavailable" "" } */
+int f6(INT2 x) __attribute__ ((__unavailable__));
+
+typedef enum Color {red, green, blue} Color __attribute__((unavailable));
+
+int g1;
+int g2 __attribute__ ((unavailable));
+int g3 __attribute__ ((__unavailable__));
+Color k; /* { dg-error "'Color' is unavailable" "" } */
+
+typedef struct {
+ int field1;
+ int field2 __attribute__ ((unavailable));
+ int field3;
+ int field4 __attribute__ ((__unavailable__));
+ union {
+ int field5;
+ int field6 __attribute__ ((unavailable));
+ } u1;
+ int field7:1;
+ int field8:1 __attribute__ ((unavailable));
+ union {
+ int field9;
+ int field10;
+ } u2 __attribute__ ((unavailable));
+} S1;
+
+int func1()
+{
+ INT1 w; /* { dg-error "'INT1' is unavailable" "" } */
+ int x __attribute__ ((unavailable));
+ int y __attribute__ ((__unavailable__));
+ int z;
+ int (*pf)() = f1; /* { dg-error "'INT1 f1\\(\\)' is unavailable" "" } */
+
+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable" "" } */
+ /* { dg-error "'y' is unavailable" "y" { target *-*-* } .-1 } */
+ /* { dg-error "'g2' is unavailable" "g2" { target *-*-* } .-2 } */
+ /* { dg-error "'g3' is unavailable" "g3" { target *-*-* } .-3 } */
+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable" "f1" } */
+}
+
+int func2(S1 *p)
+{
+ S1 lp;
+
+ if (p->field1)
+ return p->field2; /* { dg-error "'S1::field2' is unavailable" "" } */
+ else if (lp.field4) /* { dg-error "'S1::field4' is unavailable" "" } */
+ return p->field3;
+
+ p->u1.field5 = g1 + p->field7;
+ p->u2.field9; /* { dg-error "'S1::u2' is unavailable" "" } */
+ return p->u1.field6 + p->field8; /* { dg-error "'S1::<unnamed union>::field6' is unavailable" "" } */
+ /* { dg-error "'S1::field8' is unavailable" "field8" { target *-*-* } .-1 } */
+}
+
+struct SS1 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */
+} __attribute__ ((unavailable));
+
+struct SS1 *p1; /* { dg-error "'SS1' is unavailable" "" } */
+
+struct __attribute__ ((__unavailable__)) SS2 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */
+};
+
+struct SS2 *p2; /* { dg-error "'SS2' is unavailable" "" } */
+
+#ifdef __cplusplus
+class T {
+ public:
+ void member1(int) __attribute__ ((unavailable));
+ void member2(INT1) __attribute__ ((__unavailable__));
+ int member3(T *);
+ int x;
+} __attribute__ ((unavailable));
+
+T *p3; // { dg-error "'T' is unavailable" }
+
+inline void T::member1(int) {}
+
+int T::member3(T *p) // { dg-error "'T' is unavailable" }
+{
+ p->member1(1); /* { dg-error "'void T::member1\\(int\\)' is unavailable" "" } */
+ (*p).member1(2); /* { dg-error "'void T::member1\\(int\\)' is unavailable" "" } */
+ p->member2(1); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable" "" } */
+ (*p).member2(2); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable" "" } */
+ p->member3(p);
+ (*p).member3(p);
+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable" "" } */
+}
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C
new file mode 100644
index 0000000..3de5532
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C
@@ -0,0 +1,10 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void func(void);
+void func(void) __attribute__((unavailable));
+
+void f(void) {
+ func(); /* { dg-error "'void func\\(\\)' is unavailable" } */
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C
new file mode 100644
index 0000000..1f267ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C
@@ -0,0 +1,14 @@
+/* Check operator with __attribute__((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct Foo
+{
+ operator int() __attribute__((unavailable));
+};
+
+void g(void)
+{
+ Foo f;
+ (int)f; // { dg-error "'Foo::operator int\\(\\)' is unavailable" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C
new file mode 100644
index 0000000..b7f352e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C
@@ -0,0 +1,11 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct B {
+ virtual int foo() __attribute__((unavailable));
+};
+
+int main(void) {
+ ((B*)0)->foo(); // { dg-error "unavailable" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C
new file mode 100644
index 0000000..3beea5d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C
@@ -0,0 +1,6 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct Foo { int i; } __attribute__ ((unavailable));
+void foo() { Foo f; } // { dg-error "unavailable" }
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C
new file mode 100644
index 0000000..8a57ea0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C
@@ -0,0 +1,110 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int INT1 __attribute__((unavailable("You can't use INT1")));
+typedef INT1 INT2 __attribute__ ((__unavailable__("You can't use INT2")));
+
+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+
+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+INT1a should_not_be_unavailable;
+
+INT1 f1(void) __attribute__ ((unavailable("You can't use f1")));
+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+
+INT2 f3(void) __attribute__ ((__unavailable__("You can't use f3")));
+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable: You can't use INT2" "" } */
+int f5(INT2 x); /* { dg-error "'INT2' is unavailable" "" } */
+int f6(INT2 x) __attribute__ ((__unavailable__("You can't use f6")));
+
+typedef enum Color {red, green, blue} Color __attribute__((unavailable("You can't use Color")));
+
+int g1;
+int g2 __attribute__ ((unavailable("You can't use g2")));
+int g3 __attribute__ ((__unavailable__("You can't use g3")));
+Color k; /* { dg-error "'Color' is unavailable: You can't use Color" "" } */
+
+typedef struct {
+ int field1;
+ int field2 __attribute__ ((unavailable("You can't use field2")));
+ int field3;
+ int field4 __attribute__ ((__unavailable__("You can't use field4")));
+ union {
+ int field5;
+ int field6 __attribute__ ((unavailable("You can't use field6")));
+ } u1;
+ int field7:1;
+ int field8:1 __attribute__ ((unavailable("You can't use field8")));
+ union {
+ int field9;
+ int field10;
+ } u2 __attribute__ ((unavailable("You can't use u2")));
+} S1;
+
+int func1()
+{
+ INT1 w; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+ int x __attribute__ ((unavailable("You can't use x")));
+ int y __attribute__ ((__unavailable__("You can't use y")));
+ int z;
+ int (*pf)() = f1; /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't use f1" "" } */
+
+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable: You can't use x" "" } */
+ /* { dg-error "'y' is unavailable: You can't use y" "y" { target *-*-* } .-1 } */
+ /* { dg-error "'g2' is unavailable: You can't use g2" "g2" { target *-*-* } .-2 } */
+ /* { dg-error "'g3' is unavailable: You can't use g3" "g3" { target *-*-* } .-3 } */
+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't use f1" "f1" } */
+}
+
+int func2(S1 *p)
+{
+ S1 lp;
+
+ if (p->field1)
+ return p->field2; /* { dg-error "'S1::field2' is unavailable: You can't use field2" "" } */
+ else if (lp.field4) /* { dg-error "'S1::field4' is unavailable: You can't use field4" "" } */
+ return p->field3;
+
+ p->u1.field5 = g1 + p->field7;
+ p->u2.field9; /* { dg-error "'S1::u2' is unavailable: You can't use u2" "" } */
+ return p->u1.field6 + p->field8; /* { dg-error "'S1::<unnamed union>::field6' is unavailable: You can't use field6" "" } */
+ /* { dg-error "'S1::field8' is unavailable: You can't use field8" "field8" { target *-*-* } .-1 } */
+}
+
+struct SS1 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+} __attribute__ ((unavailable("You can't use SS1")));
+
+struct SS1 *p1; /* { dg-error "'SS1' is unavailable: You can't use SS1" "" } */
+
+struct __attribute__ ((__unavailable__("You can't use SS2"))) SS2 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+};
+
+struct SS2 *p2; /* { dg-error "'SS2' is unavailable: You can't use SS2" "" } */
+
+class T {
+ public:
+ void member1(int) __attribute__ ((unavailable("You can't use member1")));
+ void member2(INT1) __attribute__ ((__unavailable__("You can't use member2")));
+ int member3(T *);
+ int x;
+} __attribute__ ((unavailable("You can't use T")));
+
+T *p3; // { dg-error "'T' is unavailable: You can't use T" }
+
+inline void T::member1(int) {}
+
+int T::member3(T *p) // { dg-error "'T' is unavailable: You can't use T" }
+{
+ p->member1(1); /* { dg-error "'void T::member1\\(int\\)' is unavailable: You can't use member1" "" } */
+ (*p).member1(2); /* { dg-error "'void T::member1\\(int\\)' is unavailable: You can't use member1" "" } */
+ p->member2(1); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable: You can't use member2" "" } */
+ (*p).member2(2); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable: You can't use member2" "" } */
+ p->member3(p);
+ (*p).member3(p);
+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't use f1" "" } */
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C
new file mode 100644
index 0000000..c061aa3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C
@@ -0,0 +1,19 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int g_nn;
+int& g_n __attribute__((unavailable)) = g_nn;
+
+void f()
+{
+ int f_nn;
+ int& f_n __attribute__((unavailable)) = f_nn;
+ f_n = 1; // { dg-error "'f_n' is unavailable" }
+}
+
+int main()
+{
+ g_n = 1; // { dg-error "'g_n' is unavailable" }
+ f();
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C
new file mode 100644
index 0000000..334a2cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C
@@ -0,0 +1,17 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+class ToBeunavailable {
+} __attribute__ ((unavailable ("unavailable!")));
+
+typedef ToBeunavailable NotToBeunavailable; // { dg-error "'ToBeunavailable' is unavailable" }
+
+int main() {
+
+ ToBeunavailable(); // { dg-error "'ToBeunavailable' is unavailable" }
+ ToBeunavailable x; // { dg-error "'ToBeunavailable' is unavailable" }
+
+ NotToBeunavailable();
+ NotToBeunavailable y;
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C b/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C
new file mode 100644
index 0000000..4416133
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C
@@ -0,0 +1,17 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+template<typename T> struct __attribute__ ((unavailable)) S {};
+S<int> s;
+
+template <template <class> class T> struct A { };
+A<S> a;
+
+template <class T> void f() __attribute__ ((unavailable));
+
+int main()
+{
+ f<int>(); // { dg-error "unavailable" }
+ void (*p)() = f<char>; // { dg-error "unavailable" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/conv2.C b/gcc/testsuite/g++.dg/ext/conv2.C
new file mode 100644
index 0000000..baf2a43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/conv2.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fpermissive" }
+
+struct A {
+ A(int*, int);
+};
+
+void f(A);
+
+int main() {
+ const int n = 0;
+ f({&n, 42}); // { dg-warning "invalid conversion from 'const int\\*' to 'int\\*'" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary39.C b/gcc/testsuite/g++.dg/ext/flexary39.C
new file mode 100644
index 0000000..8eb81f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary39.C
@@ -0,0 +1,65 @@
+// PR c++/88578
+// { dg-do run }
+// { dg-options -Wno-pedantic }
+
+#define STR(s) #s
+#define ASSERT(exp) \
+ ((exp) ? (void)0 : (void)(__builtin_printf ("%s:%i: assertion %s failed\n", \
+ __FILE__, __LINE__, STR(exp)), \
+ __builtin_abort ()))
+
+typedef int int32_t __attribute__((mode (__SI__)));
+
+struct Ax { int32_t n, a[]; };
+struct AAx { int32_t i; Ax ax; };
+
+int32_t i = 12345678;
+
+void
+test ()
+{
+ {
+ // OK. Does not assign any elements to flexible array.
+ Ax s = { 0 };
+ ASSERT (s.n == 0);
+ }
+ {
+ // OK only for statically allocated objects, otherwise error.
+ static Ax s = { 0, { } };
+ ASSERT (s.n == 0);
+ }
+ {
+ static Ax s = { 1, { 2 } };
+ ASSERT (s.n == 1 && s.a [0] == 2);
+ }
+ {
+ static Ax s = { 2, { 3, 4 } };
+ ASSERT (s.n = 2 && s.a [0] == 3 && s.a [1] == 4);
+ }
+ {
+ static Ax s = { 123, i };
+ ASSERT (s.n == 123 && s.a [0] == i);
+ }
+ {
+ static Ax s = { 456, { i } };
+ ASSERT (s.n == 456 && s.a [0] == i);
+ }
+ {
+ int32_t j = i + 1, k = j + 1;
+ static Ax s = { 3, { i, j, k } };
+ ASSERT (s.n == 3 && s.a [0] == i && s.a [1] == j && s.a [2] == k);
+ }
+
+ {
+ // OK. Does not assign any elements to flexible array.
+ AAx s = { 1, { 2 } };
+ ASSERT (s.i == 1 && s.ax.n == 2);
+ }
+}
+
+int
+main ()
+{
+ test ();
+ test ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary40.C b/gcc/testsuite/g++.dg/ext/flexary40.C
new file mode 100644
index 0000000..ee824c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary40.C
@@ -0,0 +1,50 @@
+// PR c++/102295
+// { dg-do run }
+// { dg-options "" }
+
+struct A { int a; int b[]; };
+struct B { B (); int k; };
+struct C { int l; B m[]; };
+
+int x[4];
+A c = { 42, { ++x[0], ++x[1], ++x[2], ++x[3] } };
+A d = { 43, { 0, ++x[0], ++x[1], ++x[2], ++x[3] } };
+A e = { 44, { ++x[0], ++x[1], ++x[2], 17 } };
+A f = { 45 };
+C n = { 50, { B (), B () } };
+C o = { 51, {} };
+
+int
+main ()
+{
+ static A g = { 46, { ++x[0], ++x[1], ++x[2], ++x[3] } };
+ static A h = { 47, { 0, ++x[0], ++x[1], ++x[2], ++x[3] } };
+ static A i = { 48, { ++x[0], ++x[1], ++x[2], 18 } };
+ static A j = { 49 };
+ if (c.a != 42 || c.b[0] != 1 || c.b[1] != 1 || c.b[2] != 1 || c.b[3] != 1)
+ __builtin_abort ();
+ if (d.a != 43 || d.b[0] != 0 || d.b[1] != 2 || d.b[2] != 2 || d.b[3] != 2 || d.b[4] != 2)
+ __builtin_abort ();
+ if (e.a != 44 || e.b[0] != 3 || e.b[1] != 3 || e.b[2] != 3 || e.b[3] != 17)
+ __builtin_abort ();
+ if (f.a != 45)
+ __builtin_abort ();
+ if (g.a != 46 || g.b[0] != 4 || g.b[1] != 4 || g.b[2] != 4 || g.b[3] != 3)
+ __builtin_abort ();
+ if (h.a != 47 || h.b[0] != 0 || h.b[1] != 5 || h.b[2] != 5 || h.b[3] != 5 || h.b[4] != 4)
+ __builtin_abort ();
+ if (i.a != 48 || i.b[0] != 6 || i.b[1] != 6 || i.b[2] != 6 || i.b[3] != 18)
+ __builtin_abort ();
+ if (j.a != 49)
+ __builtin_abort ();
+ if (n.l != 50 || n.m[0].k != 42 || n.m[1].k != 42)
+ __builtin_abort ();
+ if (o.l != 51)
+ __builtin_abort ();
+ if (x[0] != 6 || x[1] != 6 || x[2] != 6 || x[3] != 4)
+ __builtin_abort ();
+}
+
+B::B () : k (42)
+{
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible6.C b/gcc/testsuite/g++.dg/ext/is_constructible6.C
new file mode 100644
index 0000000..7fce153
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible6.C
@@ -0,0 +1,10 @@
+// Verify we respect the order of trailing arguments passed to
+// __is_constructible.
+
+struct A { };
+struct B { };
+struct C { C(A, B); };
+
+extern int n[true];
+extern int n[ __is_constructible(C, A, B)];
+extern int n[!__is_constructible(C, B, A)];
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C
new file mode 100644
index 0000000..f6fbf8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C
@@ -0,0 +1,17 @@
+// PR c++/102535
+// Verify __is_trivially_constructible works with multi-arg paren init of
+// aggrs.
+
+struct A { int x; };
+struct B { float y; };
+struct C { char z; };
+struct D { A a; B b; C c; };
+
+extern int n[1 + __is_trivially_constructible(D, A)];
+extern int n[1 + __is_trivially_constructible(D, A, B)];
+extern int n[1 + __is_trivially_constructible(D, A, B, C)];
+#if __cpp_aggregate_paren_init
+extern int n[1 + true];
+#else
+extern int n[1 + false];
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/vla22.C b/gcc/testsuite/g++.dg/ext/vla22.C
index 967adb9..2308ee7 100644
--- a/gcc/testsuite/g++.dg/ext/vla22.C
+++ b/gcc/testsuite/g++.dg/ext/vla22.C
@@ -6,4 +6,4 @@ void
f ()
{
const int tbl[(long) "h"] = { 12 }; // { dg-error "size of array .tbl. is not an integral constant-expression" }
-} // { dg-warning "narrowing conversion" "" { target c++11 } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/gcov/gcov.py b/gcc/testsuite/g++.dg/gcov/gcov.py
index a8c4ea9..5137f3a 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov.py
+++ b/gcc/testsuite/g++.dg/gcov/gcov.py
@@ -5,6 +5,9 @@ import os
def gcov_from_env():
# return parsed JSON content a GCOV_PATH file
- json_filename = os.environ['GCOV_PATH'] + '.gcov.json.gz'
+ json_filename = os.environ['GCOV_PATH']
+ # strip extension
+ json_filename = json_filename[:json_filename.rindex('.')]
+ json_filename += '.gcov.json.gz'
json_data = gzip.open(json_filename).read()
return json.loads(json_data)
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-4.C b/gcc/testsuite/g++.dg/gomp/allocate-4.C
new file mode 100644
index 0000000..dd5e5f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-4.C
@@ -0,0 +1,108 @@
+// { 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 (allocator (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 (allocator (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 (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ }
+ int s;
+};
+
+template <typename T>
+struct U
+{
+ int foo ()
+ {
+ #pragma omp parallel allocate (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ return 1;
+ }
+ T s;
+};
+
+template <typename T, int N>
+int foo (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x)
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int bar (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t): x) // { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ return 0;
+}
+
+template <typename T, int N>
+int baz (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int qux ()
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (align ((T) 16): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+omp_allocator_handle_t h;
+int a = foo<omp_allocator_handle_t, 16> (h);
+int b = bar (0);
+int c = U<int> ().foo ();
+int d = baz<omp_allocator_handle_t, 13> (h);
+int e = qux<long double> ();
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-18.C b/gcc/testsuite/g++.dg/gomp/atomic-18.C
index 896cf46..adaee84 100644
--- a/gcc/testsuite/g++.dg/gomp/atomic-18.C
+++ b/gcc/testsuite/g++.dg/gomp/atomic-18.C
@@ -1,6 +1,7 @@
// { dg-do compile }
// { dg-additional-options "-fdump-tree-original" }
-// { dg-final { scan-tree-dump-times "omp atomic release" 5 "original" } }
+// { dg-final { scan-tree-dump-times "omp atomic release" 4 "original" } }
+// { dg-final { scan-tree-dump-times "omp atomic acq_rel" 1 "original" } }
// { dg-final { scan-tree-dump-times "omp atomic seq_cst" 1 "original" } }
// { dg-final { scan-tree-dump-times "omp atomic relaxed" 2 "original" } }
// { dg-final { scan-tree-dump-times "omp atomic capture acq_rel" 3 "original" } }
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-20.C b/gcc/testsuite/g++.dg/gomp/atomic-20.C
new file mode 100644
index 0000000..cb7a37b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/atomic-20.C
@@ -0,0 +1,104 @@
+// { dg-do compile }
+
+int x, r, z;
+double d, v;
+long double ld;
+
+template <int N>
+void
+foo (int y, double e, long double f)
+{
+ #pragma omp atomic compare update seq_cst
+ x = x > y ? y : x;
+ #pragma omp atomic compare relaxed
+ d = e > d ? e : d;
+ #pragma omp atomic compare
+ d = f < d ? f : d;
+ #pragma omp atomic compare seq_cst fail(relaxed)
+ x = 12U < x ? 12U : x;
+ #pragma omp atomic compare
+ x = x == 7 ? 24 : x;
+ #pragma omp atomic compare
+ x = x == 123UL ? 256LL : x;
+ #pragma omp atomic compare
+ ld = ld == f ? f + 5.0L : ld;
+ #pragma omp atomic compare
+ if (x == 9) { x = 5; }
+ #pragma omp atomic compare
+ if (x > 5) { x = 5; }
+ #pragma omp atomic compare
+ if (7 > x) { x = 7; }
+ #pragma omp atomic compare update capture seq_cst fail(acquire)
+ v = d = f > d ? f : d;
+ #pragma omp atomic update capture compare
+ v = x = x < 24ULL ? 24ULL : x;
+ #pragma omp atomic compare, capture, update
+ v = x = x == e ? f : x;
+ #pragma omp atomic capture compare
+ { v = d; if (d > e) { d = e; } }
+ #pragma omp atomic compare capture
+ { if (e < d) { d = e; } v = d; }
+ #pragma omp atomic compare capture
+ { y = x; if (x == 42) { x = 7; } }
+ #pragma omp atomic capture compare weak
+ { if (x == 42) { x = 7; } y = x; }
+ #pragma omp atomic capture compare fail(seq_cst)
+ if (d == 8.0) { d = 16.0; } else { v = d; }
+ #pragma omp atomic capture compare
+ { r = x == 8; if (r) { x = 24; } }
+ #pragma omp atomic compare capture
+ { r = x == y; if (r) { x = y + 6; } else { z = x; } }
+}
+
+template <typename I, typename D, typename LD>
+void
+bar (I &x, I &r, I &z, D &d, D &v, LD &ld, I y, D e, LD f)
+{
+ #pragma omp atomic compare update seq_cst
+ x = x > y ? y : x;
+ #pragma omp atomic compare relaxed
+ d = e > d ? e : d;
+ #pragma omp atomic compare
+ d = f < d ? f : d;
+ #pragma omp atomic compare seq_cst fail(relaxed)
+ x = 12U < x ? 12U : x;
+ #pragma omp atomic compare
+ x = x == 7 ? 24 : x;
+ #pragma omp atomic compare
+ x = x == 123UL ? 256LL : x;
+ #pragma omp atomic compare
+ ld = ld == f ? f + 5.0L : ld;
+ #pragma omp atomic compare
+ if (x == 9) { x = 5; }
+ #pragma omp atomic compare
+ if (x > 5) { x = 5; }
+ #pragma omp atomic compare
+ if (7 > x) { x = 7; }
+ #pragma omp atomic compare update capture seq_cst fail(acquire)
+ v = d = f > d ? f : d;
+ #pragma omp atomic update capture compare
+ v = x = x < 24ULL ? 24ULL : x;
+ #pragma omp atomic compare, capture, update
+ v = x = x == e ? f : x;
+ #pragma omp atomic capture compare
+ { v = d; if (d > e) { d = e; } }
+ #pragma omp atomic compare capture
+ { if (e < d) { d = e; } v = d; }
+ #pragma omp atomic compare capture
+ { y = x; if (x == 42) { x = 7; } }
+ #pragma omp atomic capture compare weak
+ { if (x == 42) { x = 7; } y = x; }
+ #pragma omp atomic capture compare fail(seq_cst)
+ if (d == 8.0) { d = 16.0; } else { v = d; }
+ #pragma omp atomic capture compare
+ { r = x == 8; if (r) { x = 24; } }
+ #pragma omp atomic compare capture
+ { r = x == y; if (r) { x = y + 6; } else { z = x; } }
+}
+
+void
+baz (int y, double e, long double f)
+{
+ foo <0> (y, e, f);
+ bar (x, r, z, d, v, ld, y, e, f);
+}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-5.C b/gcc/testsuite/g++.dg/gomp/atomic-5.C
index 78f6344..e2fd591 100644
--- a/gcc/testsuite/g++.dg/gomp/atomic-5.C
+++ b/gcc/testsuite/g++.dg/gomp/atomic-5.C
@@ -23,7 +23,7 @@ void f1(void)
#pragma omp atomic
bar() += 1; /* { dg-error "lvalue required" } */
#pragma omp atomic a /* { dg-error "expected end of line" } */
- x++; /* { dg-error "expected 'read', 'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
+ x++; /* { dg-error "expected 'read', 'write', 'update', 'capture', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
#pragma omp atomic
; /* { dg-error "expected primary-expression" } */
#pragma omp atomic
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C
index cd20845..2a5f2cf 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-1.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C
@@ -63,7 +63,7 @@ foo (int d, int m, int i1, int i2, int p, int *idp, int s,
ll++;
[[omp::directive (distribute
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16)
- allocate (omp_default_mem_alloc:f))]]
+ allocate (omp_default_mem_alloc:f) order(concurrent))]]
for (int i = 0; i < 64; i++)
ll++;
}
@@ -85,14 +85,27 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s,
[[omp::directive (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) allocate (p))]]
+ lastprivate (l) schedule(static, 4) copyin(t) allocate (p))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
+ [[omp::directive (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) allocate (p))]]
for (int i = 0; i < 64; i++)
ll++;
[[omp::directive (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) allocate (f))]]
+ safelen(8) simdlen(4) aligned(q: 32) copyin(t) allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
+ [[omp::directive (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) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
[[omp::directive (distribute simd
@@ -207,7 +220,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
;
[[omp::sequence (omp::directive (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)
+ shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) order(concurrent)
collapse(1) dist_schedule(static, 16) nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]]
for (int i = 0; i < 64; i++)
;
@@ -292,7 +305,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
[[omp::sequence (directive (target nowait depend(inout: dd[0]) in_reduction(+:r2)),
directive (teams distribute
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl)
- collapse(1) dist_schedule(static, 16) allocate (omp_default_mem_alloc: f)))]]
+ collapse(1) dist_schedule(static, 16) allocate (omp_default_mem_alloc: f) order(concurrent)))]]
for (int i = 0; i < 64; i++)
;
[[omp::directive (teams
@@ -327,20 +340,36 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
ll++;
[[omp::directive (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)
+ collapse(1) dist_schedule(static, 16)
if (parallel: i2) num_threads (nth) proc_bind(spread)
lastprivate (l) schedule(static, 4) copyin(t) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (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) allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (teams distribute parallel for simd
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)
safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t)
allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (teams distribute parallel for simd
+ 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)
+ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm)
+ allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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)
@@ -528,6 +557,12 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
;
[[omp::directive (flush acq_rel)]]
;
+ [[omp::directive (flush acquire)]]
+ ;
+ [[omp::directive (flush release)]]
+ ;
+ [[omp::directive (flush seq_cst)]]
+ ;
[[omp::directive (flush (p, f))]]
;
[[omp::directive (simd
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-14.C b/gcc/testsuite/g++.dg/gomp/attrs-14.C
new file mode 100644
index 0000000..959f776
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-14.C
@@ -0,0 +1,4 @@
+// PR c++/102413
+// { dg-do compile { target c++11 } }
+
+[[omp::directive(error]]; // { dg-error "expected|declare" }
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C
index 5c54905..c00be7f 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-2.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C
@@ -63,7 +63,7 @@ foo (int d, int m, int i1, int i2, int p, int *idp, int s,
ll++;
[[omp::directive (distribute,
private (p),firstprivate (f),collapse(1),dist_schedule(static, 16),
- allocate (omp_default_mem_alloc:f))]]
+ allocate (omp_default_mem_alloc:f),order(concurrent))]]
for (int i = 0; i < 64; i++)
ll++;
}
@@ -85,14 +85,27 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s,
[[omp::directive (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),allocate (p))]]
+ lastprivate (l),schedule(static, 4),copyin(t),allocate (p))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
+ [[omp::directive (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),allocate (p))]]
for (int i = 0; i < 64; i++)
ll++;
[[omp::directive (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),allocate (f))]]
+ safelen(8),simdlen(4),aligned(q: 32),copyin(t),allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
+ [[omp::directive (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),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
[[omp::directive (distribute simd,
@@ -207,7 +220,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
;
[[omp::sequence (omp::directive (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),
+ shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl),order(concurrent),
collapse(1),dist_schedule(static, 16),nowait depend(inout: dd[0]),allocate (omp_default_mem_alloc:f),in_reduction(+:r2)))]]
for (int i = 0; i < 64; i++)
;
@@ -292,7 +305,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
[[omp::sequence (directive (target, nowait,depend(inout: dd[0]),in_reduction(+:r2)),
directive (teams distribute,
private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl),
- collapse(1),dist_schedule(static, 16),allocate (omp_default_mem_alloc: f)))]]
+ collapse(1),dist_schedule(static, 16),allocate (omp_default_mem_alloc: f),order(concurrent)))]]
for (int i = 0; i < 64; i++)
;
[[omp::directive (teams,
@@ -327,20 +340,36 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
ll++;
[[omp::directive (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),
+ collapse(1),dist_schedule(static, 16),
if (parallel: i2),num_threads (nth),proc_bind(spread),
lastprivate (l),schedule(static, 4),copyin(t),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (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),allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (teams distribute parallel for simd,
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),
safelen(8),simdlen(4),aligned(q: 32),if (simd: i3),nontemporal(ntm),copyin(t),
allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (teams distribute parallel for simd,
+ 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),
+ safelen(8),simdlen(4),aligned(q: 32),if (simd: i3),nontemporal(ntm),
+ allocate (f))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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),
@@ -528,6 +557,12 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
;
[[omp::directive (flush, acq_rel)]]
;
+ [[omp::directive (flush, acquire)]]
+ ;
+ [[omp::directive (flush, release)]]
+ ;
+ [[omp::directive (flush, seq_cst)]]
+ ;
[[omp::directive (flush (p, f))]]
;
[[omp::directive (simd,
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-6.C b/gcc/testsuite/g++.dg/gomp/attrs-6.C
index 30b47e1..af8b973 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-6.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-6.C
@@ -26,6 +26,41 @@ foo ()
#pragma omp section
{ a[3]++; }
}
+ #pragma omp parallel sections
+ {
+ #pragma omp section
+ a[0]++;
+ a[4]++;
+ l1: a[5]++;
+ if (a[5] == 42) goto l1;
+ [[omp::directive (section)]] {
+ a[1]++;
+ a[6]++;
+ } [[omp::directive (section)]]
+ a[2]++;
+ a[7]++;
+ #pragma omp section
+ { a[3]++; }
+ a[8]++;
+ }
+ [[omp::directive (parallel sections)]]
+ {
+ #pragma omp section
+ a[0]++;
+ a[4]++;
+ [[omp::directive (section)]] {
+ a[1]++;
+ a[5]++;
+ } [[omp::directive (section)]]
+ a[2]++;
+ l2: a[6]++;
+ if (a[6] == 42)
+ goto l2;
+ a[7]++;
+ #pragma omp section
+ a[8]++;
+ { a[3]++; }
+ }
}
int
@@ -46,5 +81,23 @@ bar (int a, int *c, int *d, int *e, int *f)
#pragma omp scan inclusive (a)
d[i] = a;
}
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ int t = a;
+ d[i] = t;
+ [[omp::directive (scan, exclusive (a))]]
+ int u = c[i];
+ a += u;
+ }
+ [[omp::directive (simd reduction (inscan, +: a))]]
+ for (i = 0; i < 64; i++)
+ {
+ int t = c[i];
+ a += t;
+ #pragma omp scan inclusive (a)
+ int u = a;
+ d[i] = u;
+ }
return a;
}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-7.C b/gcc/testsuite/g++.dg/gomp/attrs-7.C
index cf84281..900ef66 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-7.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-7.C
@@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int *f)
{
d[i] = a;
[[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" }
- a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
- }
+ // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+ a += c[i]; // { dg-error "expected" }
+ } // { dg-error "expected" }
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
for (i = 0; i < 64; i++)
{
a += c[i];
[[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" }
- d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
- }
+ // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+ d[i] = a; // { dg-error "expected" }
+ } // { dg-error "expected" }
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
for (i = 0; i < 64; i++)
{
d[i] = a;
[[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" }
- a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
- }
+ // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+ a += c[i]; // { dg-error "expected" }
+ } // { dg-error "expected" }
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
for (i = 0; i < 64; i++)
{
d[i] = a;
[[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" }
- a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
- }
+ // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+ a += c[i]; // { dg-error "expected" }
+ } // { dg-error "expected" }
[[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
for (i = 0; i < 64; i++)
{
diff --git a/gcc/testsuite/g++.dg/gomp/default-1.C b/gcc/testsuite/g++.dg/gomp/default-1.C
new file mode 100644
index 0000000..e39df12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/default-1.C
@@ -0,0 +1,112 @@
+namespace N
+{
+ int x;
+ extern int z;
+}
+
+struct S
+{
+ static int s;
+};
+
+#if __cpp_variable_templates >= 201304
+template <int N>
+int t = N;
+#endif
+
+void
+foo (void)
+{
+ int y = 0, i;
+ static int w;
+ #pragma omp task default(firstprivate) /* { dg-message "note: enclosing 'task'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
+ S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'task'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'task'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp taskloop default(firstprivate) /* { dg-message "note: enclosing 'taskloop'" } */
+ for (i = 0; i < 64; i++)
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
+ S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'taskloop'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'taskloop'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp teams default(firstprivate) /* { dg-message "note: enclosing 'teams'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
+ S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'teams'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'teams'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp parallel default(firstprivate) /* { dg-message "note: enclosing 'parallel'" } */
+ {
+ y++; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
+ w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
+ S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'parallel'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'parallel'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp task default(private) /* { dg-message "note: enclosing 'task'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
+ S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'task'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'task'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp taskloop default(private) /* { dg-message "note: enclosing 'taskloop'" } */
+ for (i = 0; i < 64; i++)
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
+ S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'taskloop'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'taskloop'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp teams default(private) /* { dg-message "note: enclosing 'teams'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
+ S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'teams'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'teams'" "" { target c++14 } } */
+#endif
+ }
+ #pragma omp parallel default(private) /* { dg-message "note: enclosing 'parallel'" } */
+ {
+ y = 1; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
+ w = 1; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
+ S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'parallel'" } */
+ N::x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
+ N::z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
+#if __cpp_variable_templates >= 201304
+ t<5>++; /* { dg-error "'t' not specified in enclosing 'parallel'" "" { target c++14 } } */
+#endif
+ }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/sections-2.C b/gcc/testsuite/g++.dg/gomp/sections-2.C
index aabdfaf..6d8305a 100644
--- a/gcc/testsuite/g++.dg/gomp/sections-2.C
+++ b/gcc/testsuite/g++.dg/gomp/sections-2.C
@@ -19,11 +19,11 @@ void foo(void)
{
#pragma omp section
bar(2);
- bar(3); // { dg-error "expected" }
+ bar(3);
bar(4);
#pragma omp section
bar(5);
- bar(6); // { dg-error "expected" }
+ bar(6);
bar(7);
}
}
diff --git a/gcc/testsuite/g++.dg/gomp/simd-3.C b/gcc/testsuite/g++.dg/gomp/simd-3.C
new file mode 100644
index 0000000..db66c08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/simd-3.C
@@ -0,0 +1,16 @@
+// PR middle-end/102492
+// { dg-do compile }
+
+struct S { S (int); };
+void bar (S &);
+
+void
+foo ()
+{
+ #pragma omp simd
+ for (int i = 0; i < 64; i++)
+ {
+ S s = 26;
+ bar (s);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
index 62b2132..fba3d1a 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 -mkl -mwidekl -mavxvnni" } */
+/* { 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 -mavx512fp16" } */
/* 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 843aa2b..5cc0fa8 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 -mkl -mwidekl -mavxvnni" } */
+/* { 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 -mavx512fp16" } */
/* 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/parse/pr101783.C b/gcc/testsuite/g++.dg/parse/pr101783.C
new file mode 100644
index 0000000..4e0a435
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr101783.C
@@ -0,0 +1,5 @@
+template<class T> struct A{
+ typedef T& Type;
+};
+template<class T> void f(const typename A<T>::Type){}
+template <> void f<int>(const typename A<int>::Type){}
diff --git a/gcc/testsuite/g++.dg/pr101331.C b/gcc/testsuite/g++.dg/pr101331.C
new file mode 100644
index 0000000..015aba2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr101331.C
@@ -0,0 +1,7 @@
+// PR c++/101331
+// { dg-do compile }
+// { dg-options "-fsanitize-coverage=trace-pc -O2 -std=c++11" }
+
+int a[2];
+int b = 1;
+int c { b && (a[b] = 0) };
diff --git a/gcc/testsuite/g++.dg/pr102359_1.C b/gcc/testsuite/g++.dg/pr102359_1.C
new file mode 100644
index 0000000..da643cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102359_1.C
@@ -0,0 +1,13 @@
+/* PR middle-end/102359 ICE gimplification failed since
+ r12-3433-ga25e0b5e6ac8a77a. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target c++17 } */
+
+struct A {
+ double a = 111;
+ auto foo() {
+ return [*this] { return a; };
+ }
+};
+int X = A{}.foo()();
diff --git a/gcc/testsuite/g++.dg/pr102359_2.C b/gcc/testsuite/g++.dg/pr102359_2.C
new file mode 100644
index 0000000..d026d72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102359_2.C
@@ -0,0 +1,13 @@
+/* PR middle-end/102359 ICE gimplification failed since
+ r12-3433-ga25e0b5e6ac8a77a. */
+/* { dg-do run} */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target c++17 } */
+
+int main()
+{
+ int i = 42;
+ auto l = [=]() mutable { return i; };
+ if (l() != i)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/pr102360.C b/gcc/testsuite/g++.dg/pr102360.C
new file mode 100644
index 0000000..fdf9e08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102360.C
@@ -0,0 +1,54 @@
+// { dg-do compile }
+// { dg-options "-fno-tree-dse -O1 -ftrivial-auto-var-init=pattern" }
+
+class A;
+template <typename _Tp, int m, int n> class B {
+public:
+ _Tp val[m * n];
+};
+class C {
+public:
+ C(A);
+};
+struct D {
+ D();
+ unsigned long &operator[](int);
+ unsigned long *p;
+};
+class A {
+public:
+ template <typename _Tp, int m, int n> A(const B<_Tp, m, n> &, bool);
+ int rows, cols;
+ unsigned char *data;
+ unsigned char *datastart;
+ unsigned char *dataend;
+ unsigned char *datalimit;
+ D step;
+};
+template <typename _Tp, int m, int n>
+A::A(const B<_Tp, m, n> &p1, bool)
+ : rows(m), cols(n) {
+ step[0] = cols * sizeof(_Tp);
+ datastart = data = (unsigned char *)p1.val;
+ datalimit = dataend = datastart + rows * step[0];
+}
+class F {
+public:
+ static void compute(C);
+ template <typename _Tp, int m, int n, int nm>
+ static void compute(const B<_Tp, m, n> &, B<_Tp, nm, 1> &, B<_Tp, m, nm> &,
+ B<_Tp, n, nm> &);
+};
+D::D() {}
+unsigned long &D::operator[](int p1) { return p[p1]; }
+template <typename _Tp, int m, int n, int nm>
+void F::compute(const B<_Tp, m, n> &, B<_Tp, nm, 1> &, B<_Tp, m, nm> &,
+ B<_Tp, n, nm> &p4) {
+ A a(p4, false);
+ compute(a);
+}
+void fn1() {
+ B<double, 4, 4> b, c, e;
+ B<double, 4, 1> d;
+ F::compute(b, d, c, e);
+}
diff --git a/gcc/testsuite/g++.dg/pr88173-1.C b/gcc/testsuite/g++.dg/pr88173-1.C
new file mode 100644
index 0000000..08fcf97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr88173-1.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=c++11" } */
+
+#define big __builtin_huge_val()
+#define nan __builtin_nan("")
+
+constexpr bool b1 = big > nan;
+constexpr bool b2 = nan < big;
+
diff --git a/gcc/testsuite/g++.dg/pr88173-2.C b/gcc/testsuite/g++.dg/pr88173-2.C
new file mode 100644
index 0000000..aa7d784
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr88173-2.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsignaling-nans -std=c++11" } */
+
+#define big __builtin_huge_val()
+#define nan __builtin_nan("")
+
+constexpr bool b1 = big > nan;
+constexpr bool b2 = nan < big;
+
diff --git a/gcc/testsuite/g++.dg/rtti/undeclared1.C b/gcc/testsuite/g++.dg/rtti/undeclared1.C
new file mode 100644
index 0000000..9594c22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/undeclared1.C
@@ -0,0 +1,5 @@
+// PR c++/48396
+
+namespace std {
+ type_info *p; // { dg-error "type_info" }
+}
diff --git a/gcc/testsuite/g++.dg/spellcheck-pr77565.C b/gcc/testsuite/g++.dg/spellcheck-pr77565.C
new file mode 100644
index 0000000..2257f7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/spellcheck-pr77565.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+typdef int my_int; // { dg-error "1: 'typdef' does not name a type; did you mean 'typedef'\\?" }
+inlien int i_fn(); // { dg-error "1: 'inlien' does not name a type; did you mean 'inline'\\?" }
+coonst int ci = 1; // { dg-error "1: 'coonst' does not name a type; did you mean 'const'\\?" }
+voltil int vi = 2; // { dg-error "1: 'voltil' does not name a type; did you mean 'volatile'\\?" }
+
+class my_class {
+ explict my_class(int); // { dg-error "3: 'explict' does not name a type; did you mean 'explicit'\\?" }
+ friends double f_fn(); // { dg-error "3: 'friends' does not name a type; did you mean 'friend'\\?" }
+ virtial double v_fn(); // { dg-error "3: 'virtial' does not name a type; did you mean 'virtual'\\?" }
+};
diff --git a/gcc/testsuite/g++.dg/template/access2.C b/gcc/testsuite/g++.dg/template/access2.C
index 0620c10..4a80bb4 100644
--- a/gcc/testsuite/g++.dg/template/access2.C
+++ b/gcc/testsuite/g++.dg/template/access2.C
@@ -5,6 +5,9 @@
template <class T> struct A {
typename T::X x; // { dg-error "this context" }
+};
+
+template <class T> struct A2 {
int f() { return T::i; } // { dg-error "this context" }
};
@@ -16,5 +19,6 @@ class B {
int main()
{
A<B> ab; // { dg-message "required" }
- ab.f(); // { dg-message "required" }
+ A2<B> a2b;
+ a2b.f(); // { dg-message "required" }
}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-15.C b/gcc/testsuite/g++.dg/template/canon-type-15.C
new file mode 100644
index 0000000..b001b5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-15.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+namespace g {
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+}
+static_assert(decltype(g::return_size('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-16.C b/gcc/testsuite/g++.dg/template/canon-type-16.C
new file mode 100644
index 0000000..99361cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-16.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+template<bool u> struct bool_c{ static constexpr bool value = u; };
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+struct foo { void operator()() noexcept; };
+static_assert(decltype(noexcepty(foo{}))::value, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-17.C b/gcc/testsuite/g++.dg/template/canon-type-17.C
new file mode 100644
index 0000000..0555c8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-17.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+static_assert(decltype(return_size('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/canon-type-18.C b/gcc/testsuite/g++.dg/template/canon-type-18.C
new file mode 100644
index 0000000..2510181
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-18.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-pedantic" }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+static_assert(decltype(get_align('a'))::value == 1u, "");
diff --git a/gcc/testsuite/g++.dg/template/conv17.C b/gcc/testsuite/g++.dg/template/conv17.C
new file mode 100644
index 0000000..f0f10f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv17.C
@@ -0,0 +1,63 @@
+// PR c++/101904
+// Verify we stop at the first bad argument conversion when considering a
+// candidate during overload resolution.
+
+template<class T>
+struct A { typedef typename T::type type; };
+
+struct B {
+ // A conversion function that always induces a hard error when instantiated.
+ template<class T> B(T, typename A<T>::type = 0);
+};
+
+struct C {
+ template<class T> void f(T, typename A<T>::type); // #1
+ template<class T> void f(T, T) const; // #2
+
+ static void g(int*, B); // #3
+ static void g(int, int); // #4
+
+#if __cpp_ref_qualifiers
+ void h(B) &; // #5
+ void h(int) &&; // #6
+#endif
+};
+
+int main() {
+ const C c;
+
+ // The bad conversion for the 'this' argument should preclude us from further
+ // considering the non-const #1 (which would have caused a hard error during
+ // instantiation). This behavior is essentially DR 1391 extended to the
+ // 'this' argument.
+ c.f(0, 0); // resolves to #2
+ c.f<int>(0, 0);
+
+ // Likewise for the bad conversion for the 1st argument in #3.
+ C::g(42, 42); // resolves to #4
+
+#if __cpp_ref_qualifiers
+ // Likewise for the bad 'this' conversion in #5.
+ C().h(0); // resolves to #6
+#endif
+}
+
+#if __cpp_concepts
+// Test the same calls in a SFINAE context.
+template<class T>
+concept D = requires (const T t) {
+ t.f(0, 0);
+ t.template f<int>(0, 0);
+ T::g(42, 42);
+ T().h(0);
+};
+
+static_assert(D<C>);
+
+// Test that when there's no strictly viable candidate and we're in a
+// SFINAE context, we still stop at the first bad argument conversion.
+template<class T>
+concept E = requires { T().h(nullptr); };
+
+static_assert(!E<C>);
+#endif
diff --git a/gcc/testsuite/g++.dg/template/dependent-name15.C b/gcc/testsuite/g++.dg/template/dependent-name15.C
new file mode 100644
index 0000000..1c34bc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name15.C
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template <class T> void f(T t1) {
+ A<sizeof(t1)>::foo();
+}
+
+template <class T> void g(T t2) {
+ /* if the comparing_specializations check breaks in cp_tree_equal
+ case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+ A<sizeof(t2)>::foo(); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+}
+
+void h() {
+ f(0);
+ g('0');
+}
diff --git a/gcc/testsuite/g++.dg/template/dependent-name16.C b/gcc/testsuite/g++.dg/template/dependent-name16.C
new file mode 100644
index 0000000..ef8c4f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name16.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template<class T1> auto f(T1 t1) -> decltype(A<sizeof(t1)>::foo());
+
+/* if the comparing_specializations check breaks in cp_tree_equal
+case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+template<class T2> auto g(T2 t2) -> decltype(A<sizeof(t2)>::foo()); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+
+void h() {
+ f(0);
+ g('0'); // { dg-error "no matching function" }
+}
diff --git a/gcc/testsuite/g++.dg/template/dtor11.C b/gcc/testsuite/g++.dg/template/dtor11.C
new file mode 100644
index 0000000..9bb58b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor11.C
@@ -0,0 +1,22 @@
+template <class T>
+struct B
+{
+ void f(T *p)
+ {
+ p->template A<int>::~A<int>();
+ p->A::~A();
+ p->~A<int>();
+ p->~A();
+ p->~T();
+ p->T::~T();
+ }
+};
+
+template <class T>
+struct A
+{ };
+
+int main()
+{
+ B<A<int> >().f(0);
+}
diff --git a/gcc/testsuite/g++.dg/template/dtor5.C b/gcc/testsuite/g++.dg/template/dtor5.C
index 8fa4eeb..d9a1c69 100644
--- a/gcc/testsuite/g++.dg/template/dtor5.C
+++ b/gcc/testsuite/g++.dg/template/dtor5.C
@@ -11,7 +11,7 @@ template <class T> void f(A<T> *ap) {
}
template <class T> void g(A<T> *ap) {
- ap->~B(); // { dg-error "destructor name" }
+ ap->~B(); // { dg-error "" }
}
int main()
diff --git a/gcc/testsuite/g++.dg/template/error56.C b/gcc/testsuite/g++.dg/template/error56.C
index e85471a..71206a1 100644
--- a/gcc/testsuite/g++.dg/template/error56.C
+++ b/gcc/testsuite/g++.dg/template/error56.C
@@ -3,12 +3,12 @@
struct A
{
template <class T> void f(T);
- void f();
+ void f(int);
};
int main()
{
- A().f<1>(); // { dg-error "f<1>" }
+ A().f<1>(0); // { dg-error "f<1>" }
// { dg-error "type/value mismatch at argument 1" "" { target *-*-* } .-1 }
// { dg-message "expected a type, got .1." "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/g++.dg/template/explicit-args6.C b/gcc/testsuite/g++.dg/template/explicit-args6.C
new file mode 100644
index 0000000..d853564
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-args6.C
@@ -0,0 +1,34 @@
+// PR c++/101460
+// { dg-do compile { target c++11 } }
+
+template<bool> struct enable_if { };
+template<> struct enable_if<true> { using type = void; };
+
+template<bool B>
+using enable_if_t = typename enable_if<B>::type;
+
+struct tuple { };
+struct pair { };
+
+template<unsigned N> enable_if_t<N == 1> get(tuple&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(const tuple&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(pair&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(const pair&) { } // { dg-bogus "candidate" }
+
+template<int N>
+constexpr unsigned
+frob()
+{
+ static_assert(N == 1, "user-friendly diagnostic"); // { dg-error "user-friendly" }
+ // narrowing check, reject negative values
+ return unsigned{N}; // { dg-prune-output "narrowing" }
+} // { dg-prune-output "flows off the end" }
+// { dg-prune-output "not a return-statement" }
+
+template<int N> void get_n(tuple& t) { get<frob<N>()>(t); } // { dg-error "" }
+
+int main()
+{
+ tuple t;
+ get_n<-1>(t);
+}
diff --git a/gcc/testsuite/g++.dg/template/explicit-args7.C b/gcc/testsuite/g++.dg/template/explicit-args7.C
new file mode 100644
index 0000000..fb5e89e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-args7.C
@@ -0,0 +1,33 @@
+// PR c++/12672
+// Verify we don't substitute explicit template arguments into
+// candidate function templates when the arity of the function
+// template disagrees with the arity of the call.
+
+template<class T>
+struct A { typedef typename T::type type; };
+
+template<class T> void f(T); // arity 1
+template<class T> void f(T, T, T); // arity 3
+
+template<class T> typename A<T>::type f(T, T); // arity 2
+template<class T, class U> typename A<T>::type f(U, U); // arity 2
+
+struct B {
+ template<class T> void f(T); // arity 1
+ template<class T> void f(T, T, T); // arity 3
+
+ template<class T> typename A<T>::type f(T, T); // arity 2
+ template<class T, class U> typename A<T>::type f(U, U); // arity 2
+};
+
+int main() {
+ // If overload resolution attempts deduction for any of the arity-2 function
+ // templates, the substitution of explicit arguments into the template would
+ // cause a hard error.
+ f<int>(1);
+ f<int>(1, 1, 1);
+
+ B b;
+ b.f<int>(1);
+ b.f<int>(1, 1, 1);
+}
diff --git a/gcc/testsuite/g++.dg/template/fnspec2.C b/gcc/testsuite/g++.dg/template/fnspec2.C
new file mode 100644
index 0000000..7a4b101
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fnspec2.C
@@ -0,0 +1,9 @@
+template <class T>
+void f(T);
+
+template<> void f(int, ...); // { dg-error "match" }
+
+template <class T>
+void g(T, ...);
+
+template<> void g(int); // { dg-error "match" }
diff --git a/gcc/testsuite/g++.dg/template/param6.C b/gcc/testsuite/g++.dg/template/param6.C
new file mode 100644
index 0000000..8306e75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/param6.C
@@ -0,0 +1,32 @@
+// PR c++/61355
+// Verify we perform array-to-pointer and function-to-pointer conversion
+// on the substituted/deduced type of an NTTP.
+
+int f();
+int p[5];
+
+namespace cpp98 {
+ template<class T, T> struct X;
+ typedef X<int(), f> ty1;
+ typedef X<int[5], p> ty2;
+}
+
+namespace cpp11 {
+#if __cpp_variadic_templates
+ template<class T, T...> struct X;
+ using ty1 = X<int(), f>;
+ using ty2 = X<int[5], p>;
+#endif
+}
+
+namespace cpp17 {
+#if __cpp_nontype_template_parameter_auto
+ template<decltype(auto)> struct X;
+ using ty1 = X<f>;
+ using ty2 = X<p>;
+
+ template<decltype(auto)...> struct Y;
+ using ty3 = Y<f>;
+ using ty4 = Y<p>;
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/template/parm-cv1.C b/gcc/testsuite/g++.dg/template/parm-cv1.C
new file mode 100644
index 0000000..2677992
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv1.C
@@ -0,0 +1,15 @@
+// CWG 1001
+
+template<class T> struct A {
+ typedef T arr[3];
+};
+
+template<class T> void f(const typename A<T>::arr) { } // #1
+
+template void f<int>(const A<int>::arr);
+
+template <class T> struct B {
+ void g(T);
+};
+
+template <class T> void B<T>::g(const T) { } // #2
diff --git a/gcc/testsuite/g++.dg/template/parm-cv2.C b/gcc/testsuite/g++.dg/template/parm-cv2.C
new file mode 100644
index 0000000..cd40e86
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv2.C
@@ -0,0 +1,23 @@
+// PR c++/51851
+
+template<class T>
+struct A
+{
+ typedef double Point[2];
+ virtual double calculate(const Point point) const = 0;
+};
+
+template<class T>
+struct B : public A<T>
+{
+ virtual double calculate(const typename A<T>::Point point) const
+ {
+ return point[0];
+ }
+};
+
+int main()
+{
+ B<int> b;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/parm-cv3.C b/gcc/testsuite/g++.dg/template/parm-cv3.C
new file mode 100644
index 0000000..1b69c3b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/parm-cv3.C
@@ -0,0 +1,142 @@
+// CWG 1001/1322
+
+// PR c++/101402
+// PR c++/102033
+// PR c++/102034
+// PR c++/102039
+// PR c++/102044
+
+namespace test2{
+template <class T>
+void f(const T);
+
+template<>
+void f<int[]>(const int*){}
+}
+
+namespace test3{
+template <class T>
+struct A{
+void f(T);
+};
+
+template<class T>
+void A<T>::f(const T){}
+
+template<>
+void A<int[3]>::f(const int*){}
+}
+
+namespace test4 {
+template<class TA>
+struct A{
+ template<class TB>
+ struct B{
+ typedef TB Arr3[3];
+ };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::B<char>::Arr3){}
+}
+
+namespace test5
+{
+struct A{
+ typedef int Arr3[3];
+};
+
+template<class T>
+void f(const typename T::Arr3){}
+
+template<>
+void f<A>(const int[3]){}
+}
+
+namespace test6
+{
+struct A{
+ typedef int Arr3[3];
+};
+template<class T>
+void f(const typename T::Arr3){}
+template<>
+void f<A>(const int*){}
+}
+
+#if __cpp_alias_templates
+namespace test7
+{
+template<class TA>
+struct A{
+ template<class TB>
+ using Type=TB[3];
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template Type<TB>){}
+template <>
+void f<int, char>(const typename A<int>::template Type<char>){}
+}
+namespace test8
+{
+template<class TA>
+struct A{
+ template<class TB>
+ struct B{
+ using TB_Alias=TB;
+ template<class TC=TB_Alias>
+ struct C{
+ typedef TC Arr3[3];
+ };
+ };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::template C<>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::template B<char>::template C<>::Arr3){}
+}
+#endif
+
+#if __cpp_decltype
+namespace test0
+{
+template <class T>
+struct A{
+ T arr3[3];
+};
+template <class T>
+void f(const decltype(A<T>::arr3)){}
+template <>
+void f<int>(const int[3]){}
+}
+
+#if __cpp_variable_templates
+namespace test9
+{
+template<unsigned int N, class T>
+void f(const T[N]){}
+
+template<unsigned int N, class T>
+using fPtr=decltype(f<N,T>)*;
+
+template<unsigned int N, class T>
+fPtr<N,T> af[N]={&f<N,T>};
+
+template<unsigned int N, class T>
+void g(const decltype(af<N,T>)){}
+
+template<>
+void g<1,int>(const fPtr<1,int>[1]){}
+}
+#endif
+#endif
+
+#if __cpp_concepts
+template<class T>
+concept IsLambdaAry3=__is_same(T, decltype(+[]{})[3]);
+template<IsLambdaAry3 T>
+void bar(const T){}
+template<>
+void bar<decltype(+[]{})[3]>(const decltype(+[]{})[3]){}
+#endif
diff --git a/gcc/testsuite/g++.dg/tls/pr102496-1.C b/gcc/testsuite/g++.dg/tls/pr102496-1.C
new file mode 100644
index 0000000..8220e1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr102496-1.C
@@ -0,0 +1,20 @@
+// PR c++/102496
+// { dg-do link { target c++11 } }
+// { dg-require-effective-target tls }
+// { dg-add-options tls }
+// { dg-additional-sources pr102496-2.C }
+
+template <int N>
+int
+foo ()
+{
+ extern __thread int t1;
+ return t1;
+}
+
+int
+main ()
+{
+ extern __thread int t2;
+ return foo <0> () + t2;
+}
diff --git a/gcc/testsuite/g++.dg/tls/pr102496-2.C b/gcc/testsuite/g++.dg/tls/pr102496-2.C
new file mode 100644
index 0000000..a71a9cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr102496-2.C
@@ -0,0 +1,6 @@
+// PR c++/102496
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target tls }
+
+__thread int t1;
+__thread int t2;
diff --git a/gcc/testsuite/g++.dg/torture/pr10148.C b/gcc/testsuite/g++.dg/torture/pr10148.C
new file mode 100644
index 0000000..ed278f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr10148.C
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+#include <stdlib.h>
+#include <assert.h>
+
+static bool flag = false;
+
+class C
+{
+ bool prev;
+
+public:
+ C() : prev(flag)
+ {
+ flag = true;
+ }
+
+ ~C() {
+ flag = prev;
+ }
+};
+
+void* operator new(size_t size)
+{
+ assert(flag);
+ return malloc(size);
+}
+
+void operator delete(void *p)
+{
+ free(p);
+}
+
+void g(int* p)
+{
+ delete p;
+}
+
+void f()
+{
+ int* p;
+ {
+ C c;
+ p = new int;
+ }
+ g(p);
+}
+
+int main(int, char**)
+{
+ f();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr102142.C b/gcc/testsuite/g++.dg/torture/pr102142.C
new file mode 100644
index 0000000..8e3ea5d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr102142.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+extern short arr_597[];
+extern bool arr_601[];
+int test_var_13;
+void test(short arr_391[][9][2][2]) {
+ for (int i_60 = 0; i_60 < 11; i_60 += test_var_13)
+ arr_597[22] = arr_601[i_60] = arr_391[0][0][1][4];
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr102581.C b/gcc/testsuite/g++.dg/torture/pr102581.C
new file mode 100644
index 0000000..7f172d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr102581.C
@@ -0,0 +1,51 @@
+// { dg-do compile }
+/* { dg-additional-options "-fno-strict-aliasing" } */
+enum VkStructureType {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR
+} typedef VkPhysicalDeviceSparseProperties;
+struct VkPhysicalDeviceProperties {
+ int apiVersion;
+ VkPhysicalDeviceSparseProperties sparseProperties;
+};
+typedef struct {
+ VkStructureType sType;
+ int *pPhysicalDevices;
+} VkPhysicalDeviceFeatures2;
+typedef struct VkPhysicalDeviceProperties2 {
+ VkStructureType sType;
+ void *pNext;
+} VkPhysicalDeviceMemoryProperties2;
+struct VulkanVersion {
+ int major;
+ int minor;
+ int patch;
+};
+int make_vulkan_version_version;
+VulkanVersion make_vulkan_version() {
+ return {make_vulkan_version_version, make_vulkan_version_version,
+ make_vulkan_version_version};
+}
+struct AppGpu {
+ int &inst;
+ int id;
+ int *phys_device = nullptr;
+ VulkanVersion api_version{};
+ VkPhysicalDeviceProperties props{};
+ VkPhysicalDeviceProperties2 props2{};
+ int memory_props{};
+ VkPhysicalDeviceMemoryProperties2 memory_props2{};
+ int features{};
+ VkPhysicalDeviceFeatures2 features2{};
+ int *dev = nullptr;
+ int enabled_features{};
+ int AppGpu_phys_device;
+ int AppGpu_inst;
+ AppGpu() : inst(AppGpu_inst), id() {
+ api_version = make_vulkan_version();
+ props2.sType = memory_props2.sType = features2.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
+ }
+};
+int
+main() { AppGpu(); return 0; }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr81408.C b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
index 39e32fd..bc14309 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -std=gnu++11 -fopt-info-loop-missed" } */
+/* { dg-options "-O2 -std=gnu++11 -fopt-info-loop-missed -fno-tree-vectorize" } */
struct p
{
char *ay;
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr94403.C b/gcc/testsuite/g++.dg/tree-ssa/pr94403.C
index d47e7fc..5f8f868 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr94403.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr94403.C
@@ -3,7 +3,7 @@
// are either big or little endian (not pdp endian).
// { dg-do compile { target { lp64 && { i?86-*-* x86_64-*-* powerpc*-*-* aarch64*-*-* } } } }
// { dg-require-effective-target store_merge }
-// { dg-options "-O2 -fdump-tree-store-merging -std=c++17" }
+// { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging -std=c++17" }
namespace std {
template <typename T>
diff --git a/gcc/testsuite/g++.dg/vect/pr102226.cc b/gcc/testsuite/g++.dg/vect/pr102226.cc
new file mode 100644
index 0000000..ddf5e46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr102226.cc
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve } }
+
+template <typename a> struct b { using c = a; };
+template <typename a, template <typename> class> using f = b<a>;
+template <typename a, template <typename> class g>
+using h = typename f<a, g>::c;
+struct i {
+ template <typename j> using k = typename j::l;
+};
+struct m : i {
+ using l = h<char *, k>;
+};
+class n {
+public:
+ char operator[](long o) {
+ m::l s;
+ return s[o];
+ }
+} p;
+n r;
+int q() {
+ long d;
+ for (long e; e; e++)
+ if (p[e] == r[e])
+ d++;
+ return d;
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr102421.cc b/gcc/testsuite/g++.dg/vect/pr102421.cc
new file mode 100644
index 0000000..ccab695
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr102421.cc
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64-*-* } } */
+
+#include <vector>
+
+template<typename ValueType>
+struct BasicVector
+{
+ ValueType& operator[](int i) { return x_[i]; }
+ ValueType operator[](int i) const { return x_[i]; }
+ ValueType x_[3];
+};
+typedef int ivec1[3];
+typedef BasicVector<double> RVec1;
+void foo (
+ std::vector<RVec1> &x_,
+ std::vector<RVec1> &xp_,
+ int homenr,
+ unsigned short* cFREEZE,
+ const ivec1* nFreeze)
+{
+ std::vector<RVec1> xp = xp_;
+ std::vector<RVec1> x = x_;
+ for (int i = 0; i < homenr; i++)
+ {
+ const int g = cFREEZE[i];
+ for (int d = 0; d < 3; d++)
+ {
+ if (nFreeze[g][d] == 0)
+ x[i][d] = xp[i][d];
+ }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr102572.cc b/gcc/testsuite/g++.dg/vect/pr102572.cc
new file mode 100644
index 0000000..0a71308
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr102572.cc
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-additional-options "-O3" }
+// { dg-additional-options "-march=skylake-avx512" { target x86_64-*-* i?86-*-* } }
+
+int a, b, c, f;
+void g(bool h, int d[][5])
+{
+ for (short i = f; i; i += 1)
+ {
+ a = h && d[0][i];
+ for (int j = 0; j < 4; j += c)
+ b = 0;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr102696.cc b/gcc/testsuite/g++.dg/vect/pr102696.cc
new file mode 100644
index 0000000..5560354
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr102696.cc
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-additional-options "-O3" }
+// { dg-additional-options "-march=skylake-avx512" { target x86_64-*-* i?86-*-* } }
+
+int a;
+extern bool b[][14];
+char h;
+void f(short g[][14])
+{
+ for (short d = h; d < 21; d += 1)
+ for (unsigned char e = 0; e < 14; e += 1)
+ {
+ a = 0;
+ b[d][e] = g[d][e];
+ }
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr102788.cc b/gcc/testsuite/g++.dg/vect/pr102788.cc
new file mode 100644
index 0000000..fa9c366
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr102788.cc
@@ -0,0 +1,32 @@
+// { dg-do run }
+// { dg-additional-options "-O3" }
+
+unsigned long long int var_4 = 235;
+unsigned long long int var_5 = 74;
+signed char var_12 = -99;
+unsigned long long int var_349;
+unsigned char var_645;
+void test();
+
+const unsigned long long &min(const unsigned long long &a,
+ const unsigned long long &b)
+{
+ return b < a ? b : a;
+}
+
+void __attribute__((noipa)) test()
+{
+ for (short c = var_12; c; c += 5)
+ ;
+ for (int e = 0; e < 12; e += 1) {
+ var_349 = var_4 ? 235 : 74;
+ var_645 = min((unsigned long long)true, var_5 ? var_12 : var_4);
+ }
+}
+
+int main()
+{
+ test();
+ if (var_645 != 1)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-5.C b/gcc/testsuite/g++.dg/warn/Waddress-5.C
new file mode 100644
index 0000000..b1ad38a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-5.C
@@ -0,0 +1,115 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+struct A
+{
+ void f ();
+ virtual void vf ();
+ virtual void pvf () = 0;
+
+ void sf ();
+
+ int *p;
+ int a[2];
+};
+
+void T (bool);
+
+void warn_memptr_if ()
+{
+ // Exercise warnings for addresses of nonstatic member functions.
+ if (&A::f == 0) // { dg-warning "the address '&A::f'" }
+ T (0);
+
+ if (&A::vf) // { dg-warning "-Waddress" }
+ T (0);
+
+ if (&A::pvf != 0) // { dg-warning "-Waddress" }
+ T (0);
+
+ // Exercise warnings for addresses of static member functions.
+ if (&A::sf == 0) // { dg-warning "-Waddress" }
+ T (0);
+
+ if (&A::sf) // { dg-warning "-Waddress" }
+ T (0);
+
+ // Exercise warnings for addresses of nonstatic data members.
+ if (&A::p == 0) // { dg-warning "the address '&A::p'" }
+ T (0);
+
+ if (&A::a == nullptr) // { dg-warning "-Waddress" }
+ T (0);
+}
+
+void warn_memptr_bool ()
+{
+ // Exercise warnings for addresses of nonstatic member functions.
+ T (&A::f == 0); // { dg-warning "-Waddress" }
+ T (&A::vf); // { dg-warning "-Waddress" }
+ T (&A::pvf != 0); // { dg-warning "-Waddress" }
+
+ // Exercise warnings for addresses of static member functions.
+ T (&A::sf == 0); // { dg-warning "-Waddress" }
+ T (&A::sf); // { dg-warning "-Waddress" }
+
+ // Exercise warnings for addresses of nonstatic data members.
+ T (&A::p == 0); // { dg-warning "-Waddress" }
+ T (&A::a == nullptr); // { dg-warning "-Waddress" }
+}
+
+
+/* Verify that no warnings are issued for a dependent expression in
+ a template. */
+
+template <int>
+struct B
+{
+ // This is why.
+ struct F { void* operator& () const { return 0; } } f;
+};
+
+template <class Type, int N>
+void nowarn_dependent (Type targ)
+{
+ T (&Type::x == 0);
+ T (&targ == 0);
+
+ Type tarr[1];
+ T (&tarr[0] == nullptr);
+
+ T (&B<N>::f == 0);
+
+ /* Like in the case above, the address-of operator could be a member
+ of B<N>::vf that returns zero. */
+ T (&B<N>::vf);
+ T (&B<N>::pvf != 0);
+ T (&B<N>::p == 0);
+ T (&B<N>::a == 0);
+}
+
+
+/* Verify that in an uninstantiated template warnings are not issued
+ for dependent expressions but are issued otherwise. */
+
+template <class Type>
+void warn_non_dependent (Type targ, Type *tptr, int i)
+{
+ /* The address of a pointer to a dependent type cannot be null but
+ the warning doesn't have a chance to see it. */
+ T (&tptr == 0); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+ T (&i == 0); // { dg-warning "-Waddress" }
+
+ int iarr[1];
+ T (&iarr == 0); // { dg-warning "-Waddress" }
+ T (&*iarr != 0); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+ T (&iarr[0] == 0); // { dg-warning "-Waddress" }
+
+ Type tarr[1];
+ T (&tarr == nullptr); // { dg-warning "-Waddress" "pr102378" { xfail *-*-* } }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-6.C b/gcc/testsuite/g++.dg/warn/Waddress-6.C
new file mode 100644
index 0000000..c22a83a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-6.C
@@ -0,0 +1,79 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ Verify -Waddress for member arrays of structs and notes.
+ { dg-options "-Wall" } */
+
+#if __cplusplus < 201103L
+# define nullptr __null
+#endif
+
+void T (bool);
+
+struct A
+{
+ int n;
+ int ia[]; // { dg-message "'A::ia' declared here" }
+};
+
+struct B
+{
+ A a[3]; // { dg-message "'B::a' declared here" }
+};
+
+struct C
+{
+ B b[3]; // { dg-message "'C::b' declared here" }
+};
+
+struct D
+{
+ C c[3]; // { dg-message "'D::c' declared here" }
+};
+
+
+void test_waddress_1d ()
+{
+ D d[2]; // { dg-message "'d' declared here" }
+
+ T (d); // { dg-warning "address of 'd'" }
+ T (d == nullptr); // { dg-warning "address of 'd'" }
+ T (&d); // { dg-warning "address of 'd'" }
+ T (d->c); // { dg-warning "address of 'D::c'" }
+ T (d->c != nullptr); // { dg-warning "address of 'D::c'" }
+ T (d->c->b); // { dg-warning "address of 'C::b'" }
+ T (d->c[1].b->a); // { dg-warning "address of 'B::a'" }
+ T (d->c->b[2].a->ia); // { dg-warning "address of 'A::ia'" }
+
+ if (d->c->b[2].a[1].ia) // { dg-warning "address of 'A::ia'" }
+ T (0);
+
+ if (bool b = d->c->b[1].a) // { dg-warning "address of 'B::a'" }
+ T (b);
+
+ /* The following is represented as a declaration of P followed
+ by an if statement and so it isn't diagnosed. It's not clear
+ that it should be since the pointer is then used.
+ void *p = d->c->b[2].a;
+ if (p) ...
+ */
+ if (void *p = d->c->b[2].a) // { dg-warning "address of 'A::ia'" "" { xfail *-*-* } }
+ T (p);
+}
+
+
+void test_waddress_2d (int i)
+{
+ D d[2][3]; // { dg-message "'d' declared here" }
+
+ T (d); // { dg-warning "address of 'd'" }
+ T (d == nullptr); // { dg-warning "address of 'd'" }
+ T (&d); // { dg-warning "address of 'd'" }
+ T (*d); // { dg-warning "address of 'd'" }
+ T (d[1] != nullptr); // { dg-warning "address of 'd'" }
+ T (&d[1]->c); // { dg-warning "address of 'D::c'" }
+ T (d[1]->c); // { dg-warning "address of 'D::c'" }
+ T (d[1]->c == nullptr); // { dg-warning "address of 'D::c'" }
+ T (d[i]->c[1].b); // { dg-warning "address of 'C::b'" }
+ T ((*(d + i))->c->b->a); // { dg-warning "address of 'B::a'" }
+ T (d[1][2].c->b->a->ia); // { dg-warning "address of 'A::ia'" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winit-list5.C b/gcc/testsuite/g++.dg/warn/Winit-list5.C
new file mode 100644
index 0000000..07b3a69
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winit-list5.C
@@ -0,0 +1,61 @@
+// PR c++/102482
+// { dg-do compile { target c++11 } }
+// Test we don't warn for non-const lvalue refs.
+
+#include <initializer_list>
+
+struct X { };
+
+struct span
+{
+ span(std::initializer_list<int>& il)
+ : begin(il.begin()) // { dg-bogus "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn
+{
+ span_warn(std::initializer_list<int> il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn2
+{
+ span_warn2(std::initializer_list<int>&& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn3
+{
+ span_warn3(std::initializer_list<int> const& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn4
+{
+ span_warn4(std::initializer_list<int> const il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
+
+struct span_warn5
+{
+ span_warn5(std::initializer_list<int> const&& il)
+ : begin(il.begin()) // { dg-warning "initializer_list" }
+ { }
+
+ const int* begin;
+};
diff --git a/gcc/testsuite/g++.dg/warn/Winterference-2.C b/gcc/testsuite/g++.dg/warn/Winterference-2.C
new file mode 100644
index 0000000..2af75c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference-2.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fmodules-ts }
+
+module ;
+
+#include <new>
+
+export module foo;
+
+export {
+ struct A {
+ alignas(std::hardware_destructive_interference_size) int x; // { dg-warning Winterference-size }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.C b/gcc/testsuite/g++.dg/warn/Winterference.C
new file mode 100644
index 0000000..57c001b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.C
@@ -0,0 +1,6 @@
+// Test that we warn about use of std::hardware_destructive_interference_size
+// in a header.
+// { dg-do compile { target c++17 } }
+
+// { dg-warning Winterference-size "" { target *-*-* } 0 }
+#include "Winterference.H"
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.H b/gcc/testsuite/g++.dg/warn/Winterference.H
new file mode 100644
index 0000000..36f0ad5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.H
@@ -0,0 +1,7 @@
+#include <new>
+
+struct A
+{
+ alignas(std::hardware_destructive_interference_size) int i;
+ alignas(std::hardware_destructive_interference_size) int j;
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wlogical-op-3.C b/gcc/testsuite/g++.dg/warn/Wlogical-op-3.C
new file mode 100644
index 0000000..50b09d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wlogical-op-3.C
@@ -0,0 +1,12 @@
+// PR c++/101592
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Wlogical-op" }
+
+decltype(nullptr) foo ();
+
+bool
+bar ()
+{
+ return foo () > nullptr // { dg-error "ordered comparison" }
+ || foo () < nullptr; // { dg-error "ordered comparison" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-10.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-10.C
new file mode 100644
index 0000000..6b71a83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-10.C
@@ -0,0 +1,13 @@
+/* PR middle-end/102243 - ICE on placement new at global scope
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void *operator new (__SIZE_TYPE__, void *);
+
+char a[2][sizeof (int)];
+
+int *p = new (a[1]) int;
+
+void *operator new[] (__SIZE_TYPE__, void *p) { return p; }
+
+int *q = new (a[1]) int[1];
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
index bfe1445..fae8b7e 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -9,7 +9,7 @@ const intptr_t&
return_addr_label_as_intref (void)
{
label:
- if ((const intptr_t*)&&label == 0)
+ if ((const intptr_t)&&label == 0)
__builtin_exit (1);
return *(const intptr_t*)&&label; // { dg-warning "\\\[-Wreturn-local-addr]" } */
@@ -19,7 +19,7 @@ const intptr_t&
return_addr_local_as_intref (void)
{
int a[1];
- if ((const intptr_t*)a == 0)
+ if ((const intptr_t)a == 0)
__builtin_exit (1);
return (const intptr_t&)a; // { dg-warning "\\\[-Wreturn-local-addr]" } */
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-13.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-13.C
index 49ee878..b74a2fa 100644
--- a/gcc/testsuite/g++.dg/warn/Wuninitialized-13.C
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-13.C
@@ -1,7 +1,10 @@
/* PR c/98597 - ICE in -Wuninitialized printing a MEM_REF
{ dg-do compile }
- { dg-options "-O2 -Wall" } */
+ { dg-options "-O2 -Wall -fno-tree-vectorize" } */
+/* After vectorization, the location of the warning that's off,
+ the warning itself is still issued but it's swallowed by
+ the dg-prune-output directive. Refer to pr102700. */
struct shared_count {
shared_count () { }
shared_count (shared_count &r)
diff --git a/gcc/testsuite/g++.dg/warn/pr101219.C b/gcc/testsuite/g++.dg/warn/pr101219.C
index 0d23d73..d5d44e4 100644
--- a/gcc/testsuite/g++.dg/warn/pr101219.C
+++ b/gcc/testsuite/g++.dg/warn/pr101219.C
@@ -7,5 +7,7 @@ struct S { void m(); };
template <int> bool f() {
void (S::*mp)();
- return &S::m == mp; // no warning emitted here (no instantiation)
+ /* The expression below isn't type-dependent so also verify
+ it's diagnosed even though the template isn't instantiated. */
+ return &S::m == mp; // { dg-warning "\\\[-Waddress" }
}
diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
index 56dc894..e08a36d 100644
--- a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
+++ b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
@@ -1,7 +1,7 @@
/* PR tree-optimization/98508 - Sanitizer disable -Wall and -Wextra
{ dg-do compile }
- { dg-require-effective-target no_fsanitize_address }
- { dg-options "-O0 -Wall -fsanitize=address" } */
+ { dg-options "-O0 -Wall -fsanitize=address" }
+ { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
struct S
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C b/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
index 2678cf7..e24dca4 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/nontype5.C
@@ -19,5 +19,5 @@ static int g() { return f(); }
int f() { return 0; }
int main() {
-return B<int,&f>::g(); // { dg-error "" } could not convert arg
+return B<int,&f>::g();
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
index d122ec2..ee14cea 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
@@ -23,8 +23,8 @@ template<class T> void foo(T const *){} // { dg-error "pointer to reference" }
void f()
{
- foo<int &>(); // { dg-error "" } attempt to build int & const *
- foo<void ()>(); // { dg-error "" } attempt to build void (const *)()
+ foo<int &>(0); // { dg-error "" } attempt to build int & const *
+ foo<void ()>(0); // OK by [dcl.fct]/7, the const is silently dropped
}
typedef void (*Fptr)();
diff --git a/gcc/testsuite/g++.target/aarch64/interference.C b/gcc/testsuite/g++.target/aarch64/interference.C
new file mode 100644
index 0000000..0fc0165
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Most AArch64 CPUs have an L1 cache line size of 64, but some recent ones use
+// 128 or even 256.
+static_assert(std::hardware_destructive_interference_size == 256);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr102252.C b/gcc/testsuite/g++.target/aarch64/sve/pr102252.C
new file mode 100644
index 0000000..f90f121
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr102252.C
@@ -0,0 +1,37 @@
+/* PR target/102252. */
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-march=armv8.2-a+sve -msve-vector-bits=512" } */
+
+/* We used to generate invalid assembly for SVE predicate loads. */
+
+#include <arm_sve.h>
+
+class SimdBool
+{
+private:
+ typedef svbool_t simdInternalType_ __attribute__((arm_sve_vector_bits(512)));
+
+public:
+ SimdBool() {}
+
+ simdInternalType_ simdInternal_;
+
+};
+
+static svfloat32_t selectByMask(svfloat32_t a, SimdBool m) {
+ return svsel_f32(m.simdInternal_, a, svdup_f32(0.0));
+}
+
+struct s {
+ SimdBool array[1];
+};
+
+
+
+void foo(struct s* const work, int offset)
+{
+ svfloat32_t tz_S0;
+
+ tz_S0 = selectByMask(tz_S0, work->array[offset]);
+}
+
diff --git a/gcc/testsuite/g++.target/aarch64/sve/static-var-in-template.C b/gcc/testsuite/g++.target/aarch64/sve/static-var-in-template.C
new file mode 100644
index 0000000..74237ff
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/static-var-in-template.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+template <int N>
+void f()
+{
+ static svbool_t pg = svwhilelt_b64(0, N);
+}
+
+int main(int argc, char **argv)
+{
+ f<2>();
+ return 0;
+}
+
+/* { dg-error "SVE type 'svbool_t' does not have a fixed size" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/g++.target/arm/interference.C b/gcc/testsuite/g++.target/arm/interference.C
new file mode 100644
index 0000000..34fe8a5
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Recent ARM CPUs have a cache line size of 64. Older ones have
+// a size of 32, but I guess they're old enough that we don't care?
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C
new file mode 100644
index 0000000..6d50f49
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-minmax.C
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vminph" 3 } } */
+/* { dg-final { scan-assembler-times "vmaxph" 3 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+
+#define VCONDMINMAX(size, op, name) \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vminmax_##v##size##hf##v##size##hf##name (v##size##hf a, v##size##hf b) \
+{ \
+ return (a op b) ? a : b; \
+}
+
+VCONDMINMAX (8, <, min)
+VCONDMINMAX (8, >, max)
+VCONDMINMAX (16, <, min)
+VCONDMINMAX (16, >, max)
+VCONDMINMAX (32, <, min)
+VCONDMINMAX (32, >, max)
+
diff --git a/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C
new file mode 100644
index 0000000..de93e2c
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/avx512fp16-vcondmn-vec.C
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 45 } } */
+/* { dg-final { scan-assembler-times "vpcmpuw" 12 } } */
+/* { dg-final { scan-assembler-times "vpcmpw" 18 } } */
+/* { dg-final { scan-assembler-times "(?:vpblendmw|vmovdqu16\[^\{\n\]+\{%k\[1-7\]\})" 75 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+typedef short v16hi __attribute__ ((vector_size (32)));
+typedef short v32hi __attribute__ ((vector_size (64)));
+typedef unsigned short v8uhi __attribute__ ((vector_size (16)));
+typedef unsigned short v16uhi __attribute__ ((vector_size (32)));
+typedef unsigned short v32uhi __attribute__ ((vector_size (64)));
+
+#define VCONDMOV(size, op, name) \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##hf##name (v##size##hf a, v##size##hf b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hi##v##size##hf##name (v##size##hi a, v##size##hi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##hi \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##hi##name (v##size##hi a, v##size##hi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (c op d) ? a : b; \
+} \
+v##size##hf \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##uhi##v##size##hf##name (v##size##uhi a, v##size##uhi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (a op b) ? c : d; \
+}\
+v##size##uhi \
+__attribute__ ((noinline, noclone)) \
+vcond_##v##size##hf##v##size##uhi##name (v##size##uhi a, v##size##uhi b, \
+ v##size##hf c, v##size##hf d) \
+{ \
+ return (c op d) ? a : b; \
+} \
+
+VCONDMOV (8, <, lt)
+VCONDMOV (8, >, gt)
+VCONDMOV (8, ==, eq)
+VCONDMOV (8, <=, le)
+VCONDMOV (8, >=, ge)
+VCONDMOV (16, <, lt)
+VCONDMOV (16, >, gt)
+VCONDMOV (16, <=, le)
+VCONDMOV (16, >=, ge)
+VCONDMOV (16, ==, eq)
+VCONDMOV (32, <, lt)
+VCONDMOV (32, >, gt)
+VCONDMOV (32, <=, le)
+VCONDMOV (32, >=, ge)
+VCONDMOV (32, ==, eq)
diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C
new file mode 100644
index 0000000..95d1ac2
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/float16-1.C
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16/* { dg-error "does not name a type" } */
+foo (_Float16 x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.target/i386/float16-2.C b/gcc/testsuite/g++.target/i386/float16-2.C
new file mode 100644
index 0000000..99eb797
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/float16-2.C
@@ -0,0 +1,14 @@
+/* { dg-do assemble { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+union flt
+{
+ _Float16 flt;
+ short s;
+};
+
+_Float16
+foo (union flt x)
+{
+ return x.flt;
+}
diff --git a/gcc/testsuite/g++.target/i386/float16-3.C b/gcc/testsuite/g++.target/i386/float16-3.C
new file mode 100644
index 0000000..9408785
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/float16-3.C
@@ -0,0 +1,10 @@
+/* { dg-do assemble { target avx512fp16 } } */
+/* { dg-options "-O0 -mavx512fp16" } */
+
+template <typename> void a(char *) {}
+char b, d;
+void c()
+{
+ a<unsigned char>(&d);
+ a<_Float16>(&b);
+}
diff --git a/gcc/testsuite/g++.target/i386/interference.C b/gcc/testsuite/g++.target/i386/interference.C
new file mode 100644
index 0000000..c7b910e
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/interference.C
@@ -0,0 +1,8 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// It is generally agreed that these are the right values for all x86.
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/i386/mv30.C b/gcc/testsuite/g++.target/i386/mv30.C
new file mode 100644
index 0000000..b4947f0
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv30.C
@@ -0,0 +1,50 @@
+// PR target/101696
+// Test that dispatching can choose the right multiversion
+// for x86-64 microarchitecture levels.
+
+// { dg-do run }
+// { dg-require-ifunc "" }
+// { dg-options "-O2" }
+
+#include <assert.h>
+
+int __attribute__ ((target("default")))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((target("arch=x86-64"))) foo () {
+ return 1;
+}
+
+int __attribute__ ((target("arch=x86-64-v2"))) foo () {
+ return 2;
+}
+
+int __attribute__ ((target("arch=x86-64-v3"))) foo () {
+ return 3;
+}
+
+int __attribute__ ((target("arch=x86-64-v4"))) foo () {
+ return 4;
+}
+
+
+int main ()
+{
+ int val = foo ();
+
+ if (__builtin_cpu_supports ("x86-64-v4"))
+ assert (val == 4);
+ else if (__builtin_cpu_supports ("x86-64-v3"))
+ assert (val == 3);
+ else if (__builtin_cpu_supports ("x86-64-v2"))
+ assert (val == 2);
+ else if (__builtin_cpu_supports ("x86-64"))
+ assert (val == 1);
+ else
+ assert (val == 0);
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/i386/pr102166.C b/gcc/testsuite/g++.target/i386/pr102166.C
new file mode 100644
index 0000000..751cd2c
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102166.C
@@ -0,0 +1,20 @@
+/* PR target/102166 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -std=c++14" } */
+
+#include<immintrin.h>
+__attribute__((target("amx-tile"))) void amx()
+{
+ _tile_loadd(0, 0, 0);
+ _tile_release();
+}
+
+__attribute__((target("amx-int8"))) void amxint8()
+{
+ _tile_dpbssd(0, 1, 2);
+}
+
+__attribute__((target("amx-bf16"))) void amxbf16()
+{
+ _tile_dpbf16ps (0, 1, 2);
+}
diff --git a/gcc/testsuite/g++.target/i386/pr102295.C b/gcc/testsuite/g++.target/i386/pr102295.C
new file mode 100644
index 0000000..09efc3c
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102295.C
@@ -0,0 +1,12 @@
+// PR c++/102295
+// { dg-do compile { target *-*-linux* } }
+// { dg-options "-Wno-pedantic" }
+
+struct S {
+ int a;
+ int b[];
+} S;
+
+struct S s = { 1, { 2, 3 } };
+
+/* { dg-final { scan-assembler ".size\[\t \]*s, 12" } } */
diff --git a/gcc/testsuite/g++.target/i386/pr102548.C b/gcc/testsuite/g++.target/i386/pr102548.C
new file mode 100644
index 0000000..e1238c3
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102548.C
@@ -0,0 +1,12 @@
+// PR c++/102548
+// { dg-do compile { target { c++14 && ia32 } } }
+
+typedef decltype(sizeof(0)) size_t;
+struct tm;
+extern "C" size_t __attribute__((__cdecl__)) strftime (char *, size_t, const char *, const struct tm *);
+
+auto
+foo (void)
+{
+ return strftime;
+}
diff --git a/gcc/testsuite/g++.target/i386/pr102639.C b/gcc/testsuite/g++.target/i386/pr102639.C
new file mode 100644
index 0000000..f094e4d
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102639.C
@@ -0,0 +1,19 @@
+/* PR target/102639 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=c++14 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vminsh" 1 } } */
+
+typedef _Float16 v16hf __attribute__((vector_size(2)));
+v16hf vcond_v16hfv16hfge_b, vcond_v16hfv16hfge_c, vcond_v16hfv16hfge_d,
+ __attribute__vcond_v16hfv16hfge_a;
+v16hf __attribute__vcond_v16hfv16hfge() {
+ return __attribute__vcond_v16hfv16hfge_a >= vcond_v16hfv16hfge_b
+ ? vcond_v16hfv16hfge_c
+ : vcond_v16hfv16hfge_d;
+}
+
+v16hf __attribute__vcond_v16hfv16hfmax() {
+ return __attribute__vcond_v16hfv16hfge_a < vcond_v16hfv16hfge_b
+ ? __attribute__vcond_v16hfv16hfge_a
+ : vcond_v16hfv16hfge_b;
+}
diff --git a/gcc/testsuite/g++.target/i386/pr80566-1.C b/gcc/testsuite/g++.target/i386/pr80566-1.C
index 753f974..29da31d 100644
--- a/gcc/testsuite/g++.target/i386/pr80566-1.C
+++ b/gcc/testsuite/g++.target/i386/pr80566-1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-O2 -march=haswell" }
+// { dg-options "-O2 -march=haswell -mtune-ctrl=avx256_store_by_pieces" }
#include <cstring>
diff --git a/gcc/testsuite/g++.target/i386/pr80566-2.C b/gcc/testsuite/g++.target/i386/pr80566-2.C
index 2a2e82d..9ffd2c8 100644
--- a/gcc/testsuite/g++.target/i386/pr80566-2.C
+++ b/gcc/testsuite/g++.target/i386/pr80566-2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-O2 -march=haswell" }
+// { dg-options "-O2 -march=haswell -mtune-ctrl=avx256_move_by_pieces" }
#include <cstring>
diff --git a/gcc/testsuite/g++.target/powerpc/pr102024.C b/gcc/testsuite/g++.target/powerpc/pr102024.C
new file mode 100644
index 0000000..7695850
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/pr102024.C
@@ -0,0 +1,23 @@
+// PR target/102024
+// { dg-do compile { target powerpc_elfv2 } }
+// { dg-options "-O2" }
+
+// Test that a zero-width bit field in an otherwise homogeneous aggregate
+// generates a psabi warning and passes arguments in GPRs.
+
+// { dg-final { scan-assembler-times {\mstd\M} 4 } }
+
+struct a_thing
+{
+ double x;
+ double y;
+ double z;
+ int : 0;
+ double w;
+};
+
+double
+foo (a_thing a) // { dg-message "ELFv2 parameter passing for an argument containing zero-width bit fields but that is otherwise a homogeneous aggregate was corrected in GCC 12" }
+{
+ return a.x * a.y + a.z - a.w;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/920826-1.c b/gcc/testsuite/gcc.c-torture/compile/920826-1.c
index c2d8843..2a175456 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920826-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920826-1.c
@@ -1,3 +1,3 @@
/* { dg-require-effective-target indirect_jumps } */
-f(int*x){goto*(char)*x;}
+f(int*x){goto*(void*)(__INTPTR_TYPE__)(char)*x;}
diff --git a/gcc/testsuite/gcc.c-torture/compile/920831-1.c b/gcc/testsuite/gcc.c-torture/compile/920831-1.c
index 9e422a9..945c521 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920831-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920831-1.c
@@ -1,3 +1,3 @@
/* { dg-require-effective-target indirect_jumps } */
-f(x){goto*(char)x;}
+f(x){goto*(void *)x;}
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c
new file mode 100644
index 0000000..121ae17
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method-2.c
@@ -0,0 +1,11 @@
+/* { dg-additional-options "-fcx-limited-range -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+#pragma GCC optimize "-fno-cx-limited-range"
+
+void do_div (_Complex double *a, _Complex double *b)
+{
+ *a = *b / (4.0 - 5.0fi);
+}
+
+/* { dg-final { scan-tree-dump "__divdc3" "optimized" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c
new file mode 100644
index 0000000..046de7e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-complex-method.c
@@ -0,0 +1,11 @@
+/* { dg-additional-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+#pragma GCC optimize "-fcx-limited-range"
+
+void do_div (_Complex double *a, _Complex double *b)
+{
+ *a = *b / (4.0 - 5.0fi);
+}
+
+/* { dg-final { scan-tree-dump-not "__divdc3" "optimized" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr100316.c b/gcc/testsuite/gcc.c-torture/compile/pr100316.c
new file mode 100644
index 0000000..38eca86
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr100316.c
@@ -0,0 +1,18 @@
+void foo(){
+ __builtin___clear_cache(0, 0);
+}
+
+void foo1(){
+ __builtin___clear_cache((void*)0, (void*)0);
+}
+
+void foo2(){
+ void *yy = 0;
+ __builtin___clear_cache(yy, yy);
+}
+
+void foo3(){
+ void *yy = (void*)0x1000;
+ __builtin___clear_cache(yy, yy);
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr27863.c b/gcc/testsuite/gcc.c-torture/compile/pr27863.c
index 926312e4..1428ce3 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr27863.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr27863.c
@@ -14,7 +14,7 @@ int main(int argc,char**argv,char **envp)
_loc1:;
*++esp=(long)&&_loc35;
_loc35:;
-goto *(*esp--);
+goto *(void *)(*esp--);
*++esp=(long)&&_loc36;
_loc36:;
*++esp=(long)&&_loc37;
@@ -27,5 +27,5 @@ _loc66:;
*++esp=(long)&&_loc119;
_loc119:;
SetTermStruc:
- goto *(*esp--);
+ goto *(void*)(__INTPTR_TYPE__)(*esp--);
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70190.c b/gcc/testsuite/gcc.c-torture/compile/pr70190.c
index d3d209a..6c57b50 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr70190.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr70190.c
@@ -8,7 +8,7 @@ fn1 ()
static char a[] = "foo";
static void *b[] = { &&l1, &&l2 };
goto *(b[1]);
- l1: goto *(a[0]);
+ l1: goto *(void*)(__INTPTR_TYPE__)(a[0]);
l2: return 0;
}
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
new file mode 100644
index 0000000..bdbf573
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/102622 */
+/* Wrong code introduced due to phi-opt
+ introducing undefined signed interger overflow
+ with one bit signed integer negation. */
+
+struct f{signed t:1;};
+int g(struct f *a, int t) __attribute__((noipa));
+int g(struct f *a, int t)
+{
+ if (t)
+ a->t = -1;
+ else
+ a->t = 0;
+ int t1 = a->t;
+ if (t1) return 1;
+ return t1;
+}
+
+int main(void)
+{
+ struct f a;
+ if (!g(&a, 1)) __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr102134.c b/gcc/testsuite/gcc.c-torture/execute/pr102134.c
new file mode 100644
index 0000000..55cf4eb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr102134.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/102134 */
+
+typedef unsigned long long u64;
+
+u64 g;
+
+void
+foo (u64 a, u64 b, u64 c, u64 *r)
+{
+ b *= b;
+ u64 x = a && ((b >> (c & 63)) | ((b << (c & 63)) & g));
+ *r = x + a;
+}
+
+int
+main ()
+{
+ u64 x;
+ foo (1, 3000, 0, &x);
+ if (x != 2)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Waddress-3.c b/gcc/testsuite/gcc.dg/Waddress-3.c
new file mode 100644
index 0000000..c404f6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Waddress-3.c
@@ -0,0 +1,35 @@
+/* PR c/102103 - missing warning comparing array address to null
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef _Complex float Cflt;
+
+extern Cflt cf, cfa[], cfa2[][2];
+
+Cflt *pcf (void);
+
+void T (int);
+
+void test_complex (Cflt *p, int i)
+{
+ T (&__real__ cf == 0); // { dg-warning "address of '__real__ cf'" }
+ T (&__imag__ cf == 0); // { dg-warning "address of '__imag__ cf'" }
+
+ T (0 != &__real__ cf); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ cf); // { dg-warning "-Waddress" }
+
+ T (&__real__ cfa[0] == 0); // { dg-warning "-Waddress" }
+ T (&__imag__ cfa[1] == 0); // { dg-warning "-Waddress" }
+
+ T (0 != &__real__ cfa2[i][i]); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ cfa2[i][i]); // { dg-warning "-Waddress" }
+
+ T (0 == &__real__ *p); // { dg-warning "-Waddress" }
+ T (0 == &__imag__ *p); // { dg-warning "-Waddress" }
+
+ T (0 == &__real__ p[i]); // { dg-warning "-Waddress" }
+ T (0 == &__imag__ p[i]); // { dg-warning "-Waddress" }
+
+ T (&__real__ *pcf () == 0); // { dg-warning "-Waddress" }
+ T (0 != &__imag__ *pcf ()); // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/gcc.dg/Waddress.c b/gcc/testsuite/gcc.dg/Waddress.c
index 146b1a9..b26e7b1 100644
--- a/gcc/testsuite/gcc.dg/Waddress.c
+++ b/gcc/testsuite/gcc.dg/Waddress.c
@@ -6,5 +6,5 @@ int
foo(void)
{
char a[1];
- return a == 0;
+ return a == 0; // { dg-warning "-Waddress" }
}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51.c b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
index 6028b11..de60d87 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-51.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
@@ -1,7 +1,8 @@
/* PR middle-end/92333 - missing variable name referencing VLA in warnings
PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index
{ dg-do compile }
- { dg-options "-O2 -Wall" } */
+ { dg-options "-O2 -Wall" }
+ { dg-additional-options "-mtune=generic" { target { i?86-*-* x86_64-*-* } } } */
void sink (void*);
@@ -38,7 +39,7 @@ void test_struct_char_vla_location (void)
} s;
s.cvla[0] = __LINE__;
- s.cvla[nelts - 1] = 0;
+ s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (&s);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-89.c b/gcc/testsuite/gcc.dg/Warray-bounds-89.c
new file mode 100644
index 0000000..2604f65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-89.c
@@ -0,0 +1,139 @@
+/* Verify warnings and notes for MIN_EXPRs involving either pointers
+ to distinct objects or one to a known object and the other to
+ an unknown one. The relational expressions are strictly invalid
+ but that should be diagnosed by a separate warning.
+ { dg-do compile }
+ { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow" } */
+
+/* Verify the note points to the larger of the two objects and mentions
+ the offset into it (alhough the offset would ideally be a part of
+ the warning). */
+extern char a3[3];
+extern char a5[5]; // { dg-message "at offset 5 into object 'a5' of size 5" "note" }
+
+void min_a3_a5 (int i)
+{
+ char *p = a3 + i;
+ char *q = a5 + i;
+
+ /* The relational expression below is invalid and should be diagnosed
+ by its own warning independently of -Warray-bounds. */
+ char *d = p < q ? p : q;
+
+ d[4] = 0;
+
+ /* Verify the type in the warning corresponds to the larger of the two
+ objects. */
+ d[5] = 0; // { dg-warning "subscript 5 is outside array bounds of 'char\\\[5]'" }
+}
+
+
+// Same as above but with the larger array as the first MIN_EXPR operand.
+extern char b4[4];
+extern char b6[6]; // { dg-message "at offset 6 into object 'b6' of size 6" "note" }
+
+void min_b6_b4 (int i)
+{
+ char *p = b6 + i;
+ char *q = b4 + i;
+ char *d = p < q ? p : q;
+
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "subscript 6 is outside array bounds of 'char\\\[6]'" }
+}
+
+
+/* Same as above but with the first MIN_EXPR operand pointing to an unknown
+ object. */
+extern char c7[7]; // { dg-message "at offset 7 into object 'c7' of size 7" "note" }
+
+void min_p_c7 (char *p, int i)
+{
+ char *q = c7 + i;
+ char *d = p < q ? p : q;
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "subscript 7 is outside array bounds of 'char\\\[7]'" }
+}
+
+
+/* Same as above but with the second MIN_EXPR operand pointing to an unknown
+ object. */
+extern char d8[8]; // { dg-message "at offset 8 into object 'd8' of size 8" "note" }
+
+void min_d8_p (char *q, int i)
+{
+ char *p = d8 + i;
+ char *d = p < q ? p : q;
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "subscript 8 is outside array bounds of 'char\\\[8]'" }
+}
+
+
+/* The following are diagnosed by -Wstringop-overflow but, as a result
+ of PR 101374, not by -Warray-bounds. */
+
+struct A3_5
+{
+ char a3[3];
+ char a5[5]; // { dg-message "at offset 5 into object 'a5' of size 5" "note" { xfail *-*-* } }
+};
+
+void min_A3_A5 (int i, struct A3_5 *pa3_5)
+{
+ char *p = pa3_5->a3 + i;
+ char *q = pa3_5->a5 + i;
+
+ char *d = p < q ? p : q;
+
+ // d[4] = 0;
+ d[5] = 0; // { dg-warning "subscript 5 is outside array bounds of 'char\\\[5]'" "pr??????" { xfail *-*-* } }
+}
+
+
+struct B4_B6
+{
+ char b4[4];
+ char b6[6]; // { dg-message "at offset 6 into object 'b6' of size 6" "note" { xfail *-*-* } }
+};
+
+void min_B6_B4 (int i, struct B4_B6 *pb4_b6)
+{
+ char *p = pb4_b6->b6 + i;
+ char *q = pb4_b6->b4 + i;
+ char *d = p < q ? p : q;
+
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "subscript 6 is outside array bounds of 'char\\\[6]'" "pr??????" { xfail *-*-* } }
+}
+
+
+struct C7
+{
+ char c7[7]; // { dg-message "at offset 7 into object 'c7' of size 7" "note" { xfail *-*-* } }
+};
+
+void min_p_C7 (char *p, int i, struct C7 *pc7)
+{
+ char *q = pc7->c7 + i;
+ char *d = p < q ? p : q;
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "subscript 7 is outside array bounds of 'char\\\[7]'" "pr??????" { xfail *-*-* } }
+}
+
+
+struct D8
+{
+ char d8[8]; // { dg-message "at offset 8 into object 'd8' of size 8" "note" { xfail *-*-* } }
+};
+
+void min_D8_p (char *q, int i, struct D8 *pd8)
+{
+ char *p = pd8->d8 + i;
+ char *d = p < q ? p : q;
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "subscript 8 is outside array bounds of 'char\\\[8]'" "pr??????" { xfail *-*-* } }
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
index cbf3e93..e8a269c 100644
--- a/gcc/testsuite/gcc.dg/Warray-parameter-3.c
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
@@ -59,7 +59,7 @@ void fas1 (int[static 2]); // { dg-warning "\\\[-Warray-parameter=" }
/* Also verify that -Warray-bounds doesn't trigger for ordinary array
parameters... */
-#pragma GCC optimize "2"
+#pragma GCC optimize ("2")
__attribute__ ((noipa)) void
gca3 (char a[3])
@@ -77,7 +77,7 @@ gia3 (int a[3])
__attribute__ ((noipa)) void
gcas3 (char a[static 3])
{
- a[0] = 0; a[1] = 1; a[2] = 2;
+ a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
a[3] = 3; // { dg-warning "\\\[-Warray-bounds" }
}
diff --git a/gcc/testsuite/gcc.dg/Wint-in-bool-context-4.c b/gcc/testsuite/gcc.dg/Wint-in-bool-context-4.c
new file mode 100644
index 0000000..0e96dd7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wint-in-bool-context-4.c
@@ -0,0 +1,35 @@
+/* PR c/102245 */
+/* { dg-options "-Wint-in-bool-context" } */
+/* { dg-do compile } */
+
+_Bool test1(_Bool x)
+{
+ return !(x << 0); /* { dg-warning "boolean context" } */
+}
+
+_Bool test2(_Bool x)
+{
+ return !(x << 1); /* { dg-warning "boolean context" } */
+}
+
+_Bool test3(_Bool x, int y)
+{
+ return !(x << y); /* { dg-warning "boolean context" } */
+}
+
+_Bool test4(int x, int y)
+{
+ return !(x << y); /* { dg-warning "boolean context" } */
+}
+
+_Bool test5(int x, int y)
+{
+ return !((x << y) << 0); /* { dg-warning "boolean context" } */
+}
+
+int test6(_Bool x)
+{
+ int v = 0;
+ return (v & ~1L) | (1L & (x << 0)); /* { dg-bogus "boolean context" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
index ec3c97e..cf53652 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
@@ -56,7 +56,7 @@ void test_memset_array_cst_range_off (void)
T (2, SR ( 1, 2), 4);
T (2, SR ( 1, 2), 5); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
- T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-* } } */
+ T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (2, UR ( 1, 2), 7); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
T (7, UR (-7, 0), 7);
T (7, UR (-7, 0), 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
@@ -134,7 +134,7 @@ void test_memcpy_array_cst_range_off (const void *s)
T (2, SR ( 1, 2), 4);
T (2, SR ( 1, 2), 5); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
- T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-* } } */
+ T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (2, UR ( 1, 2), 7); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
T (7, UR (-7, 0), 7);
T (7, UR (-7, 0), 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
@@ -211,7 +211,7 @@ void test_strcpy_array_cst_range_off (void)
T (2, SR ( 1, 2), 3);
T (2, SR ( 1, 2), 4); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
- T (2, SR ( 0, 1), 5); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-* } } */
+ T (2, SR ( 0, 1), 5); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (2, UR ( 1, 2), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
T (7, UR (-7, 0), 6);
T (7, UR (-7, 0), 8); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
@@ -277,7 +277,7 @@ void test_strncpy_array_cst_range_off (const char *s)
T (2, SR ( 1, 2), 4);
T (2, SR ( 1, 2), 5); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
- T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-* } } */
+ T (2, SR ( 0, 1), 6); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (2, UR ( 1, 2), 7); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
T (7, UR (-7, 0), 7);
T (7, UR (-7, 0), 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
index 7c3dc8c..1ba7720 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
@@ -25,9 +25,7 @@ void test_memcpy_array_cst_range_off (const void *s)
T (d + UR (1, 2), 5);
T (d + UR (0, 1), 6);
- /* 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 (0, 1), 7); /* { dg-warning ".memcpy. writing 7 bytes into a region of size 6 overflows the destination" "pr89428" } */
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 " } */
@@ -66,7 +64,7 @@ void test_memset_array_unsigned_off (void)
T (d + UR (1, 2), 5);
T (d + UR (0, 1), 6);
- T (d + UR (0, 1), 7); /* { dg-warning ".memset. writing 6 bytes into a region of size 5 overflows the destination" "pr89428" { xfail *-*-* } } */
+ T (d + UR (0, 1), 7); /* { dg-warning ".memset. writing 7 bytes into a region of size 6 overflows the destination" "pr89428" } */
T (d + UR (1, 2), 6); /* { dg-warning ".memset. 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 " } */
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
index d6201b0..7683084 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
@@ -2,7 +2,8 @@
types than char are diagnosed.
{ dg-do compile }
{ dg-require-effective-target int32plus }
- { dg-options "-O2 -Wall -Wno-array-bounds" } */
+ { dg-options "-O2 -Wall -Wno-array-bounds" }
+ { dg-additional-options "-mtune=generic" { target { i?86-*-* x86_64-*-* } } } */
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
@@ -35,8 +36,8 @@ void test_memcpy_cond (int i)
void test_int16 (void)
{
char *p = a4 + 1;
- *(int16_t*)p = 0;
- *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" }
+ *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } }
+ *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { i?86-*-* x86_64-*-* } } }
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
index 3a27460..d88bde9 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
@@ -23,10 +23,10 @@ void test_store_zero_length (int i)
{
char a[3];
struct S0 *p = (struct S0*)a;
- p->a = 0;
+ p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
p->b[0] = 0;
p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" }
- p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
+ p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
p->b[i] = 2;
sink (p);
}
@@ -50,10 +50,10 @@ void test_store_flexarray (int i)
{
char a[3];
struct Sx *p = (struct Sx*)a;
- p->a = 0;
+ p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
p->b[0] = 0;
p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" }
- p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
+ p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
p->b[i] = 2;
sink (p);
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c
index 6d045c5..9100661 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c
@@ -161,8 +161,11 @@ void warn_memset_reversed_range (void)
/* Since the offset is excessive, either starting before &a11[0]
ot just past &a[11], the region size in the warning should
- probably be zero, but accept other sizes too. */
- T1 (p, SAR (INT_MIN, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" }
+ probably be zero, but accept other sizes too.
+
+ The problem isn't detected anymore because the offset is in
+ the anti-range ~[INT_MIN, -11] which isn't handled. */
+ T1 (p, SAR (INT_MIN, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" "" { xfail *-*-* } }
/* The following are represented as ordinary ranges with reversed bounds
and those are handled. */
@@ -170,7 +173,7 @@ void warn_memset_reversed_range (void)
T1 (p, SAR (INT_MIN, 1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" }
T1 (p, SAR (INT_MIN, 0), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" }
/* Also represented as a true anti-range. */
- T1 (p, SAR ( -12, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" }
+ T1 (p, SAR ( -12, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" "" { xfail *-*-* } }
T1 (p, SAR ( -12, -1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" }
T1 (p, SAR ( -11, 0), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" }
T1 (p, SAR ( -11, 11), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
index 318d9bd..4b6d1ab 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
@@ -117,7 +117,7 @@ void test_min (void)
{
/* 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 a6[6]; // { dg-message "(at offset 1 into )?destination object 'a6'" "note" }
char *p1 = ptr;
char *p2 = a6 + 1;
char *q = MIN (p1, p2);
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
index 6bcba27..09df000 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
@@ -58,11 +58,11 @@ void warn_comp_lit_zero (void)
void warn_comp_lit (void)
{
*(AC2*)a1 = Ac2; // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } }
- *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail *-*-* } }
- *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail *-*-* } }
- *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail *-*-* } }
- *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail *-*-* } }
- *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail *-*-* } }
+ *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
+ *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
+ *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
+ *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
+ *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
}
void warn_aggr_decl (void)
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-70.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-70.c
index 82c4d9f..ccfe2ce 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-70.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-70.c
@@ -17,8 +17,8 @@ void* warn_loop (void)
char *p = __builtin_malloc (15);
for (int i = 0; i != 16; ++i)
/* The size of the write below depends on the target. When vectorized
- the vector size may be 4 or 16, otherwise it may be a series of byte
+ the vector size may be 4, 8 or 16, otherwise it may be a series of byte
assignments. */
- p[i] = i; // { dg-warning "writing (1|2|4|16) bytes? into a region of size (0|1|3|15)" }
+ p[i] = i; // { dg-warning "writing (1|2|4|8|16) bytes? into a region of size (0|1|3|7|15)" }
return p;
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-73.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-73.c
new file mode 100644
index 0000000..0bb4afe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-73.c
@@ -0,0 +1,35 @@
+/*
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+int memcmp (const void*, const void*, size_t);
+int strncmp (const char*, const char*, size_t);
+char* stpncpy (char*, const char*, size_t);
+char* strncpy (char*, const char*, size_t);
+
+extern char a4[4], b5[5];
+
+struct A { char a4[4]; };
+
+extern volatile int i;
+extern void* volatile ptr;
+
+void test_stpncpy (struct A *p)
+{
+ ptr = stpncpy (a4, b5, 4);
+ ptr = stpncpy (a4, b5, 5); // { dg-warning "writing 5 bytes" }
+
+ ptr = stpncpy (p->a4, b5, 4);
+ ptr = stpncpy (p->a4, b5, 5); // { dg-warning "writing 5 bytes" }
+}
+
+void test_strncpy (struct A *p)
+{
+ ptr = strncpy (a4, b5, 4);
+ ptr = strncpy (a4, b5, 5); // { dg-warning "writing 5 bytes" }
+
+ ptr = strncpy (p->a4, b5, 4);
+ ptr = strncpy (p->a4, b5, 5); // { dg-warning "writing 5 bytes" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-74.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-74.c
new file mode 100644
index 0000000..bacec96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-74.c
@@ -0,0 +1,22 @@
+/* PR middle-end/102200 - ICE on a min of a decl and pointer in a loop
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern char a[], n;
+
+void f (void)
+{
+ char *p = a;
+ size_t end = 1;
+
+ while (n)
+ {
+ if (p < (char*)end)
+ *p = ';';
+
+ if (p > (char*)&end)
+ p = (char*)&end;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-75.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-75.c
new file mode 100644
index 0000000..0b242e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-75.c
@@ -0,0 +1,133 @@
+/* Verify warnings and notes for MIN_EXPRs involving either pointers
+ to distinct objects or one to a known object and the other to
+ an unknown one. The relational expressions are strictly invalid
+ but that should be diagnosed by a separate warning.
+ { dg-do compile }
+ { dg-options "-O2 -Wno-array-bounds" } */
+
+/* Verify the note points to the larger of the two objects and mentions
+ the offset into it (although the offset might be better included in
+ the warning). */
+extern char a3[3];
+extern char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" }
+
+void min_a3_a5 (int i)
+{
+ char *p = a3 + i;
+ char *q = a5 + i;
+
+ /* The relational expression below is invalid and should be diagnosed
+ by its own warning independently of -Wstringop-overflow. */
+ char *d = p < q ? p : q;
+
+ d[4] = 0;
+ d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+// Same as above but with the larger array as the first MIN_EXPR operand.
+extern char b4[4];
+extern char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" }
+
+void min_b6_b4 (int i)
+{
+ char *p = b6 + i;
+ char *q = b4 + i;
+ char *d = p < q ? p : q;
+
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+/* Same as above but with the first MIN_EXPR operand pointing to an unknown
+ object. */
+extern char c7[7]; // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+
+void min_p_c7 (char *p, int i)
+{
+ char *q = c7 + i;
+ char *d = p < q ? p : q;
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+/* Same as above but with the second MIN_EXPR operand pointing to an unknown
+ object. */
+extern char d8[8]; // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+
+void min_d8_p (char *q, int i)
+{
+ char *p = d8 + i;
+ char *d = p < q ? p : q;
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct A3_5
+{
+ char a3[3];
+ char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" }
+};
+
+void min_A3_A5 (int i, struct A3_5 *pa3_5)
+{
+ char *p = pa3_5->a3 + i;
+ char *q = pa3_5->a5 + i;
+
+ char *d = p < q ? p : q;
+
+ // d[4] = 0;
+ d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct B4_B6
+{
+ char b4[4];
+ char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" }
+};
+
+void min_B6_B4 (int i, struct B4_B6 *pb4_b6)
+{
+ char *p = pb4_b6->b6 + i;
+ char *q = pb4_b6->b4 + i;
+ char *d = p < q ? p : q;
+
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct C7
+{
+ char c7[7]; // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+};
+
+void min_p_C7 (char *p, int i, struct C7 *pc7)
+{
+ char *q = pc7->c7 + i;
+ char *d = p < q ? p : q;
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct D8
+{
+ char d8[8]; // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+};
+
+void min_D8_p (char *q, int i, struct D8 *pd8)
+{
+ char *p = pd8->d8 + i;
+ char *d = p < q ? p : q;
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
new file mode 100644
index 0000000..0c7b53c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
@@ -0,0 +1,148 @@
+/* Verify warnings and notes for MAX_EXPRs involving either pointers
+ to distinct objects or one to a known object and the other to
+ an unknown one. Unlike for the same object, for unrelated objects
+ the expected warnings and notes are the same as for MIN_EXPR: when
+ the order of the objects in the address space cannot be determined
+ the larger of them is assumed to be used. (This is different for
+ distinct struct members where the order is given.)
+ The relational expressions are strictly invalid but that should be
+ diagnosed by a separate warning.
+ { dg-do compile }
+ { dg-options "-O2 -Wno-array-bounds" } */
+
+#define MAX(p, q) ((p) > (q) ? (p) : (q))
+
+/* Verify that even for MAX_EXPR and like for MIN_EXPR, the note points
+ to the larger of the two objects and mentions the offset into it
+ (although the offset might be better included in the warning). */
+extern char a3[3];
+extern char a5[5]; // { dg-message "at offset \[^a-zA-Z\n\r\]*5\[^a-zA-Z0-9\]* into destination object 'a5' of size 5" "note" }
+
+void max_a3_a5 (int i)
+{
+ char *p = a3 + i;
+ char *q = a5 + i;
+
+ /* The relational expression below is invalid and should be diagnosed
+ by its own warning independently of -Wstringop-overflow. */
+ char *d = MAX (p, q);
+
+ d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } }
+ d[3] = 0;
+ d[4] = 0;
+ d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
+}
+
+
+// Same as above but with the larger array as the first MAX_EXPR operand.
+extern char b4[4];
+extern char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" }
+
+void max_b6_b4 (int i)
+{
+ char *p = b6 + i;
+ char *q = b4 + i;
+ char *d = MAX (p, q);
+
+ d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } }
+ d[4] = 0;
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
+}
+
+
+/* Same as above but with the first MAX_EXPR operand pointing to an unknown
+ object. */
+extern char c7[7]; // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+
+void max_p_c7 (char *p, int i)
+{
+ char *q = c7 + i;
+ char *d = MAX (p, q);
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+/* Same as above but with the second MIN_EXPR operand pointing to an unknown
+ object. */
+extern char d8[8]; // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+
+void max_d8_p (char *q, int i)
+{
+ char *p = d8 + i;
+ char *d = MAX (p, q);
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct A3_5
+{
+ char a3[3]; // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
+ char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { i?86-*-* x86_64-*-* } } }
+};
+
+void max_A3_A5 (int i, struct A3_5 *pa3_5)
+{
+ char *p = pa3_5->a3 + i;
+ char *q = pa3_5->a5 + i;
+
+ char *d = MAX (p, q);
+
+ d[2] = 0;
+ d[3] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } }
+ d[4] = 0;
+ d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
+}
+
+
+struct B4_B6
+{
+ char b4[4];
+ char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" { xfail { i?86-*-* x86_64-*-* } } }
+};
+
+void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
+{
+ char *p = pb4_b6->b6 + i;
+ char *q = pb4_b6->b4 + i;
+ char *d = MAX (p, q);
+
+ d[3] = 0;
+ d[4] = 0;
+ d[5] = 0;
+ d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
+}
+
+
+struct C7
+{
+ char c7[7]; // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+};
+
+void max_p_C7 (char *p, int i, struct C7 *pc7)
+{
+ char *q = pc7->c7 + i;
+ char *d = MAX (p, q);
+
+ d[6] = 0;
+ d[7] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct D8
+{
+ char d8[8]; // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+};
+
+void max_D8_p (char *q, int i, struct D8 *pd8)
+{
+ char *p = pd8->d8 + i;
+ char *d = MAX (p, q);
+
+ d[7] = 0;
+ d[8] = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/capacity-2.c b/gcc/testsuite/gcc.dg/analyzer/capacity-2.c
index 9f92bcf..2db1b3f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/capacity-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/capacity-2.c
@@ -8,7 +8,8 @@ void *
test_realloc_1 (void *p, size_t new_sz)
{
void *q = realloc (p, new_sz);
- __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'UNKNOWN\\(sizetype\\)'" } */
+ __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'UNKNOWN\\(sizetype\\)'" "failure" } */
+ /* { dg-warning "capacity: 'INIT_VAL\\(new_sz\[^\n\r\]*\\)'" "success" { target *-*-* } .-1 } */
return q;
}
@@ -18,8 +19,9 @@ test_realloc_2 (size_t sz_a, size_t sz_b)
void *p = malloc (sz_a);
__analyzer_dump_capacity (p); /* { dg-warning "capacity: 'INIT_VAL\\(sz_a_\[^\n\r\]*\\)'" } */
void *q = realloc (p, sz_b);
- __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'UNKNOWN\\(sizetype\\)'" } */
- return p;
+ __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'UNKNOWN\\(sizetype\\)'" "failure" } */
+ /* { dg-warning "capacity: 'INIT_VAL\\(sz_b\[^\n\r\]*\\)'" "success" { target *-*-* } .-1 } */
+ return q; /* { dg-warning "leak of 'p'" } */
}
void *
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99193-1.c b/gcc/testsuite/gcc.dg/analyzer/pr99193-1.c
index c6179e9..459357c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr99193-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr99193-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
/* Verify absence of false positive from -Wanalyzer-mismatching-deallocation
on realloc(3).
Based on https://github.com/libguestfs/libguestfs/blob/f19fd566f6387ce7e4d82409528c9dde374d25e0/daemon/command.c#L115
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99193-3.c b/gcc/testsuite/gcc.dg/analyzer/pr99193-3.c
index 3e7ffd6..d64b045 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr99193-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr99193-3.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
/* Verify absence of false positive from -Wanalyzer-mismatching-deallocation
on realloc(3).
Based on https://github.com/libguestfs/libguestfs/blob/f19fd566f6387ce7e4d82409528c9dde374d25e0/daemon/debug.c#L115
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-1.c b/gcc/testsuite/gcc.dg/analyzer/realloc-1.c
index a6c6bfc..ef117ad 100644
--- a/gcc/testsuite/gcc.dg/analyzer/realloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-free-nonheap-object" } */
+
typedef __SIZE_TYPE__ size_t;
#define NULL ((void *)0)
@@ -20,11 +22,10 @@ void *test_1 (void *ptr)
void *test_2 (void *ptr)
{
- void *p = malloc (1024);
- p = realloc (p, 4096);
- /* TODO: should warn about the leak when the above call fails (PR analyzer/99260). */
+ void *p = malloc (1024); /* { dg-message "allocated here" } */
+ p = realloc (p, 4096); /* { dg-message "when 'realloc' fails" } */
free (p);
-}
+} /* { dg-warning "leak of 'p'" } */ // ideally this would be on the realloc stmt
void *test_3 (void *ptr)
{
@@ -44,8 +45,8 @@ void *test_4 (void)
int *test_5 (int *p)
{
*p = 42;
- int *q = realloc (p, sizeof(int) * 4);
- *q = 43; /* { dg-warning "possibly-NULL 'q'" "PR analyzer/99260" { xfail *-*-* } } */
+ int *q = realloc (p, sizeof(int) * 4); /* { dg-message "when 'realloc' fails" } */
+ *q = 43; /* { dg-warning "dereference of NULL 'q'" } */
return q;
}
@@ -53,3 +54,42 @@ void test_6 (size_t sz)
{
void *p = realloc (NULL, sz);
} /* { dg-warning "leak of 'p'" } */
+
+/* The analyzer should complain about realloc of non-heap. */
+
+void *test_7 (size_t sz)
+{
+ char buf[100];
+ void *p = realloc (&buf, sz); /* { dg-warning "'realloc' of '&buf' which points to memory not on the heap" } */
+ return p;
+}
+
+/* Mismatched allocator. */
+
+struct foo
+{
+ int m_int;
+};
+
+extern void foo_release (struct foo *);
+extern struct foo *foo_acquire (void)
+ __attribute__ ((malloc (foo_release)));
+
+void test_8 (void)
+{
+ struct foo *p = foo_acquire ();
+ void *q = realloc (p, 1024); /* { dg-warning "'p' should have been deallocated with 'foo_release' but was deallocated with 'realloc'" } */
+}
+
+/* We should complain about realloc on a freed pointer. */
+
+void test_9 (void *p)
+{
+ free (p);
+ void *q = realloc (p, 1024); /* { dg-warning "double-'free' of 'p'" } */
+}
+
+void test_10 (char *s, int n)
+{
+ __builtin_realloc(s, n); /* { dg-warning "ignoring return value of '__builtin_realloc' declared with attribute 'warn_unused_result'" } */
+} /* { dg-warning "leak" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-2.c b/gcc/testsuite/gcc.dg/analyzer/realloc-2.c
new file mode 100644
index 0000000..a397753
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-2.c
@@ -0,0 +1,80 @@
+#include "analyzer-decls.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+#define NULL ((void *)0)
+
+extern void *malloc (size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__malloc__))
+ __attribute__ ((__alloc_size__ (1)));
+extern void *realloc (void *__ptr, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__warn_unused_result__))
+ __attribute__ ((__alloc_size__ (2)));
+extern void free (void *__ptr)
+ __attribute__ ((__nothrow__ , __leaf__));
+
+char *test_8 (size_t sz)
+{
+ char *p, *q;
+
+ p = malloc (3);
+ if (!p)
+ return NULL;
+
+ __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(size_t\\)3'" } */
+
+ p[0] = 'a';
+ p[1] = 'b';
+ p[2] = 'c';
+
+ __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
+
+ q = realloc (p, 6);
+
+ /* We should have 3 nodes, corresponding to "failure",
+ "success without moving", and "success with moving". */
+ __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */
+
+ if (q)
+ {
+ __analyzer_dump_capacity (q); /* { dg-warning "capacity: '\\(size_t\\)6'" } */
+ q[3] = 'd';
+ q[4] = 'e';
+ q[5] = 'f';
+ if (q == p)
+ {
+ /* "realloc" success, growing the buffer in-place. */
+ __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
+ // TODO
+ }
+ else
+ {
+ /* "realloc" success, moving the buffer (and thus freeing "p"). */
+ __analyzer_eval (q[0] == 'a'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (q[1] == 'b'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (q[2] == 'c'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[0] == 'a'); /* { dg-warning "UNKNOWN" "unknown" } */
+ /* { dg-warning "use after 'free' of 'p'" "use after free" { target *-*-* } .-1 } */
+ }
+ __analyzer_eval (q[3] == 'd'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (q[4] == 'e'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (q[5] == 'f'); /* { dg-warning "TRUE" } */
+ }
+ else
+ {
+ /* "realloc" failure. p should be unchanged. */
+ __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(size_t\\)3'" } */
+ __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
+ return p;
+ }
+
+ return q;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/strndup-1.c b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c
index 23d9b60..5822353 100644
--- a/gcc/testsuite/gcc.dg/analyzer/strndup-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c
@@ -1,3 +1,4 @@
+/* { dg-skip-if "no strndup in libc" { *-*-darwin[789]* *-*-darwin10* } } */
#include <string.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c b/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
index 0a1c48f..69d0165 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/asm-x86-linux-rdmsr.c
@@ -6,7 +6,7 @@
/* Adapted from Linux: arch/x86/include/asm/msr.h (GPL-2.0) */
#ifdef __x86_64__
-#define DECLARE_ARGS(val, low, high) unsigned long low, high
+#define DECLARE_ARGS(val, low, high) unsigned long long low, high
#define EAX_EDX_VAL(val, low, high) ((low) | (high) << 32)
#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
#else
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr102225.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr102225.c
new file mode 100644
index 0000000..a7c3249
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr102225.c
@@ -0,0 +1,6 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+void bad_realloc(char *s, int n)
+{
+ char *p = __builtin_realloc(s, n);
+} /* { dg-warning "leak" } */
diff --git a/gcc/testsuite/gcc.dg/array-quals-1.c b/gcc/testsuite/gcc.dg/array-quals-1.c
index 2c04164..b9b55f7 100644
--- a/gcc/testsuite/gcc.dg/array-quals-1.c
+++ b/gcc/testsuite/gcc.dg/array-quals-1.c
@@ -7,26 +7,26 @@
/* { dg-additional-options "-fno-pie" { target pie } } */
/* 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|srodata)|\[RO\]} } } */
+/* { dg-final { scan-assembler-symbol-section {^_?a$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
static const int a[2] = { 1, 2 };
/* { dg-final { scan-assembler-symbol-section {^_?a1$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
const int a1[2] = { 1, 2 };
typedef const int ci;
-/* { dg-final { scan-assembler-symbol-section {^_?b$} {^\.(const|rodata|srodata)|\[RO\]} } } */
+/* { dg-final { scan-assembler-symbol-section {^_?b$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
static ci b[2] = { 3, 4 };
/* { dg-final { scan-assembler-symbol-section {^_?b1$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
ci b1[2] = { 3, 4 };
typedef int ia[2];
-/* { dg-final { scan-assembler-symbol-section {^_?c$} {^\.(const|rodata|srodata)|\[RO\]} } } */
+/* { dg-final { scan-assembler-symbol-section {^_?c$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
static const ia c = { 5, 6 };
/* { dg-final { scan-assembler-symbol-section {^_?c1$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
const ia c1 = { 5, 6 };
typedef const int cia[2];
-/* { dg-final { scan-assembler-symbol-section {^_?d$} {^\.(const|rodata|srodata)|\[RO\]} } } */
+/* { dg-final { scan-assembler-symbol-section {^_?d$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
static cia d = { 7, 8 };
/* { dg-final { scan-assembler-symbol-section {^_?d1$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
cia d1 = { 7, 8 };
-/* { dg-final { scan-assembler-symbol-section {^_?e$} {^\.(const|rodata|srodata)|\[RO\]} } } */
+/* { dg-final { scan-assembler-symbol-section {^_?e$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
static cia e[2] = { { 1, 2 }, { 3, 4 } };
/* { dg-final { scan-assembler-symbol-section {^_?e1$} {^\.(const|rodata|srodata|sdata)|\[RO\]} } } */
cia e1[2] = { { 1, 2 }, { 3, 4 } };
diff --git a/gcc/testsuite/gcc.dg/associative-math-1.c b/gcc/testsuite/gcc.dg/associative-math-1.c
new file mode 100644
index 0000000..3f9ce5b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/associative-math-1.c
@@ -0,0 +1,17 @@
+/* Test __ASSOCIATIVE_MATH__ is defined with -fassociative-math. */
+/* { dg-do compile } */
+/* { dg-options "-fassociative-math -fno-signed-zeros -fno-trapping-math" } */
+
+#ifndef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-associative-math"
+#ifdef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-fassociative-math"
+#ifndef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ not defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/associative-math-2.c b/gcc/testsuite/gcc.dg/associative-math-2.c
new file mode 100644
index 0000000..764d6f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/associative-math-2.c
@@ -0,0 +1,17 @@
+/* Test __ASSOCIATIVE_MATH__ is not defined with -fno-associative-math. */
+/* { dg-do compile } */
+/* { dg-options "-fno-associative-math" } */
+
+#ifdef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-fassociative-math"
+#ifndef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-associative-math"
+#ifdef __ASSOCIATIVE_MATH__
+#error "__ASSOCIATIVE_MATH__ defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-1.c b/gcc/testsuite/gcc.dg/attr-unavailable-1.c
new file mode 100644
index 0000000..768214f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-1.c
@@ -0,0 +1,88 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int INT1 __attribute__((unavailable));
+typedef INT1 INT2 __attribute__ ((__unavailable__));
+
+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable" "" } */
+typedef INT1 INT1b __attribute__ ((unavailable));
+
+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable" "" } */
+INT1a should_not_be_unavailable;
+
+INT1 f1(void) __attribute__ ((unavailable));
+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable" "" } */
+
+INT2 f3(void) __attribute__ ((__unavailable__));
+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable" "" } */
+int f5(INT2 x); /* { dg-error "'INT2' is unavailable" "" } */
+int f6(INT2 x) __attribute__ ((__unavailable__)); /* { dg-error "'INT2' is unavailable" "" } */
+
+typedef enum {red, green, blue} Color __attribute__((unavailable));
+
+int g1;
+int g2 __attribute__ ((unavailable));
+int g3 __attribute__ ((__unavailable__));
+Color k; /* { dg-error "'Color' is unavailable" "" } */
+
+typedef struct {
+ int field1;
+ int field2 __attribute__ ((unavailable));
+ int field3;
+ int field4 __attribute__ ((__unavailable__));
+ union {
+ int field5;
+ int field6 __attribute__ ((unavailable));
+ } u1;
+ int field7:1;
+ int field8:1 __attribute__ ((unavailable));
+ union {
+ int field9;
+ int field10;
+ } u2 __attribute__ ((unavailable));
+} S1;
+
+int func1()
+{
+ INT1 w; /* { dg-error "'INT1' is unavailable" "" } */
+ int x __attribute__ ((unavailable));
+ int y __attribute__ ((__unavailable__));
+ int z;
+ int (*pf)() = f1; /* { dg-error "'f1' is unavailable" "" } */
+
+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable" "" } */
+ /* { dg-error "'y' is unavailable" "y" { target *-*-* } .-1 } */
+ /* { dg-error "'g2' is unavailable" "g2" { target *-*-* } .-2 } */
+ /* { dg-error "'g3' is unavailable" "g3" { target *-*-* } .-3 } */
+ return f1(); /* { dg-error "'f1' is unavailable" "f1" } */
+}
+
+int func2(S1 *p)
+{
+ S1 lp;
+
+ if (p->field1)
+ return p->field2; /* { dg-error "'field2' is unavailable" "" } */
+ else if (lp.field4) /* { dg-error "'field4' is unavailable" "" } */
+ return p->field3;
+
+ p->u1.field5 = g1 + p->field7;
+ p->u2.field9; /* { dg-error "'u2' is unavailable" "" } */
+ return p->u1.field6 + p->field8; /* { dg-error "'field6' is unavailable" "" } */
+ /* { dg-error "'field8' is unavailable" "field8" { target *-*-* } .-1 } */
+}
+
+struct SS1 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */
+} __attribute__ ((unavailable));
+
+struct SS1 *p1; /* { dg-error "'SS1' is unavailable" "" } */
+
+struct __attribute__ ((__unavailable__)) SS2 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */
+};
+
+struct SS2 *p2; /* { dg-error "'SS2' is unavailable" "" } */
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-2.c b/gcc/testsuite/gcc.dg/attr-unavailable-2.c
new file mode 100644
index 0000000..303f973
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-2.c
@@ -0,0 +1,6 @@
+/* Test __attribute__((unavailable)). Test types without names. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct { int a; } __attribute__((unavailable)) x; /* { dg-error "type is unavailable" } */
+typeof(x) y; /* { dg-error "type is unavailable" } */
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-3.c b/gcc/testsuite/gcc.dg/attr-unavailable-3.c
new file mode 100644
index 0000000..7274c19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-3.c
@@ -0,0 +1,10 @@
+/* Test __attribute__((unavailable)). */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void func(void);
+void func(void) __attribute__((unavailable));
+
+void f(void) {
+ func(); /* { dg-error "'func' is unavailable" } */
+}
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-4.c b/gcc/testsuite/gcc.dg/attr-unavailable-4.c
new file mode 100644
index 0000000..9e39c50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-4.c
@@ -0,0 +1,88 @@
+/* Test __attribute__ ((unavailable("message"))) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int INT1 __attribute__((unavailable("You can't use INT1")));
+typedef INT1 INT2 __attribute__ ((__unavailable__("You can't use INT2")));
+
+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+typedef INT1 INT1b __attribute__ ((unavailable("You can't use INT1b")));
+
+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+INT1a should_not_be_unavailable;
+
+INT1 f1(void) __attribute__ ((unavailable("You can't use f1")));
+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+
+INT2 f3(void) __attribute__ ((__unavailable__("You can't use f3")));
+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable: You can't use INT2" "" } */
+int f5(INT2 x); /* { dg-error "'INT2' is unavailable: You can't use INT2" "" } */
+int f6(INT2 x) __attribute__ ((__unavailable__("You can't use f6"))); /* { dg-error "'INT2' is unavailable: You can't use INT2" "" } */
+
+typedef enum {red, green, blue} Color __attribute__((unavailable("You can't use Color")));
+
+int g1;
+int g2 __attribute__ ((unavailable("You can't use g2")));
+int g3 __attribute__ ((__unavailable__("You can't use g3")));
+Color k; /* { dg-error "'Color' is unavailable: You can't use Color" "" } */
+
+typedef struct {
+ int field1;
+ int field2 __attribute__ ((unavailable("You can't use field2")));
+ int field3;
+ int field4 __attribute__ ((__unavailable__("You can't use field4")));
+ union {
+ int field5;
+ int field6 __attribute__ ((unavailable("You can't use field6")));
+ } u1;
+ int field7:1;
+ int field8:1 __attribute__ ((unavailable("You can't use field8")));
+ union {
+ int field9;
+ int field10;
+ } u2 __attribute__ ((unavailable("You can't use u2")));
+} S1;
+
+int func1()
+{
+ INT1 w; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+ int x __attribute__ ((unavailable("Avoid x")));
+ int y __attribute__ ((__unavailable__("Bad y")));
+ int z;
+ int (*pf)() = f1; /* { dg-error "'f1' is unavailable: You can't use f1" "" } */
+
+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable: Avoid x" "" } */
+ /* { dg-error "'y' is unavailable: Bad y" "y" { target *-*-* } .-1 } */
+ /* { dg-error "'g2' is unavailable: You can't use g2" "g2" { target *-*-* } .-2 } */
+ /* { dg-error "'g3' is unavailable: You can't use g3" "g3" { target *-*-* } .-3 } */
+ return f1(); /* { dg-error "'f1' is unavailable: You can't use f1" "" } */
+}
+
+int func2(S1 *p)
+{
+ S1 lp;
+
+ if (p->field1)
+ return p->field2; /* { dg-error "'field2' is unavailable: You can't use field2" "" } */
+ else if (lp.field4) /* { dg-error "'field4' is unavailable: You can't use field4" "" } */
+ return p->field3;
+
+ p->u1.field5 = g1 + p->field7;
+ p->u2.field9; /* { dg-error "'u2' is unavailable: You can't use u2" "" } */
+ return p->u1.field6 + p->field8; /* { dg-error "'field6' is unavailable: You can't use field6" "" } */
+ /* { dg-error "'field8' is unavailable: You can't use field8" "field8" { target *-*-* } .-1 } */
+}
+
+struct SS1 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+} __attribute__ ((unavailable("You can't use SS1")));
+
+struct SS1 *p1; /* { dg-error "'SS1' is unavailable: You can't use SS1" "" } */
+
+struct __attribute__ ((__unavailable__("You can't use SS2"))) SS2 {
+ int x;
+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */
+};
+
+struct SS2 *p2; /* { dg-error "'SS2' is unavailable: You can't use SS2" "" } */
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-5.c b/gcc/testsuite/gcc.dg/attr-unavailable-5.c
new file mode 100644
index 0000000..051f960
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-5.c
@@ -0,0 +1,6 @@
+/* Test __attribute__((unavailable)). Test types without names. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct { int a; } __attribute__((unavailable ("Do not use"))) x; /* { dg-error "type is unavailable" } */
+typeof(x) y; /* { dg-error "type is unavailable: Do not use" } */
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-6.c b/gcc/testsuite/gcc.dg/attr-unavailable-6.c
new file mode 100644
index 0000000..f5f4560
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-unavailable-6.c
@@ -0,0 +1,11 @@
+/* Test __attribute__((unavailable)). Test merging with multiple
+ declarations. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void func(void);
+void func(void) __attribute__((unavailable ("Do not use")));
+
+void f(void) {
+ func(); /* { dg-error "'func' is unavailable: Do not use" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c b/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c
new file mode 100644
index 0000000..7c9de99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-hardreg-1.c
@@ -0,0 +1,9 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+int
+main ()
+{
+ register long *sp __asm__("sp");
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-sra-1.c b/gcc/testsuite/gcc.dg/auto-init-sra-1.c
new file mode 100644
index 0000000..88fd666
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-sra-1.c
@@ -0,0 +1,24 @@
+/* Verify that SRA total scalarization will not be confused by padding
+ and also not confused by auto initialization. */
+/* { dg-do compile } */
+/* { dg-options "-O1 --param sra-max-scalarization-size-Ospeed=16 -fdump-tree-release_ssa -ftrivial-auto-var-init=zero" } */
+
+struct S
+{
+ int i;
+ unsigned short f1;
+ char f2;
+ unsigned short f3, f4;
+};
+
+
+int foo (struct S *p)
+{
+ struct S l;
+
+ l = *p;
+ l.i++;
+ *p = l;
+}
+
+/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" } } */
diff --git a/gcc/testsuite/gcc.dg/auto-init-sra-2.c b/gcc/testsuite/gcc.dg/auto-init-sra-2.c
new file mode 100644
index 0000000..d260f5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-sra-2.c
@@ -0,0 +1,24 @@
+/* Verify that SRA total scalarization will not be confused by padding
+ and also not confused by auto initialization. */
+/* { dg-do compile } */
+/* { dg-options "-O1 --param sra-max-scalarization-size-Ospeed=16 -fdump-tree-release_ssa -ftrivial-auto-var-init=pattern" } */
+
+struct S
+{
+ int i;
+ unsigned short f1;
+ char f2;
+ unsigned short f3, f4;
+};
+
+
+int foo (struct S *p)
+{
+ struct S l;
+
+ l = *p;
+ l.i++;
+ *p = l;
+}
+
+/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" } } */
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-1.c b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
new file mode 100644
index 0000000..502db59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
@@ -0,0 +1,5 @@
+/* Spurious uninitialized variable warnings, case 1.
+ Taken from cppfiles.c (merge_include_chains) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-1.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-12.c b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
new file mode 100644
index 0000000..65da110
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
@@ -0,0 +1,4 @@
+/* PR 23497 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-12.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-13.c b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
new file mode 100644
index 0000000..87dd8b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo()
+{
+ C f;
+ __imag__ f = 0;
+ return f; /* { dg-warning "is used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-14.c b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
new file mode 100644
index 0000000..9ffe00a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
@@ -0,0 +1,4 @@
+/* PR 24931 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-14.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-15.c b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
new file mode 100644
index 0000000..121f0cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/17506
+ We issue an uninitialized variable warning at a wrong location at
+ line 11, which is very confusing. Make sure we print out a note to
+ make it less confusing. (not xfailed alternative)
+ But it is of course ok if we warn in bar about uninitialized use
+ of j. (not xfailed alternative) */
+/* { dg-do compile } */
+/* { dg-options "-O1 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+inline int
+foo (int i)
+{
+ if (i) /* { dg-warning "used uninitialized" } */
+ return 1;
+ return 0;
+}
+
+void baz (void);
+
+void
+bar (void)
+{
+ int j; /* { dg-message "note: 'j' was declared here" "" } */
+ for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */
+ baz ();
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-16.c b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
new file mode 100644
index 0000000..38e1950
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* -ftrivial-auto-var-init will make the uninitialized warning for address
+ taken auto var going away, FIXME later. */
+
+int foo, bar;
+
+static
+void decode_reloc(int reloc, int *is_alt)
+{
+ if (reloc >= 20)
+ *is_alt = 1;
+ else if (reloc >= 10)
+ *is_alt = 0;
+}
+
+void testfunc()
+{
+ int alt_reloc;
+
+ decode_reloc(foo, &alt_reloc);
+
+ if (alt_reloc) /* { dg-warning "may be used uninitialized" "" { xfail *-*-* } } */
+ bar = 42;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-17.c b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
new file mode 100644
index 0000000..9eec944
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f; /* { dg-warning "may be used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-18.c b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
new file mode 100644
index 0000000..1c9afa9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-18.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-19.c b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
new file mode 100644
index 0000000..38d27e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-additional-options "-finline-small-functions" { target avr-*-* } } */
+
+int a, l, m;
+float *b;
+float c, d, e, g, h;
+unsigned char i, k;
+void
+fn1 (int p1, float *f1, float *f2, float *f3, unsigned char *c1, float *f4,
+ unsigned char *c2, float *p10)
+{
+ if (p1 & 8)
+ b[3] = p10[a];
+ /* { dg-warning "may be used uninitialized" "" { target { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } .-1 } */
+}
+
+void
+fn2 ()
+{
+ float *n;
+ if (l & 6)
+ n = &c + m;
+ fn1 (l, &d, &e, &g, &i, &h, &k, n);
+ /* { dg-warning "may be used uninitialized" "" { target { ! { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-2.c b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
new file mode 100644
index 0000000..4c32dc8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
@@ -0,0 +1,5 @@
+/* Spurious uninitialized variable warnings, case 2.
+ Taken from cpphash.c (macroexpand) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-2.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-20.c b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
new file mode 100644
index 0000000..d81957e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
@@ -0,0 +1,4 @@
+/* Spurious uninitialized variable warnings, from gdb */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-20.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-21.c b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
new file mode 100644
index 0000000..cc61746
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
@@ -0,0 +1,4 @@
+/* PR69537, spurious warning because of a missed optimization. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-short-enums -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-21.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-22.c b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
new file mode 100644
index 0000000..1e522ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wuninitialized --param vect-max-version-for-alias-checks=20 -ftrivial-auto-var-init=zero" } */
+#include "uninit-22.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-23.c b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
new file mode 100644
index 0000000..f1f7839
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/78455 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int ij;
+
+void
+ql (void)
+{
+ int m5 = 0;
+
+ for (;;)
+ {
+ if (0)
+ for (;;)
+ {
+ int *go;
+ int *t4 = go; /* { dg-warning "is used uninitialized" } */
+
+ l1:
+ *t4 = (*t4 != 0) ? 0 : 2; /* { dg-warning "is used uninitialized" } */
+ }
+
+ if (ij != 0)
+ goto l1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-24.c b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
new file mode 100644
index 0000000..0f839ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-24.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-25.c b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
new file mode 100644
index 0000000..f36d95f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+ unsigned u;
+ if (v != 1)
+ u = bar ();
+
+ // Prevent the "dom" pass from changing the CFG layout based on the inference
+ // 'if (v != 1) is false then (v != 2) is true'. (Now it would have to
+ // duplicate the loop in order to do so, which is deemed expensive.)
+ for (int i = 0; i < 10; i++)
+ quux ();
+
+ if (v != 2)
+ return u; /* { dg-warning "may be used uninitialized" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-26.c b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
new file mode 100644
index 0000000..ae97ecf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+ unsigned u;
+ if (v != 100)
+ u = bar ();
+
+ // Prevent the "dom" pass from changing the CFG layout based on the inference
+ // 'if (v != 100) is false then (v < 105) is true'. (Now it would have to
+ // duplicate the loop in order to do so, which is deemed expensive.)
+ for (int i = 0; i < 10; i++)
+ quux ();
+
+ if (v < 105) /* v == 100 falls into this range. */
+ return u; /* { dg-warning "may be used uninitialized" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-3.c b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
new file mode 100644
index 0000000..5c10920
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
@@ -0,0 +1,5 @@
+/* Spurious uninit variable warnings, case 3.
+ Inspired by cppexp.c (parse_charconst) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-3.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-34.c b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
new file mode 100644
index 0000000..1a68765
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
@@ -0,0 +1,60 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+ arguments
+ Verify that passing pointers to uninitialized objects to arguments
+ to functions declared with attribute access is diagnosed where expected.
+ { dg-do compile }
+ { dg-options "-O -Wall -ftrivial-auto-var-init=zero" } */
+/* -ftrivial-auto-var-init will make the uninitialized warning for address
+ taken auto var going away, FIXME later. */
+
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+
+RW (1) RW (3) void
+f4pi (int*, int*, int*, int*); // { dg-message "in a call to 'f4pi' declared with attribute 'access \\\(read_write, \[13\]\\\)'" }
+
+
+void nowarn_scalar (void)
+{
+ int i1 = 0, i2, i3 = 1, i4;
+ f4pi (&i1, &i2, &i3, &i4);
+}
+
+void warn_scalar_1 (void)
+{
+ int i1; // { dg-message "declared here" "" { xfail *-*-* } }
+ int i2, i3 = 1, i4;
+
+ f4pi (&i1, &i2, &i3, &i4); // { dg-warning "'i1' may be used uninitialized" "" { xfail *-*-* } }
+}
+
+void warn_scalar_2 (void)
+{
+ int j1 = 0, j2, j4;
+ int j3;
+
+ f4pi (&j1, &j2, &j3, &j4); // { dg-warning "'j3' may be used uninitialized" "" { xfail *-*-* } }
+}
+
+
+void nowarn_array_init (void)
+{
+ int a1[4] = { 0 }, a2[5], a3[6] = { 0 }, a4[7];
+
+ f4pi (a1, a2, a3, a4);
+}
+
+void warn_array_1 (void)
+{
+ int a1[4]; // { dg-message "'a1' declared here" }
+ int a2[5], a3[6] = { 0 }, a4[7];
+
+ f4pi (a1, a2, a3, a4); // { dg-warning "'a1' may be used uninitialized" }
+}
+
+void warn_array_2 (void)
+{
+ int a1[4] = { 0 }, a2[5], a4[7];
+ int a3[6]; // { dg-message "'a3' declared here" }
+
+ f4pi (a1, a2, a3, a4); // { dg-warning "'a3' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-36.c b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
new file mode 100644
index 0000000..64377d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
@@ -0,0 +1,238 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+ arguments
+ Verify that passing pointers to uninitialized objects to const
+ arguments to built-ins is diagnosed where expected.
+ { dg-do compile }
+ { dg-options "-O -Wall -ftrivial-auto-var-init=zero" }
+ { dg-require-effective-target alloca } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+void* memcpy (void*, const void*, size_t);
+char* strcpy (char*, const char*);
+size_t strlen (const char*);
+
+void sink (void*);
+
+void nowarn_array_memcpy (void *d, unsigned n)
+{
+ int a[2];
+ /* Diagnose this? */
+ memcpy (d, a, n /* Non-constant to avoid folding into MEM_REF. */);
+}
+
+void nowarn_array_plus_cst_memcpy (void *d, unsigned n)
+{
+ int a[3];
+ /* Diagnose this? */
+ memcpy (d, a + 1, n);
+}
+
+void nowarn_array_plus_var_memcpy (void *d, unsigned n, int i)
+{
+ int a[4];
+ /* Diagnose this? */
+ memcpy (d, a + i, n);
+}
+
+void nowarn_array_assign_memcpy (char *d, unsigned n)
+{
+ int a[3];
+ a[1] = 3;
+ memcpy (d, a, n);
+}
+
+void nowarn_array_init_memcpy (char *d, unsigned n)
+{
+ int a[4] = { 0 };
+ memcpy (d, a, n);
+}
+
+void nowarn_array_compound_memcpy (void *d, unsigned n)
+{
+ memcpy (d, (int[2]){ 0 }, n);
+}
+
+void nowarn_struct_assign_memcpy (void *d, unsigned n)
+{
+ struct S { int a, b, c, d; } s;
+ s.b = 1;
+ s.d = 2;
+ memcpy (d, &s, n);
+}
+
+
+void nowarn_array_init_strcpy (char *d[], unsigned n)
+{
+ char a[8] = "012";
+
+ strcpy (d[0], a);
+ strcpy (d[1], a + 1);
+ strcpy (d[1], a + 2);
+ strcpy (d[1], a + 3);
+ strcpy (d[1], a + 4);
+ strcpy (d[1], a + 5);
+ strcpy (d[1], a + 6);
+ strcpy (d[1], a + 7);
+}
+
+
+void nowarn_array_assign_strcpy (char *d[], unsigned n)
+{
+ char a[8];
+ a[0] = '0';
+ a[1] = '1';
+ a[2] = '2';
+ a[3] = '\0';
+
+ strcpy (d[0], a);
+ strcpy (d[1], a + 1);
+ strcpy (d[1], a + 2);
+ strcpy (d[1], a + 3);
+}
+
+void warn_array_plus_cst_strcpy (char *d, unsigned n)
+{
+ char a[8];
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ a[3] = '\0';
+
+ strcpy (d, a + 4); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 5); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 6); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 7); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+void nowarn_array_plus_var_strcpy (char *d, int i)
+{
+ char a[8];
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ a[3] = '\0';
+
+ strcpy (d, a + i);
+}
+
+
+size_t nowarn_array_assign_strlen (const char *s)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ size_t n = 0;
+
+ n += strlen (a);
+ n += strlen (a + 1);
+ n += strlen (a + 2);
+ n += strlen (a + 3);
+ return n;
+}
+
+size_t warn_array_plus_cst_strlen (const char *s)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ return strlen (a + 4); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+size_t nowarn_array_plus_var_strlen (const char *s, int i)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ return strlen (a + i);
+}
+
+
+size_t nowarn_alloca_assign_strlen (int i)
+{
+ char *p = (char*)alloca (8);
+ p[i] = '\0';
+ return strlen (p);
+}
+
+size_t nowarn_alloca_escape_strlen (int i)
+{
+ char *p = (char*)alloca (8);
+ sink (p);
+ return strlen (p);
+}
+
+size_t warn_alloca_strlen (void)
+{
+ char *p = (char*)alloca (8);
+ return strlen (p); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_malloc_assign_strlen (int i)
+{
+ char *p = (char*)malloc (8);
+ p[i] = '\0';
+ return strlen (p);
+}
+
+size_t nowarn_malloc_escape_strlen (int i)
+{
+ char *p = (char*)malloc (8);
+ sink (p);
+ return strlen (p);
+}
+
+size_t warn_malloc_strlen (void)
+{
+ char *p = (char*)malloc (8);
+ return strlen (p); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_realloc_strlen (void *p)
+{
+ char *q = (char*)realloc (p, 8);
+ return strlen (q);
+}
+
+
+size_t nowarn_vla_assign_strlen (int n, int i)
+{
+ char vla[n];
+ vla[i] = '\0';
+ return strlen (vla);
+}
+
+size_t nowarn_vla_strcpy_strlen (int n, const char *s, int i)
+{
+ char vla[n];
+ strcpy (vla, s);
+ return strlen (vla + i);
+}
+
+size_t nowarn_vla_escape_strlen (int n, int i)
+{
+ char vla[n];
+ sink (vla);
+ return strlen (vla);
+}
+
+size_t warn_vla_strlen (unsigned n)
+{
+ char vla[n];
+ return strlen (vla); // { dg-warning "\\\[-Wuninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-37.c b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
new file mode 100644
index 0000000..2791b37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
@@ -0,0 +1,156 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const arguments
+ Verify that -Wuninitialized and -Wmaybe-uninitialized trigger (or don't)
+ when passing uninitialized variables by reference to functions declared
+ with or without attribute access and with (or without) const qualified
+ arguments of array, VLA, or pointer types.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0 -ftrivial-auto-var-init=zero" } */
+/* -ftrivial-auto-var-init will make the uninitialized warning for address
+ taken auto var going away, FIXME later. */
+
+#define NONE /* none */
+#define RO(...) __attribute__ ((access (read_only, __VA_ARGS__)))
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+#define WO(...) __attribute__ ((access (write_only, __VA_ARGS__)))
+#define X(...) __attribute__ ((access (none, __VA_ARGS__)))
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define UNIQ(pfx) CAT (pfx, __LINE__)
+
+extern void sink (void*);
+
+
+#define T1(attr, name, type) \
+ void UNIQ (CAT (test_, name))(void) { \
+ extern attr void UNIQ (name)(type); \
+ int x; \
+ UNIQ (name)(&x); \
+ sink (&x); \
+ }
+
+#define T2(attr, name, types) \
+ void UNIQ (CAT (test_, name))(void) { \
+ extern attr void UNIQ (name)(types); \
+ int x; \
+ UNIQ (name)(1, &x); \
+ sink (&x); \
+ }
+
+
+typedef int IA_[];
+typedef const int CIA_[];
+
+T1 (NONE, fia_, IA_);
+T1 (NONE, fcia_, CIA_); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froia_, IA_); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwia_, IA_); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoia_, IA_);
+T1 (X (1), fxia_, IA_);
+
+
+typedef int IA1[1];
+typedef const int CIA1[1];
+
+T1 (NONE, fia1, IA1);
+T1 (NONE, fcia1, CIA1); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froia1, IA1); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwia1, IA1); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoia1, IA1);
+T1 (X (1), fxia1, IA1);
+
+
+#define IARS1 int[restrict static 1]
+#define CIARS1 const int[restrict static 1]
+
+T1 (NONE, fiars1, IARS1);
+T1 (NONE, fciars1, CIARS1);// { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froiars1, IARS1); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwiars1, IARS1); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoiars1, IARS1);
+T1 (X (1), fxiars1, IARS1);
+
+
+#define IAS1 int[static 1]
+#define CIAS1 const int[static 1]
+
+T1 (NONE, fias1, IAS1);
+T1 (NONE, fcias1, CIAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froias1, IAS1); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwias1, IAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoias1, IAS1);
+T1 (X (1), fxias1, IAS1);
+
+
+#define IAX int[*]
+#define CIAX const int[*]
+
+T1 (NONE, fiax, IAX);
+T1 (NONE, fciax, CIAX); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froiax, IAX); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwiax, IAX); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoiax, IAX);
+T1 (X (1), fxiax, IAX);
+
+
+#define IAN int n, int[n]
+#define CIAN int n, const int[n]
+
+T2 (NONE, fian, IAN);
+T2 (NONE, fcian, CIAN); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T2 (RO (2, 1), froian, IAN); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T2 (RW (2, 1), frwian, IAN); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T2 (WO (2, 1), fwoian, IAN);
+T2 (X (2, 1), fxian, IAN);
+
+
+typedef int* IP;
+typedef const int* CIP;
+
+T1 (NONE, fip, IP);
+T1 (NONE, fcip, CIP); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (RO (1), froip, IP); // { dg-warning "\\\[-Wuninitialized" "" { xfail *-*-* } }
+T1 (RW (1), frwip, IP); // { dg-warning "\\\[-Wmaybe-uninitialized" "" { xfail *-*-* } }
+T1 (WO (1), fwoip, IP);
+T1 (X (1), fxip, IP);
+
+
+/* Verify that the notes printed after the warning mention attribute
+ access only when the attribute is explicitly used in the declaration
+ and not otherwise. */
+
+void test_note_cst_restrict (void)
+{
+ extern void
+ fccar (const char[restrict]); // { dg-message "by argument 1 of type 'const char\\\[restrict]' to 'fccar'" "note" }
+
+ char a[1]; // { dg-message "'a' declared here" "note" }
+ fccar (a); // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_vla (int n)
+{
+ extern void
+ fccvla (const char[n]); // { dg-message "by argument 1 of type 'const char\\\[n]' to 'fccvla'" "note" }
+
+ char a[2]; // { dg-message "'a' declared here" "note" }
+ fccvla (a); // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_ro (void)
+{
+ extern RO (1) void
+ frocar (char[restrict]); // { dg-message "in a call to 'frocar' declared with attribute 'access \\\(read_only, 1\\\)'" "note" }
+
+ char a[3]; // { dg-message "'a' declared here" "note" }
+ frocar (a); // { dg-warning "'a' is used uninitialized" }
+}
+
+void test_note_rw (void)
+{
+ extern RW (1) void
+ frwcar (char[restrict]); // { dg-message "in a call to 'frwcar' declared with attribute 'access \\\(read_write, 1\\\)'" "note" }
+
+ char a[4]; // { dg-message "'a' declared here" "note" }
+ frwcar (a); // { dg-warning "'a' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-4.c b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
new file mode 100644
index 0000000..29ec860
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
@@ -0,0 +1,10 @@
+/* Spurious uninit variable warnings, case 4.
+ Simplified version of cppexp.c (cpp_parse_expr).
+
+ This one is really fragile, it gets it right if you take out case
+ 1, or if the structure is replaced by an int, or if the structure
+ has fewer members (!) */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-4.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-5.c b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
new file mode 100644
index 0000000..65b251a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
@@ -0,0 +1,6 @@
+/* Spurious uninitialized-variable warnings. */
+/* Disable jump threading, etc to test compiler analysis. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -fno-tree-dce -fno-tree-vrp -fno-tree-dominator-opts -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-5.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-6.c b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
new file mode 100644
index 0000000..7c10dfc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
@@ -0,0 +1,7 @@
+/* Spurious uninitialized variable warnings.
+ This one inspired by java/class.c:build_utf8_ref. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-6.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-8.c b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
new file mode 100644
index 0000000..eaa9c0c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
@@ -0,0 +1,8 @@
+/* Uninitialized variable warning tests...
+ Inspired by part of optabs.c:expand_binop.
+ May be the same as uninit-1.c. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-8.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-9.c b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
new file mode 100644
index 0000000..6dccf01
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
@@ -0,0 +1,8 @@
+/* Spurious uninitialized variable warnings. Slight variant on the
+ documented case, inspired by reg-stack.c:record_asm_reg_life. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target alloca } */
+
+#include "uninit-9.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-A.c b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
new file mode 100644
index 0000000..0ef1d92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
@@ -0,0 +1,7 @@
+/* Inspired by part of java/parse.y.
+ May be a real bug in CSE. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-A.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-B.c b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
new file mode 100644
index 0000000..b6d3efd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
@@ -0,0 +1,17 @@
+/* Origin: PR c/179 from Gray Watson <gray@256.com>, adapted as a testcase
+ by Joseph Myers <jsm28@cam.ac.uk>. */
+/* -ftrivial-auto-var-init will make the uninitialized warning for address
+ taken auto var going away, FIXME later. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+extern void foo (int *);
+extern void bar (int);
+
+void
+baz (void)
+{
+ int i;
+ if (i) /* { dg-warning "is used uninitialized" "uninit i warning" { xfail *-*-* } } */
+ bar (i);
+ foo (&i);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-C.c b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
new file mode 100644
index 0000000..be19796
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
@@ -0,0 +1,5 @@
+/* Spurious uninitialized variable warning, inspired by libgcc2.c. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-C.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-H.c b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
new file mode 100644
index 0000000..e442fab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
@@ -0,0 +1,5 @@
+/* PR 14204 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wall -Werror -ftrivial-auto-var-init=zero" } */
+
+#include "uninit-H.c"
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-I.c b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
new file mode 100644
index 0000000..4f9ae6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+#include "uninit-H.c"
diff --git a/gcc/testsuite/gcc.dg/comp-goto-5.c b/gcc/testsuite/gcc.dg/comp-goto-5.c
new file mode 100644
index 0000000..d487729
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/comp-goto-5.c
@@ -0,0 +1,11 @@
+/* PR c/32122 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+enum {a=1};
+void foo()
+{
+ goto *
+ a; /* { dg-error "computed goto must be pointer type" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/comp-goto-6.c b/gcc/testsuite/gcc.dg/comp-goto-6.c
new file mode 100644
index 0000000..497f6cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/comp-goto-6.c
@@ -0,0 +1,6 @@
+/* PR c/32122 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+void foo(void *a) { goto *10000000; } /* { dg-error "computed goto must be pointer type" } */
+void foo1(void *a) { goto *a; }
+
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c
new file mode 100644
index 0000000..efcfbc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c
@@ -0,0 +1,5 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11" } */
+
+#include "c2x-elifdef-1.c"
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c
new file mode 100644
index 0000000..e5bd705
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c
@@ -0,0 +1,63 @@
+/* Test #elifdef and #elifndef in GNU11: erroneous usages. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11" } */
+
+#define A
+#undef B
+
+#elifdef A /* { dg-error "#elifdef without #if" } */
+#elifdef B /* { dg-error "#elifdef without #if" } */
+#elifndef A /* { dg-error "#elifndef without #if" } */
+#elifndef B /* { dg-error "#elifndef without #if" } */
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifdef A /* { dg-error "#elifdef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifdef B /* { dg-error "#elifdef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifndef A /* { dg-error "#elifndef after #else" } */
+#endif
+
+#if 1 /* { dg-error "-:began here" } */
+#else
+#elifndef B /* { dg-error "#elifndef after #else" } */
+#endif
+
+#if 0
+#elifdef A = /* { dg-warning "extra tokens at end of #elifdef directive" } */
+#endif
+
+#if 0
+#elifdef B = /* { dg-warning "extra tokens at end of #elifdef directive" } */
+#endif
+
+#if 0
+#elifndef A = /* { dg-warning "extra tokens at end of #elifndef directive" } */
+#endif
+
+#if 0
+#elifndef B = /* { dg-warning "extra tokens at end of #elifndef directive" } */
+#endif
+
+#if 0
+#elifdef /* { dg-error "no macro name given in #elifdef directive" } */
+#endif
+
+#if 0
+#elifndef /* { dg-error "no macro name given in #elifndef directive" } */
+#endif
+
+#if 0
+#elifdef , /* { dg-error "macro names must be identifiers" } */
+#endif
+
+#if 0
+#elifndef , /* { dg-error "macro names must be identifiers" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c
new file mode 100644
index 0000000..0b769a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c
@@ -0,0 +1,65 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11 -pedantic" } */
+
+#define A
+#undef B
+
+#if 0
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#endif
+
+/* As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group. */
+
+#if 1
+#elifdef x * y /* { dg-warning "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef ! /* { dg-warning "#elifndef before C2X is a GCC extension" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c
new file mode 100644
index 0000000..aba3467
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c
@@ -0,0 +1,65 @@
+/* Test #elifdef and #elifndef in GNU11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu11 -pedantic-errors" } */
+
+#define A
+#undef B
+
+#if 0
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#define M1 1
+#endif
+
+#if M1 != 1
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifdef B
+#error "#elifdef B applied"
+#endif
+
+#if 0
+#elifndef A
+#error "#elifndef A applied"
+#endif
+
+#if 0
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#define M2 2
+#endif
+
+#if M2 != 2
+#error "#elifndef B did not apply"
+#endif
+
+#if 0
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#else
+#error "#elifdef A did not apply"
+#endif
+
+#if 0
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#else
+#error "#elifndef B did not apply"
+#endif
+
+#if 1
+#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#endif
+
+/* As with #elif, the syntax of the new directives is relaxed after a
+ non-skipped group. */
+
+#if 1
+#elifdef x * y /* { dg-error "#elifdef before C2X is a GCC extension" } */
+#endif
+
+#if 1
+#elifndef ! /* { dg-error "#elifndef before C2X is a GCC extension" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/ucnid-4-utf8.c b/gcc/testsuite/gcc.dg/cpp/ucnid-4-utf8.c
index ccc7a1e..0a527ef 100644
--- a/gcc/testsuite/gcc.dg/cpp/ucnid-4-utf8.c
+++ b/gcc/testsuite/gcc.dg/cpp/ucnid-4-utf8.c
@@ -9,9 +9,9 @@
Ö
΄
-٩ /* { dg-error "not valid at the start of an identifier" } */
-๙ /* { dg-error "not valid at the start of an identifier" } */
+๙
A๙
diff --git a/gcc/testsuite/gcc.dg/cpp/ucnid-4.c b/gcc/testsuite/gcc.dg/cpp/ucnid-4.c
index e41a3f5..dceed66 100644
--- a/gcc/testsuite/gcc.dg/cpp/ucnid-4.c
+++ b/gcc/testsuite/gcc.dg/cpp/ucnid-4.c
@@ -9,9 +9,9 @@
\u00D6
\u0384
-\u0669 /* { dg-error "not valid at the start of an identifier" } */
+\u0669
A\u0669
0\u00BA
0\u0669
-\u0E59 /* { dg-error "not valid at the start of an identifier" } */
+\u0E59
A\u0E59
diff --git a/gcc/testsuite/gcc.dg/cpp/ucnid-5-utf8.c b/gcc/testsuite/gcc.dg/cpp/ucnid-5-utf8.c
new file mode 100644
index 0000000..79767b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/ucnid-5-utf8.c
@@ -0,0 +1,17 @@
+/* { dg-do preprocess } */
+/* { dg-options "-std=c99 -pedantic" } */
+
+« /* not a preprocessing error because we lex it into its own token */
+¶ /* not a preprocessing error because we lex it into its own token */
+΄ /* not a preprocessing error because we lex it into its own token */
+
+٩ /* { dg-error "not valid at the start of an identifier" } */
+A٩
+0º
+0٩
+๙ /* { dg-error "not valid at the start of an identifier" } */
+A๙
diff --git a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
index 302e233..1cbcad5 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
@@ -3,21 +3,25 @@
int test_uninit_1 (void)
{
- int result;
- return result; /* { dg-warning "uninitialized" } */
-/* { dg-begin-multiline-output "" }
- return result;
- ^~~~~~
+ int result_1; /* { dg-message "declared here" } */
+ return result_1; /* { dg-warning "uninitialized" } */
+ /* { dg-begin-multiline-output "" }
+ return result_1;
+ ^~~~~~~~
+ int result_1;
+ ^~~~~~~~
{ dg-end-multiline-output "" } */
}
int test_uninit_2 (void)
{
- int result;
- result += 3; /* { dg-warning "uninitialized" } */
-/* { dg-begin-multiline-output "" }
- result += 3;
- ~~~~~~~^~~~
+ int result_2; /* { dg-message "declared here" } */
+ result_2 += 3; /* { dg-warning "uninitialized" } */
+ /* { dg-begin-multiline-output "" }
+ result_2 += 3;
+ ~~~~~~~~~^~~~
+ int result_2;
+ ^~~~~~~~
{ dg-end-multiline-output "" } */
- return result;
+ return result_2;
}
diff --git a/gcc/testsuite/gcc.dg/fold-negate-1.c b/gcc/testsuite/gcc.dg/fold-negate-1.c
new file mode 100644
index 0000000..00ec8b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-negate-1.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define SHIFT ((8*__SIZEOF_INT__)-1)
+
+int test_rshift_1(int x)
+{
+ int t = x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_2(int x)
+{
+ unsigned int t = (unsigned int)x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_3(int x)
+{
+ int t = (unsigned int)x >> SHIFT;
+ return -t;
+}
+
+int test_rshift_4(int x)
+{
+ unsigned int t = x >> SHIFT;
+ return -t;
+}
+
+double test_mul_1(double x)
+{
+ double t = -5.0 * x;
+ return -t;
+}
+
+double test_mul_2(double x, double y)
+{
+ double t1 = -x;
+ double t2 = t1 * y;
+ return -t2;
+}
+
+double test_rdiv_1(double x, double y)
+{
+ double t1 = -x;
+ double t2 = t1 / y;
+ return -t2;
+}
+
+double test_rdiv_2(double x, double y)
+{
+ double t1 = -y;
+ double t2 = x / t1;
+ return -t2;
+}
+
+/* { dg-final { scan-tree-dump-not " -" "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/format/c11-dfp-printf-1.c b/gcc/testsuite/gcc.dg/format/c11-dfp-printf-1.c
new file mode 100644
index 0000000..356a23e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c11-dfp-printf-1.c
@@ -0,0 +1,35 @@
+/* Test for printf formats: rejection of DFP formats in pedantic mode. */
+/* { dg-do compile } */
+/* { dg-require-effective-target dfp } */
+/* { dg-options "-std=gnu11 -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (_Decimal32 d32, _Decimal64 d64, _Decimal128 d128) /* { dg-warning "ISO C" } */
+{
+ printf ("%Ha", d32); /* { dg-warning "C" } */
+ printf ("%HA", d32); /* { dg-warning "C" } */
+ printf ("%He", d32); /* { dg-warning "C" } */
+ printf ("%HE", d32); /* { dg-warning "C" } */
+ printf ("%Hf", d32); /* { dg-warning "C" } */
+ printf ("%HF", d32); /* { dg-warning "C" } */
+ printf ("%Hg", d32); /* { dg-warning "C" } */
+ printf ("%HG", d32); /* { dg-warning "C" } */
+ printf ("%Da", d64); /* { dg-warning "C" } */
+ printf ("%DA", d64); /* { dg-warning "C" } */
+ printf ("%De", d64); /* { dg-warning "C" } */
+ printf ("%DE", d64); /* { dg-warning "C" } */
+ printf ("%Df", d64); /* { dg-warning "C" } */
+ printf ("%DF", d64); /* { dg-warning "C" } */
+ printf ("%Dg", d64); /* { dg-warning "C" } */
+ printf ("%DG", d64); /* { dg-warning "C" } */
+ printf ("%DDa", d128); /* { dg-warning "C" } */
+ printf ("%DDA", d128); /* { dg-warning "C" } */
+ printf ("%DDe", d128); /* { dg-warning "C" } */
+ printf ("%DDE", d128); /* { dg-warning "C" } */
+ printf ("%DDf", d128); /* { dg-warning "C" } */
+ printf ("%DDF", d128); /* { dg-warning "C" } */
+ printf ("%DDg", d128); /* { dg-warning "C" } */
+ printf ("%DDG", d128); /* { dg-warning "C" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/c11-dfp-scanf-1.c b/gcc/testsuite/gcc.dg/format/c11-dfp-scanf-1.c
new file mode 100644
index 0000000..35bd631
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c11-dfp-scanf-1.c
@@ -0,0 +1,35 @@
+/* Test for scanf formats: rejection of DFP formats in pedantic mode. */
+/* { dg-do compile } */
+/* { dg-require-effective-target dfp } */
+/* { dg-options "-std=gnu11 -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (_Decimal32 *d32, _Decimal64 *d64, _Decimal128 *d128) /* { dg-warning "ISO C" } */
+{
+ scanf ("%Ha", d32); /* { dg-warning "C" } */
+ scanf ("%HA", d32); /* { dg-warning "C" } */
+ scanf ("%He", d32); /* { dg-warning "C" } */
+ scanf ("%HE", d32); /* { dg-warning "C" } */
+ scanf ("%Hf", d32); /* { dg-warning "C" } */
+ scanf ("%HF", d32); /* { dg-warning "C" } */
+ scanf ("%Hg", d32); /* { dg-warning "C" } */
+ scanf ("%HG", d32); /* { dg-warning "C" } */
+ scanf ("%Da", d64); /* { dg-warning "C" } */
+ scanf ("%DA", d64); /* { dg-warning "C" } */
+ scanf ("%De", d64); /* { dg-warning "C" } */
+ scanf ("%DE", d64); /* { dg-warning "C" } */
+ scanf ("%Df", d64); /* { dg-warning "C" } */
+ scanf ("%DF", d64); /* { dg-warning "C" } */
+ scanf ("%Dg", d64); /* { dg-warning "C" } */
+ scanf ("%DG", d64); /* { dg-warning "C" } */
+ scanf ("%DDa", d128); /* { dg-warning "C" } */
+ scanf ("%DDA", d128); /* { dg-warning "C" } */
+ scanf ("%DDe", d128); /* { dg-warning "C" } */
+ scanf ("%DDE", d128); /* { dg-warning "C" } */
+ scanf ("%DDf", d128); /* { dg-warning "C" } */
+ scanf ("%DDF", d128); /* { dg-warning "C" } */
+ scanf ("%DDg", d128); /* { dg-warning "C" } */
+ scanf ("%DDG", d128); /* { dg-warning "C" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/c11-printf-1.c b/gcc/testsuite/gcc.dg/format/c11-printf-1.c
new file mode 100644
index 0000000..7b8a992
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c11-printf-1.c
@@ -0,0 +1,13 @@
+/* Test for printf formats: rejection of C2X (and C2X-recommended) formats in
+ pedantic mode. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (int i)
+{
+ printf ("%b", i); /* { dg-warning "C" } */
+ printf ("%B", i); /* { dg-warning "C" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/c11-scanf-1.c b/gcc/testsuite/gcc.dg/format/c11-scanf-1.c
new file mode 100644
index 0000000..d2b9bfb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c11-scanf-1.c
@@ -0,0 +1,11 @@
+/* Test for printf formats: rejection of C2X formats in pedantic mode. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (unsigned int *uip)
+{
+ scanf ("%b", uip); /* { dg-warning "C" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/c2x-dfp-printf-1.c b/gcc/testsuite/gcc.dg/format/c2x-dfp-printf-1.c
new file mode 100644
index 0000000..dc40f99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c2x-dfp-printf-1.c
@@ -0,0 +1,35 @@
+/* Test for printf formats: acceptance of DFP formats in pedantic mode. */
+/* { dg-do compile } */
+/* { dg-require-effective-target dfp } */
+/* { dg-options "-std=c2x -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (_Decimal32 d32, _Decimal64 d64, _Decimal128 d128)
+{
+ printf ("%Ha", d32);
+ printf ("%HA", d32);
+ printf ("%He", d32);
+ printf ("%HE", d32);
+ printf ("%Hf", d32);
+ printf ("%HF", d32);
+ printf ("%Hg", d32);
+ printf ("%HG", d32);
+ printf ("%Da", d64);
+ printf ("%DA", d64);
+ printf ("%De", d64);
+ printf ("%DE", d64);
+ printf ("%Df", d64);
+ printf ("%DF", d64);
+ printf ("%Dg", d64);
+ printf ("%DG", d64);
+ printf ("%DDa", d128);
+ printf ("%DDA", d128);
+ printf ("%DDe", d128);
+ printf ("%DDE", d128);
+ printf ("%DDf", d128);
+ printf ("%DDF", d128);
+ printf ("%DDg", d128);
+ printf ("%DDG", d128);
+}
diff --git a/gcc/testsuite/gcc.dg/format/c2x-dfp-scanf-1.c b/gcc/testsuite/gcc.dg/format/c2x-dfp-scanf-1.c
new file mode 100644
index 0000000..81e39a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c2x-dfp-scanf-1.c
@@ -0,0 +1,35 @@
+/* Test for scanf formats: acceptance of DFP formats in pedantic mode. */
+/* { dg-do compile } */
+/* { dg-require-effective-target dfp } */
+/* { dg-options "-std=c2x -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (_Decimal32 *d32, _Decimal64 *d64, _Decimal128 *d128)
+{
+ scanf ("%Ha", d32);
+ scanf ("%HA", d32);
+ scanf ("%He", d32);
+ scanf ("%HE", d32);
+ scanf ("%Hf", d32);
+ scanf ("%HF", d32);
+ scanf ("%Hg", d32);
+ scanf ("%HG", d32);
+ scanf ("%Da", d64);
+ scanf ("%DA", d64);
+ scanf ("%De", d64);
+ scanf ("%DE", d64);
+ scanf ("%Df", d64);
+ scanf ("%DF", d64);
+ scanf ("%Dg", d64);
+ scanf ("%DG", d64);
+ scanf ("%DDa", d128);
+ scanf ("%DDA", d128);
+ scanf ("%DDe", d128);
+ scanf ("%DDE", d128);
+ scanf ("%DDf", d128);
+ scanf ("%DDF", d128);
+ scanf ("%DDg", d128);
+ scanf ("%DDG", d128);
+}
diff --git a/gcc/testsuite/gcc.dg/format/c2x-printf-1.c b/gcc/testsuite/gcc.dg/format/c2x-printf-1.c
new file mode 100644
index 0000000..3ae7713
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c2x-printf-1.c
@@ -0,0 +1,26 @@
+/* Test for printf formats. Formats using C2X features. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (unsigned int u, unsigned short us, unsigned char uc, unsigned long ul,
+ unsigned long long ull, uintmax_t uj, size_t z, unsigned_ptrdiff_t ut)
+{
+ /* Use of %b with each length modifier and other valid features. */
+ printf ("%b %hb %hhb %lb %llb %jb %zb %tb\n", u, us, uc, ul, ull, uj, z, ut);
+ printf ("%*.*llb\n", 1, 2, ull);
+ printf ("%-b\n", u);
+ printf ("%#b\n", u);
+ printf ("%08b\n", u);
+ /* Flags valid on signed conversions only. */
+ printf ("%+b\n", u); /* { dg-warning "flag" } */
+ printf ("% b\n", u); /* { dg-warning "flag" } */
+ /* Flags ignored in certain combinations. */
+ printf ("%-08b\n", u); /* { dg-warning "ignored" } */
+ printf ("%08.5b\n", u); /* { dg-warning "ignored" } */
+ /* Use of 'L' and 'q' for long long is an extension. */
+ printf ("%Lb", ull); /* { dg-warning "does not support" } */
+ printf ("%qb", ull); /* { dg-warning "does not support" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c b/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
new file mode 100644
index 0000000..f46a715
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c2x-scanf-1.c
@@ -0,0 +1,17 @@
+/* Test for scanf formats. Formats using C2X features. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (unsigned int *uip, unsigned short int *uhp, unsigned char *uhhp,
+ unsigned long int *ulp, unsigned long long *ullp, uintmax_t *ujp,
+ size_t *zp, unsigned_ptrdiff_t *utp)
+{
+ scanf ("%*b");
+ scanf ("%2b", uip);
+ scanf ("%hb%hhb%lb%llb%jb%zb%tb", uhp, uhhp, ulp, ullp, ujp, zp, utp);
+ scanf ("%Lb", ullp); /* { dg-warning "does not support" } */
+ scanf ("%qb", ullp); /* { dg-warning "does not support" } */
+}
diff --git a/gcc/testsuite/gcc.dg/format/ext-10.c b/gcc/testsuite/gcc.dg/format/ext-10.c
new file mode 100644
index 0000000..370ea86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/ext-10.c
@@ -0,0 +1,13 @@
+/* Test for scanf format extensions using formats from C2X. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x -Wformat" } */
+
+#include "format.h"
+
+void
+foo (u_quad_t *uqp, unsigned long long int *ullp)
+{
+ /* Deprecated length modifiers with %b. */
+ scanf ("%qb", uqp);
+ scanf ("%Lb", ullp);
+}
diff --git a/gcc/testsuite/gcc.dg/format/ext-9.c b/gcc/testsuite/gcc.dg/format/ext-9.c
new file mode 100644
index 0000000..15f59e2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/ext-9.c
@@ -0,0 +1,29 @@
+/* Test for printf format extensions using formats from or recommended by
+ C2X. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x -Wformat" } */
+
+#include "format.h"
+
+void
+foo (u_quad_t uq, unsigned int u, unsigned short us, unsigned char uc,
+ unsigned long ul, unsigned long long ull, uintmax_t uj, size_t z,
+ unsigned_ptrdiff_t ut)
+{
+ /* Deprecated length modifiers with %b and %B. */
+ printf ("%qb%qB", uq, uq);
+ printf ("%Lb%LB", ull, ull);
+ printf ("%Zb%ZB", z, z);
+ /* Use of %B in cases valid for %b. */
+ printf ("%B %hB %hhB %lB %llB %jB %zB %tB\n", u, us, uc, ul, ull, uj, z, ut);
+ printf ("%*.*llB\n", 1, 2, ull);
+ printf ("%-B\n", u);
+ printf ("%#B\n", u);
+ printf ("%08B\n", u);
+ /* Flags valid on signed conversions only. */
+ printf ("%+B\n", u); /* { dg-warning "flag" } */
+ printf ("% B\n", u); /* { dg-warning "flag" } */
+ /* Flags ignored in certain combinations. */
+ printf ("%-08B\n", u); /* { dg-warning "ignored" } */
+ printf ("%08.5B\n", u); /* { dg-warning "ignored" } */
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-46.c b/gcc/testsuite/gcc.dg/gimplefe-46.c
new file mode 100644
index 0000000..fb91f7d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-46.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+char global[10];
+
+void bar (void);
+
+void __GIMPLE (ssa)
+foo (char * p)
+{
+ __BB(2):
+ if (p_2(D) == _Literal (char *)&global[2])
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ bar ();
+ goto __BB4;
+
+ __BB(4):
+ return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-47.c b/gcc/testsuite/gcc.dg/gimplefe-47.c
new file mode 100644
index 0000000..3bbd34d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-47.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+char * begfield (int tab, char * ptr, char * lim, int sword, int schar);
+
+int __GIMPLE (ssa)
+main ()
+{
+ char * lim;
+ char * s;
+ char * _1;
+
+ __BB(2):
+ _1 = begfield (58, ":ab", &__MEM <char[4]> ((void *)&":ab" + _Literal
+(void *) 3), 1, 1);
+ if (_1 != _Literal (char *) &__MEM <char[4]> ((void *)&":ab" + _Literal (void *) 2))
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ __builtin_abort ();
+
+ __BB(4):
+ __builtin_exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-error-12.c b/gcc/testsuite/gcc.dg/gimplefe-error-12.c
new file mode 100644
index 0000000..981ff7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-error-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int get_current ();
+
+__GIMPLE
+void foo()
+{
+ get_current()->flags; /* { dg-error "non-pointer" } */
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-5.c b/gcc/testsuite/gcc.dg/gomp/atomic-5.c
index 70cfb35..36d1422 100644
--- a/gcc/testsuite/gcc.dg/gomp/atomic-5.c
+++ b/gcc/testsuite/gcc.dg/gomp/atomic-5.c
@@ -27,7 +27,7 @@ void f1(void)
#pragma omp atomic
bar() += 1; /* { dg-error "lvalue required" } */
#pragma omp atomic a /* { dg-error "expected end of line" } */
- x++; /* { dg-error "expected 'read', 'write', 'update', 'capture', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
+ x++; /* { dg-error "expected 'read', 'write', 'update', 'capture', 'compare', 'weak', 'fail', 'seq_cst', 'acq_rel', 'release', 'relaxed' or 'hint' clause" "" { target *-*-* } .-1 } */
#pragma omp atomic
; /* { dg-error "expected expression" } */
#pragma omp atomic
diff --git a/gcc/testsuite/gcc.dg/gomp/pr46032-2.c b/gcc/testsuite/gcc.dg/gomp/pr46032-2.c
index e110880..2e56261 100644
--- a/gcc/testsuite/gcc.dg/gomp/pr46032-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/pr46032-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fopenmp -std=c99 -fipa-pta -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fopenmp -std=c99 -fipa-pta -fdump-tree-optimized" } */
#define N 2
diff --git a/gcc/testsuite/gcc.dg/gomp/pr46032-3.c b/gcc/testsuite/gcc.dg/gomp/pr46032-3.c
index a4af7ec..da1ab48 100644
--- a/gcc/testsuite/gcc.dg/gomp/pr46032-3.c
+++ b/gcc/testsuite/gcc.dg/gomp/pr46032-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fopenmp -std=c99 -fipa-pta -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fopenmp -std=c99 -fipa-pta -fdump-tree-optimized" } */
#define N 2
diff --git a/gcc/testsuite/gcc.dg/gomp/sections-2.c b/gcc/testsuite/gcc.dg/gomp/sections-2.c
index aabdfaf..6d8305a 100644
--- a/gcc/testsuite/gcc.dg/gomp/sections-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/sections-2.c
@@ -19,11 +19,11 @@ void foo(void)
{
#pragma omp section
bar(2);
- bar(3); // { dg-error "expected" }
+ bar(3);
bar(4);
#pragma omp section
bar(5);
- bar(6); // { dg-error "expected" }
+ bar(6);
bar(7);
}
}
diff --git a/gcc/testsuite/gcc.dg/graphite/fuse-1.c b/gcc/testsuite/gcc.dg/graphite/fuse-1.c
index 527b6e5..61289d3 100644
--- a/gcc/testsuite/gcc.dg/graphite/fuse-1.c
+++ b/gcc/testsuite/gcc.dg/graphite/fuse-1.c
@@ -1,6 +1,6 @@
/* Check that the two loops are fused and that we manage to fold the two xor
operations. */
-/* { dg-options "-O2 -floop-nest-optimize -fdump-tree-forwprop4 -fdump-tree-graphite-all" } */
+/* { dg-options "-O2 -fno-tree-vectorize -floop-nest-optimize -fdump-tree-forwprop4 -fdump-tree-graphite-all" } */
/* Make sure we fuse the loops like this:
AST generated by isl:
diff --git a/gcc/testsuite/gcc.dg/guality/example.c b/gcc/testsuite/gcc.dg/guality/example.c
index 6f1c017..32014e2b 100644
--- a/gcc/testsuite/gcc.dg/guality/example.c
+++ b/gcc/testsuite/gcc.dg/guality/example.c
@@ -1,5 +1,5 @@
-/* { dg-do run { xfail { ! aarch64*-*-* } } } */
/* { dg-options "-g" } */
+/* { dg-do run { xfail { ! aarch64*-*-* } } } */
/* { dg-xfail-run-if "" aarch64*-*-* "*" { "-O[01g]" } } */
#define GUALITY_DONT_FORCE_LIVE_AFTER -1
diff --git a/gcc/testsuite/gcc.dg/ipa/inline-8.c b/gcc/testsuite/gcc.dg/ipa/inline-8.c
index 388283c..c51eec2 100644
--- a/gcc/testsuite/gcc.dg/ipa/inline-8.c
+++ b/gcc/testsuite/gcc.dg/ipa/inline-8.c
@@ -6,13 +6,13 @@
#include <math.h>
extern int isnanf (float);
/* Can't be inlined because isnanf will be optimized out. */
-int
+static int
cmp (float a)
{
return isnanf (a);
}
/* Can be inlined. */
-int
+static int
move (int a)
{
return a;
diff --git a/gcc/testsuite/gcc.dg/ipa/pr102714.c b/gcc/testsuite/gcc.dg/ipa/pr102714.c
new file mode 100644
index 0000000..65dd86f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr102714.c
@@ -0,0 +1,117 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing -fdump-ipa-sra-details -fdump-tree-optimized" } */
+
+typedef _Bool bool;
+
+enum {
+ false = 0,
+ true = 1
+};
+
+struct xarray {
+ unsigned int xa_lock;
+ unsigned int xa_flags;
+ void * xa_head;
+
+};
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+struct callback_head {
+ struct callback_head *next;
+ void (*func)(struct callback_head *head);
+} __attribute__((aligned(sizeof(void *))));
+
+struct xa_node {
+ unsigned char shift;
+ unsigned char offset;
+ unsigned char count;
+ unsigned char nr_values;
+ struct xa_node *parent;
+ struct xarray *array;
+ union {
+ struct list_head private_list;
+ struct callback_head callback_head;
+ };
+ void *slots[(1UL << (0 ? 4 : 6))];
+ union {
+ unsigned long tags[3][((((1UL << (0 ? 4 : 6))) + (64) - 1) / (64))];
+ unsigned long marks[3][((((1UL << (0 ? 4 : 6))) + (64) - 1) / (64))];
+ };
+};
+
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) __attribute__((no_instrument_function)) unsigned long shift_maxindex(unsigned int shift)
+{
+ return ((1UL << (0 ? 4 : 6)) << shift) - 1;
+}
+
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) __attribute__((no_instrument_function)) unsigned long node_maxindex(const struct xa_node *node)
+{
+ return shift_maxindex(node->shift);
+}
+
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) __attribute__((no_instrument_function)) struct xa_node *entry_to_node(void *ptr)
+{
+ return (void *)((unsigned long)ptr & ~2UL);
+}
+
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) __attribute__((no_instrument_function)) bool radix_tree_is_internal_node(void *ptr)
+{
+ return ((unsigned long)ptr & 3UL) ==
+ 2UL;
+}
+
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) __attribute__((no_instrument_function)) void *xa_mk_internal(unsigned long v)
+{
+ return (void *)((v << 2) | 2);
+}
+
+static unsigned radix_tree_load_root(const struct xarray *root,
+ struct xa_node **nodep, unsigned long *maxindex)
+{
+ struct xa_node *node =
+ ({
+ typeof(root->xa_head) ________p1 = ({(*(const volatile typeof(root->xa_head) *)&(root->xa_head)); });
+ ((typeof(*root->xa_head) *)(________p1));
+ });
+
+ *nodep = node;
+
+ if (__builtin_expect(!!(radix_tree_is_internal_node(node)), 1)) {
+ node = entry_to_node(node);
+ *maxindex = node_maxindex(node);
+ return node->shift + (0 ? 4 : 6);
+ }
+
+ *maxindex = 0;
+ return 0;
+}
+
+void *__radix_tree_lookup(const struct xarray *root,
+ unsigned long index, struct xa_node **nodep,
+ void ***slotp)
+{
+ struct xa_node *node, *parent;
+ unsigned long maxindex;
+
+ restart:
+ parent = ((void *)0);
+ radix_tree_load_root(root, &node, &maxindex);
+ while (radix_tree_is_internal_node(node)) {
+
+ parent = entry_to_node(node);
+ if (node == xa_mk_internal(256))
+ goto restart;
+ if (parent->shift == 0)
+ break;
+ }
+ if (nodep)
+ *nodep = parent;
+
+ return node;
+}
+
+/* { dg-final { scan-ipa-dump-not "IPA_PARAM_OP_SPLIT" "sra" } } */
+/* { dg-final { scan-tree-dump " ={v} " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/no-signed-zeros-1.c b/gcc/testsuite/gcc.dg/no-signed-zeros-1.c
new file mode 100644
index 0000000..3b9cd71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-signed-zeros-1.c
@@ -0,0 +1,17 @@
+/* Test __NO_SIGNED_ZEROS__ is defined with -fno-signed-zeros. */
+/* { dg-do compile } */
+/* { dg-options "-fno-signed-zeros" } */
+
+#ifndef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ not defined"
+#endif
+
+#pragma GCC optimize "-fsigned-zeros"
+#ifdef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ defined"
+#endif
+
+#pragma GCC optimize "-fno-signed-zeros"
+#ifndef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ not defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/no-signed-zeros-2.c b/gcc/testsuite/gcc.dg/no-signed-zeros-2.c
new file mode 100644
index 0000000..865a29f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-signed-zeros-2.c
@@ -0,0 +1,17 @@
+/* Test __NO_SIGNED_ZEROS__ is not defined with -fsigned-zeros. */
+/* { dg-do compile } */
+/* { dg-options "-fsigned-zeros" } */
+
+#ifdef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ defined"
+#endif
+
+#pragma GCC optimize "-fno-signed-zeros"
+#ifndef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ not defined"
+#endif
+
+#pragma GCC optimize "-fsigned-zeros"
+#ifdef __NO_SIGNED_ZEROS__
+#error "__NO_SIGNED_ZEROS__ defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/no-trapping-math-1.c b/gcc/testsuite/gcc.dg/no-trapping-math-1.c
new file mode 100644
index 0000000..f4faec9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-trapping-math-1.c
@@ -0,0 +1,17 @@
+/* Test __NO_TRAPPING_MATH__ is defined with -fno-trapping-math. */
+/* { dg-do compile } */
+/* { dg-options "-fno-trapping-math" } */
+
+#ifndef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-ftrapping-math"
+#ifdef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-fno-trapping-math"
+#ifndef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ not defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/no-trapping-math-2.c b/gcc/testsuite/gcc.dg/no-trapping-math-2.c
new file mode 100644
index 0000000..1904b5d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-trapping-math-2.c
@@ -0,0 +1,17 @@
+/* Test __NO_TRAPPING_MATH__ is not defined with -ftrapping-math. */
+/* { dg-do compile } */
+/* { dg-options "-ftrapping-math" } */
+
+#ifdef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-fno-trapping-math"
+#ifndef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-ftrapping-math"
+#ifdef __NO_TRAPPING_MATH__
+#error "__NO_TRAPPING_MATH__ defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-2.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-2.c
new file mode 100644
index 0000000..2e93ee5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-2.c
@@ -0,0 +1,15 @@
+/* { dg-require-effective-target global_constructor } */
+/* { dg-options "-O2 -fprofile-generate -fprofile-update=single -fdump-tree-optimized" } */
+
+__attribute__ ((no_profile_instrument_function))
+int foo()
+{
+ return 0;
+}
+
+int bar()
+{
+ return foo();
+}
+
+/* { dg-final { scan-tree-dump-not " = foo \\(\\)" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
index 91a5284..5934aac 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target bswap } */
-/* { dg-options "-O2 -fdump-tree-optimized -fno-inline-functions" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-optimized -fno-inline-functions" } */
/* { dg-additional-options "-march=z900" { target s390-*-* } } */
struct L { unsigned int l[2]; };
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-6.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-6.c
index 3c089b3..75f8aec 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapsi-6.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-6.c
@@ -1,7 +1,7 @@
/* PR tree-optimization/42587 */
/* { dg-do compile } */
/* { dg-require-effective-target bswap } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
/* { dg-additional-options "-march=z900" { target s390-*-* } } */
typedef unsigned char u8;
diff --git a/gcc/testsuite/gcc.dg/out-of-bounds-1.c b/gcc/testsuite/gcc.dg/out-of-bounds-1.c
index 1c76341..5c134c0 100644
--- a/gcc/testsuite/gcc.dg/out-of-bounds-1.c
+++ b/gcc/testsuite/gcc.dg/out-of-bounds-1.c
@@ -8,6 +8,6 @@
void ProjectOverlay(const float localTextureAxis[2], char *lump)
{
const void *d = &localTextureAxis;
- int size = sizeof(float)*8 ;
+ int size = sizeof(float)*7 ;
__builtin_memcpy( &lump[ 0 ], d, size ); /* { dg-warning "reading" } */
}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
index 4cba87b..8818192 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
@@ -332,8 +332,8 @@ pr87652 (const char *stem, int counter)
OFFSET + end_idx); \
} while (0)
-/* { dg-error "unable to read substring location: unable to read source line" "" { target c } 329 } */
-/* { dg-error "unable to read substring location: failed to get ordinary maps" "" { target c++ } 329 } */
+/* { dg-error "unable to read substring location: failed to get ordinary maps" "" { target c } 329 } */
+/* { dg-error "unable to read substring location: macro expansion" "" { target c++ } 329 } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range(__FILE__":%5d: " format, \
^~~~~~~~
diff --git a/gcc/testsuite/gcc.dg/pr102087.c b/gcc/testsuite/gcc.dg/pr102087.c
new file mode 100644
index 0000000..5cd094f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102087.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+unsigned __attribute__ ((noinline))
+foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n)
+{
+ while (n < ++l)
+ *a++ = *b++ + 1;
+ return l;
+}
+
+volatile int a[1];
+unsigned b;
+int c;
+
+int
+check ()
+{
+ int d;
+ for (; b > 1; b++)
+ for (c = 0; c < 2; c++)
+ for (d = 0; d < 2; d++)
+ a[0];
+ return 0;
+}
+
+char **clip_image_gfi_0;
+int clip_image_y, clip_image_shift;
+void
+clip_image ()
+{
+ for (; clip_image_y >= clip_image_shift; clip_image_y++)
+ clip_image_gfi_0[clip_image_shift]
+ = clip_image_gfi_0[clip_image_y];
+}
diff --git a/gcc/testsuite/gcc.dg/pr102141.c b/gcc/testsuite/gcc.dg/pr102141.c
new file mode 100644
index 0000000..f3fc8d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102141.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/102141 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned int __attribute__((__vector_size__ (4))) v;
+
+void
+foo (unsigned long long x)
+{
+ v &= (unsigned) (x >> 56 | x >> 40 & 0xff00);
+}
diff --git a/gcc/testsuite/gcc.dg/pr102152.c b/gcc/testsuite/gcc.dg/pr102152.c
new file mode 100644
index 0000000..4e0c1f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102152.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftree-loop-vectorize -fno-tree-fre" } */
+/* { dg-additional-options "-march=armv8-a+sve" { target aarch64-*-* } } */
+
+
+
+signed char i;
+
+void
+foo (void)
+{
+ for (i = 0; i < 6; i += 5)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102207.c b/gcc/testsuite/gcc.dg/pr102207.c
new file mode 100644
index 0000000..08540d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102207.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/102207 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2" } */
+
+typedef unsigned __int128 u128;
+
+u128
+foo (unsigned short a)
+{
+ u128 g;
+ __builtin_sub_overflow ((unsigned long long) -a, 1, &g);
+ return g;
+}
+
+int
+main ()
+{
+ if (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ != 64
+ || __SIZEOF_SHORT__ * __CHAR_BIT__ != 16)
+ return 0;
+ if (foo (1) != 0xfffffffffffffffeULL)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102224.c b/gcc/testsuite/gcc.dg/pr102224.c
new file mode 100644
index 0000000..9f09ba5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102224.c
@@ -0,0 +1,49 @@
+/* PR target/102224 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+__attribute__((noipa)) float
+foo (float x)
+{
+ return x * __builtin_copysignf (1.0f, x);
+}
+
+__attribute__((noipa)) float
+bar (float x, float y)
+{
+ return x * __builtin_copysignf (1.0f, y);
+}
+
+__attribute__((noipa)) float
+baz (float z, float x)
+{
+ return x * __builtin_copysignf (1.0f, x);
+}
+
+__attribute__((noipa)) float
+qux (float z, float x, float y)
+{
+ return x * __builtin_copysignf (1.0f, y);
+}
+
+int
+main ()
+{
+ if (foo (1.0f) != 1.0f
+ || foo (-4.0f) != 4.0f)
+ __builtin_abort ();
+ if (bar (1.25f, 7.25f) != 1.25f
+ || bar (1.75f, -3.25f) != -1.75f
+ || bar (-2.25f, 7.5f) != -2.25f
+ || bar (-3.0f, -4.0f) != 3.0f)
+ __builtin_abort ();
+ if (baz (5.5f, 1.0f) != 1.0f
+ || baz (4.25f, -4.0f) != 4.0f)
+ __builtin_abort ();
+ if (qux (1.0f, 1.25f, 7.25f) != 1.25f
+ || qux (2.0f, 1.75f, -3.25f) != -1.75f
+ || qux (3.0f, -2.25f, 7.5f) != -2.25f
+ || qux (4.0f, -3.0f, -4.0f) != 3.0f)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102269.c b/gcc/testsuite/gcc.dg/pr102269.c
new file mode 100644
index 0000000..9d41b8f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102269.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+void fn() { int a[0]; }
diff --git a/gcc/testsuite/gcc.dg/pr102273.c b/gcc/testsuite/gcc.dg/pr102273.c
new file mode 100644
index 0000000..568e44e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102273.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+void bar();
+
+struct A { char d; };
+void foo()
+{
+ struct A e;
+ void baz() { bar(e); }
+}
diff --git a/gcc/testsuite/gcc.dg/pr102385.c b/gcc/testsuite/gcc.dg/pr102385.c
new file mode 100644
index 0000000..1339540
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102385.c
@@ -0,0 +1,14 @@
+/* { dg-options "-Wall -Wextra -O2 -fno-toplevel-reorder -fno-tree-ch -fno-tree-dce -fno-tree-dominator-opts -fno-tree-dse -fno-tree-loop-ivcanon -fpredictive-commoning" } */
+
+short a, b;
+int c[9];
+void(d)() {}
+void e() {
+ a = 0;
+ for (; a <= 4; a++) {
+ short *f = &b;
+ c[a] || (*f = 0);
+ d(c[a + 2]);
+ }
+}
+int main() {return 0;}
diff --git a/gcc/testsuite/gcc.dg/pr102463.c b/gcc/testsuite/gcc.dg/pr102463.c
new file mode 100644
index 0000000..ca63f0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102463.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+_Bool _bfd_elf_merge_symbol_h, _bfd_elf_merge_symbol_h_1;
+_Bool _bfd_elf_merge_symbol_olddef;
+_Bool bfd_is_com_section();
+
+void
+_bfd_elf_merge_symbol() {
+ _Bool newdef = bfd_is_com_section(), ntdef, tdef;
+ _bfd_elf_merge_symbol_olddef = _bfd_elf_merge_symbol_h;
+ if (_bfd_elf_merge_symbol_h_1) {
+ ntdef = newdef;
+ tdef = _bfd_elf_merge_symbol_h;
+ } else {
+ ntdef = _bfd_elf_merge_symbol_h;
+ tdef = newdef;
+ }
+ if (tdef && ntdef)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102511.c b/gcc/testsuite/gcc.dg/pr102511.c
new file mode 100644
index 0000000..8a9af34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102511.c
@@ -0,0 +1,21 @@
+// { dg-do run }
+// { dg-options "-O3" }
+
+char arr_15 [8];
+__attribute__((noipa))
+void test(signed char a, unsigned short b, unsigned long long c,
+ unsigned short f) {
+ for (int d = b - 8; d < b; d += 2)
+ for (short e = 0; e < (unsigned short)((f ? 122 : 0) ^ (a ? c : 0)) - 64055;
+ e += 3)
+ arr_15[d] = 42;
+}
+int main() {
+ test(37, 8, 12325048486467861044ULL, 45936);
+ for (int i = 0; i < 8; ++i)
+ {
+ if (arr_15[i] != ((i&1) ? 0 : 42))
+ __builtin_abort();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr102738.c b/gcc/testsuite/gcc.dg/pr102738.c
new file mode 100644
index 0000000..cd58c25
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102738.c
@@ -0,0 +1,49 @@
+/* PR tree-optimization/102738 */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+/* { dg-do compile { target int128 } } */
+
+/* Remove arithmetic shift right when the LHS is known to be 0 or -1. */
+
+int a1(__int128 f, int g)
+{
+ /* Leaves f >> 127. */
+ return (f >> 127) >> g;
+}
+
+int a2(int f, int g)
+{
+ /* Leaves f >> 31. */
+ return (f >> 31) >> g;
+}
+
+int a3(int f, int g)
+{
+ if (f == 0 || f == -1)
+ return f >> g;
+ __builtin_unreachable();
+}
+
+int a4(int f, int g)
+{
+ if (f == 0 || f == 1)
+ return (-f) >> g;
+ __builtin_unreachable();
+}
+
+int a5(int f, int g)
+{
+ if (f == 0 || f == 1)
+ return (f-1) >> g;
+ return 0;
+}
+
+int a6(int f, int g)
+{
+ if (f == 6 || f == 7)
+ return (f-7) >> g;
+ __builtin_unreachable();
+}
+
+/* { dg-final { scan-tree-dump-times " >> 127" 1 "evrp" } } */
+/* { dg-final { scan-tree-dump-times " >> 31" 1 "evrp" } } */
+/* { dg-final { scan-tree-dump-times " >> " 2 "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr102798.c b/gcc/testsuite/gcc.dg/pr102798.c
new file mode 100644
index 0000000..3a50546
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102798.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-tree-pta" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+__attribute__((__noipa__))
+void BUF_reverse (unsigned char *out, const unsigned char *in, size_t size)
+{
+ size_t i;
+ if (in)
+ {
+ out += size - 1;
+ for (i = 0; i < size; i++)
+ *out++ = *in++;
+ }
+ else
+ {
+ unsigned char *q;
+ char c;
+ q = out + size - 1;
+ for (i = 0; i < size ; i++)
+ {
+ *out++ = 1;
+ }
+ }
+}
+
+int
+main (void)
+{
+ unsigned char buf[40];
+ unsigned char buf1[40];
+ for (unsigned i = 0; i < sizeof (buf); i++)
+ buf[i] = i;
+ BUF_reverse (buf, 0, sizeof (buf));
+ for (unsigned i = 0; i < sizeof (buf); i++)
+ if (buf[i] != 1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr67089-6.c b/gcc/testsuite/gcc.dg/pr67089-6.c
index db2ffdf..b59d75b 100644
--- a/gcc/testsuite/gcc.dg/pr67089-6.c
+++ b/gcc/testsuite/gcc.dg/pr67089-6.c
@@ -1,6 +1,6 @@
/* PR target/67089 */
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-loop-if-convert -fdump-tree-widening_mul" } */
+/* { dg-options "-O2 -fno-tree-vectorize -ftree-loop-if-convert -fdump-tree-widening_mul" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/pr78408-1.c b/gcc/testsuite/gcc.dg/pr78408-1.c
index 94e2090..dc9870a 100644
--- a/gcc/testsuite/gcc.dg/pr78408-1.c
+++ b/gcc/testsuite/gcc.dg/pr78408-1.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fdump-tree-fab1-details" } */
/* { dg-final { scan-tree-dump-times "after previous" 17 "fab1" } } */
-struct S { char a[32]; };
+struct S { char a[33]; };
struct T { char a[65536]; };
void bar (int, struct S *, struct S *, struct T *, struct T *);
void baz (char *, char *);
diff --git a/gcc/testsuite/gcc.dg/pr79412.c b/gcc/testsuite/gcc.dg/pr79412.c
new file mode 100644
index 0000000..b60d5e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr79412.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+int a;
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
+void fn1 ()
+{
+ a++;
+}
+int a[] = {2}; /* { dg-error "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/pr82929-2.c b/gcc/testsuite/gcc.dg/pr82929-2.c
index 3442f91..b886f1c 100644
--- a/gcc/testsuite/gcc.dg/pr82929-2.c
+++ b/gcc/testsuite/gcc.dg/pr82929-2.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/82929 */
/* { dg-do compile { target store_merge } } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
void
foo (short *p, short *q, short *r)
diff --git a/gcc/testsuite/gcc.dg/pr82929.c b/gcc/testsuite/gcc.dg/pr82929.c
index bb84f2b..123e191 100644
--- a/gcc/testsuite/gcc.dg/pr82929.c
+++ b/gcc/testsuite/gcc.dg/pr82929.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/82929 */
/* { dg-do compile { target store_merge } } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
void
foo (short *p, short *q, short *r)
diff --git a/gcc/testsuite/gcc.dg/pr89984.c b/gcc/testsuite/gcc.dg/pr89984.c
new file mode 100644
index 0000000..471fe92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr89984.c
@@ -0,0 +1,20 @@
+/* PR target/89984 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+__attribute__((noipa)) float
+foo (float x, float y)
+{
+ return x * __builtin_copysignf (1.0f, y) + y;
+}
+
+int
+main ()
+{
+ if (foo (1.25f, 7.25f) != 1.25f + 7.25f
+ || foo (1.75f, -3.25f) != -1.75f + -3.25f
+ || foo (-2.25f, 7.5f) != -2.25f + 7.5f
+ || foo (-3.0f, -4.0f) != 3.0f + -4.0f)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr91441.c b/gcc/testsuite/gcc.dg/pr91441.c
index 4f7a8fb..4c785f6 100644
--- a/gcc/testsuite/gcc.dg/pr91441.c
+++ b/gcc/testsuite/gcc.dg/pr91441.c
@@ -1,11 +1,11 @@
/* PR target/91441 */
/* { dg-do compile } */
-/* { dg-require-effective-target no_fsanitize_address }*/
/* { dg-options "--param asan-stack=1 -fsanitize=kernel-address" } */
+/* { dg-skip-if "no address sanitizer" { no_fsanitize_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 } */
+/* { dg-warning ".'-fsanitize=kernel-address' with stack protection is not supported without '-fasan-shadow-offset=' for this target" "" { target riscv*-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr94726.c b/gcc/testsuite/gcc.dg/pr94726.c
new file mode 100644
index 0000000..d6911a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94726.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+typedef unsigned int type __attribute__ ( ( vector_size ( 2*sizeof(int) ) ) ) ;
+type a , b;
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
+void foo ( void ) {
+ type var = { 2 , 2 } ;
+ b = __builtin_shuffle ( a , var ) ;
+}
+
+void * a [ ] = { } ; /* { dg-error "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/pr96260.c b/gcc/testsuite/gcc.dg/pr96260.c
index 734832f..587afb7 100644
--- a/gcc/testsuite/gcc.dg/pr96260.c
+++ b/gcc/testsuite/gcc.dg/pr96260.c
@@ -1,7 +1,7 @@
/* 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" } */
+/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
int *bar(int *);
int *f( int a)
diff --git a/gcc/testsuite/gcc.dg/pr96307.c b/gcc/testsuite/gcc.dg/pr96307.c
index cd1c17c..89002b8 100644
--- a/gcc/testsuite/gcc.dg/pr96307.c
+++ b/gcc/testsuite/gcc.dg/pr96307.c
@@ -1,7 +1,7 @@
/* 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" } */
+/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
#include <limits.h>
enum a {test1, test2, test3=INT_MAX};
diff --git a/gcc/testsuite/gcc.dg/reciprocal-math-1.c b/gcc/testsuite/gcc.dg/reciprocal-math-1.c
new file mode 100644
index 0000000..49173e2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/reciprocal-math-1.c
@@ -0,0 +1,17 @@
+/* Test __RECIPROCAL_MATH__ is defined with -freciprocal-math. */
+/* { dg-do compile } */
+/* { dg-options "-freciprocal-math" } */
+
+#ifndef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-reciprocal-math"
+#ifdef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-freciprocal-math"
+#ifndef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ not defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/reciprocal-math-2.c b/gcc/testsuite/gcc.dg/reciprocal-math-2.c
new file mode 100644
index 0000000..959baa7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/reciprocal-math-2.c
@@ -0,0 +1,17 @@
+/* Test __RECIPROCAL_MATH__ is not defined with -fno-reciprocal-math. */
+/* { dg-do compile } */
+/* { dg-options "-fno-reciprocal-math" } */
+
+#ifdef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-freciprocal-math"
+#ifndef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-reciprocal-math"
+#ifdef __RECIPROCAL_MATH__
+#error "__RECIPROCAL_MATH__ defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/rounding-math-1.c b/gcc/testsuite/gcc.dg/rounding-math-1.c
new file mode 100644
index 0000000..3b13549
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rounding-math-1.c
@@ -0,0 +1,17 @@
+/* Test __ROUNDING_MATH__ is defined with -frounding-math. */
+/* { dg-do compile } */
+/* { dg-options "-frounding-math" } */
+
+#ifndef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-rounding-math"
+#ifdef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-frounding-math"
+#ifndef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ not defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/rounding-math-2.c b/gcc/testsuite/gcc.dg/rounding-math-2.c
new file mode 100644
index 0000000..6468a84
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rounding-math-2.c
@@ -0,0 +1,17 @@
+/* Test __ROUNDING_MATH__ is not defined with -fno-rounding-math. */
+/* { dg-do compile } */
+/* { dg-options "-fno-rounding-math" } */
+
+#ifdef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ defined"
+#endif
+
+#pragma GCC optimize "-frounding-math"
+#ifndef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ not defined"
+#endif
+
+#pragma GCC optimize "-fno-rounding-math"
+#ifdef __ROUNDING_MATH__
+#error "__ROUNDING_MATH__ defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/store_merging_1.c b/gcc/testsuite/gcc.dg/store_merging_1.c
index 4cc43df..91ca925 100644
--- a/gcc/testsuite/gcc.dg/store_merging_1.c
+++ b/gcc/testsuite/gcc.dg/store_merging_1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
struct bar {
int a;
diff --git a/gcc/testsuite/gcc.dg/store_merging_11.c b/gcc/testsuite/gcc.dg/store_merging_11.c
index 2ec2394..60ed5cd 100644
--- a/gcc/testsuite/gcc.dg/store_merging_11.c
+++ b/gcc/testsuite/gcc.dg/store_merging_11.c
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
struct S { unsigned char b[2]; unsigned short c; unsigned char d[4]; unsigned long e; };
diff --git a/gcc/testsuite/gcc.dg/store_merging_13.c b/gcc/testsuite/gcc.dg/store_merging_13.c
index a053f21..6e5206d 100644
--- a/gcc/testsuite/gcc.dg/store_merging_13.c
+++ b/gcc/testsuite/gcc.dg/store_merging_13.c
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
struct S { unsigned char a, b; unsigned short c; unsigned char d, e, f, g; unsigned long long h; };
diff --git a/gcc/testsuite/gcc.dg/store_merging_15.c b/gcc/testsuite/gcc.dg/store_merging_15.c
index acd7de5..13fcca4 100644
--- a/gcc/testsuite/gcc.dg/store_merging_15.c
+++ b/gcc/testsuite/gcc.dg/store_merging_15.c
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
struct S { unsigned char a, b; unsigned short c; unsigned char d, e, f, g; unsigned long long h; };
diff --git a/gcc/testsuite/gcc.dg/store_merging_16.c b/gcc/testsuite/gcc.dg/store_merging_16.c
index 9545dcc..cd83f1c 100644
--- a/gcc/testsuite/gcc.dg/store_merging_16.c
+++ b/gcc/testsuite/gcc.dg/store_merging_16.c
@@ -2,7 +2,7 @@
are either big or little endian (not pdp endian). */
/* { dg-do run { target { lp64 && { i?86-*-* x86_64-*-* powerpc*-*-* aarch64*-*-* } } } } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
__attribute__((noipa)) void
f1 (unsigned char *p, unsigned long long q)
diff --git a/gcc/testsuite/gcc.dg/store_merging_19.c b/gcc/testsuite/gcc.dg/store_merging_19.c
index 0841bb4..0a2bbc4 100644
--- a/gcc/testsuite/gcc.dg/store_merging_19.c
+++ b/gcc/testsuite/gcc.dg/store_merging_19.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/83843 */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
/* { dg-final { scan-tree-dump-times "Merging successful" 3 "store-merging" { target store_merge } } } */
__attribute__((noipa)) void
diff --git a/gcc/testsuite/gcc.dg/store_merging_24.c b/gcc/testsuite/gcc.dg/store_merging_24.c
index 744fe60..5291bb9 100644
--- a/gcc/testsuite/gcc.dg/store_merging_24.c
+++ b/gcc/testsuite/gcc.dg/store_merging_24.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/87859 */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging-details" } */
/* { dg-final { scan-tree-dump "New sequence of \[23] stores to replace old one of 19 stores" "store-merging" { target i?86-*-* x86_64-*-* } } } */
/* { dg-final { scan-tree-dump "New sequence of 1 stores to replace old one of 6 stores" "store-merging" { target i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/store_merging_25.c b/gcc/testsuite/gcc.dg/store_merging_25.c
index cf18219..96611b5 100644
--- a/gcc/testsuite/gcc.dg/store_merging_25.c
+++ b/gcc/testsuite/gcc.dg/store_merging_25.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/87859 */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging-details" } */
/* { dg-final { scan-tree-dump "New sequence of \[23] stores to replace old one of 14 stores" "store-merging" { target i?86-*-* x86_64-*-* } } } */
/* { dg-final { scan-tree-dump "New sequence of 1 stores to replace old one of 6 stores" "store-merging" { target i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/store_merging_28.c b/gcc/testsuite/gcc.dg/store_merging_28.c
index 2d6cffc4..fadb7ff 100644
--- a/gcc/testsuite/gcc.dg/store_merging_28.c
+++ b/gcc/testsuite/gcc.dg/store_merging_28.c
@@ -1,7 +1,7 @@
/* PR tree-optimization/88709 */
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-store-merging-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fno-ipa-icf -fdump-tree-store-merging-details" } */
/* { dg-final { scan-tree-dump-times "New sequence of \[24] stores to replace old one of 16 stores" 8 "store-merging" { target { i?86-*-* x86_64-*-* } } } } */
/* { dg-final { scan-tree-dump-times "New sequence of \[24] stores to replace old one of 6 stores" 1 "store-merging" { target { ! arm*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/store_merging_30.c b/gcc/testsuite/gcc.dg/store_merging_30.c
index 694d560..baf94ef 100644
--- a/gcc/testsuite/gcc.dg/store_merging_30.c
+++ b/gcc/testsuite/gcc.dg/store_merging_30.c
@@ -1,7 +1,7 @@
/* PR tree-optimization/94573 */
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging-details" } */
/* { dg-final { scan-tree-dump "New sequence of 4 stores to replace old one of 8 stores" "store-merging" { target lp64 } } } */
int var[43][12];
diff --git a/gcc/testsuite/gcc.dg/store_merging_5.c b/gcc/testsuite/gcc.dg/store_merging_5.c
index 6e7c725..b0cb0da 100644
--- a/gcc/testsuite/gcc.dg/store_merging_5.c
+++ b/gcc/testsuite/gcc.dg/store_merging_5.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
/* Make sure that non-aliasing non-constant interspersed stores do not
stop chains. */
diff --git a/gcc/testsuite/gcc.dg/store_merging_7.c b/gcc/testsuite/gcc.dg/store_merging_7.c
index c744ece..dbe000a 100644
--- a/gcc/testsuite/gcc.dg/store_merging_7.c
+++ b/gcc/testsuite/gcc.dg/store_merging_7.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
/* Check that we can merge consecutive array members through the pointer.
PR rtl-optimization/23684. */
diff --git a/gcc/testsuite/gcc.dg/store_merging_8.c b/gcc/testsuite/gcc.dg/store_merging_8.c
index e710a54..d719e0a 100644
--- a/gcc/testsuite/gcc.dg/store_merging_8.c
+++ b/gcc/testsuite/gcc.dg/store_merging_8.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
struct baz {
struct bar {
diff --git a/gcc/testsuite/gcc.dg/strlenopt-85.c b/gcc/testsuite/gcc.dg/strlenopt-85.c
index e049e0c..2ba1ee05 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-85.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-85.c
@@ -4,7 +4,7 @@
of memory allocated by calloc() even if one or more nul bytes are
written into it.
{ dg-do compile }
- { dg-options "-O2 -fdump-tree-optimized" } */
+ { dg-options "-O2 -fno-tree-vectorize -fdump-tree-optimized" } */
unsigned n0, n1;
diff --git a/gcc/testsuite/gcc.dg/torture/20210916.c b/gcc/testsuite/gcc.dg/torture/20210916.c
new file mode 100644
index 0000000..0ea6d45
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/20210916.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+typedef union tree_node *tree;
+struct tree_base {
+ unsigned : 1;
+ unsigned lang_flag_2 : 1;
+};
+struct tree_type {
+ tree main_variant;
+};
+union tree_node {
+ struct tree_base base;
+ struct tree_type type;
+};
+tree finish_struct_t, finish_struct_x;
+void finish_struct()
+{
+ for (; finish_struct_t->type.main_variant;)
+ finish_struct_x->base.lang_flag_2 = 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr102124.c b/gcc/testsuite/gcc.dg/torture/pr102124.c
new file mode 100644
index 0000000..a158b4a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102124.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/102124 */
+
+int
+foo (const unsigned char *a, const unsigned char *b, unsigned long len)
+{
+ int ab, ba;
+ unsigned long i;
+ for (i = 0, ab = 0, ba = 0; i < len; i++)
+ {
+ ab |= a[i] - b[i];
+ ba |= b[i] - a[i];
+ }
+ return (ab | ba) >= 0;
+}
+
+int
+main ()
+{
+ unsigned char a[32] = { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' };
+ unsigned char b[32] = { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' };
+ unsigned char c[32] = { 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b' };
+ if (!foo (a, b, 16))
+ __builtin_abort ();
+ if (foo (a, c, 16))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr102139.c b/gcc/testsuite/gcc.dg/torture/pr102139.c
new file mode 100644
index 0000000..06c1357
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102139.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-slp-vectorize" } */
+
+typedef double aligned_double __attribute__((aligned(2*sizeof(double))));
+
+void __attribute__((noipa))
+bar (int aligned, double *p)
+{
+ if (aligned)
+ {
+ *(aligned_double *)p = 3.;
+ p[1] = 4.;
+ }
+ else
+ {
+ p[2] = 0.;
+ p[3] = 1.;
+ }
+}
+
+void __attribute__((noipa))
+foo (int i)
+{
+ if (i)
+ __builtin_exit (0);
+}
+void __attribute__((noipa))
+baz (double *p)
+{
+ p[0] = 0.;
+ p[1] = 1.;
+ foo (1);
+ *(aligned_double *)p = 3.;
+ p[1] = 4.;
+}
+
+double x[8] __attribute__((aligned(2*sizeof (double))));
+int main()
+{
+ bar (0, &x[1]);
+ baz (&x[1]);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr102149.c b/gcc/testsuite/gcc.dg/torture/pr102149.c
new file mode 100644
index 0000000..34a8c21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102149.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-vect-cost-model" } */
+
+int a[8];
+int *b = &a[6];
+char c;
+int main()
+{
+ int d = 7;
+ for (; d >= 0; d--)
+ {
+ *b = 1;
+ c = a[d] >> 3;
+ a[d] = c;
+ }
+ if (a[6] != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr102518.c b/gcc/testsuite/gcc.dg/torture/pr102518.c
new file mode 100644
index 0000000..bd181ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102518.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+struct A {
+ int *x;
+};
+int i;
+int f(int *const c) {
+ struct A * b = (struct A *)(&c);
+ return b->x != 0;
+}
+void g() { f(&i); }
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr102762.c b/gcc/testsuite/gcc.dg/torture/pr102762.c
new file mode 100644
index 0000000..67c6b00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr102762.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* We fail to diagnose the invalid __builtin_va_arg_pack use with -flto. */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+void log_bad_request();
+void foo(a, b)
+ int a, b;
+{
+ log_bad_request(0, __builtin_va_arg_pack()); /* { dg-error "invalid use" } */
+ foo(0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr55107.c b/gcc/testsuite/gcc.dg/torture/pr55107.c
index d757c04..2edb75f 100644
--- a/gcc/testsuite/gcc.dg/torture/pr55107.c
+++ b/gcc/testsuite/gcc.dg/torture/pr55107.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-additional-options "-fno-split-loops" } */
+/* { dg-additional-options "-fno-split-loops -w" } */
typedef unsigned short uint16_t;
diff --git a/gcc/testsuite/gcc.dg/torture/pr69760.c b/gcc/testsuite/gcc.dg/torture/pr69760.c
index 53733c7..47e01ae 100644
--- a/gcc/testsuite/gcc.dg/torture/pr69760.c
+++ b/gcc/testsuite/gcc.dg/torture/pr69760.c
@@ -1,11 +1,10 @@
/* PR tree-optimization/69760 */
/* { dg-do run { target { { *-*-linux* *-*-gnu* *-*-uclinux* } && mmap } } } */
-/* { dg-options "-O2" } */
#include <unistd.h>
#include <sys/mman.h>
-__attribute__((noinline, noclone)) void
+__attribute__((noinline, noclone)) static void
test_func (double *a, int L, int m, int n, int N)
{
int i, k;
diff --git a/gcc/testsuite/gcc.dg/torture/pr89135.c b/gcc/testsuite/gcc.dg/torture/pr89135.c
index 278303f..4cf0533 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89135.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89135.c
@@ -28,7 +28,7 @@ h:
g = foo ();
*o = g;
if (c)
- goto *d;
+ goto *(void*)d;
}
}
goto *i;
diff --git a/gcc/testsuite/gcc.dg/torture/pr90071.c b/gcc/testsuite/gcc.dg/torture/pr90071.c
index 702c143..1c4099c 100644
--- a/gcc/testsuite/gcc.dg/torture/pr90071.c
+++ b/gcc/testsuite/gcc.dg/torture/pr90071.c
@@ -21,6 +21,6 @@ h: ++e;
goto i;
}
f:
- goto *({ d || e < 0 || e >= 2; });
+ goto *(void*)(__INTPTR_TYPE__)({ d || e < 0 || e >= 2; });
&e;
}
diff --git a/gcc/testsuite/gcc.dg/torture/pr93491.c b/gcc/testsuite/gcc.dg/torture/pr93491.c
new file mode 100644
index 0000000..2cb4c0c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr93491.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+extern void exit (int);
+
+__attribute__((noipa))
+void f(int i)
+{
+ exit(i);
+}
+
+__attribute__((const,noipa))
+int g(int i)
+{
+ return 1 / i;
+}
+
+int main()
+{
+ while (1)
+ {
+ f(0);
+ f(g(0));
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c b/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c
index 1f30467..de019a7 100644
--- a/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c
+++ b/gcc/testsuite/gcc.dg/torture/ssa-pta-fn-1.c
@@ -6,13 +6,13 @@ extern void abort (void);
int *g;
int dummy;
-int * __attribute__((noinline,const))
+int * __attribute__((noinline,const,noipa))
foo_const(int *p) { return p; }
-int * __attribute__((noinline,pure))
+int * __attribute__((noinline,pure,noipa))
foo_pure(int *p) { return p + dummy; }
-int * __attribute__((noinline))
+int * __attribute__((noinline,noipa))
foo_normal(int *p) { g = p; return p; }
void test_const(void)
@@ -58,4 +58,4 @@ int main()
/* { dg-final { scan-tree-dump "q_const_. = { NONLOCAL i }" "alias" } } */
/* { dg-final { scan-tree-dump "q_pure_. = { ESCAPED NONLOCAL i }" "alias" } } */
-/* { dg-final { scan-tree-dump "q_normal_. = { ESCAPED NONLOCAL }" "alias" } } */
+/* { dg-final { scan-tree-dump "q_normal_. = { ESCAPED NONLOCAL i }" "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
index eb663f2..9585ff1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c
@@ -32,7 +32,8 @@ get_alias_set (t)
}
}
-/* There should be exactly three IF conditionals if we thread jumps
- properly. */
-/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */
+/* There should be exactly 4 IF conditionals if we thread jumps
+ properly. There used to be 3, but one thread was crossing
+ loops. */
+/* { dg-final { scan-tree-dump-times "if " 4 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c
index 70659c0..6c80390 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c
@@ -1,6 +1,6 @@
/* PR middle-end/90676 - default GIMPLE dumps lack information
{ dg-do compile }
- { dg-options "-O2 -fdump-tree-store-merging" }
+ { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" }
{ dg-require-effective-target int32plus }
{ dg-require-effective-target store_merge } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp-ignore.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp-ignore.c
new file mode 100644
index 0000000..9bfaed6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp-ignore.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp -fno-tree-fre -fdisable-tree-ethread" } */
+
+void kill(void);
+
+void foo (int x, int y, int z)
+{
+ // Establish y = [-INF, 54]
+ if (y < 55)
+ return;
+
+ // Establish z == x
+ if (z != x)
+ return;
+
+ // EVRP should transform this to if (0 != 0)
+ if (y < 30)
+ x = 0;
+
+ // # x_1 = PHI <x_5(D)(6), 0(7)>
+ // The earlier transformation should make the edge from bb7
+ // unexecutable, allowing x_1 == x_5 to be registered, and
+ // then fold away this condition as well.
+ if (x != z)
+ kill();
+
+}
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-1.c
new file mode 100644
index 0000000..6abfd27
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-1.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target s390x-*-* } } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrQI" 2 "ldist" { target s390x-*-* } } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrHI" 2 "ldist" { target s390x-*-* } } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrSI" 2 "ldist" { target s390x-*-* } } } */
+
+/* Rawmemchr pattern: reduction stmt and no store */
+
+#include <stdint.h>
+#include <assert.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void* malloc (size_t);
+extern void* memset (void*, int, size_t);
+
+#define test(T, pattern) \
+__attribute__((noinline)) \
+T *test_##T (T *p) \
+{ \
+ while (*p != (T)pattern) \
+ ++p; \
+ return p; \
+}
+
+test (uint8_t, 0xab)
+test (uint16_t, 0xabcd)
+test (uint32_t, 0xabcdef15)
+
+test (int8_t, 0xab)
+test (int16_t, 0xabcd)
+test (int32_t, 0xabcdef15)
+
+#define run(T, pattern, i) \
+{ \
+T *q = p; \
+q[i] = (T)pattern; \
+assert (test_##T (p) == &q[i]); \
+q[i] = 0; \
+}
+
+int main(void)
+{
+ void *p = malloc (1024);
+ assert (p);
+ memset (p, 0, 1024);
+
+ run (uint8_t, 0xab, 0);
+ run (uint8_t, 0xab, 1);
+ run (uint8_t, 0xab, 13);
+
+ run (uint16_t, 0xabcd, 0);
+ run (uint16_t, 0xabcd, 1);
+ run (uint16_t, 0xabcd, 13);
+
+ run (uint32_t, 0xabcdef15, 0);
+ run (uint32_t, 0xabcdef15, 1);
+ run (uint32_t, 0xabcdef15, 13);
+
+ run (int8_t, 0xab, 0);
+ run (int8_t, 0xab, 1);
+ run (int8_t, 0xab, 13);
+
+ run (int16_t, 0xabcd, 0);
+ run (int16_t, 0xabcd, 1);
+ run (int16_t, 0xabcd, 13);
+
+ run (int32_t, 0xabcdef15, 0);
+ run (int32_t, 0xabcdef15, 1);
+ run (int32_t, 0xabcdef15, 13);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-2.c
new file mode 100644
index 0000000..00d6ea0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-rawmemchr-2.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target s390x-*-* } } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrQI" 2 "ldist" { target s390x-*-* } } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrHI" 2 "ldist" { target s390x-*-* } } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrSI" 2 "ldist" { target s390x-*-* } } } */
+
+/* Rawmemchr pattern: reduction stmt and store */
+
+#include <stdint.h>
+#include <assert.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void* malloc (size_t);
+extern void* memset (void*, int, size_t);
+
+uint8_t *p_uint8_t;
+uint16_t *p_uint16_t;
+uint32_t *p_uint32_t;
+
+int8_t *p_int8_t;
+int16_t *p_int16_t;
+int32_t *p_int32_t;
+
+#define test(T, pattern) \
+__attribute__((noinline)) \
+T *test_##T (void) \
+{ \
+ while (*p_##T != pattern) \
+ ++p_##T; \
+ return p_##T; \
+}
+
+test (uint8_t, 0xab)
+test (uint16_t, 0xabcd)
+test (uint32_t, 0xabcdef15)
+
+test (int8_t, (int8_t)0xab)
+test (int16_t, (int16_t)0xabcd)
+test (int32_t, (int32_t)0xabcdef15)
+
+#define run(T, pattern, i) \
+{ \
+T *q = p; \
+q[i] = pattern; \
+p_##T = p; \
+T *r = test_##T (); \
+assert (r == p_##T); \
+assert (r == &q[i]); \
+q[i] = 0; \
+}
+
+int main(void)
+{
+ void *p = malloc (1024);
+ assert (p);
+ memset (p, '\0', 1024);
+
+ run (uint8_t, 0xab, 0);
+ run (uint8_t, 0xab, 1);
+ run (uint8_t, 0xab, 13);
+
+ run (uint16_t, 0xabcd, 0);
+ run (uint16_t, 0xabcd, 1);
+ run (uint16_t, 0xabcd, 13);
+
+ run (uint32_t, 0xabcdef15, 0);
+ run (uint32_t, 0xabcdef15, 1);
+ run (uint32_t, 0xabcdef15, 13);
+
+ run (int8_t, (int8_t)0xab, 0);
+ run (int8_t, (int8_t)0xab, 1);
+ run (int8_t, (int8_t)0xab, 13);
+
+ run (int16_t, (int16_t)0xabcd, 0);
+ run (int16_t, (int16_t)0xabcd, 1);
+ run (int16_t, (int16_t)0xabcd, 13);
+
+ run (int32_t, (int32_t)0xabcdef15, 0);
+ run (int32_t, (int32_t)0xabcdef15, 1);
+ run (int32_t, (int32_t)0xabcdef15, 13);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-1.c
new file mode 100644
index 0000000..918b600
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-1.c
@@ -0,0 +1,100 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+/* { dg-final { scan-tree-dump-times "generated strlenQI\n" 4 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated strlenHI\n" 4 "ldist" { target s390x-*-* } } } */
+/* { dg-final { scan-tree-dump-times "generated strlenSI\n" 4 "ldist" { target s390x-*-* } } } */
+
+#include <stdint.h>
+#include <assert.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void* malloc (size_t);
+extern void* memset (void*, int, size_t);
+
+#define test(T, U) \
+__attribute__((noinline)) \
+U test_##T##U (T *s) \
+{ \
+ U i; \
+ for (i=0; s[i]; ++i); \
+ return i; \
+}
+
+test (uint8_t, size_t)
+test (uint16_t, size_t)
+test (uint32_t, size_t)
+test (uint8_t, int)
+test (uint16_t, int)
+test (uint32_t, int)
+
+test (int8_t, size_t)
+test (int16_t, size_t)
+test (int32_t, size_t)
+test (int8_t, int)
+test (int16_t, int)
+test (int32_t, int)
+
+#define run(T, U, i) \
+{ \
+T *q = p; \
+q[i] = 0; \
+assert (test_##T##U (p) == i); \
+memset (&q[i], 0xf, sizeof (T)); \
+}
+
+int main(void)
+{
+ void *p = malloc (1024);
+ assert (p);
+ memset (p, 0xf, 1024);
+
+ run (uint8_t, size_t, 0);
+ run (uint8_t, size_t, 1);
+ run (uint8_t, size_t, 13);
+
+ run (int8_t, size_t, 0);
+ run (int8_t, size_t, 1);
+ run (int8_t, size_t, 13);
+
+ run (uint8_t, int, 0);
+ run (uint8_t, int, 1);
+ run (uint8_t, int, 13);
+
+ run (int8_t, int, 0);
+ run (int8_t, int, 1);
+ run (int8_t, int, 13);
+
+ run (uint16_t, size_t, 0);
+ run (uint16_t, size_t, 1);
+ run (uint16_t, size_t, 13);
+
+ run (int16_t, size_t, 0);
+ run (int16_t, size_t, 1);
+ run (int16_t, size_t, 13);
+
+ run (uint16_t, int, 0);
+ run (uint16_t, int, 1);
+ run (uint16_t, int, 13);
+
+ run (int16_t, int, 0);
+ run (int16_t, int, 1);
+ run (int16_t, int, 13);
+
+ run (uint32_t, size_t, 0);
+ run (uint32_t, size_t, 1);
+ run (uint32_t, size_t, 13);
+
+ run (int32_t, size_t, 0);
+ run (int32_t, size_t, 1);
+ run (int32_t, size_t, 13);
+
+ run (uint32_t, int, 0);
+ run (uint32_t, int, 1);
+ run (uint32_t, int, 13);
+
+ run (int32_t, int, 0);
+ run (int32_t, int, 1);
+ run (int32_t, int, 13);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-2.c
new file mode 100644
index 0000000..e25d6ea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-2.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+/* { dg-final { scan-tree-dump-times "generated strlenQI\n" 3 "ldist" } } */
+
+#include <assert.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void* malloc (size_t);
+extern void* memset (void*, int, size_t);
+
+__attribute__((noinline))
+int test_pos (char *s)
+{
+ int i;
+ for (i=42; s[i]; ++i);
+ return i;
+}
+
+__attribute__((noinline))
+int test_neg (char *s)
+{
+ int i;
+ for (i=-42; s[i]; ++i);
+ return i;
+}
+
+__attribute__((noinline))
+int test_including_null_char (char *s)
+{
+ int i;
+ for (i=1; s[i-1]; ++i);
+ return i;
+}
+
+int main(void)
+{
+ void *p = malloc (1024);
+ assert (p);
+ memset (p, 0xf, 1024);
+ char *s = (char *)p + 100;
+
+ s[42+13] = 0;
+ assert (test_pos (s) == 42+13);
+ s[42+13] = 0xf;
+
+ s[13] = 0;
+ assert (test_neg (s) == 13);
+ s[13] = 0xf;
+
+ s[-13] = 0;
+ assert (test_neg (s) == -13);
+ s[-13] = 0xf;
+
+ s[13] = 0;
+ assert (test_including_null_char (s) == 13+1);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-3.c
new file mode 100644
index 0000000..370fd5e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-strlen-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+/* { dg-final { scan-tree-dump-times "generated strlenSI\n" 1 "ldist" { target s390x-*-* } } } */
+
+extern int s[];
+
+int test ()
+{
+ int i = 0;
+ for (; s[i]; ++i);
+ return i;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-9.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-9.c
new file mode 100644
index 0000000..02de2f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-9.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O2 --param modref-max-accesses=2 -fdump-tree-modref1" } */
+/* { dg-do compile } */
+void
+test(char *a)
+{
+ a[0] = 0;
+ a[1] = 1;
+ a[3] = 3;
+ a[7] = 7;
+ a[9] = 9;
+}
+/* We allow only two accesses per function.
+ It is best to group together {0,1,3} and {7,9}. */
+/* { dg-final { scan-tree-dump "access: Parm 0 param offset:0 offset:0 size:8 max_size:32" "modref1" } } */
+/* { dg-final { scan-tree-dump "access: Parm 0 param offset:7 offset:0 size:8 max_size:24" "modref1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
index 5227c87..59663dd 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (int);
void g1 (int);
@@ -27,4 +27,4 @@ f (long a, long b, long c, long d, long x)
g (a);
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
index eaf89bb..0c2f6e0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (void);
void g1 (void);
@@ -20,4 +20,4 @@ f (long a, long b, long c, long d, int x)
}
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
index d5a1e0b..6a3d359 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (void);
void g1 (void);
@@ -22,4 +22,4 @@ f (long a, long b, long c, long d, int x)
}
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
index 53acabc..9bc4c6d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */
void g (int);
void g1 (int);
@@ -37,4 +37,4 @@ f (long a, long b, long c, long d, int x)
g (c + d);
}
-/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
new file mode 100644
index 0000000..4bd9874
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-optimized" }
+
+static int a;
+static char b, c, d;
+void bar(void);
+void foo(void);
+
+int main() {
+ int f = 0;
+ for (; f <= 5; f++) {
+ bar();
+ b = b && f;
+ d = f << f;
+ if (!(a >= d || f))
+ foo();
+ c = 1;
+ for (; c; c = 0)
+ ;
+ }
+}
+
+// { dg-final { scan-tree-dump-not "foo" "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c
new file mode 100644
index 0000000..8871dff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102563.c
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O2 -w" }
+
+int _bdf_parse_glyphs_bp;
+long _bdf_parse_glyphs_nibbles;
+
+void _bdf_parse_glyphs_p()
+{
+ long p_2;
+
+ _bdf_parse_glyphs_nibbles = p_2 << 1;
+
+ for (; 0 < _bdf_parse_glyphs_nibbles;)
+ if (1 < _bdf_parse_glyphs_nibbles)
+ _bdf_parse_glyphs_bp = _bdf_parse_glyphs_p;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102736.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102736.c
new file mode 100644
index 0000000..c693a71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102736.c
@@ -0,0 +1,21 @@
+// { dg-do run }
+// { dg-options "-O1 -ftree-vrp" }
+
+int a, b = -1, c;
+int d = 1;
+static inline signed char e(signed char f, int g) { return g ? f : 0; }
+static inline signed char h(signed char f) { return f < a ? f : f < a; }
+static inline unsigned char i(unsigned char f, int g) { return g ? f : f > g; }
+void j() {
+L:
+ c = e(1, i(h(b), d));
+ if (b)
+ return;
+ goto L;
+}
+int main() {
+ j();
+ if (c != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
index 50d86a0..b9e40e9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fopt-info-loop-missed" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fopt-info-loop-missed" } */
extern void g(void);
void
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c
index fc14af4..b934c9c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c
@@ -49,5 +49,5 @@ L23:
/* We should thread the backedge to the top of the loop; ie we only
execute the if (expr->common.code != 142) test once per loop
iteration. */
-/* { dg-final { scan-tree-dump-times "FSM jump thread" 1 "thread4" } } */
+/* { dg-final { scan-tree-dump-times "jump thread" 1 "thread4" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
index b406566..51b3b7a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp-thread1-details" } */
static int blocksize = 4096;
@@ -39,6 +39,6 @@ void foo (void)
statement. We also realize that the final bytes == 0 test is useless,
and thread over it. We also know that toread != 0 is useless when
entering while loop and thread over it. */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47059.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47059.c
index 9f9c61a..860cde1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr47059.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr47059.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Os -fdump-tree-optimized" } */
+/* { dg-options "-Os -fno-tree-vectorize -fdump-tree-optimized" } */
struct struct1
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
index dab16ab..2caa1f5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-vrp1-details" } */
+/* { dg-options "-Ofast -fdump-tree-vrp-thread1-details" } */
typedef unsigned short u16;
typedef unsigned char u8;
@@ -56,6 +56,11 @@ main (int argc, char argv[])
return crc;
}
-/* { dg-final { scan-tree-dump-times "Registering jump thread" 3 "vrp1" } } */
-/* { dg-final { scan-tree-dump-not "joiner" "vrp1" } } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */
+/* Previously we had 3 jump threads, but one of them crossed loops.
+ The reason the old threader was allowing it, was because there was
+ an ASSERT_EXPR getting in the way. Without the ASSERT_EXPR, we
+ have an empty pre-header block as the final block in the thread,
+ which the threader will simply join with the next block which *is*
+ in a different loop. */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */
+/* { dg-final { scan-tree-dump-not "joiner" "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
index ddc53fb..0229a82 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/61839. */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
/* { dg-require-effective-target int32plus } */
__attribute__ ((noinline))
@@ -38,7 +38,11 @@ int main ()
}
/* Scan for c = 972195717) >> [0, 1] in function foo. */
-/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp-thread1" } } */
+
+/* Previously we were checking for two ?: with constant PHI arguments,
+ but now we collapse them into one. */
/* Scan for c = 972195717) >> [2, 3] in function bar. */
-/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 1 "vrp-thread1" } } */
+
/* { dg-final { scan-tree-dump-times "486097858" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
index cc322d6..7be1873 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/61839. */
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */
__attribute__ ((noinline))
int foo (int a, unsigned b)
@@ -22,5 +22,5 @@ int main ()
}
/* Scan for c [12, 13] << 8 in function foo. */
-/* { dg-final { scan-tree-dump-times "3072 : 3328" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "3072 : 3328" 1 "vrp-thread1" } } */
/* { dg-final { scan-tree-dump-times "3072" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
index 896c8bf..ba7025a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-dce2" } */
+/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread4" } */
extern int status, pt;
extern int count;
@@ -32,10 +32,15 @@ foo (int N, int c, int b, int *a)
pt--;
}
-/* There are 4 FSM jump threading opportunities, all of which will be
- realized, which will eliminate testing of FLAG, completely. */
-/* { dg-final { scan-tree-dump-times "Registering FSM" 4 "thread1"} } */
+/* There are 2 jump threading opportunities (which don't cross loops),
+ all of which will be realized, which will eliminate testing of
+ FLAG, completely. */
+/* { dg-final { scan-tree-dump-times "Registering jump" 2 "thread1"} } */
-/* There should be no assignments or references to FLAG, verify they're
- eliminated as early as possible. */
-/* { dg-final { scan-tree-dump-not "if .flag" "dce2"} } */
+/* We used to remove references to FLAG by DCE2, but this was
+ depending on early threaders threading through loop boundaries
+ (which we shouldn't do). However, the late threading passes, which
+ run after loop optimizations , can successfully eliminate the
+ references to FLAG. Verify that ther are no references by the late
+ threading passes. */
+/* { dg-final { scan-tree-dump-not "if .flag" "thread4"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c
index 59d562e..af8b7a5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c
@@ -37,5 +37,5 @@ c_finish_omp_clauses (tree clauses)
}
}
-/* There are 3 FSM jump threading opportunities. */
-/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "thread1"} } */
+/* There are 3 jump threading opportunities. */
+/* { dg-final { scan-tree-dump-times "Registering jump" 3 "thread1"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c
index 960491f..dfabb48 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target sparc*-*-* i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -fdump-tree-thread1-details -fdisable-tree-ethread" } */
-/* { dg-final { scan-tree-dump "FSM did not thread around loop and would copy too many statements" "thread1" } } */
+/* { dg-final { scan-tree-dump "Did not thread around loop and would copy too many statements" "thread1" } } */
typedef __builtin_va_list __gnuc_va_list;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr70232.c b/gcc/testsuite/gcc.dg/tree-ssa/pr70232.c
index 6cc987a..d636672 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr70232.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr70232.c
@@ -1,12 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O2 -w -fdump-tree-vrp1-details -fdump-tree-vrp2-details -fdump-tree-dom2-details -fdump-tree-dom3-details" } */
-/* All the threads found by the FSM threader should have too
- many statements to be profitable. */
-/* { dg-final { scan-tree-dump-not "Registering FSM " "dom2"} } */
-/* { dg-final { scan-tree-dump-not "Registering FSM " "dom3"} } */
-/* { dg-final { scan-tree-dump-not "Registering FSM " "vrp1"} } */
-/* { dg-final { scan-tree-dump-not "Registering FSM " "vrp2"} } */
+/* All the threads found by the threader should have too many
+ statements to be profitable. */
+/* { dg-final { scan-tree-dump-not "Registering jump " "dom2"} } */
+/* { dg-final { scan-tree-dump-not "Registering jump " "dom3"} } */
+/* { dg-final { scan-tree-dump-not "Registering jump " "vrp1"} } */
+/* { dg-final { scan-tree-dump-not "Registering jump " "vrp2"} } */
typedef _Bool bool;
typedef unsigned char uint8_t;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
index 66a5405..a2386ba 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-ffast-math -O3 -fdump-tree-vrp1-details" } */
+/* { dg-options "-ffast-math -O3 -fdump-tree-vrp-thread1-details" } */
int I = 50, J = 50;
int S, L;
@@ -39,4 +39,4 @@ void foo (int K)
bar (LD, SD);
}
}
-/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
index f9fc212..18f7aab 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
@@ -123,8 +123,8 @@ enum STATES FMS( u8 **in , u32 *transitions) {
aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
to change decisions in switch expansion which in turn can expose new
jump threading opportunities. Skip the later tests on aarch64. */
-/* { dg-final { scan-tree-dump "Jumps threaded: 1\[1-9\]" "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Invalid sum" 4 "thread1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread1" } } */
+/* { dg-final { scan-tree-dump-times "Invalid sum" 1 "thread1" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread1" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread2" } } */
/* { dg-final { scan-tree-dump-not "optimizing for size" "thread3" { target { ! aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445.c
index 98eb0f2..883a63d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445.c
@@ -25,5 +25,5 @@ main (int argc)
if (b)
test2 ();
}
-/* { dg-final { scan-tree-dump-times "Registering FSM jump thread" 2 "thread3" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "thread3" } } */
/* { dg-final { scan-tree-dump-not "Invalid sum" "thread3" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr86017.c b/gcc/testsuite/gcc.dg/tree-ssa/pr86017.c
index f216e83..c7ef73a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr86017.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr86017.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */
void f (void*);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c
index d0061b6..c48dba5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c
@@ -1,17 +1,17 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+/* { dg-options "-O2 -fno-code-hoisting -fdump-tree-pre-stats" } */
int f();
int d;
-void c()
+void c(int x)
{
- for (;;)
- {
- f();
- int (*fp)() __attribute__((const)) = (void *)f;
- d = fp();
- }
+ int (*fp)() __attribute__((const)) = (void *)f;
+ if (x)
+ d = fp ();
+ int tem = fp ();
+ f();
+ d = tem;
}
-/* We shouldn't ICE and hoist the const call of fp out of the loop. */
+/* We shouldn't ICE and PRE the const call. */
/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c
index 8ee1850..d9fb2ed 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
unsigned test(unsigned k, unsigned b) {
unsigned a[2];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c
index 9b96875..bb39df2 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
int c;
unsigned test(unsigned k, unsigned b) {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c
index 0fac9f9..0016637 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
unsigned a[2];
unsigned test(unsigned k, unsigned b) {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c
index 54b8c11..127cbdf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
int *p;
unsigned test(unsigned k, unsigned b) {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c
index b2d0411..6a00f54 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
int test(int b, int k) {
struct {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c
index 8d3c4f7..ecc083e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
int test(int b, int k) {
typedef struct {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c
index c35a2af..4fad2d1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
typedef union {
int i;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c
index f9e66ae..5f93112 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fdump-tree-cselim-details" } */
int *t;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91482.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91482.c
index 7d6a724..0ddad57 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr91482.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91482.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ccp1 -fdump-tree-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-ccp1 -fdump-tree-store-merging" } */
void write64 (void *p)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr99473-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr99473-1.c
index a9fd542..0fda566 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr99473-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr99473-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fallow-store-data-races -fdump-tree-cselim-details" } */
+/* { dg-options "-O2 -ftree-cselim -fallow-store-data-races -fdump-tree-cselim-details" } */
void f (int*);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c b/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c
new file mode 100644
index 0000000..9127449
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr99793.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */
+
+extern void foo(void);
+static int a, *b = &a, c, *d = &c;
+int main()
+{
+ int **e = &d;
+ if (!((unsigned)((*e = d) == 0) - (*b = 1)))
+ foo();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c
index f68be2b..8c3d9a4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-do run } */
-/* { dg-options "-O2 -funroll-loops --param max-unroll-times=8 -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -funroll-loops --param max-unroll-times=8 -fpredictive-commoning -fdump-tree-pcom-details" } */
void abort (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c
index 1174cd1..9abbe6c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -funroll-loops --param max-unroll-times=8 -fpredictive-commoning -fdump-tree-pcom-details -fno-tree-pre" } */
+/* { dg-options "-O2 -funroll-loops --param max-unroll-times=8 -fpredictive-commoning -fdump-tree-pcom-details -fno-tree-pre -fno-tree-loop-vectorize" } */
int a[1000], b[1000];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
index ec08d6c..1fc8f08 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
int arr1[105] = {2, 3, 5, 7, 11, 13, 0};
int arr2[105] = {2, 3, 5, 7, 11, 13, 0};
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c
index 467903b..46f0d0c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c
@@ -1,7 +1,7 @@
/* Prefetching used to prefer nonsensical unroll factor of 5 in this testcase. */
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fprefetch-loop-arrays -march=amdfam10 -fdump-tree-aprefetch-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fprefetch-loop-arrays -march=amdfam10 -fdump-tree-aprefetch-details" } */
#define N 1000000
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c
index 12f0901..3fa7168 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 --param min-insn-to-prefetch-ratio=6 -fdump-tree-aprefetch-details" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 --param min-insn-to-prefetch-ratio=6 -fdump-tree-aprefetch-details" } */
#define N 1000
#define K 900
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
index cbd6a80..00f41c3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
#define K 1000000
int a[K];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
index da48473..e8848c3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
#define K 1000000
int a[K], b[K];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
index cb85ec1..aa639b4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
@@ -22,5 +22,5 @@ int bar (int b)
return *foo (&q);
}
-/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { f.* i q }" "alias" } } */
+/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { NONLOCAL f.* i q }" "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ranger-threader-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ranger-threader-4.c
index e8d1cfc..d5aa2e8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ranger-threader-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ranger-threader-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-additional-options "-O2 -fdump-tree-vrp-details -fdump-tree-thread1-details --param logical-op-non-short-circuit=1" } */
-/* { dg-final { scan-tree-dump-times "Registering FSM jump" 8 "thread1" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump" 8 "thread1" } } */
/* Copied from ssa-thread-14. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c
new file mode 100644
index 0000000..97563dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#include "reassoc-46.h"
+
+/* Check that the loop accumulator is added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h
new file mode 100644
index 0000000..e60b490
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-46.h
@@ -0,0 +1,33 @@
+#define M 1024
+unsigned int arr1[M];
+unsigned int arr2[M];
+volatile unsigned int sink;
+
+unsigned int
+test (void)
+{
+ unsigned int sum = 0;
+ for (int i = 0; i < M; i++)
+ {
+#ifdef MODIFY
+ /* Modify the loop accumulator using a chain of operations - this should
+ not affect its rank biasing. */
+ sum |= 1;
+ sum ^= 2;
+#endif
+#ifdef STORE
+ /* Save the loop accumulator into a global variable - this should not
+ affect its rank biasing. */
+ sink = sum;
+#endif
+#ifdef USE
+ /* Add a tricky use of the loop accumulator - this should prevent its
+ rank biasing. */
+ i = (i + sum) % M;
+#endif
+ /* Use addends with different ranks. */
+ sum += arr1[i];
+ sum += arr2[((i ^ 1) + 1) % M];
+ }
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c
new file mode 100644
index 0000000..1b0f0fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-47.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is saved into a global variable, it's
+ still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c
new file mode 100644
index 0000000..13836eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-48.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define STORE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is modified using a chain of operations
+ other than addition, its new value is still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c
new file mode 100644
index 0000000..c1136a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-49.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define STORE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator is both modified using a chain of
+ operations other than addition and stored into a global variable, its new
+ value is still added last. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c
new file mode 100644
index 0000000..e35a4ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-50.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define USE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator has multiple uses inside the loop, it's
+ not forced to the end of the reassociation chain. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c
new file mode 100644
index 0000000..0717567
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-51.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -ftree-vectorize" } */
+
+#define MODIFY
+#define STORE
+#define USE
+#include "reassoc-46.h"
+
+/* Check that if the loop accumulator has multiple uses inside the loop, it's
+ not forced to the end of the reassociation chain. */
+/* { dg-final { scan-tree-dump-times {(?:vect_)?sum_[\d._]+ = (?:(?:vect_)?_[\d._]+ \+ (?:vect_)?sum_[\d._]+|(?:vect_)?sum_[\d._]+ \+ (?:vect_)?_[\d._]+)} 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c
index 863aa79..fdfe37e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c
@@ -21,11 +21,12 @@ int main(void)
return 0;
}
-/* We now can prove the infiniteness of the loop during CCP and fail
- to eliminate the code inside the infinite loop because we start
- by marking the j % 7 condition as useful. See PR45178. */
+/* We now can prove the infiniteness of the loop during CCP but we
+ still want to eliminate the code inside the infinite loop. See PR45178. */
/* We should eliminate the inner condition, but the loop must be preserved
- as it is infinite. Therefore there should be just one goto and no PHI. */
+ as it is infinite. Therefore there should be just one goto and no PHI
+ and no if. */
/* { dg-final { scan-tree-dump-times "PHI " 0 "cddce1" } } */
+/* { dg-final { scan-tree-dump-times "if " 0 "cddce1" } } */
/* { dg-final { scan-tree-dump-times "goto" 1 "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
index 856ab38..73969bb 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2" } */
+/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2 -fdisable-tree-vrp-thread1 " } */
static int *bb_ticks;
extern void frob (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
index 3bc4b37..a25fe8b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
@@ -37,5 +37,5 @@ expand_shift_1 (int code, int unsignedp, int rotate,
we will enter the TRUE arm of the conditional and we can thread
the test to compute the first first argument of the expand_binop
call if we look backwards through the boolean logicals. */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
+/* { dg-final { scan-tree-dump-times "Threaded" 2 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
index ffbdc98..1b677f4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1 -fdisable-tree-vrp-thread1" } */
unsigned char
validate_subreg (unsigned int offset, unsigned int isize, unsigned int osize, int zz, int qq)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
index 03872e7..0246ebf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */
#include "ssa-dom-thread-4.c"
@@ -21,5 +21,7 @@
condition.
All the cases are picked up by VRP1 as jump threads. */
-/* { dg-final { scan-tree-dump-times "Registering FSM jump" 6 "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp1" } } */
+
+/* There used to be 6 jump threads found by thread1, but they all
+ depended on threading through distinct loops in ethread. */
+/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
index b972f64..8f0a12c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom2-stats" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-stats -fdump-tree-dom2-stats" } */
void bla();
@@ -16,6 +16,6 @@ void thread_entry_through_header (void)
/* There's a single jump thread that should be handled by the VRP
jump threading pass. */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp1"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp-thread1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp-thread1"} } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
index e1c33e8..823ada9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-dom2-stats -fdisable-tree-ethread" } */
+/* { dg-options "-O2 -fdump-tree-thread3-stats -fdump-tree-dom2-stats -fdisable-tree-ethread" } */
void foo();
void bla();
@@ -26,4 +26,4 @@ void thread_latch_through_header (void)
case. And we want to thread through the header as well. These
are both caught by threading in DOM. */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "thread1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "thread3"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
index 521754f..46e464f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */
struct bitmap_head_def;
typedef struct bitmap_head_def *bitmap;
typedef const struct bitmap_head_def *const_bitmap;
@@ -58,4 +58,5 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
code we missed the edge when the first conditional is false
(b_elt is zero, which means the second conditional is always
zero. VRP1 catches all three. */
-/* { dg-final { scan-tree-dump-times "Threaded" 3 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */
+/* { dg-final { scan-tree-dump-times "Path crosses loops" 1 "vrp-thread1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
index c7bf867..b0a7d42 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
@@ -1,41 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread2-details" } */
+/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread3-details" } */
-/* All the threads in the thread1 dump start on a X->BB12 edge, as can
- be seen in the dump:
-
- Registering FSM jump thread: (x, 12) incoming edge; ...
- etc
- etc
-
- Before the new evrp, we were threading paths that started at the
- following edges:
-
- Registering FSM jump thread: (10, 12) incoming edge
- Registering FSM jump thread: (6, 12) incoming edge
- Registering FSM jump thread: (9, 12) incoming edge
-
- This was because the PHI at BB12 had constant values coming in from
- BB10, BB6, and BB9:
-
- # state_10 = PHI <state_11(7), 0(10), state_11(5), 1(6), state_11(8), 2(9), state_11(11)>
-
- Now with the new evrp, we get:
-
- # state_10 = PHI <0(7), 0(10), state_11(5), 1(6), 0(8), 2(9), 1(11)>
-
- Thus, we have 3 more paths that are known to be constant and can be
- threaded. Which means that by the second threading pass, we can
- only find one profitable path.
-
- For the record, all these extra constants are better paths coming
- out of switches. For example:
-
- SWITCH_BB -> BBx -> BBy -> BBz -> PHI
-
- We now know the value of the switch index at PHI. */
-/* { dg-final { scan-tree-dump-times "Registering FSM jump" 6 "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Registering FSM jump" 1 "thread2" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump" 6 "thread1" } } */
+/* { dg-final { scan-tree-dump-times "Registering jump" 1 "thread3" } } */
int sum0, sum1, sum2, sum3;
int foo (char *s, char **ret)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
index 5fc2145..16abcde 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
@@ -1,23 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */
-/* Here we have the same issue as was commented in ssa-dom-thread-6.c.
- The PHI coming into the threader has a lot more constants, so the
- threader can thread more paths.
-
-$ diff clean/a.c.105t.mergephi2 a.c.105t.mergephi2
-252c252
-< # s_50 = PHI <s_49(10), 5(14), s_51(18), s_51(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), s_51(30)>
----
-> # s_50 = PHI <s_49(10), 5(14), 4(18), 5(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), 7(30)>
-272a273
-
- I spot checked a few and they all have the same pattern. We are
- basically tracking the switch index better through multiple
- paths. */
-
-/* { dg-final { scan-tree-dump "Jumps threaded: 18" "thread1" } } */
-/* { dg-final { scan-tree-dump "Jumps threaded: 8" "thread2" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 5" "thread3" { target { ! aarch64*-*-* } } } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */
/* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-18.c
index 92b2df8..2e7b5b4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-18.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-optimized" } */
int g(_Complex int*);
int f(void)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-19.c
index 718b746..7bb8d06 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-19.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-19.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-optimized" } */
int g(_Complex int*);
int f(void)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c
new file mode 100644
index 0000000..b0936be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-95.c
@@ -0,0 +1,25 @@
+/* PR100112 and dups. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1-details -fdump-tree-optimized" } */
+
+int *c, *b;
+void foo()
+{
+ int *tem = b;
+ *tem = 0;
+ int *footem = c;
+ c = footem;
+}
+
+void bar()
+{
+ int *tem = b;
+ int *bartem = c;
+ *tem = 0;
+ c = bartem;
+}
+
+/* We should elide the redundant store in foo, in bar it is not redundant since
+ the *tem = 0 store might alias. */
+/* { dg-final { scan-tree-dump "Deleted redundant store c = footem" "fre1" } } */
+/* { dg-final { scan-tree-dump "c = bartem" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
new file mode 100644
index 0000000..fd1d571
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res)
+{
+ _Bool t = __builtin_add_overflow(x, y, res);
+ unsigned res1;
+ _Bool t1 = __builtin_add_overflow(x, y, &res1);
+ *res -= res1;
+ return t==t1;
+}
+
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "fre1" } } */
+/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-16.c
new file mode 100644
index 0000000..741582b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-16.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-lim2-details" } */
+
+volatile int flag, bar;
+double foo (double *valp)
+{
+ double sum = 0;
+ for (int i = 0; i < 256; ++i)
+ {
+ for (int j = 0; j < 256; ++j)
+ bar = flag;
+ if (flag)
+ sum += 1.;
+ sum += *valp; // we should move the load of *valp out of the loop
+ }
+ return sum;
+}
+
+/* { dg-final { scan-tree-dump-times "Moving statement" 1 "lim2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-17.c
new file mode 100644
index 0000000..1c840e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-17.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-lim2-details" } */
+
+volatile int flag, bar;
+double foo (double *valp)
+{
+ double sum = 0;
+ for (int i = 0; i < 256; ++i)
+ {
+ if (flag)
+ for (int j = 0; j < 256; ++j)
+ bar = flag;
+ if (flag)
+ sum += 1.;
+ sum += *valp; // we should move the load of *valp out of the loop
+ }
+ return sum;
+}
+
+/* { dg-final { scan-tree-dump-times "Moving statement" 1 "lim2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
new file mode 100644
index 0000000..3b3bd62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res, int flag, _Bool *t)
+{
+ if (flag)
+ *t = __builtin_add_overflow(x, y, res);
+ unsigned res1;
+ _Bool t1 = __builtin_add_overflow(x, y, &res1);
+ *res -= res1;
+ return *t==t1;
+}
+
+/* We should hoist the .ADD_OVERFLOW to before the check. */
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
index 8f55464..08c0b8d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
@@ -1,8 +1,7 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops --param early-inlining-insns=14 -fno-inline-functions" } */
-/* { dg-final { scan-tree-dump "FSM" "thread2" } } */
-/* { dg-final { scan-tree-dump "FSM" "thread3" } } */
-/* { dg-final { scan-tree-dump "FSM" "thread4" } } */
+/* { dg-options "-O2 -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops --param early-inlining-insns=14 -fno-inline-functions" } */
+/* { dg-final { scan-tree-dump "Registering jump thread" "thread3" } } */
+/* { dg-final { scan-tree-dump "Registering jump thread" "thread4" } } */
typedef struct bitmap_head_def *bitmap;
typedef const struct bitmap_head_def *const_bitmap;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c
index 061f223..ad38b89 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ethread-details" } */
-/* { dg-final { scan-tree-dump "FSM" "ethread" } } */
+/* { dg-final { scan-tree-dump "Registering jump thread" "ethread" } } */
typedef struct rtx_def *rtx;
typedef const struct rtx_def *const_rtx;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
index f9152b9..8c5cc82 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
-/* { dg-additional-options "-O2 -fdump-tree-vrp-details --param logical-op-non-short-circuit=1" } */
+/* { dg-additional-options "-O2 -fdump-tree-vrp-thread1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-fdisable-tree-thread1" } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp-thread1" } } */
void foo (void);
void bar (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c
new file mode 100644
index 0000000..7adca97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-valid.c
@@ -0,0 +1,39 @@
+// { dg-do compile }
+// { dg-options "-O2 -fgimple -fdump-statistics" }
+
+// This is a collection of threadable paths. To simplify maintenance,
+// there should only be one threadable path per function.
+
+int global;
+
+// The thread from 3->4->5 crosses loops but is allowed because it
+// never crosses the latch (BB3) and is just an early exit out of the
+// loop.
+int __GIMPLE (ssa)
+foo1 (int x)
+{
+ int D_1420;
+ int a;
+
+ __BB(2):
+ a_4 = ~x_3(D);
+ goto __BB4;
+
+ // Latch.
+ __BB(3):
+ global = a_1;
+ goto __BB4;
+
+ __BB(4,loop_header(1)):
+ a_1 = __PHI (__BB2: a_4, __BB3: 0);
+ if (a_1 != 0)
+ goto __BB3;
+ else
+ goto __BB5;
+
+ __BB(5):
+ return;
+
+}
+
+// { dg-final { scan-tree-dump "Jumps threaded\" \"foo1\" 1" "statistics" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
index ef5611f..86d07ef 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdelete-null-pointer-checks" } */
/* { dg-skip-if "" keeps_null_pointer_checks } */
void oof (void);
@@ -29,5 +29,5 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
/* ARM Cortex-M defined LOGICAL_OP_NON_SHORT_CIRCUIT to false,
so skip below test. */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" { target { ! arm_cortex_m } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp-thread1" { target { ! arm_cortex_m } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
index e2e48d8..f25ea9c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/18046 */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" } } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-details" } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" } } */
/* During VRP we expect to thread the true arm of the conditional through the switch
and to the BB that corresponds to the 7 ... 9 case label. */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
index 8ae9b8d..a478a69 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-blocks-vops-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-vrp-thread1-blocks-vops-details -fdelete-null-pointer-checks" } */
void arf (void);
@@ -12,6 +12,6 @@ fu (char *p, int x)
arf ();
}
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" { target { ! keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp-thread1" { target { keeps_null_pointer_checks } } } } */
diff --git a/gcc/testsuite/gcc.dg/typedef-var-2.c b/gcc/testsuite/gcc.dg/typedef-var-2.c
index 716d29c..bc119a0 100644
--- a/gcc/testsuite/gcc.dg/typedef-var-2.c
+++ b/gcc/testsuite/gcc.dg/typedef-var-2.c
@@ -4,12 +4,13 @@
int f (void)
{
extern float v;
-
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
return (v > 0.0f);
}
extern int t;
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
typedef float t; /* { dg-error "redeclared as different kind of symbol" } */
-t v = 4.5f;
+t v = 4.5f; /* { dg-error "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/uninit-15-O0.c b/gcc/testsuite/gcc.dg/uninit-15-O0.c
index 36d9634..1ddddee 100644
--- a/gcc/testsuite/gcc.dg/uninit-15-O0.c
+++ b/gcc/testsuite/gcc.dg/uninit-15-O0.c
@@ -14,7 +14,7 @@ void baz();
void bar()
{
- int j; /* { dg-message "was declared here" {} { xfail *-*-* } } */
+ int j; /* { dg-message "declared here" } */
for (; foo(j); ++j) /* { dg-warning "is used uninitialized" } */
baz();
}
diff --git a/gcc/testsuite/gcc.dg/uninit-15.c b/gcc/testsuite/gcc.dg/uninit-15.c
index 85cb116..7352662 100644
--- a/gcc/testsuite/gcc.dg/uninit-15.c
+++ b/gcc/testsuite/gcc.dg/uninit-15.c
@@ -20,7 +20,7 @@ void baz (void);
void
bar (void)
{
- int j; /* { dg-message "note: 'j' was declared here" "" { xfail *-*-* } } */
+ int j; /* { dg-message "note: 'j' was declared here" } */
for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" } */
baz ();
}
diff --git a/gcc/testsuite/gcc.dg/uninit-40.c b/gcc/testsuite/gcc.dg/uninit-40.c
index c015191..8708079 100644
--- a/gcc/testsuite/gcc.dg/uninit-40.c
+++ b/gcc/testsuite/gcc.dg/uninit-40.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/98597 */
/* { dg-do compile } */
-/* { dg-options "-O2 -Wuninitialized" } */
+/* { dg-options "-O2 -fno-tree-vectorize -Wuninitialized" } */
union U { double d; int i; float f; };
struct S { char a; int b; char c; unsigned d; union U e; int f[3]; unsigned g[3]; };
diff --git a/gcc/testsuite/gcc.dg/uninit-pr102403-c2.c b/gcc/testsuite/gcc.dg/uninit-pr102403-c2.c
new file mode 100644
index 0000000..8181143
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-pr102403-c2.c
@@ -0,0 +1,34 @@
+/* PR middle-end/102403 - ICE in init_from_control_deps, at
+ gimple-predicate-analysis.cc:2364
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+extern int a[], b, c, d, e, f, g, h;
+
+inline void foo (void) { b = 1 ^ a[b ^ (c & 1)]; }
+
+void bar (void);
+
+int main (void)
+{
+ if (!f && ~h)
+ {
+ if (g)
+ goto L2;
+ }
+ else
+ {
+ int m = 0; // { dg-message "declared here" }
+ L1:
+ e = m;
+ L2:
+ m ^= 1; // { dg-warning "-Wmaybe-uninitialized" }
+ if (d)
+ bar ();
+
+ for (int j = 0; j < 10; j++)
+ foo ();
+
+ goto L1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-pr102403.c b/gcc/testsuite/gcc.dg/uninit-pr102403.c
new file mode 100644
index 0000000..1e62e98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-pr102403.c
@@ -0,0 +1,49 @@
+/* PR middle-end/102403 - ICE in init_from_control_deps, at
+ gimple-predicate-analysis.cc:2364
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+int __fmaf (void)
+{
+ int a = 0;
+ int b, c, d, e, f;
+
+ int r = 0;
+
+ switch (b) // { dg-warning "-Wuninitialized" }
+ {
+ default:
+ c |= 1;
+
+ case 0:
+ if (c == 0)
+ a = 1;
+
+ switch (d) {
+ case 15:
+ f = c;
+ break;
+
+ case 11:
+ case 6:
+ case 4:
+ f = c;
+ case 10:
+ e = a;
+ }
+
+ if (e == 0) // { dg-warning "-Wmaybe-uninitialized" }
+ f = 0;
+
+ r = f;
+ }
+
+ // The return statement below gets the unhelpful warning:
+ // 'f' may be used uninitialized in this function [-Wmaybe-uninitialized]
+ return r;
+}
+
+/* Prune out warnings issued on the wrong lines, such as:
+ uninit-pr102403.c:9:13: warning: ‘d’ is used uninitialized [-Wuninitialized]
+ { dg-prune-output "-Wuninitialized" }
+ { dg-prune-output "-Wmaybe-uninitialized" } */
diff --git a/gcc/testsuite/gcc.dg/uninit-pr93100.c b/gcc/testsuite/gcc.dg/uninit-pr93100.c
index 531a5c3..7cb0222 100644
--- a/gcc/testsuite/gcc.dg/uninit-pr93100.c
+++ b/gcc/testsuite/gcc.dg/uninit-pr93100.c
@@ -1,7 +1,7 @@
/* PR tree-optimization/93100 - gcc -fsanitize=address inhibits -Wuninitialized
{ dg-do compile }
{ dg-options "-Wall -fsanitize=address" }
- { dg-skip-if "sanitize address" { "powerpc-ibm-aix*" } } */
+ { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
struct A
{
diff --git a/gcc/testsuite/gcc.dg/unroll-7.c b/gcc/testsuite/gcc.dg/unroll-7.c
index 055369b..695af57 100644
--- a/gcc/testsuite/gcc.dg/unroll-7.c
+++ b/gcc/testsuite/gcc.dg/unroll-7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-loop2_unroll-details -funroll-loops" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fdump-rtl-loop2_unroll-details -funroll-loops" } */
/* { dg-require-effective-target int32plus } */
extern int *a;
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
index 664e93e..e68a9b6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
@@ -1,8 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* See note below as to why we disable threading. */
-/* { dg-additional-options "-fdisable-tree-thread1" } */
-
#include <stdarg.h>
#include "tree-vect.h"
@@ -30,10 +27,6 @@ main1 (int dummy)
*pout++ = *pin++ + a;
*pout++ = *pin++ + a;
*pout++ = *pin++ + a;
- /* In some architectures like ppc64, jump threading may thread
- the iteration where i==0 such that we no longer optimize the
- BB. Another alternative to disable jump threading would be
- to wrap the read from `i' into a function returning i. */
if (arr[i] = i)
a = i;
else
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
index 5d80f56..ee12136 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
@@ -1,5 +1,6 @@
/* { dg-additional-options "-O3" } */
/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-mprefer-vector-width=128" { target x86_64-*-* i?86-*-* } } */
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
index 672807f..56ec0f6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
@@ -12,12 +12,12 @@ e()
void *f[] = {&&g, &&h, &&i, &&j};
int d, c;
j:
- goto *a;
+ goto *(void*)(__INTPTR_TYPE__)a;
g:
d = 0;
h:
c = 1;
- goto *a;
+ goto *(void*)(__INTPTR_TYPE__)a;
i:
{
struct b b = {c, d};
diff --git a/gcc/testsuite/gcc.dg/vect/pr101145.c b/gcc/testsuite/gcc.dg/vect/pr101145.c
index 74031b0..cd11c03 100644
--- a/gcc/testsuite/gcc.dg/vect/pr101145.c
+++ b/gcc/testsuite/gcc.dg/vect/pr101145.c
@@ -1,5 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* { dg-options "-O3 -fdump-tree-vect-details" } */
+/* { dg-additional-options "-O3" } */
#include <limits.h>
unsigned __attribute__ ((noinline))
diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_1.c b/gcc/testsuite/gcc.dg/vect/pr101145_1.c
index 8bc26e2..9332b2c 100644
--- a/gcc/testsuite/gcc.dg/vect/pr101145_1.c
+++ b/gcc/testsuite/gcc.dg/vect/pr101145_1.c
@@ -1,5 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* { dg-options "-O3 -fdump-tree-vect-details" } */
+/* { dg-additional-options "-O3" } */
#define TYPE signed char
#define MIN -128
#define MAX 127
diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_2.c b/gcc/testsuite/gcc.dg/vect/pr101145_2.c
index b14c4b4..fa2c6be 100644
--- a/gcc/testsuite/gcc.dg/vect/pr101145_2.c
+++ b/gcc/testsuite/gcc.dg/vect/pr101145_2.c
@@ -1,5 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* { dg-options "-O3 -fdump-tree-vect-details" } */
+/* { dg-additional-options "-O3" } */
#define TYPE unsigned char
#define MIN 0
#define MAX 255
diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_3.c b/gcc/testsuite/gcc.dg/vect/pr101145_3.c
index 99289af..9f43c82 100644
--- a/gcc/testsuite/gcc.dg/vect/pr101145_3.c
+++ b/gcc/testsuite/gcc.dg/vect/pr101145_3.c
@@ -1,5 +1,5 @@
/* { dg-require-effective-target vect_int } */
-/* { dg-options "-O3 -fdump-tree-vect-details" } */
+/* { dg-additional-options "-O3" } */
#define TYPE int *
#define MIN ((TYPE)0)
#define MAX ((TYPE)((long long)-1))
diff --git a/gcc/testsuite/gcc.dg/vect/pr102318.c b/gcc/testsuite/gcc.dg/vect/pr102318.c
new file mode 100644
index 0000000..cc58efa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr102318.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+void
+vec_slp_int16_t (short int *restrict a, short int *restrict b, int n)
+{
+ short int x0 = b[0];
+ short int x1 = b[1];
+ short int x2 = b[2];
+ short int x3 = b[3];
+ for (int i = 0; i < n; ++i)
+ {
+ x0 += a[i * 4];
+ x1 += a[i * 4 + 1];
+ x2 += a[i * 4 + 2];
+ x3 += a[i * 4 + 3];
+ }
+ b[0] = x0;
+ b[1] = x1;
+ b[2] = x2;
+ b[3] = x3;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr65206.c b/gcc/testsuite/gcc.dg/vect/pr65206.c
new file mode 100644
index 0000000..3b62626
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr65206.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-fno-trapping-math -fno-allow-store-data-races" } */
+/* { dg-additional-options "-mavx" { target avx } } */
+
+#define N 1024
+
+double a[N], b[N];
+
+void foo ()
+{
+ for (int i = 0; i < N; ++i)
+ if (b[i] < 3.)
+ a[i] += b[i];
+}
+
+/* We get a .MASK_STORE because while the load of a[i] does not trap
+ the store would introduce store data races. Make sure we still
+ can handle the data dependence with zero distance. */
+
+/* { dg-final { scan-tree-dump-not "versioning for alias required" "vect" { target { vect_masked_store || avx } } } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" { target { vect_masked_store || avx } } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/help.exp b/gcc/testsuite/gcc.misc-tests/help.exp
index 5e034d2..eb6d868 100644
--- a/gcc/testsuite/gcc.misc-tests/help.exp
+++ b/gcc/testsuite/gcc.misc-tests/help.exp
@@ -79,7 +79,7 @@ check_for_options c "--help=target,optimizers" "" "" ""
check_for_options c "--help=warnings,^joined,^undocumented" "" "" ""
check_for_options c "-Q -O2 --help=optimizers" {
-O
--ftree-loop-vectorize[^\n]*disabled
+-ftree-loop-vectorize[^\n]*enabled
} " -g " ""
check_for_options c "-Q -O3 --help=optimizers" {
-O
diff --git a/gcc/testsuite/gcc.misc-tests/linkage.exp b/gcc/testsuite/gcc.misc-tests/linkage.exp
index afed2b8..2cb109e 100644
--- a/gcc/testsuite/gcc.misc-tests/linkage.exp
+++ b/gcc/testsuite/gcc.misc-tests/linkage.exp
@@ -38,6 +38,18 @@ if { [isnative] && ![is_remote host] } then {
# Need to ensure ABI for native compiler matches gcc
set native_cflags ""
+ if [istarget "mips*-linux*"] {
+ set file_string [exec file "linkage-x.o"]
+ if [ string match "*64*" $file_string ] {
+ set native_cflags "-mabi=64"
+ }
+ if [ string match "*ELF 32*" $file_string ] {
+ set native_cflags "-mabi=32"
+ }
+ if [ string match "*N32*" $file_string ] {
+ set native_cflags "-mabi=n32"
+ }
+ }
if [istarget "sparc*-sun-solaris2*"] {
set file_string [exec file "linkage-x.o"]
if [ string match "*64*" $file_string ] {
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
new file mode 100644
index 0000000..0fa4708
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 11 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
new file mode 100644
index 0000000..2c54e6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfe\\\]" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
new file mode 100644
index 0000000..7008f76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_double\:SF 0\.0" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "const_double\:DF 0\.0" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "const_double\:TF 0\.0" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
new file mode 100644
index 0000000..1019704
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump "\\-0x0\\.fefefep\\+127" "expand" } } */
+/* { dg-final { scan-rtl-dump "\\-0x0\\.f7f7f7f7f7f7fp\\+1009" "expand" } } */
+/* { dg-final { scan-rtl-dump "\\-0x0\\.ff7f7f7f7f7f7f7f7f7f7f7f7f7fp\\+16128" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
new file mode 100644
index 0000000..ac69ac3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times "\.word\t0" 14 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
new file mode 100644
index 0000000..27c16b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
@@ -0,0 +1,18 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 3 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-7.c b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
new file mode 100644
index 0000000..ac27fbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 8 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-8.c b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
new file mode 100644
index 0000000..3943f5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
@@ -0,0 +1,32 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 4 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c
new file mode 100644
index 0000000..d3a88c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c
@@ -0,0 +1,17 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c
new file mode 100644
index 0000000..b0f3acb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c
new file mode 100644
index 0000000..02f7edc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c
new file mode 100644
index 0000000..555972f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c
new file mode 100644
index 0000000..aceceb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c
@@ -0,0 +1,18 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c
new file mode 100644
index 0000000..085c386
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 4 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c
new file mode 100644
index 0000000..7a6ddbc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 5 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c
new file mode 100644
index 0000000..3c45a6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "stp\txzr, xzr," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c
new file mode 100644
index 0000000..bfef23d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c
@@ -0,0 +1,20 @@
+/* Verify pattern initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c
new file mode 100644
index 0000000..cb96c3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c
@@ -0,0 +1,20 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c
new file mode 100644
index 0000000..ce7c7cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c
new file mode 100644
index 0000000..c81e5ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 5 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/cpymem-size.c b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c
new file mode 100644
index 0000000..4a6f249
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+#include <stdlib.h>
+
+/*
+** cpy_127:
+** mov (w|x)2, 127
+** b memcpy
+*/
+void
+cpy_127 (char *out, char *in)
+{
+ __builtin_memcpy (out, in, 127);
+}
+
+/*
+** cpy_128:
+** mov (w|x)2, 128
+** b memcpy
+*/
+void
+cpy_128 (char *out, char *in)
+{
+ __builtin_memcpy (out, in, 128);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/lane-bound-1.c b/gcc/testsuite/gcc.target/aarch64/lane-bound-1.c
new file mode 100644
index 0000000..bbbe679
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/lane-bound-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+#include <arm_neon.h>
+
+void
+f (float32x4_t **ptr)
+{
+ float32x4_t res = vsetq_lane_f32 (0.0f, **ptr, 0);
+ **ptr = res;
+}
+/* GCC should be able to remove the call to "__builtin_aarch64_im_lane_boundsi"
+ and optimize out the second load from *ptr. */
+/* { dg-final { scan-tree-dump-times "__builtin_aarch64_im_lane_boundsi" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " = \\\*ptr_" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/lane-bound-2.c b/gcc/testsuite/gcc.target/aarch64/lane-bound-2.c
new file mode 100644
index 0000000..923c946
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/lane-bound-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+void
+f (void)
+{
+ __builtin_aarch64_im_lane_boundsi (16, 4, 0);
+ __builtin_aarch64_im_lane_boundsi (8, 8, 0);
+}
+/* GCC should be able to optimize these out before gimplification. */
+/* { dg-final { scan-tree-dump-times "__builtin_aarch64_im_lane_boundsi" 0 "original" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c
new file mode 100644
index 0000000..9ee96f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdint.h>
+
+/* 127 bytes should use libcall for size.
+**set127byte:
+** mov x2, 127
+** b memset
+*/
+void __attribute__((__noinline__))
+set127byte (int64_t *src, int c)
+{
+ __builtin_memset (src, c, 127);
+}
+
+/* 128 bytes should use libcall for size.
+**set128byte:
+** mov x2, 128
+** b memset
+*/
+void __attribute__((__noinline__))
+set128byte (int64_t *src, int c)
+{
+ __builtin_memset (src, c, 128);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c b/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c
new file mode 100644
index 0000000..664d43a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memset-strict-align-1.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mstrict-align" } */
+
+struct s { char x[255]; };
+void foo (struct s *);
+void bar (void) { struct s s1 = {}; foo (&s1); }
+
+/* memset (s1 = {}, sizeof = 255) should be expanded out
+ such that there are no overlap stores when -mstrict-align
+ is in use.
+ so 7 pairs of 16 bytes stores (224 bytes).
+ 1 16 byte stores
+ 1 8 byte store
+ 1 4 byte store
+ 1 2 byte store
+ 1 1 byte store
+ */
+
+/* { dg-final { scan-assembler-times "stp\tq" 7 } } */
+/* { dg-final { scan-assembler-times "str\tq" 1 } } */
+/* { dg-final { scan-assembler-times "str\txzr" 1 } } */
+/* { dg-final { scan-assembler-times "str\twzr" 1 } } */
+/* { dg-final { scan-assembler-times "strh\twzr" 1 } } */
+/* { dg-final { scan-assembler-times "strb\twzr" 1 } } */
+
+/* Also one store pair for the frame-pointer and the LR. */
+/* { dg-final { scan-assembler-times "stp\tx" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_4.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_4.c
index 4604365..a491f899 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_4.c
@@ -56,7 +56,11 @@ TEST_ALL (DEF_LOOP)
we're relying on combine to merge a SEL and an arithmetic operation,
and the SEL doesn't allow the "false" value to be zero when the "true"
value is a register. */
-/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+, z[0-9]+\n} 14 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+, z[0-9]+\n} 7 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.b, p[0-7]/z, z[0-9]+\.b} 1 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/z, z[0-9]+\.h} 2 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/z, z[0-9]+\.s} 2 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/z, z[0-9]+\.d} 2 } } */
/* { dg-final { scan-assembler-not {\tmov\tz[^\n]*z} } } */
/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c
new file mode 100644
index 0000000..af2ae59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=zero" } */
+
+void foo() { __SVFloat64_t f64; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c
new file mode 100644
index 0000000..8c9d9908
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=pattern" } */
+
+void foo() { __SVFloat64_t f64; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c
new file mode 100644
index 0000000..2f92224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mcpu=generic+sve" } */
+
+typedef unsigned char uint8_t;
+
+static inline uint8_t
+x264_clip_uint8(uint8_t x)
+{
+ uint8_t t = -x;
+ uint8_t t1 = x & ~63;
+ return (t1 != 0) ? t : x;
+}
+
+void
+mc_weight(uint8_t *restrict dst, uint8_t *restrict src, int n)
+{
+ for (int x = 0; x < n*16; x++)
+ dst[x] = x264_clip_uint8(src[x]);
+}
+
+/* { dg-final { scan-assembler-not {\tsel} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-cond-reduc.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-cond-reduc.c
new file mode 100644
index 0000000..bd53025
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-cond-reduc.c
@@ -0,0 +1,18 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+#include <stdint.h>
+
+int32_t f (int32_t *restrict array, int len, int min)
+{
+ int32_t iSum = 0;
+
+ for (int i=0; i<len; i++) {
+ if (array[i] >= min)
+ iSum += array[i];
+ }
+ return iSum;
+}
+
+
+/* { dg-final { scan-assembler-not {\tsel\tz[0-9]+\.s, p1, z[0-9]+\.s, z[0-9]+\.s} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-1.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-1.c
new file mode 100644
index 0000000..2c06564
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-1.c
@@ -0,0 +1,23 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+/*
+** f10:
+** ...
+** ld1d z1.d, p0/z, \[x1, x5, lsl 3\]
+** fcmgt p2.d, p0/z, z1.d, #0.0
+** ld1d z2.d, p2/z, \[x2, x5, lsl 3\]
+** not p1.b, p0/z, p2.b
+** ld1d z0.d, p1/z, \[x3, x5, lsl 3\]
+** ...
+*/
+
+void f10(double * restrict z, double * restrict w, double * restrict x, double * restrict y, int n)
+{
+ for (int i = 0; i < n; i++) {
+ z[i] = (w[i] > 0) ? x[i] + w[i] : y[i] - w[i];
+ }
+}
+
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
+/* { dg-final { scan-assembler-times {\tnot\tp[0-9]+\.b, p[0-9]+/z, p[0-9]+\.b\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-2.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-2.c
new file mode 100644
index 0000000..0c3b78d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-2.c
@@ -0,0 +1,23 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+/*
+** f11:
+** ...
+** ld1d z0.d, p0/z, \[x1, x2, lsl 3\]
+** fcmgt p2.d, p3/z, z0.d, #0.0
+** fcmgt p1.d, p0/z, z0.d, #0.0
+** not p1.b, p0/z, p1.b
+** ld1d z1.d, p1/z, \[x3, x2, lsl 3\]
+** ...
+*/
+
+void f11(double * restrict z, double * restrict w, double * restrict x, double * restrict y, int n)
+{
+ for (int i = 0; i < n; i++) {
+ z[i] = (w[i] > 0) ? w[i] : y[i];
+ }
+}
+
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
+/* { dg-final { scan-assembler-times {\tnot\tp[0-9]+\.b, p[0-9]+/z, p[0-9]+\.b\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-3.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-3.c
new file mode 100644
index 0000000..248f8ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-3.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+/*
+** f12:
+** ...
+** ld1w z1.s, p0/z, \[x1, x2, lsl 2\]
+** cmple p1.s, p0/z, z1.s, #0
+** ld1w z0.s, p1/z, \[x3, x2, lsl 2\]
+** ...
+*/
+
+void f12(int * restrict z, int * restrict w, int * restrict x, int * restrict y, int n)
+{
+ for (int i = 0; i < n; i++) {
+ z[i] = (w[i] > 0) ? w[i] : y[i];
+ }
+}
+
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
+/* { dg-final { scan-assembler-not {\tnot\tp[0-9]+\.b, p[0-9]+/z, p[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-4.c b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-4.c
new file mode 100644
index 0000000..9620030
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred-not-gen-4.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+#include <math.h>
+
+void f13(double * restrict z, double * restrict w, double * restrict x, double * restrict y, int n)
+{
+ for (int i = 0; i < n; i++) {
+ z[i] = (isunordered(w[i], 0)) ? x[i] + w[i] : y[i] - w[i];
+ }
+}
+
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
+/* { dg-final { scan-assembler-times {\tnot\tp[0-9]+\.b, p[0-9]+/z, p[0-9]+\.b\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/mve.exp b/gcc/testsuite/gcc.target/arm/mve/mve.exp
index d09fc27..a858e52 100644
--- a/gcc/testsuite/gcc.target/arm/mve/mve.exp
+++ b/gcc/testsuite/gcc.target/arm/mve/mve.exp
@@ -44,6 +44,9 @@ dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/intrinsics/*.\[cCS\]]] \
"" $DEFAULT_CFLAGS
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" $DEFAULT_CFLAGS
+
# All done.
set dg_runtest_extra_prunes ""
dg-finish
diff --git a/gcc/testsuite/gcc.target/arm/mve/mve_load_memory_modes.c b/gcc/testsuite/gcc.target/arm/mve/mve_load_memory_modes.c
new file mode 100644
index 0000000..e35eb11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/mve_load_memory_modes.c
@@ -0,0 +1,357 @@
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+/* { dg-additional-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_mve.h"
+/*
+**off_load8_0:
+** ...
+** vldrb.8 q0, \[r0, #16\]
+** ...
+*/
+int8x16_t off_load8_0 (int8_t * a)
+{
+ return vld1q_s8 (a + 16);
+}
+
+/*
+**off_load8_1:
+** ...
+** vldrb.u16 q0, \[r0, #1\]
+** ...
+*/
+uint16x8_t off_load8_1 (uint8_t * a)
+{
+ return vldrbq_u16 (a + 1);
+}
+
+/*
+**off_load8_2:
+** ...
+** vldrb.s32 q0, \[r0, #127\]
+** ...
+*/
+int32x4_t off_load8_2 (int8_t * a)
+{
+ return vldrbq_s32 (a + 127);
+}
+
+/*
+**off_load8_3:
+** ...
+** vldrb.8 q0, \[r0, #-127\]
+** ...
+*/
+uint8x16_t off_load8_3 (uint8_t * a)
+{
+ return vldrbq_u8 (a - 127);
+}
+
+/*
+**not_off_load8_0:
+** ...
+** vldrb.8 q0, \[r[0-9]+\]
+** ...
+*/
+int8x16_t not_off_load8_0 (int8_t * a)
+{
+ return vld1q_s8 (a + 128);
+}
+
+/*
+**off_loadfp16_0:
+** ...
+** vldrh.16 q0, \[r0, #-244\]
+** ...
+*/
+float16x8_t off_loadfp16_0 (float16_t *a)
+{
+ return vld1q_f16 (a - 122);
+}
+
+/*
+**off_load16_0:
+** ...
+** vldrh.16 q0, \[r0, #-2\]
+** ...
+*/
+uint16x8_t off_load16_0 (uint16_t * a)
+{
+ return vld1q_u16 (a - 1);
+}
+
+/*
+**off_load16_1:
+** ...
+** vldrh.u32 q0, \[r0, #254\]
+** ...
+*/
+uint32x4_t off_load16_1 (uint16_t * a)
+{
+ return vldrhq_u32 (a + 127);
+}
+
+/*
+**not_off_load16_0:
+** ...
+** vldrh.16 q0, \[r[0-9]+\]
+** ...
+*/
+int16x8_t not_off_load16_0 (int8_t * a)
+{
+ return vld1q_s16 ((int16_t *)(a + 1));
+}
+
+/*
+**not_off_load16_1:
+** ...
+** vldrh.u32 q0, \[r[0-9]+\]
+** ...
+*/
+uint32x4_t not_off_load16_1 (uint16_t * a)
+{
+ return vldrhq_u32 ((a - 128));
+}
+
+/*
+**off_loadfp32_0:
+** ...
+** vldrw.32 q0, \[r0, #24\]
+** ...
+*/
+float32x4_t off_loadfp32_0 (float32_t *a)
+{
+ return vld1q_f32 (a + 6);
+}
+
+/*
+**off_load32_0:
+** ...
+** vldrw.32 q0, \[r0, #4\]
+** ...
+*/
+uint32x4_t off_load32_0 (uint32_t * a)
+{
+ return vld1q_u32 (a + 1);
+}
+
+/*
+**off_load32_1:
+** ...
+** vldrw.32 q0, \[r0, #-508\]
+** ...
+*/
+int32x4_t off_load32_1 (int32_t * a)
+{
+ return vldrwq_s32 (a - 127);
+}
+/*
+**pre_load8_0:
+** ...
+** vldrb.8 q[0-9]+, \[r0, #16\]!
+** ...
+*/
+int8_t* pre_load8_0 (int8_t * a, int8x16_t *v)
+{
+ a += 16;
+ *v = vld1q_s8 (a);
+ return a;
+}
+
+/*
+**pre_load8_1:
+** ...
+** vldrb.u16 q[0-9]+, \[r0, #4\]!
+** ...
+*/
+uint8_t* pre_load8_1 (uint8_t * a, uint16x8_t *v)
+{
+ a += 4;
+ *v = vldrbq_u16 (a);
+ return a;
+}
+
+/*
+**pre_loadfp16_0:
+** ...
+** vldrh.16 q[0-9]+, \[r0, #128\]!
+** ...
+*/
+float16_t* pre_loadfp16_0 (float16_t *a, float16x8_t *v)
+{
+ a += 64;
+ *v = vld1q_f16 (a);
+ return a;
+}
+
+/*
+**pre_load16_0:
+** ...
+** vldrh.16 q[0-9]+, \[r0, #-254\]!
+** ...
+*/
+int16_t* pre_load16_0 (int16_t * a, int16x8_t *v)
+{
+ a -= 127;
+ *v = vldrhq_s16 (a);
+ return a;
+}
+
+/*
+**pre_load16_1:
+** ...
+** vldrh.s32 q[0-9]+, \[r0, #52\]!
+** ...
+*/
+int16_t* pre_load16_1 (int16_t * a, int32x4_t *v)
+{
+ a += 26;
+ *v = vldrhq_s32 (a);
+ return a;
+}
+
+/*
+**pre_loadfp32_0:
+** ...
+** vldrw.32 q[0-9]+, \[r0, #-72\]!
+** ...
+*/
+float32_t* pre_loadfp32_0 (float32_t *a, float32x4_t *v)
+{
+ a -= 18;
+ *v = vld1q_f32 (a);
+ return a;
+}
+
+
+/*
+**pre_load32_0:
+** ...
+** vldrw.32 q[0-9]+, \[r0, #-4\]!
+** ...
+*/
+uint32_t* pre_load32_0 (uint32_t * a, uint32x4_t *v)
+{
+ a -= 1;
+ *v = vld1q_u32 (a);
+ return a;
+}
+
+
+/*
+**post_load8_0:
+** ...
+** vldrb.8 q[0-9]+, \[r0\], #26
+** ...
+*/
+uint8_t* post_load8_0 (uint8_t * a, uint8x16_t *v)
+{
+ *v = vld1q_u8 (a);
+ a += 26;
+ return a;
+}
+
+/*
+**post_load8_1:
+** ...
+** vldrb.s16 q[0-9]+, \[r0\], #-1
+** ...
+*/
+int8_t* post_load8_1 (int8_t * a, int16x8_t *v)
+{
+ *v = vldrbq_s16 (a);
+ a--;
+ return a;
+}
+
+/*
+**post_load8_2:
+** ...
+** vldrb.8 q[0-9]+, \[r0\], #26
+** ...
+*/
+uint8_t* post_load8_2 (uint8_t * a, uint8x16_t *v)
+{
+ *v = vld1q_u8 (a);
+ a += 26;
+ return a;
+}
+
+/*
+**post_load8_3:
+** ...
+** vldrb.s16 q[0-9]+, \[r0\], #-1
+** ...
+*/
+int8_t* post_load8_3 (int8_t * a, int16x8_t *v)
+{
+ *v = vldrbq_s16 (a);
+ a--;
+ return a;
+}
+
+/*
+**post_loadfp16_0:
+** ...
+** vldrh.16 q[0-9]+, \[r0\], #-24
+** ...
+*/
+float16_t* post_loadfp16_0 (float16_t *a, float16x8_t *v)
+{
+ *v = vld1q_f16 (a);
+ a -= 12;
+ return a;
+}
+
+/*
+**post_load16_0:
+** ...
+** vldrh.16 q[0-9]+, \[r0\], #-126
+** ...
+*/
+uint16_t* post_load16_0 (uint16_t * a, uint16x8_t *v)
+{
+ *v = vldrhq_u16 (a);
+ a -= 63;
+ return a;
+}
+
+/*
+**post_load16_1:
+** ...
+** vldrh.u32 q[0-9]+, \[r0\], #16
+** ...
+*/
+uint16_t* post_load16_1 (uint16_t * a, uint32x4_t *v)
+{
+ *v = vldrhq_u32 (a);
+ a += 8;
+ return a;
+}
+
+/*
+**post_loadfp32_0:
+** ...
+** vldrw.32 q[0-9]+, \[r0\], #4
+** ...
+*/
+float32_t* post_loadfp32_0 (float32_t *a, float32x4_t *v)
+{
+ *v = vld1q_f32 (a);
+ a++;
+ return a;
+}
+
+/*
+**post_load32_0:
+** ...
+** vldrw.32 q[0-9]+, \[r0\], #-16
+** ...
+*/
+int32_t* post_load32_0 (int32_t * a, int32x4_t *v)
+{
+ *v = vld1q_s32 (a);
+ a -= 4;
+ return a;
+}
diff --git a/gcc/testsuite/gcc.target/arm/mve/mve_store_memory_modes.c b/gcc/testsuite/gcc.target/arm/mve/mve_store_memory_modes.c
new file mode 100644
index 0000000..632f5b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/mve_store_memory_modes.c
@@ -0,0 +1,370 @@
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+/* { dg-additional-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_mve.h"
+/*
+**off_store8_0:
+** ...
+** vstrb.8 q0, \[r0, #16\]
+** ...
+*/
+uint8_t *off_store8_0 (uint8_t * a, uint8x16_t v)
+{
+ vst1q_u8 (a + 16, v);
+ return a;
+}
+
+/*
+**off_store8_1:
+** ...
+** vstrb.16 q0, \[r0, #-1\]
+** ...
+*/
+int8_t *off_store8_1 (int8_t * a, int16x8_t v)
+{
+ vstrbq_s16 (a - 1, v);
+ return a;
+}
+
+/*
+**off_store8_2:
+** ...
+** vstrb.32 q0, \[r0, #-127\]
+** ...
+*/
+uint8_t *off_store8_2 (uint8_t * a, uint32x4_t v)
+{
+ vstrbq_u32 (a - 127, v);
+ return a;
+}
+
+/*
+**off_store8_3:
+** ...
+** vstrb.8 q0, \[r0, #127\]
+** ...
+*/
+int8_t *off_store8_3 (int8_t * a, int8x16_t v)
+{
+ vstrbq_s8 (a + 127, v);
+ return a;
+}
+
+/*
+**not_off_store8_0:
+** ...
+** vstrb.8 q0, \[r[0-9]+\]
+** ...
+*/
+uint8_t *not_off_store8_0 (uint8_t * a, uint8x16_t v)
+{
+ vst1q_u8 (a - 128, v);
+ return a;
+}
+
+/*
+**off_storefp16_0:
+** ...
+** vstrh.16 q0, \[r0, #250\]
+** ...
+*/
+float16_t *off_storefp16_0 (float16_t *a, float16x8_t v)
+{
+ vst1q_f16 (a + 125, v);
+ return a;
+}
+
+/*
+**off_store16_0:
+** ...
+** vstrh.16 q0, \[r0, #4\]
+** ...
+*/
+int16_t *off_store16_0 (int16_t * a, int16x8_t v)
+{
+ vst1q_s16 (a + 2, v);
+ return a;
+}
+
+/*
+**off_store16_1:
+** ...
+** vstrh.32 q0, \[r0, #-254\]
+** ...
+*/
+int16_t *off_store16_1 (int16_t * a, int32x4_t v)
+{
+ vstrhq_s32 (a - 127, v);
+ return a;
+}
+
+/*
+**not_off_store16_0:
+** ...
+** vstrh.16 q0, \[r[0-9]+\]
+** ...
+*/
+uint8_t *not_off_store16_0 (uint8_t * a, uint16x8_t v)
+{
+ vst1q_u16 ((uint16_t *)(a - 1), v);
+ return a;
+}
+
+/*
+**not_off_store16_1:
+** ...
+** vstrh.32 q0, \[r[0-9]+\]
+** ...
+*/
+int16_t *not_off_store16_1 (int16_t * a, int32x4_t v)
+{
+ vstrhq_s32 ((a + 128), v);
+ return a;
+}
+
+/*
+**off_storefp32_0:
+** ...
+** vstrw.32 q0, \[r0, #-412\]
+** ...
+*/
+float32_t *off_storefp32_0 (float32_t *a, float32x4_t v)
+{
+ vst1q_f32 (a - 103, v);
+ return a;
+}
+
+/*
+**off_store32_0:
+** ...
+** vstrw.32 q0, \[r0, #-4\]
+** ...
+*/
+int32_t *off_store32_0 (int32_t * a, int32x4_t v)
+{
+ vst1q_s32 (a - 1, v);
+ return a;
+}
+
+/*
+**off_store32_1:
+** ...
+** vstrw.32 q0, \[r0, #508\]
+** ...
+*/
+uint32_t *off_store32_1 (uint32_t * a, uint32x4_t v)
+{
+ vstrwq_u32 (a + 127, v);
+ return a;
+}
+
+/*
+**pre_store8_0:
+** ...
+** vstrb.8 q[0-9]+, \[r0, #-16\]!
+** ...
+*/
+uint8_t* pre_store8_0 (uint8_t * a, uint8x16_t v)
+{
+ a -= 16;
+ vst1q_u8 (a, v);
+ return a;
+}
+
+/*
+**pre_store8_1:
+** ...
+** vstrb.16 q[0-9]+, \[r0, #4\]!
+** ...
+*/
+int8_t* pre_store8_1 (int8_t * a, int16x8_t v)
+{
+ a += 4;
+ vstrbq_s16 (a, v);
+ return a;
+}
+
+/*
+**pre_storefp16_0:
+** ...
+** vstrh.16 q0, \[r0, #8\]!
+** ...
+*/
+float16_t *pre_storefp16_0 (float16_t *a, float16x8_t v)
+{
+ a += 4;
+ vst1q_f16 (a, v);
+ return a;
+}
+
+/*
+**pre_store16_0:
+** ...
+** vstrh.16 q[0-9]+, \[r0, #254\]!
+** ...
+*/
+uint16_t* pre_store16_0 (uint16_t * a, uint16x8_t v)
+{
+ a += 127;
+ vstrhq_u16 (a, v);
+ return a;
+}
+
+/*
+**pre_store16_1:
+** ...
+** vstrh.32 q[0-9]+, \[r0, #-52\]!
+** ...
+*/
+int16_t* pre_store16_1 (int16_t * a, int32x4_t v)
+{
+ a -= 26;
+ vstrhq_s32 (a, v);
+ return a;
+}
+
+/*
+**pre_storefp32_0:
+** ...
+** vstrw.32 q0, \[r0, #-4\]!
+** ...
+*/
+float32_t *pre_storefp32_0 (float32_t *a, float32x4_t v)
+{
+ a--;
+ vst1q_f32 (a, v);
+ return a;
+}
+
+/*
+**pre_store32_0:
+** ...
+** vstrw.32 q[0-9]+, \[r0, #4\]!
+** ...
+*/
+int32_t* pre_store32_0 (int32_t * a, int32x4_t v)
+{
+ a += 1;
+ vst1q_s32 (a, v);
+ return a;
+}
+
+
+/*
+**post_store8_0:
+** ...
+** vstrb.8 q[0-9]+, \[r0\], #-26
+** ...
+*/
+int8_t* post_store8_0 (int8_t * a, int8x16_t v)
+{
+ vst1q_s8 (a, v);
+ a -= 26;
+ return a;
+}
+
+/*
+**post_store8_1:
+** ...
+** vstrb.16 q[0-9]+, \[r0\], #1
+** ...
+*/
+uint8_t* post_store8_1 (uint8_t * a, uint16x8_t v)
+{
+ vstrbq_u16 (a, v);
+ a++;
+ return a;
+}
+
+/*
+**post_store8_2:
+** ...
+** vstrb.8 q[0-9]+, \[r0\], #-26
+** ...
+*/
+int8_t* post_store8_2 (int8_t * a, int8x16_t v)
+{
+ vst1q_s8 (a, v);
+ a -= 26;
+ return a;
+}
+
+/*
+**post_store8_3:
+** ...
+** vstrb.16 q[0-9]+, \[r0\], #7
+** ...
+*/
+uint8_t* post_store8_3 (uint8_t * a, uint16x8_t v)
+{
+ vstrbq_u16 (a, v);
+ a += 7;
+ return a;
+}
+
+/*
+**post_storefp16_0:
+** ...
+** vstrh.16 q[0-9]+, \[r0\], #-16
+** ...
+*/
+float16_t *post_storefp16_0 (float16_t *a, float16x8_t v)
+{
+ vst1q_f16 (a, v);
+ a -= 8;
+ return a;
+}
+
+/*
+**post_store16_0:
+** ...
+** vstrh.16 q[0-9]+, \[r0\], #126
+** ...
+*/
+int16_t* post_store16_0 (int16_t * a, int16x8_t v)
+{
+ vstrhq_s16 (a, v);
+ a += 63;
+ return a;
+}
+
+/*
+**post_store16_1:
+** ...
+** vstrh.32 q[0-9]+, \[r0\], #-16
+** ...
+*/
+uint16_t* post_store16_1 (uint16_t * a, uint32x4_t v)
+{
+ vstrhq_u32 (a, v);
+ a -= 8;
+ return a;
+}
+
+/*
+**post_storefp32_0:
+** ...
+** vstrw.32 q[0-9]+, \[r0\], #-16
+** ...
+*/
+float32_t* post_storefp32_0 (float32_t * a, float32x4_t v)
+{
+ vst1q_f32 (a, v);
+ a -= 4;
+ return a;
+}
+
+/*
+**post_store32_0:
+** ...
+** vstrw.32 q[0-9]+, \[r0\], #16
+** ...
+*/
+int32_t* post_store32_0 (int32_t * a, int32x4_t v)
+{
+ vst1q_s32 (a, v);
+ a += 4;
+ return a;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr51534.c b/gcc/testsuite/gcc.target/arm/pr51534.c
index ac7f1ea..5e121f5 100644
--- a/gcc/testsuite/gcc.target/arm/pr51534.c
+++ b/gcc/testsuite/gcc.target/arm/pr51534.c
@@ -64,8 +64,9 @@ GEN_COND_TESTS(vceq)
/* { dg-final { scan-assembler-times "vceq\.i8\[ \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" 4 } } */
/* { dg-final { scan-assembler-times "vceq\.i16\[ \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" 4 } } */
/* { dg-final { scan-assembler-times "vceq\.i32\[ \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" 4 } } */
-/* { dg-final { scan-assembler-times "vmov\.i32\[ \]+\[dD\]\[0-9\]+, #0xffffffff" 3 } } */
-/* { dg-final { scan-assembler-times "vmov\.i32\[ \]+\[qQ\]\[0-9\]+, #4294967295" 3 } } */
+/* { dg-final { scan-assembler-times "vmov\.i32\[ \]+\[dD\]\[0-9\]+, #0xffffffff" 3 { target { arm_hard_ok } } } } */
+/* { dg-final { scan-assembler-times "vmov\.i32\[ \]+\[qQ\]\[0-9\]+, #4294967295" 3 { target { arm_hard_ok } } } } */
+/* { dg-final { scan-assembler-times "mov\[ \]+r\[0-9\]+, #-1" 6 { target { arm_softfp_ok } } } } */
/* And ensure we don't have unexpected output too. */
/* { dg-final { scan-assembler-not "vc\[gl\]\[te\]\.u\[0-9\]+\[ \]+\[qQdD\]\[0-9\]+, \[qQdD\]\[0-9\]+, #0" } } */
diff --git a/gcc/testsuite/gcc.target/bfin/ones.c b/gcc/testsuite/gcc.target/bfin/ones.c
new file mode 100644
index 0000000..cdffe84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/ones.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short foo ()
+{
+ int t = 5;
+ short r = __builtin_bfin_ones(t);
+ return r;
+}
+
+/* { dg-final { scan-assembler-not "ONES" } } */
diff --git a/gcc/testsuite/gcc.target/bfin/parity.c b/gcc/testsuite/gcc.target/bfin/parity.c
new file mode 100644
index 0000000..6490b7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/parity.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int foo(int x)
+{
+ return __builtin_parity(x);
+}
+
+/* { dg-final { scan-assembler "ONES" } } */
diff --git a/gcc/testsuite/gcc.target/bfin/popcount.c b/gcc/testsuite/gcc.target/bfin/popcount.c
new file mode 100644
index 0000000..51c19be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/popcount.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int foo(int x)
+{
+ return __builtin_popcount(x);
+}
+
+/* { dg-final { scan-assembler "ONES" } } */
diff --git a/gcc/testsuite/gcc.target/bfin/ssabs.c b/gcc/testsuite/gcc.target/bfin/ssabs.c
new file mode 100644
index 0000000..e9d8bae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/ssabs.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int foo()
+{
+ int t = -2147483648;
+ int r = __builtin_bfin_abs_fr1x32(t);
+ return r;
+}
+
+/* { dg-final { scan-assembler "32767" } } */
diff --git a/gcc/testsuite/gcc.target/bfin/ssneg.c b/gcc/testsuite/gcc.target/bfin/ssneg.c
new file mode 100644
index 0000000..44ad7ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/ssneg.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short foo()
+{
+ short t = -32768;
+ short r = __builtin_bfin_negate_fr1x16(t);
+ return r;
+}
+
+/* { dg-final { scan-assembler "32767" } } */
diff --git a/gcc/testsuite/gcc.target/bpf/alu-1.c b/gcc/testsuite/gcc.target/bpf/alu-1.c
new file mode 100644
index 0000000..9814930
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/alu-1.c
@@ -0,0 +1,56 @@
+/* Ensure 32-bit ALU instructions are not generated if -malu32 is
+ not enabled. */
+
+/* { dg-do compile } */
+/* { dg-options "-mno-alu32" } */
+
+int foo (int a, int b)
+{
+ a += 1;
+ b += a;
+ b -= 5;
+ a -= a;
+
+ a *= 2;
+ b *= a;
+
+ a |= 0xfafa;
+ b |= a;
+ b &= 0x00ffff00;
+ b &= a;
+
+ a <<= 2;
+ b <<= a;
+ b >>= 5;
+ a >>= b;
+
+ int c = a;
+ int d = 5;
+
+ d ^= a;
+ c ^= 0xe5e5e5e5;
+ c = -c;
+
+ unsigned int x = a;
+ unsigned int y = b;
+ x /= 3;
+ y /= x;
+ x %= 4;
+ y %= x;
+
+ return a + b - c + d - x + y;
+}
+
+/* { dg-final { scan-assembler-times "mov32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "add32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "sub32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "mul32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "div32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "mod32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "neg32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "and32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "or32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "xor32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "rsh32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "lsh32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "arsh32\t0" 0 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-1.c b/gcc/testsuite/gcc.target/bpf/core-attr-1.c
new file mode 100644
index 0000000..1af9dc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-1.c
@@ -0,0 +1,23 @@
+/* Basic test for struct __attribute__((preserve_access_index))
+ for BPF CO-RE support. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ int a;
+ int b;
+ int c;
+} __attribute__((preserve_access_index));
+
+void
+func (struct S * s)
+{
+ /* 0:2 */
+ int *x = &(s->c);
+
+ *x = 4;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-2.c b/gcc/testsuite/gcc.target/bpf/core-attr-2.c
new file mode 100644
index 0000000..25c819a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-2.c
@@ -0,0 +1,21 @@
+/* Basic test for union __attribute__((preserve_access_index))
+ for BPF CO-RE support. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+union U {
+ int a;
+ char c;
+} __attribute__((preserve_access_index));
+
+void
+func (union U *u)
+{
+ /* 0:1 */
+ char *c = &(u->c);
+ *c = 'c';
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-3.c b/gcc/testsuite/gcc.target/bpf/core-attr-3.c
new file mode 100644
index 0000000..b46549f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-3.c
@@ -0,0 +1,41 @@
+/* Test for __attribute__((preserve_access_index)) for BPF CO-RE support
+ for nested structure.
+
+ Note that even though struct O lacks the attribute, when accessed as a
+ member of another attributed type, CO-RE relocations should still be
+ generated. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct O {
+ int e;
+ int f;
+};
+
+struct S {
+ int a;
+ struct {
+ int b;
+ int c;
+ } inner;
+ struct O other;
+} __attribute__((preserve_access_index));
+
+void
+func (struct S *foo)
+{
+ /* 0:1:1 */
+ int *x = &(foo->inner.c);
+
+ /* 0:2:0 */
+ int *y = &(foo->other.e);
+
+ *x = 4;
+ *y = 5;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-4.c b/gcc/testsuite/gcc.target/bpf/core-attr-4.c
new file mode 100644
index 0000000..9c0f966
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-4.c
@@ -0,0 +1,35 @@
+/* Test for BPF CO-RE __attribute__((preserve_access_index)) with accesses on
+ LHS and both LHS and RHS of assignment. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct T {
+ int a;
+ int b;
+ struct U {
+ int c;
+ struct V {
+ int d;
+ int e[4];
+ int f;
+ } v;
+ } u;
+} __attribute__((preserve_access_index));
+
+
+void
+func (struct T *t)
+{
+ /* 0:2:1:1:3 */
+ t->u.v.e[3] = 0xa1;
+
+ /* 0:2:0, 0:0, 0:1 */
+ t->u.c = t->a + t->b;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 4 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-1.c
new file mode 100644
index 0000000..e994dc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-1.c
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ int a;
+ int b;
+ char c;
+};
+
+union U {
+ unsigned int u;
+ int i;
+ unsigned char uc[4];
+ signed char ic[4];
+};
+
+struct S my_s;
+union U my_u;
+
+unsigned long ula[8];
+
+#define _(x) (__builtin_preserve_access_index (x))
+
+void
+func (void)
+{
+ /* 1 */
+ int b = _(my_s.b);
+
+ /* 2 */
+ char c = _(my_s.c);
+
+ /* 2:3 */
+ unsigned char uc = _(my_u.uc[3]);
+
+ /* 6 */
+ unsigned long ul = _(ula[6]);
+}
+
+char
+s_ptr (struct S *ps)
+{
+ /* 0:2 */
+ char x = _(ps->c);
+ return x;
+}
+
+unsigned char
+u_ptr (union U *pu)
+{
+ /* 0:2:3 */
+ unsigned char x = _(pu->uc[3]);
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"2:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"6.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "bpfcr_type" 6 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x6c\[\t \]+\[^\n\]*core_relo_len" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-2.c
new file mode 100644
index 0000000..c9ec899
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ int a;
+ union {
+ int _unused;
+ int b;
+ char c;
+ } u[4];
+};
+
+struct S foo;
+
+#define _(x) (__builtin_preserve_access_index (x))
+
+void func (void)
+{
+ char *x = __builtin_preserve_access_index (&foo.u[3].c);
+
+ *x = 's';
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]0x4000002\[\t \]+\[^\n\]*btt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"1:3:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-3.c b/gcc/testsuite/gcc.target/bpf/core-builtin-3.c
new file mode 100644
index 0000000..190ec26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct T {
+ int a;
+ int b;
+ struct U {
+ int c;
+ struct V {
+ int d;
+ int e[4];
+ int f;
+ } v;
+ } u;
+};
+
+void func (struct T * foo)
+{
+ /* Access string: "0:2:1:1:3" */
+ int *x = __builtin_preserve_access_index (&(foo->u.v.e[3]));
+
+ *x = 17;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-lto-1.c b/gcc/testsuite/gcc.target/bpf/core-lto-1.c
new file mode 100644
index 0000000..927de23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-lto-1.c
@@ -0,0 +1,9 @@
+/* Test -mco-re with -flto.
+
+ -mco-re is used to generate information for BPF CO-RE usecase. To support
+ the generataion of the .BTF and .BTF.ext sections in GCC, -flto is disabled
+ with -mco-re. */
+
+/* { dg-do compile } */
+/* { dg-message "sorry, unimplemented: BPF CO-RE does not support LTO" "" { target bpf-*-* } 0 } */
+/* { dg-options "-gbtf -mco-re -flto" } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-section-1.c b/gcc/testsuite/gcc.target/bpf/core-section-1.c
new file mode 100644
index 0000000..031acd5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-section-1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA -mco-re" } */
+
+struct T {
+ int a;
+ int b;
+ struct U {
+ int c;
+ struct V {
+ int d;
+ int e[4];
+ int f;
+ } v;
+ } u;
+};
+
+__attribute__((section("foo_sec"), used))
+int foo_func (struct T *t)
+{
+ t->u.c = 5;
+ return __builtin_preserve_access_index (t->u.v.e[3]);
+}
+
+__attribute__((section("bar_sec"), used))
+int bar_func (struct T *t)
+{
+ int *x = __builtin_preserve_access_index (&(t->u.v.f));
+ int old = *x;
+ *x = 4;
+ return old;
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:1:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */
+/* { dg-final { scan-assembler-times "btfext_secinfo_rec_size" 2 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/jmp-1.c b/gcc/testsuite/gcc.target/bpf/jmp-1.c
new file mode 100644
index 0000000..eaf8253
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/jmp-1.c
@@ -0,0 +1,57 @@
+/* Ensure jlt, jslt, jle and jsle instructions are not generated if
+ -mjmpext is not enabled, and no 32-bit jump instructions are generated
+ if -mjmp32 is not enabled. */
+
+/* { dg-do compile } */
+/* { dg-options "-mno-jmpext -mno-jmp32" } */
+
+int foo (int a, int b)
+{
+ if (a == 1)
+ b += 1;
+ if (a != 3)
+ b += 2;
+ if (a > 5)
+ b += 3;
+ if (a >= 7)
+ b += 4;
+ if (a < 9)
+ b += 5;
+ if (a <= 10)
+ b += 6;
+
+ return a + b;
+}
+
+unsigned int bar (unsigned int a, unsigned int b)
+{
+ if (a == 1)
+ b += 1;
+ if (a != 3)
+ b += 2;
+ if (a > 5)
+ b += 3;
+ if (a >= 7)
+ b += 4;
+ if (a < 9)
+ b += 5;
+ if (a <= 10)
+ b += 6;
+
+ return a + b;
+}
+
+/* { dg-final { scan-assembler-times "jlt\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jslt\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jle\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jsle\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jeq32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jne32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jlt32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jgt32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jle32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jge32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jslt32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jsgt32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jsle32\t0" 0 } } */
+/* { dg-final { scan-assembler-times "jsge32\t0" 0 } } */
diff --git a/gcc/testsuite/gcc.target/i386/387-12.c b/gcc/testsuite/gcc.target/i386/387-12.c
index 62c1d48..7fe50a2 100644
--- a/gcc/testsuite/gcc.target/i386/387-12.c
+++ b/gcc/testsuite/gcc.target/i386/387-12.c
@@ -1,6 +1,6 @@
/* PR target/26915 */
/* { dg-do compile } */
-/* { dg-options "-O -mfpmath=387 -mfancy-math-387" } */
+/* { dg-options "-O -m32 -mfpmath=387 -mfancy-math-387" } */
double testm0(void)
{
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-2.c b/gcc/testsuite/gcc.target/i386/addr-space-2.c
index d5c24b6..9744368 100644
--- a/gcc/testsuite/gcc.target/i386/addr-space-2.c
+++ b/gcc/testsuite/gcc.target/i386/addr-space-2.c
@@ -1,10 +1,11 @@
/* { dg-do compile } */
-/* { dg-options "-O" } */
+/* { dg-options "-O -Wall" } */
/* { dg-final { scan-assembler "fs:16" } } */
/* { dg-final { scan-assembler "gs:16" } } */
int test(void)
{
+ /* Also verify the accesses don't trigger warnings. */
int __seg_fs *f = (int __seg_fs *)16;
int __seg_gs *g = (int __seg_gs *)16;
return *f + *g;
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-3.c b/gcc/testsuite/gcc.target/i386/addr-space-3.c
new file mode 100644
index 0000000..cf0f400
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/addr-space-3.c
@@ -0,0 +1,17 @@
+/* PR middle-end/102630 - Spurious -Warray-bounds with named address space
+ { dg-do compile }
+ { dg-options "-O -Wall" }
+ { dg-final { scan-assembler "fs:0" } }
+ { dg-final { scan-assembler "gs:0" } } */
+
+void test_fs_null_store (void)
+{
+ int __seg_fs *fs = (int __seg_fs *)0;
+ *fs = 1;
+}
+
+void test_gs_null_store (void)
+{
+ int __seg_gs *gs = (int __seg_gs *)0;
+ *gs = 2;
+}
diff --git a/gcc/testsuite/gcc.target/i386/attr-optimize.c b/gcc/testsuite/gcc.target/i386/attr-optimize.c
new file mode 100644
index 0000000..f5db028f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/attr-optimize.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1 -ftree-slp-vectorize -march=znver1 -fdump-tree-optimized" } */
+
+/* Use -O2, but -ftree-slp-vectorize option should be preserved and used. */
+#pragma GCC optimize "-O2"
+
+typedef struct {
+ long n[4];
+} secp256k1_fe;
+
+void *a;
+int c;
+static void
+fn1(secp256k1_fe *p1, int p2)
+{
+ p1->n[0] = p1->n[1] = p2;
+}
+void
+fn2()
+{
+ fn1(a, !c);
+}
+
+/* { dg-final { scan-tree-dump { MEM <vector\(2\) long int> \[[^]]*\] = } "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-1.c b/gcc/testsuite/gcc.target/i386/auto-init-1.c
new file mode 100644
index 0000000..3391be1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -fno-stack-protector -march=x86-64 -mtune=generic" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 10 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-2.c b/gcc/testsuite/gcc.target/i386/auto-init-2.c
new file mode 100644
index 0000000..e22930a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-2.c
@@ -0,0 +1,37 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" { target lp64 } } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 3 "expand" { target lp64 } } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 4 "expand" { target { ! lp64 } } } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 1 "expand" { target { ! lp64 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-21.c b/gcc/testsuite/gcc.target/i386/auto-init-21.c
new file mode 100644
index 0000000..1192a90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-21.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-22.c b/gcc/testsuite/gcc.target/i386/auto-init-22.c
new file mode 100644
index 0000000..431d966
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-22.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-23.c b/gcc/testsuite/gcc.target/i386/auto-init-23.c
new file mode 100644
index 0000000..72094f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-23.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+void g(void *);
+
+void foo(int a)
+{
+ int x[a][a];
+ g(x);
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-24.c b/gcc/testsuite/gcc.target/i386/auto-init-24.c
new file mode 100644
index 0000000..5cc3a75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-24.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+void g(void *);
+
+void foo(int a)
+{
+ int x[a][a];
+ g(x);
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-3.c b/gcc/testsuite/gcc.target/i386/auto-init-3.c
new file mode 100644
index 0000000..891eab1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -march=x86-64 -mtune=generic -msse" } */
+/* { dg-additional-options "-mfpmath=387" { target ia32 } } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times "pxor\t\\\%xmm0, \\\%xmm0" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "fldz" 3 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-4.c b/gcc/testsuite/gcc.target/i386/auto-init-4.c
new file mode 100644
index 0000000..7b46c74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-4.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" { target { ! ia32 } } } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" { target { ! ia32 } } } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" { target { ! ia32 } } } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" { target ia32 } } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 2 "expand" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-5.c b/gcc/testsuite/gcc.target/i386/auto-init-5.c
new file mode 100644
index 0000000..0e9d74f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-5.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times "\\.long\t0" 14 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "\\.long\t0" 12 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-6.c b/gcc/testsuite/gcc.target/i386/auto-init-6.c
new file mode 100644
index 0000000..f75081e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-6.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-7.c b/gcc/testsuite/gcc.target/i386/auto-init-7.c
new file mode 100644
index 0000000..7e32576
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-7.c
@@ -0,0 +1,33 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -march=x86-64 -mtune=generic -fno-stack-protector -msse" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)\\\)" 3 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-8.c b/gcc/testsuite/gcc.target/i386/auto-init-8.c
new file mode 100644
index 0000000..666ee14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-8.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 2 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c
new file mode 100644
index 0000000..149a04f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c
new file mode 100644
index 0000000..1125bcf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c
new file mode 100644
index 0000000..4f90ad2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c
@@ -0,0 +1,26 @@
+/* Verify zero initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c
new file mode 100644
index 0000000..21a1ee2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c
@@ -0,0 +1,26 @@
+/* Verify pattern initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c
new file mode 100644
index 0000000..483b79a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
new file mode 100644
index 0000000..7c20a28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
@@ -0,0 +1,30 @@
+/* Verify zero initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -march=x86-64" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$16," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "rep stosq" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\t\\\$32," { target ia32 } } } */
+/* { dg-final { scan-assembler "rep stosl" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c
new file mode 100644
index 0000000..2908b3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c
@@ -0,0 +1,28 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c
new file mode 100644
index 0000000..e17a621
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c
new file mode 100644
index 0000000..754f8af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
new file mode 100644
index 0000000..c3823de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand -march=x86-64 -mtune=generic -msse -fno-stack-protector" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" { target ia32 } } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
new file mode 100644
index 0000000..4f45755
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand -march=x86-64 -mtune=generic -msse -fno-stack-protector" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\) repeated x16" 1 "expand" { target ia32 } } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0 \\\[0\\\]\\\)" 1 "expand" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
new file mode 100644
index 0000000..a87b68b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
@@ -0,0 +1,25 @@
+/* Verify zero initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -march=x86-64" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$20," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "rep stosq" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\t\\\$40," { target ia32} } } */
+/* { dg-final { scan-assembler "rep stosl" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-1.c b/gcc/testsuite/gcc.target/i386/avx-1.c
index 6178e38..154e7b3 100644
--- a/gcc/testsuite/gcc.target/i386/avx-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mavx2 -maes -mpclmul -mgfni -mavx512bw" } */
+/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mavx2 -maes -mpclmul -mgfni -mavx512bw -mavx512fp16 -mavx512vl" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
@@ -685,6 +685,141 @@
#define __builtin_ia32_vpshld_v2di(A, B, C) __builtin_ia32_vpshld_v2di(A, B, 1)
#define __builtin_ia32_vpshld_v2di_mask(A, B, C, D, E) __builtin_ia32_vpshld_v2di_mask(A, B, 1, D, E)
+/* avx512fp16intrin.h */
+#define __builtin_ia32_addph512_mask_round(A, B, C, D, E) __builtin_ia32_addph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subph512_mask_round(A, B, C, D, E) __builtin_ia32_subph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulph512_mask_round(A, B, C, D, E) __builtin_ia32_mulph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divph512_mask_round(A, B, C, D, E) __builtin_ia32_divph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_addsh_mask_round(A, B, C, D, E) __builtin_ia32_addsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subsh_mask_round(A, B, C, D, E) __builtin_ia32_subsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulsh_mask_round(A, B, C, D, E) __builtin_ia32_mulsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divsh_mask_round(A, B, C, D, E) __builtin_ia32_divsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxph512_mask_round(A, B, C, D, E) __builtin_ia32_maxph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minph512_mask_round(A, B, C, D, E) __builtin_ia32_minph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxsh_mask_round(A, B, C, D, E) __builtin_ia32_maxsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minsh_mask_round(A, B, C, D, E) __builtin_ia32_minsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_cmpph512_mask(A, B, C, D) __builtin_ia32_cmpph512_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph512_mask_round(A, B, C, D, E) __builtin_ia32_cmpph512_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_cmpsh_mask_round(A, B, C, D, E) __builtin_ia32_cmpsh_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_sqrtph512_mask_round(C, A, B, D) __builtin_ia32_sqrtph512_mask_round(C, A, B, 8)
+#define __builtin_ia32_sqrtsh_mask_round(D, C, A, B, E) __builtin_ia32_sqrtsh_mask_round(D, C, A, B, 8)
+#define __builtin_ia32_scalefph512_mask_round(A, B, C, D, E) __builtin_ia32_scalefph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_scalefsh_mask_round(A, B, C, D, E) __builtin_ia32_scalefsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_reduceph512_mask_round(A, B, C, D, E) __builtin_ia32_reduceph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_reduceph128_mask(A, B, C, D) __builtin_ia32_reduceph128_mask(A, 123, C, D)
+#define __builtin_ia32_reduceph256_mask(A, B, C, D) __builtin_ia32_reduceph256_mask(A, 123, C, D)
+#define __builtin_ia32_reducesh_mask_round(A, B, C, D, E, F) __builtin_ia32_reducesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_rndscaleph512_mask_round(A, B, C, D, E) __builtin_ia32_rndscaleph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_rndscaleph128_mask(A, B, C, D) __builtin_ia32_rndscaleph128_mask(A, 123, C, D)
+#define __builtin_ia32_rndscaleph256_mask(A, B, C, D) __builtin_ia32_rndscaleph256_mask(A, 123, C, D)
+#define __builtin_ia32_rndscalesh_mask_round(A, B, C, D, E, F) __builtin_ia32_rndscalesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_fpclassph512_mask(A, D, C) __builtin_ia32_fpclassph512_mask(A, 1, C)
+#define __builtin_ia32_fpclasssh_mask(A, D, U) __builtin_ia32_fpclasssh_mask(A, 1, U)
+#define __builtin_ia32_getexpph512_mask(A, B, C, D) __builtin_ia32_getexpph512_mask(A, B, C, 8)
+#define __builtin_ia32_getexpsh_mask_round(A, B, C, D, E) __builtin_ia32_getexpsh_mask_round(A, B, C, D, 4)
+#define __builtin_ia32_getmantph512_mask(A, F, C, D, E) __builtin_ia32_getmantph512_mask(A, 1, C, D, 8)
+#define __builtin_ia32_getmantsh_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsh_mask_round(A, B, 1, W, U, 4)
+#define __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2si32_round(A, B) __builtin_ia32_vcvtsh2si32_round(A, 8)
+#define __builtin_ia32_vcvtsh2si64_round(A, B) __builtin_ia32_vcvtsh2si64_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi32_round(A, B) __builtin_ia32_vcvtsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi64_round(A, B) __builtin_ia32_vcvtsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvttsh2si32_round(A, B) __builtin_ia32_vcvttsh2si32_round(A, 8)
+#define __builtin_ia32_vcvttsh2si64_round(A, B) __builtin_ia32_vcvttsh2si64_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi32_round(A, B) __builtin_ia32_vcvttsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi64_round(A, B) __builtin_ia32_vcvttsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvtsi2sh32_round(A, B, C) __builtin_ia32_vcvtsi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtsi2sh64_round(A, B, C) __builtin_ia32_vcvtsi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh32_round(A, B, C) __builtin_ia32_vcvtusi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh64_round(A, B, C) __builtin_ia32_vcvtusi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, D) __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
+
+/* avx512fp16vlintrin.h */
+#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph256_mask(A, B, C, D) __builtin_ia32_cmpph256_mask(A, B, 1, D)
+#define __builtin_ia32_fpclassph256_mask(A, D, C) __builtin_ia32_fpclassph256_mask(A, 1, C)
+#define __builtin_ia32_fpclassph128_mask(A, D, C) __builtin_ia32_fpclassph128_mask(A, 1, C)
+#define __builtin_ia32_getmantph256_mask(A, E, C, D) __builtin_ia32_getmantph256_mask(A, 1, C, D)
+#define __builtin_ia32_getmantph128_mask(A, E, C, D) __builtin_ia32_getmantph128_mask(A, 1, C, D)
+
/* vpclmulqdqintrin.h */
#define __builtin_ia32_vpclmulqdq_v4di(A, B, C) __builtin_ia32_vpclmulqdq_v4di(A, B, 1)
#define __builtin_ia32_vpclmulqdq_v2di(A, B, C) __builtin_ia32_vpclmulqdq_v2di(A, B, 1)
diff --git a/gcc/testsuite/gcc.target/i386/avx-2.c b/gcc/testsuite/gcc.target/i386/avx-2.c
index 986fbd8..642ae4d 100644
--- a/gcc/testsuite/gcc.target/i386/avx-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mavx2 -msse4a -maes -mpclmul -mavx512bw" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mavx2 -msse4a -maes -mpclmul -mavx512bw -mavx512fp16 -mavx512vl" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx-covert-1.c b/gcc/testsuite/gcc.target/i386/avx-covert-1.c
new file mode 100644
index 0000000..b6c794e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-covert-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency,^sse_partial_reg_converts_dependency" } */
+
+extern float f;
+extern double d;
+extern int i;
+
+void
+foo (void)
+{
+ d = f;
+ f = i;
+}
+
+/* { dg-final { scan-assembler "vcvtss2sd" } } */
+/* { dg-final { scan-assembler "vcvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "vcvtps2pd" } } */
+/* { dg-final { scan-assembler-not "vcvtdq2ps" } } */
+/* { dg-final { scan-assembler-not "vxorps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-fp-covert-1.c b/gcc/testsuite/gcc.target/i386/avx-fp-covert-1.c
new file mode 100644
index 0000000..c40c48b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-fp-covert-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency" } */
+
+extern float f;
+extern double d;
+
+void
+foo (void)
+{
+ d = f;
+}
+
+/* { dg-final { scan-assembler "vcvtss2sd" } } */
+/* { dg-final { scan-assembler-not "vcvtps2pd" } } */
+/* { dg-final { scan-assembler-not "vxorps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-int-covert-1.c b/gcc/testsuite/gcc.target/i386/avx-int-covert-1.c
new file mode 100644
index 0000000..01bb64e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-int-covert-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=^sse_partial_reg_converts_dependency" } */
+
+extern float f;
+extern int i;
+
+void
+foo (void)
+{
+ f = i;
+}
+
+/* { dg-final { scan-assembler "vcvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "vxorps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-pr102224.c b/gcc/testsuite/gcc.target/i386/avx-pr102224.c
new file mode 100644
index 0000000..7cb8b4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-pr102224.c
@@ -0,0 +1,23 @@
+/* PR target/102224 */
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx" } */
+/* { dg-require-effective-target avx } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#define main main1
+#include "../../gcc.dg/pr102224.c"
+#undef main
+
+#include CHECK_H
+
+static void
+TEST (void)
+{
+ main1 ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-pr89984.c b/gcc/testsuite/gcc.target/i386/avx-pr89984.c
new file mode 100644
index 0000000..3409ade
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-pr89984.c
@@ -0,0 +1,23 @@
+/* PR target/89984 */
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx" } */
+/* { dg-require-effective-target avx } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#define main main1
+#include "../../gcc.dg/pr89984.c"
+#undef main
+
+#include CHECK_H
+
+static void
+TEST (void)
+{
+ main1 ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c b/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c
index 989ba40..6a47a09 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c
@@ -78,4 +78,4 @@ avx2_test (void)
abort ();
}
-/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 6 "vect" } } */
+/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 10 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512-check.h b/gcc/testsuite/gcc.target/i386/avx512-check.h
index 0a377db..0ad9064 100644
--- a/gcc/testsuite/gcc.target/i386/avx512-check.h
+++ b/gcc/testsuite/gcc.target/i386/avx512-check.h
@@ -87,6 +87,9 @@ main ()
#ifdef AVX512VNNI
&& (ecx & bit_AVX512VNNI)
#endif
+#ifdef AVX512FP16
+ && (edx & bit_AVX512FP16)
+#endif
#ifdef VAES
&& (ecx & bit_VAES)
#endif
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqb-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqb-1.c
index 506fcf9d..11a6007 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqb-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqb-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqw-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqw-1.c
index 1b2670b..5cf8198 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqw-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpeqw-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtb-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtb-1.c
index e4014b3..bc7e8b1 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtb-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtb-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtb\[ \\t\]+|vpcmpb\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtw-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtw-1.c
index 37e8d32..02999e0 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtw-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpcmpgtw-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtw\[ \\t\]+|vpcmpw\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-abs-copysign-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-abs-copysign-1.c
index cb542d0..0107df7 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-abs-copysign-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-abs-copysign-1.c
@@ -64,8 +64,8 @@ f6 (double x)
}
/* { dg-final { scan-assembler "vandps\[^\n\r\]*xmm16" } } */
-/* { dg-final { scan-assembler "vorps\[^\n\r\]*xmm16" } } */
+/* { dg-final { scan-assembler "vpternlogd\[^\n\r\]*xmm16" } } */
/* { dg-final { scan-assembler "vxorps\[^\n\r\]*xmm16" } } */
/* { dg-final { scan-assembler "vandpd\[^\n\r\]*xmm18" } } */
-/* { dg-final { scan-assembler "vorpd\[^\n\r\]*xmm18" } } */
+/* { dg-final { scan-assembler "vpternlogq\[^\n\r\]*xmm18" } } */
/* { dg-final { scan-assembler "vxorpd\[^\n\r\]*xmm18" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
index 1ba8172..40aefb5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-3.c
@@ -8,7 +8,7 @@
#define MAX 1000
#define EPS 0.00001
-__attribute__ ((noinline, optimize (1)))
+__attribute__ ((noinline, optimize (1, "-fno-fast-math")))
void static
compute_rsqrt_ref (float *a, float *r)
{
diff --git a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
index e067a81..498f4d5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
+++ b/gcc/testsuite/gcc.target/i386/avx512er-vrsqrt28ps-5.c
@@ -8,7 +8,7 @@
#define MAX 1000
#define EPS 0.00001
-__attribute__ ((noinline, optimize (1)))
+__attribute__ ((noinline, optimize (1, "-fno-fast-math")))
void static
compute_sqrt_ref (float *a, float *r)
{
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c
new file mode 100644
index 0000000..aef6855
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-rebuild.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mavx512vl -mavx512dq -fno-tree-forwprop" } */
+
+typedef double v2df __attribute__ ((__vector_size__ (16)));
+typedef double v4df __attribute__ ((__vector_size__ (32)));
+
+v2df h (v4df x)
+{
+ v2df xx = { x[2], x[3] };
+ return xx;
+}
+
+v4df f2 (v4df x)
+{
+ v4df xx = { x[0], x[1], x[2], x[3] };
+ return xx;
+}
+
+/* { dg-final { scan-assembler-not "unpck" } } */
+/* { dg-final { scan-assembler-not "valign" } } */
+/* { dg-final { scan-assembler-times "\tv?extract(?:f128|f64x2)\[ \t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqd-1.c
index 4624442..33f4e73 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqd-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqq-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqq-1.c
index 4a6505d..595ba55 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpeqq-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtd-1.c
index 6b4a7ff..d038cfb 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtd-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtq-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtq-1.c
index d3647d4..ce2e41a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpcmpgtq-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-10a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-10a.c
new file mode 100644
index 0000000..f06ffff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-10a.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <immintrin.h>
+
+__m128h
+__attribute__ ((noinline, noclone))
+set_128 (_Float16 x)
+{
+ return _mm_set_sh (x);
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[ \t]\+\[^\n\r]*xmm0" 1 { target { ia32 } } } } */
+/* { dg-final { scan-assembler-times "vmovw\[ \t]\+\[^\n\r]*xmm0" 2 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-10b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-10b.c
new file mode 100644
index 0000000..055edd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-10b.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-10a.c"
+
+union128h u128 = { ESP_FLOAT16, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+
+static void
+do_test (void)
+{
+ __m128h v128 = set_128 (ESP_FLOAT16);
+ union128h a128;
+
+ a128.x = v128;
+ if (check_union128h (a128, u128.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-11a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-11a.c
new file mode 100644
index 0000000..28492fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-11a.c
@@ -0,0 +1,36 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <immintrin.h>
+__m512h
+__attribute__ ((noinline, noclone))
+vadd512 (__m512h a, __m512h b)
+{
+ return a + b;
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+vsub512 (__m512h a, __m512h b)
+{
+ return a - b;
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+vmul512 (__m512h a, __m512h b)
+{
+ return a * b;
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+vdiv512 (__m512h a, __m512h b)
+{
+ return a / b;
+}
+
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\[^\n\r\]*%zmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\[^\n\r\]*%zmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\[^\n\r\]*%zmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\[^\n\r\]*%zmm\[01\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-11b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-11b.c
new file mode 100644
index 0000000..5f51a5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-11b.c
@@ -0,0 +1,75 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mfpmath=sse" } */
+
+#include <string.h>
+#include <stdlib.h>
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-11a.c"
+
+/* Get random float16 between -50.x to 50.x. */
+_Float16
+get_float16_noround()
+{
+ return ((int) (100.0 * rand ()/ (RAND_MAX + 1.0)) - 50)
+ + 0.1f * (int) (10 * rand() / (RAND_MAX + 1.0));
+}
+
+static void
+do_test (void)
+{
+ _Float16 x[32];
+ _Float16 y[32];
+ _Float16 res_add[32];
+ _Float16 res_sub[32];
+ _Float16 res_mul[32];
+ _Float16 res_div[32];
+ for (int i = 0 ; i != 32; i++)
+ {
+ x[i] = get_float16_noround ();
+ y[i] = get_float16_noround ();
+ if (y[i] == 0)
+ y[i] = 1.0f;
+ res_add[i] = x[i] + y[i];
+ res_sub[i] = x[i] - y[i];
+ res_mul[i] = x[i] * y[i];
+ res_div[i] = x[i] / y[i];
+
+ }
+
+ union512h u512 = { x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15],
+ x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23],
+ x[24], x[25], x[26], x[27], x[28], x[29], x[30], x[31] };
+ union512h u512_1 = {y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7],
+ y[8], y[9], y[10], y[11], y[12], y[13], y[14], y[15],
+ y[16], y[17], y[18], y[19], y[20], y[21], y[22], y[23],
+ y[24], y[25], y[26], y[27], y[28], y[29], y[30], y[31] };
+
+ __m512h v512;
+ union512h a512;
+
+ memset (&v512, -1, sizeof (v512));
+ v512 = vadd512 (u512.x, u512_1.x);
+ a512.x = v512;
+ if (check_union512h (a512, res_add))
+ abort ();
+ memset (&v512, -1, sizeof (v512));
+ v512 = vsub512 (u512.x, u512_1.x);
+ a512.x = v512;
+ if (check_union512h (a512, res_sub))
+ abort ();
+ memset (&v512, -1, sizeof (v512));
+ v512 = vmul512 (u512.x, u512_1.x);
+ a512.x = v512;
+ if (check_union512h (a512, res_mul))
+ abort ();
+ memset (&v512, -1, sizeof (v512));
+ v512 = vdiv512 (u512.x, u512_1.x);
+ a512.x = v512;
+ if (check_union512h (a512, res_div))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-12a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-12a.c
new file mode 100644
index 0000000..8888755
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-12a.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+__attribute__ ((noinline, noclone))
+do_max (_Float16 __A, _Float16 __B)
+{
+ return __A > __B ? __A : __B;
+}
+
+_Float16
+__attribute__ ((noinline, noclone))
+do_min (_Float16 __A, _Float16 __B)
+{
+ return __A < __B ? __A : __B;
+}
+
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]" 1 } } */
+/* { dg-final { scan-assembler-not "vmovsh\[ \\t\]" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "vcomish\[ \\t\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-12b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-12b.c
new file mode 100644
index 0000000..c9e23bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-12b.c
@@ -0,0 +1,27 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-12a.c"
+
+static void
+do_test (void)
+{
+ _Float16 x = 0.1f;
+ _Float16 y = -3.2f;
+ _Float16 z;
+
+ z = do_max (x, y);
+ if (z != x)
+ abort ();
+
+ z = do_min (x, y);
+ if (z != y)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-13.c b/gcc/testsuite/gcc.target/i386/avx512fp16-13.c
new file mode 100644
index 0000000..c3bae65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-13.c
@@ -0,0 +1,140 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+#include <immintrin.h>
+void
+__attribute__ ((noinline, noclone))
+store512_ph (void *p, __m512h a)
+{
+ _mm512_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store256_ph (void *p, __m256h a)
+{
+ _mm256_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store_ph (void *p, __m128h a)
+{
+ _mm_store_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+load512_ph (void const *p)
+{
+ return _mm512_load_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+load256_ph (void const *p)
+{
+ return _mm256_load_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+load_ph (void const *p)
+{
+ return _mm_load_ph (p);
+}
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*\\)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+load512u_ph (void const *p)
+{
+ return _mm512_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%zmm\[0-9\]" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+load256u_ph (void const *p)
+{
+ return _mm256_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%ymm\[0-9\]" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+load128u_ph (void const *p)
+{
+ return _mm_loadu_ph (p);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^,\]*,\[^\{\n\]*%xmm\[0-9\]" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store512u_ph (void *p, __m512h a)
+{
+ return _mm512_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%zmm\[0-9\], *\[^,\]*" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+store256u_ph (void *p, __m256h a)
+{
+ return _mm256_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%ymm\[0-9\], *\[^,\]*" 1 } } */
+
+void
+__attribute__ ((noinline, noclone))
+storeu_ph (void *p, __m128h a)
+{
+ return _mm_storeu_ph (p, a);
+}
+
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]*\[^\{\n\]*%xmm\[0-9\], *\[^,\]*" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+abs512_ph (__m512h a)
+{
+ return _mm512_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastd\[^\n\]*%zmm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpandd\[^\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+abs256_ph (__m256h a)
+{
+ return _mm256_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastq\[^\n\]*%ymm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpand\[^\n\]*%ymm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+abs_ph (__m128h a)
+{
+ return _mm_abs_ph (a);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastq\[^\n\]*%xmm\[0-9\]+" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpand\[^\n\]*%xmm\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-14.c b/gcc/testsuite/gcc.target/i386/avx512fp16-14.c
new file mode 100644
index 0000000..5c670ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-14.c
@@ -0,0 +1,85 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512bw" } */
+
+#include <immintrin.h>
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_mask_blend_ph (__mmask32 U, __m512h A, __m512h B )
+{
+ return _mm512_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_permutex2var_ph (__m512h A, __m512i I, __m512h B)
+{
+ return _mm512_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[ti\]2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_permutexvar_ph (__m512i A, __m512h B)
+{
+ return _mm512_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_mask_blend_ph (__mmask16 U, __m256h A, __m256h B )
+{
+ return _mm256_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_permutex2var_ph (__m256h A, __m256i I, __m256h B)
+{
+ return _mm256_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[ti\]2w\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+" 1 { target { ! ia32 } } } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_permutexvar_ph (__m256i A, __m256h B)
+{
+ return _mm256_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_mask_blend_ph (__mmask8 U, __m128h A, __m128h B )
+{
+ return _mm_mask_blend_ph (U, A, B);
+}
+
+/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_permutex2var_ph (__m128h A, __m128i I, __m128h B)
+{
+ return _mm_permutex2var_ph (A, I, B);
+}
+
+/* { dg-final { scan-assembler-times "vperm\[it\]2w\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_permutexvar_ph (__m128i A, __m128h B)
+{
+ return _mm_permutexvar_ph (A, B);
+}
+
+/* { dg-final { scan-assembler-times "vpermw\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1a.c
new file mode 100644
index 0000000..45c7bdd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 __v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo1 (_Float16 x)
+{
+ return __extension__ (__m128h)(__v8hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo2 (_Float16 *x)
+{
+ return __extension__ (__m128h)(__v8hf) { *x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 2 { target { ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1b.c
new file mode 100644
index 0000000..7560c62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1b.c
@@ -0,0 +1,32 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-1a.c"
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union128h u = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m128h v;
+ union128h a;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union128h (a, u.a))
+ abort ();
+ x = 33.3;
+ u.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union128h (a, u.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c
new file mode 100644
index 0000000..b41a90b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1c.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmovsh" 1 } } */
+/* { dg-final { scan-assembler-times "vpblendw" 1 } } */
+/* { dg-final { scan-assembler "vpbroadcastw" } } */
+
+typedef _Float16 __v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo1 (__m128h a, _Float16 f)
+{
+ __v8hf x = (__v8hf) a;
+ x[2] = f;
+ return (__m128h) x;
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo2 (__m128h a, _Float16 f)
+{
+ __v8hf x = (__v8hf) a;
+ x[0] = f;
+ return (__m128h) x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1d.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1d.c
new file mode 100644
index 0000000..cdaf656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1d.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-1c.c"
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union128h u = { -1.2f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f };
+ __m128h v;
+ union128h a, b;
+ v = foo1 (u.x, x);
+ a.x = v;
+ b = u;
+ b.a[2] = x;
+ if (check_union128h (a, b.a))
+ abort ();
+ x = 33.3;
+ b = u;
+ b.a[0] = x;
+ v = foo2 (u.x, x);
+ a.x = v;
+ if (check_union128h (a, b.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-1e.c b/gcc/testsuite/gcc.target/i386/avx512fp16-1e.c
new file mode 100644
index 0000000..04d33cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-1e.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-1a.c"
+
+__m128h
+__attribute__ ((noinline,noclone))
+foo3 (__m128h x)
+{
+ return foo1(x[0]);
+}
+
+static void
+do_test (void)
+{
+ union128h u = { -1.2f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f };
+ union128h a, b = { -1.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+ __m128h v;
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union128h (a, b.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-2a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-2a.c
new file mode 100644
index 0000000..c03138f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-2a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 __v16hf __attribute__ ((__vector_size__ (32)));
+typedef _Float16 __m256h __attribute__ ((__vector_size__ (32), __may_alias__));
+
+__m256h
+__attribute__ ((noinline, noclone))
+foo1 (_Float16 x)
+{
+ return __extension__ (__m256h)(__v16hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+foo2 (_Float16 *x)
+{
+ return __extension__ (__m256h)(__v16hf) { *x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 2 { target { ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-2b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-2b.c
new file mode 100644
index 0000000..100afd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-2b.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-2a.c"
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union256h u = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m256h v;
+ union256h a;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union256h (a, u.a))
+ abort ();
+ x = 33.3;
+ u.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union256h (a, u.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-2c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-2c.c
new file mode 100644
index 0000000..cf4b42a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-2c.c
@@ -0,0 +1,36 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-2a.c"
+
+__m256h
+__attribute__ ((noinline,noclone))
+foo3 (__m256h x)
+{
+ return foo1(x[0]);
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union256h u = { x, 3.5f, -5.9f, 0.0f, 0.0f, 0.0f, 7.7f, 0.0f,
+ 4.0f, -4.20f, 0.0f, 0.0f, 0.0f, -8.7f, 0.0f, 0.0f };
+
+ union256h exp = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m256h v;
+ union256h a;
+ memset (&v, -1, sizeof (v));
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union256h (a, exp.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-3a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-3a.c
new file mode 100644
index 0000000..126e7d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-3a.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 __v32hf __attribute__ ((__vector_size__ (64)));
+typedef _Float16 __m512h __attribute__ ((__vector_size__ (64), __may_alias__));
+
+__m512h
+__attribute__ ((noinline, noclone))
+foo1 (_Float16 x)
+{
+ return __extension__ (__m512h)(__v32hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+foo2 (_Float16 *x)
+{
+ return __extension__ (__m512h)(__v32hf) { *x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vmovw\[^\n\r]*xmm0" 2 { target { ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-3b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-3b.c
new file mode 100644
index 0000000..291db06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-3b.c
@@ -0,0 +1,35 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-3a.c"
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union512h u = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m512h v;
+ union512h a;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union512h (a, u.a))
+ abort ();
+ x = 33.3;
+ u.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union512h (a, u.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-3c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-3c.c
new file mode 100644
index 0000000..21f9e16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-3c.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-3a.c"
+
+__m512h
+__attribute__ ((noinline,noclone))
+foo3 (__m512h x)
+{
+ return foo1(x[0]);
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union512h u = { x, 3.5f, -5.9f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 2.0f, -2.3f, 0.0f, 0.0f, 10.4f, 0.0f, 0.0f, 0.0f,
+ 3.0f, -3.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 4.0f, -4.20f, 0.0f, 0.0f, 0.0f, -8.7f, 0.0f, 0.0f };
+
+ union512h exp = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m512h v;
+ union512h a;
+ memset (&v, -1, sizeof (v));
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union512h (a, exp.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-4.c b/gcc/testsuite/gcc.target/i386/avx512fp16-4.c
new file mode 100644
index 0000000..1329a04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-4.c
@@ -0,0 +1,31 @@
+/* { dg-do assemble { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 __m256h __attribute__ ((__vector_size__ (32), __may_alias__));
+typedef _Float16 __m512h __attribute__ ((__vector_size__ (64), __may_alias__));
+typedef _Float16 __m128h __attribute__ ((__vector_size__ (16), __may_alias__));
+
+extern __m128h x128, y128;
+extern __m256h x256, y256;
+extern __m512h x512, y512;
+
+__m128h
+foo1 (float f1, __m128h f2)
+{
+ x128 = y128;
+ return f2;
+}
+
+__m256h
+foo2 (float f1, __m256h f2)
+{
+ x256 = y256;
+ return f2;
+}
+
+__m512h
+foo3 (float f1, __m512h f2)
+{
+ x512 = y512;
+ return f2;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-5.c b/gcc/testsuite/gcc.target/i386/avx512fp16-5.c
new file mode 100644
index 0000000..d28b965
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-5.c
@@ -0,0 +1,133 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo1 (_Float16 x)
+{
+ return __extension__ (__m128h)(__v8hf) { x, 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+foo2 (_Float16 x, _Float16 y)
+{
+ return __extension__ (__m128h)(__v8hf) { x, 0.0f, 0.0f, y,
+ 3.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+foo3 (_Float16 x)
+{
+ return __extension__ (__m256h)(__v16hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+foo4 (_Float16 x, _Float16 y)
+{
+ return __extension__ (__m256h)(__v16hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, y,
+ 3.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+foo5 (_Float16 x)
+{
+ return __extension__ (__m512h)(__v32hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+foo6 (_Float16 x, _Float16 y)
+{
+ return __extension__ (__m512h)(__v32hf) { x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, y,
+ 3.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ _Float16 y = -35.7;
+ union128h u128 = { x, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
+ union256h u256 = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ union512h u512 = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ __m128h v128;
+ __m256h v256;
+ __m512h v512;
+ union128h a128;
+ union256h a256;
+ union512h a512;
+
+ memset (&v128, -1, sizeof (v128));
+ v128 = foo1 (x);
+ a128.x = v128;
+ if (check_union128h (a128, u128.a))
+ abort ();
+ memset (&v128, -1, sizeof (v128));
+ u128.a[3] = y;
+ u128.a[4] = 3.0f;
+ v128 = foo2 (x, y);
+ a128.x = v128;
+ if (check_union128h (a128, u128.a))
+ abort ();
+
+ memset (&v256, -1, sizeof (v256));
+ v256 = foo3 (x);
+ a256.x = v256;
+ if (check_union256h (a256, u256.a))
+ abort ();
+ memset (&v256, -1, sizeof (v256));
+ u256.a[7] = y;
+ u256.a[8] = 3.0f;
+ v256 = foo4 (x, y);
+ a256.x = v256;
+ if (check_union256h (a256, u256.a))
+ abort ();
+
+ memset (&v512, -1, sizeof (v512));
+ v512 = foo5 (x);
+ a512.x = v512;
+ if (check_union512h (a512, u512.a))
+ abort ();
+ memset (&v512, -1, sizeof (v512));
+ u512.a[15] = y;
+ u512.a[16] = 3.0f;
+ v512 = foo6 (x, y);
+ a512.x = v512;
+ if (check_union512h (a512, u512.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-6.c b/gcc/testsuite/gcc.target/i386/avx512fp16-6.c
new file mode 100644
index 0000000..d85a6c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-6.c
@@ -0,0 +1,57 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+void
+__attribute__ ((noinline, noclone))
+foo128 (_Float16 *p, __m128h x)
+{
+ *p = ((__v8hf)x)[0];
+}
+
+void
+__attribute__ ((noinline, noclone))
+foo256 (_Float16 *p, __m256h x)
+{
+ *p = ((__v16hf)x)[0];
+}
+
+void
+__attribute__ ((noinline, noclone))
+foo512 (_Float16 *p, __m512h x)
+{
+ *p = ((__v32hf)x)[0];
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union128h u128 = { x, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
+ union256h u256 = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ union512h u512 = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ _Float16 y;
+
+ foo128 (&y, u128.x);
+ if (x != y)
+ abort ();
+
+ foo256 (&y, u256.x);
+ if (x != y)
+ abort ();
+
+ foo512 (&y, u512.x);
+ if (x != y)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c
new file mode 100644
index 0000000..754e909
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vaddph" 2 } } */
+/* { dg-final { scan-assembler-times "vsubph" 2 } } */
+/* { dg-final { scan-assembler-times "vmulph" 2 } } */
+/* { dg-final { scan-assembler-times "vdivph" 2 } } */
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define VEC_OP_VV(size, op, name) \
+void \
+__attribute__ ((noinline, noclone, optimize("tree-slp-vectorize"))) \
+vecop_v##size##hf##name (_Float16 * restrict dst, \
+ _Float16 * restrict src1, _Float16 * restrict src2) \
+{ \
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ dst[i] = src1[i] op src2[i]; \
+}
+
+VEC_OP_VV(4, +, add)
+VEC_OP_VV(2, +, add)
+VEC_OP_VV(4, -, sub)
+VEC_OP_VV(2, -, sub)
+VEC_OP_VV(4, *, mul)
+VEC_OP_VV(2, *, mul)
+VEC_OP_VV(4, /, div)
+VEC_OP_VV(2, /, div)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c
new file mode 100644
index 0000000..4dc6f9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-64-32-vecop-2.c
@@ -0,0 +1,75 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+static void vec_op_test (void);
+#define DO_TEST vec_op_test
+#define AVX512FP16
+#define AVX512VL
+#include "avx512f-check.h"
+#include "avx512fp16-64-32-vecop-1.c"
+
+_Float16 a[4], b[4], fexp[4], fref[4];
+
+#define EMULATE_VEC_OP_VV(size, op, name) \
+void \
+__attribute__ ((noinline, noclone)) \
+scalar_vecop_v##size##hf##name ( \
+ _Float16 * restrict dst, _Float16 * restrict src1, \
+ _Float16 * restrict src2) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ dst[i] = src1[i] op src2[i]; \
+}
+
+EMULATE_VEC_OP_VV (4, +, add)
+EMULATE_VEC_OP_VV (2, +, add)
+EMULATE_VEC_OP_VV (4, -, sub)
+EMULATE_VEC_OP_VV (2, -, sub)
+EMULATE_VEC_OP_VV (4, *, mul)
+EMULATE_VEC_OP_VV (2, *, mul)
+EMULATE_VEC_OP_VV (4, /, div)
+EMULATE_VEC_OP_VV (2, /, div)
+
+void init()
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ a[i] = i + 0.5;
+ b[i] = i * 1.5;
+ fexp[i] = fref[i] = 2.75 * i;
+ }
+}
+
+int check_cond(void *a, void *b, int size)
+{
+ int i;
+ unsigned short *pa = (unsigned short *)a,
+ *pb = (unsigned short *)b;
+ for (i = 0; i < size; i++)
+ if (pa[i] != pb[i])
+ return 0;
+ return 1;
+}
+
+#define TEST_VEC_OP_VV(size, name) \
+{ \
+ init (); \
+ scalar_vecop_v##size##hf##name (a, b, fexp); \
+ vecop_v##size##hf##name (a, b, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+}
+
+static void vec_op_test()
+{
+ TEST_VEC_OP_VV (4, add)
+ TEST_VEC_OP_VV (2, add)
+ TEST_VEC_OP_VV (4, sub)
+ TEST_VEC_OP_VV (2, sub)
+ TEST_VEC_OP_VV (4, mul)
+ TEST_VEC_OP_VV (2, mul)
+ TEST_VEC_OP_VV (4, div)
+ TEST_VEC_OP_VV (2, div)
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-7.c b/gcc/testsuite/gcc.target/i386/avx512fp16-7.c
new file mode 100644
index 0000000..26ae25f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-7.c
@@ -0,0 +1,86 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+void
+__attribute__ ((noinline, noclone))
+foo128 (_Float16 *p, __m128h x)
+{
+ *p = ((__v8hf)x)[4];
+}
+
+void
+__attribute__ ((noinline, noclone))
+foo256 (_Float16 *p, __m256h x)
+{
+ *p = ((__v16hf)x)[10];
+}
+
+void
+__attribute__ ((noinline, noclone))
+foo512 (_Float16 *p, __m512h x)
+{
+ *p = ((__v32hf)x)[30];
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union128h u128 = { 0.0f, x, 0.0f, 0.0f, x, 0.0f, 0.0f, x };
+ union256h u256 = { x, 0.0f, 0.0f, 0.0f, x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, x, 0.0f, 0.0f, x, 0.0f, 0.0f };
+ union512h u512 = { x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, x, 0.0f, 0.0f, x, 0.0f };
+ __m128h v128 = _mm_setr_ph (0.0f, x, 0.0f, 0.0f,
+ x, 0.0f, 0.0f, x);
+ __m256h v256 = _mm256_setr_ph (x, 0.0f, 0.0f, 0.0f,
+ x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, x, 0.0f,
+ 0.0f, x, 0.0f, 0.0f);
+ __m512h v512 = _mm512_setr_ph (x, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, x, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, x, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, x,
+ 0.0f, 0.0f, x, 0.0f);
+ union128h a128;
+ union256h a256;
+ union512h a512;
+ _Float16 y;
+
+ a128.x = v128;
+ if (check_union128h (a128, u128.a))
+ abort ();
+
+ a256.x = v256;
+ if (check_union256h (a256, u256.a))
+ abort ();
+
+ a512.x = v512;
+ if (check_union512h (a512, u512.a))
+ abort ();
+
+ foo128 (&y, u128.x);
+ if (x != y)
+ abort ();
+
+ foo256 (&y, u256.x);
+ if (x != y)
+ abort ();
+
+ foo512 (&y, u512.x);
+ if (x != y)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-8.c b/gcc/testsuite/gcc.target/i386/avx512fp16-8.c
new file mode 100644
index 0000000..8f10375
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-8.c
@@ -0,0 +1,53 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+_Float16
+__attribute__ ((noinline, noclone))
+foo128 (__m128h x)
+{
+ return ((__v8hf)x)[4];
+}
+
+_Float16
+__attribute__ ((noinline, noclone))
+foo256 (__m256h x)
+{
+ return ((__v16hf)x)[10];
+}
+
+_Float16
+__attribute__ ((noinline, noclone))
+foo512 (__m512h x)
+{
+ return ((__v32hf)x)[30];
+}
+
+static void
+do_test (void)
+{
+ _Float16 x = 25.3;
+ union128h u128 = { 0.0f, 0.0f, 0.0f, 0.0f, x, 0.0f, 0.0f, 0.0f };
+ union256h u256 = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, x, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ union512h u512 = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, x, 0.0f };
+
+ if (foo128 (u128.x) != x)
+ abort ();
+
+ if (foo256 (u256.x) != x)
+ abort ();
+
+ if (foo512 (u512.x) != x)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-9a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-9a.c
new file mode 100644
index 0000000..580ffb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-9a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <immintrin.h>
+
+__m128h
+__attribute__ ((noinline, noclone))
+set1_128 (_Float16 x)
+{
+ return _mm_set1_ph (x);
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+set1_256 (_Float16 x)
+{
+ return _mm256_set1_ph (x);
+}
+
+__m512h
+__attribute__ ((noinline, noclone))
+set1_512 (_Float16 x)
+{
+ return _mm512_set1_ph (x);
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastw\[ \t]\+\[^\n\r]*\[xyz\]mm0" 3 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-9b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-9b.c
new file mode 100644
index 0000000..198b23e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-9b.c
@@ -0,0 +1,49 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-9a.c"
+
+union128h u128 = { ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16 };
+union256h u256 = { ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16 };
+union512h u512 = { ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16,
+ ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16, ESP_FLOAT16 };
+
+static void
+do_test (void)
+{
+ __m128h v128 = set1_128 (ESP_FLOAT16);
+ __m256h v256 = set1_256 (ESP_FLOAT16);
+ __m512h v512 = set1_512 (ESP_FLOAT16);
+ union128h a128;
+ union256h a256;
+ union512h a512;
+
+ a128.x = v128;
+ if (check_union128h (a128, u128.a))
+ abort ();
+
+ a256.x = v256;
+ if (check_union256h (a256, u256.a))
+ abort ();
+
+ a512.x = v512;
+ if (check_union512h (a512, u512.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c
new file mode 100644
index 0000000..3e2397f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c
@@ -0,0 +1,33 @@
+/* PR target/87767 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
+/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 } } */
+/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to16\\\}" 4 } } */
+/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to32\\\}" 4 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+
+#define CONSTANT 101;
+#define FOO(VTYPE, OP_NAME, OP) \
+VTYPE \
+ __attribute__ ((noipa)) \
+foo_##OP_NAME##_##VTYPE (VTYPE a) \
+{ \
+ return a OP CONSTANT; \
+} \
+
+FOO (v8hf, add, +);
+FOO (v16hf, add, +);
+FOO (v32hf, add, +);
+FOO (v8hf, sub, -);
+FOO (v16hf, sub, -);
+FOO (v32hf, sub, -);
+FOO (v8hf, mul, *);
+FOO (v16hf, mul, *);
+FOO (v32hf, mul, *);
+FOO (v8hf, div, /);
+FOO (v16hf, div, /);
+FOO (v32hf, div, /);
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-2.c
new file mode 100644
index 0000000..016e0ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-2.c
@@ -0,0 +1,53 @@
+/* PR target/87767 */
+/* { dg-do run } */
+/* { dg-options "-O1 -mavx512fp16 -mavx512dq -mavx512vl" } */
+/* { dg-require-effective-target avx512dq } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512DQ
+#define AVX512VL
+#define AVX512FP16
+#include "avx512f-helper.h"
+
+#include "avx512fp16-broadcast-1.c"
+
+#define RTEST(VTYPE, TYPE, N, OP_NAME, OP) \
+ do \
+ { \
+ TYPE exp[N], src[N]; \
+ VTYPE res; \
+ for (int i = 0; i < N; i++) \
+ src[i] = 2.0 * i - 8.4; \
+ res = foo_##OP_NAME##_##VTYPE (*(VTYPE*)&src[0]); \
+ for (int i = 0; i < N; i ++) \
+ exp[i] = src[i] OP CONSTANT; \
+ for (int j = 0; j < N; j++) \
+ { \
+ if (res[j] != exp[j]) \
+ abort(); \
+ } \
+ } \
+ while (0)
+
+void
+test_256 (void)
+{
+ RTEST (v8hf, _Float16, 8, add, +);
+ RTEST (v16hf, _Float16, 16, add, +);
+ RTEST (v32hf, _Float16, 32, add, +);
+ RTEST (v8hf, _Float16, 8, sub, -);
+ RTEST (v16hf, _Float16, 16, sub, -);
+ RTEST (v32hf, _Float16, 32, sub, -);
+ RTEST (v8hf, _Float16, 8, mul, *);
+ RTEST (v16hf, _Float16, 16, mul, *);
+ RTEST (v32hf, _Float16, 32, mul, *);
+ RTEST (v8hf, _Float16, 8, div, /);
+ RTEST (v16hf, _Float16, 16, div, /);
+ RTEST (v32hf, _Float16, 32, div, /);
+}
+
+void
+test_128 (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c
new file mode 100644
index 0000000..62115f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-1.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+int
+f1 (_Float16 x, _Float16 y)
+{
+ return x > y;
+}
+
+int
+f2 (_Float16 x, _Float16 y)
+{
+ return x < y;
+}
+
+/* { dg-final { scan-assembler-times "seta" 2 } } */
+
+int
+f3 (_Float16 x, _Float16 y)
+{
+ return x >= y;
+}
+
+int
+f4 (_Float16 x, _Float16 y)
+{
+ return x <= y;
+}
+
+/* { dg-final { scan-assembler-times "setnb" 2 } } */
+
+int
+f5 (_Float16 x, _Float16 y)
+{
+ return __builtin_isunordered (x, y);
+}
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-times "xorl" 5 } } */
+/* { dg-final { scan-assembler-times "vcomish\[^\n\r\]*xmm\[0-9\]" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c
new file mode 100644
index 0000000..150c351
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-fpcompare-2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfpmath=sse -mavx512fp16" } */
+
+int
+foo (_Float16 y)
+{
+ return __builtin_isinf (y);
+}
+
+int
+foo2 (_Float16 y)
+{
+ return __builtin_isfinite (y);
+}
+
+int
+foo3 (_Float16 y)
+{
+ return __builtin_signbit(y);
+}
+
+int
+foo4 (_Float16 y)
+{
+ return __builtin_isnormal (y);
+}
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-times "vucomish\[^\n\r\]*xmm\[0-9\]" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c
new file mode 100644
index 0000000..90080e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-minmax-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mprefer-vector-width=512" } */
+
+_Float16
+minf1 (_Float16 a, _Float16 b)
+{
+ return __builtin_fminf16 (a, b);
+}
+
+void
+minf2 (_Float16* __restrict psrc1, _Float16* __restrict psrc2,
+ _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_fminf16 (psrc1[i], psrc2[i]);
+}
+
+_Float16
+maxf1 (_Float16 a, _Float16 b)
+{
+ return __builtin_fmaxf16 (a, b);
+}
+
+void
+maxf2 (_Float16* __restrict psrc1, _Float16* __restrict psrc2,
+ _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_fmaxf16 (psrc1[i], psrc2[i]);
+}
+
+/* { dg-final { scan-assembler-times "vmaxsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[^\n\r\]*zmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c
new file mode 100644
index 0000000..a1c6636
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+_Float16
+f1 (_Float16 x)
+{
+ return __builtin_truncf16 (x);
+}
+
+_Float16
+f2 (_Float16 x)
+{
+ return __builtin_floorf16 (x);
+}
+
+_Float16
+f3 (_Float16 x)
+{
+ return __builtin_ceilf16 (x);
+}
+
+_Float16
+f4 (_Float16 x)
+{
+ return __builtin_roundevenf16 (x);
+}
+
+_Float16
+f5 (_Float16 x)
+{
+ return __builtin_rintf16 (x);
+}
+
+_Float16
+f6 (_Float16 x)
+{
+ return __builtin_nearbyintf16 (x);
+}
+
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$11\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$10\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$9\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$8\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$4\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\\\$12\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c
new file mode 100644
index 0000000..b4efc84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-sqrt-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mprefer-vector-width=512" } */
+
+_Float16
+f1 (_Float16 x)
+{
+ return __builtin_sqrtf16 (x);
+}
+
+void
+f2 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 32; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+/* { dg-final { scan-assembler-times "vsqrtsh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*zmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin_shuffle-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin_shuffle-1.c
new file mode 100644
index 0000000..89d3567
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin_shuffle-1.c
@@ -0,0 +1,86 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-not "movw" } } */
+/* { dg-final { scan-assembler-times "vpermi2w" 3 } } */
+/* { dg-final { scan-assembler-times "vpermw" 6 } } */
+/* { dg-final { scan-assembler-times "vpshufb" 3 } } */
+/* { dg-final { scan-assembler-times "vpermt2w" 6 } } */
+
+typedef _Float16 v32hf __attribute__((vector_size (64)));
+typedef _Float16 v16hf __attribute__((vector_size (32)));
+typedef _Float16 v8hf __attribute__((vector_size (16)));
+typedef short v32hi __attribute__((vector_size (64)));
+typedef short v16hi __attribute__((vector_size (32)));
+typedef short v8hi __attribute__((vector_size (16)));
+
+#define PERM_CONST_RANDOM_v32hi \
+{ 0, 21, 15, 9, 43, 25, 37, 48, \
+ 8, 16, 27, 51, 30, 12, 6, 46, \
+ 34, 3, 11, 5, 17, 53, 26, 39, \
+ 2, 18, 40, 61, 19, 4, 50, 29 }
+
+#define PERM_CONST_RANDOM_RANGE32_v32hi \
+{ 0, 21, 10, 23, 8, 18, 7, 19, \
+ 4, 25, 3, 31, 5, 22, 11, 17, \
+ 9, 20, 2, 24, 1, 30, 12, 27, \
+ 13, 28, 6, 29, 14, 16, 15, 23 }
+
+#define PERM_CONST_RANDOM_v16hi \
+{ 0, 21, 15, 9, 13, 25, 30, 18, \
+ 8, 16, 17, 11, 4, 22, 6, 7 }
+
+#define PERM_CONST_RANDOM_RANGE16_v16hi \
+{ 0, 9, 1, 12, 4, 15, 7, 13, \
+ 3, 10, 6, 14, 5, 8, 2, 11 }
+
+#define PERM_CONST_RANDOM_v8hi \
+{ 0, 14, 15, 9, 13, 2, 3, 5 }
+
+#define PERM_CONST_RANDOM_RANGE8_v8hi \
+{ 0, 7, 2, 5, 3, 4, 1, 6 }
+
+#define PERM_CONST_RANDOM(size) \
+ PERM_CONST_RANDOM_v##size##hi
+
+#define PERM_CONST_RANDOM_RANGE(size) \
+ PERM_CONST_RANDOM_RANGE##size##_v##size##hi
+
+#define SHUFFLE_CONST_RANDOM(type, itype, size) \
+type foo_##type##shuffle_2param_const_random (type a, type b) \
+{ \
+ return __builtin_shuffle (a, b, \
+ (itype) PERM_CONST_RANDOM (size)); \
+} \
+type foo_##type##shuffle_2param_const_random_range (type a, type b) \
+{ \
+ return __builtin_shuffle (a, b, \
+ (itype) PERM_CONST_RANDOM_RANGE (size)); \
+} \
+type foo_##type##shuffle_1param_const_random (type a) \
+{ \
+ return __builtin_shuffle (a, \
+ (itype) PERM_CONST_RANDOM (size)); \
+} \
+type foo_##type##shuffle_1param_const_random_range (type a) \
+{ \
+ return __builtin_shuffle (a, \
+ (itype) PERM_CONST_RANDOM_RANGE (size)); \
+}
+
+#define SHUFFLE_VEC_INDEX(type, itype) \
+type foo##type##itype##shuffle_2param_vec (type a, type b, itype c) \
+{ \
+ return __builtin_shuffle (a, b, c); \
+} \
+type foo##type##itype##shuffle_1param_vec (type a, itype c) \
+{ \
+ return __builtin_shuffle (a, c); \
+}
+
+SHUFFLE_CONST_RANDOM (v32hf, v32hi, 32)
+SHUFFLE_CONST_RANDOM (v16hf, v16hi, 16)
+SHUFFLE_CONST_RANDOM (v8hf, v8hi, 8)
+
+SHUFFLE_VEC_INDEX (v32hf, v32hi)
+SHUFFLE_VEC_INDEX (v16hf, v16hi)
+SHUFFLE_VEC_INDEX (v8hf, v8hi)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c b/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c
new file mode 100644
index 0000000..fcd3794
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-complex-constraints.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+
+/* { dg-final { scan-assembler-not "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm1+\[^\n\r]*%zmm0+\[^\n\r]*%zmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm0+\[^\n\r]*%zmm0+\[^\n\r]*%zmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm1+\[^\n\r]*%xmm0+\[^\n\r]*%xmm0+(?:\n|\[ \\t\]+#)" } } */
+/* { dg-final { scan-assembler-not "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm0+\[^\n\r]*%xmm0+\[^\n\r]*%xmm0+(?:\n|\[ \\t\]+#)" } } */
+
+#include <immintrin.h>
+
+volatile __m512h a1;
+volatile __m128h a2;
+__m512h b1;
+__m128h b2;
+
+void extern
+avx512f_test (void)
+{
+ a1 = _mm512_fmul_pch (a1, a1);
+ b1 = _mm512_fmadd_pch (b1, b1, b1);
+ a2 = _mm_fmul_sch (a2, a2);
+ b2 = _mm_fmadd_sch (b2, b2, b2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c
new file mode 100644
index 0000000..662b23c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-conjugation-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <immintrin.h>
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_conj_pch (__m512h __A)
+{
+ return _mm512_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_mask_conj_pch (__m512h __W, __mmask16 __U, __m512h __A)
+{
+ return _mm512_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+/* { dg-final { scan-assembler-times "kmovw\[^\n\]*%k\[1-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[^\n]" 2 } } */
+
+__m512h
+__attribute__ ((noinline, noclone))
+test_mm512_maskz_conj_pch (__mmask16 __U, __m512h __A)
+{
+ return _mm512_maskz_conj_pch (__U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vpxord\[^\n\]*%zmm\[0-9\]+" 3 } } */
+/* { dg-final { scan-assembler-times "kmovw\[^\n\]*%k\[1-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c
new file mode 100644
index 0000000..8471a1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-floatvnhf.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern long long di[8];
+extern unsigned long long udi[8];
+extern int si[16];
+extern unsigned int usi[16];
+extern short hi[32];
+extern unsigned short uhi[32];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define FLOATHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+float##v##size##mode##v##size##hf () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ hf[i] = (_Float16) mode[i]; \
+}
+
+FLOATHFVV(32, hi)
+FLOATHFVV(16, hi)
+FLOATHFVV(8, hi)
+FLOATHFVV(16, si)
+FLOATHFVV(8, si)
+FLOATHFVV(4, si)
+FLOATHFVV(8, di)
+FLOATHFVV(4, di)
+FLOATHFVV(2, di)
+
+FLOATHFVV(32, uhi)
+FLOATHFVV(16, uhi)
+FLOATHFVV(8, uhi)
+FLOATHFVV(16, usi)
+FLOATHFVV(8, usi)
+FLOATHFVV(4, usi)
+FLOATHFVV(8, udi)
+FLOATHFVV(4, udi)
+FLOATHFVV(2, udi)
+
+/* { dg-final { scan-assembler-times "vcvtqq2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c
new file mode 100644
index 0000000..d78d762
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-fma-1.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16" } */
+
+typedef _Float16 v32hf __attribute__ ((__vector_size__ (64)));
+
+_Float16
+foo1 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo2 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo3 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+_Float16
+foo4 (_Float16 a, _Float16 b, _Float16 c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132sh\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v32hf
+foo5 (v32hf a, v32hf b, v32hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo6 (v32hf a, v32hf b, v32hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo7 (v32hf a, v32hf b, v32hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
+v32hf
+foo8 (v32hf a, v32hf b, v32hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*zmm\[0-9\]" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h b/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h
new file mode 100644
index 0000000..69948f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-helper.h
@@ -0,0 +1,284 @@
+/* This file is used for emulation of avx512fp16 runtime tests. To
+ verify the correctness of _Float16 type calculation, the idea is
+ convert _Float16 to float and do emulation using float instructions.
+ _Float16 type should not be emulate or check by itself. */
+
+#include "avx512f-helper.h"
+#ifndef AVX512FP16_HELPER_INCLUDED
+#define AVX512FP16_HELPER_INCLUDED
+
+#ifdef DEBUG
+#include <string.h>
+#endif
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+
+/* Useful macros. */
+#define NOINLINE __attribute__((noinline,noclone))
+#define _ROUND_NINT (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+#define _ROUND_CUR 8
+#define AVX512F_MAX_ELEM 512 / 32
+
+/* Structure for _Float16 emulation */
+typedef union
+{
+ __m512 zmm;
+ __m512h zmmh;
+ __m512i zmmi;
+ __m512d zmmd;
+ __m256 ymm[2];
+ __m256h ymmh[2];
+ __m256i ymmi[2];
+ __m256d ymmd[2];
+ __m128h xmmh[4];
+ __m128 xmm[4];
+ __m128i xmmi[4];
+ __m128d xmmd[4];
+ unsigned short u16[32];
+ unsigned int u32[16];
+ int i32[16];
+ long long s64[8];
+ unsigned long long u64[8];
+ double f64[8];
+ float f32[16];
+ _Float16 f16[32];
+} V512;
+
+/* Global variables. */
+V512 src1, src2, src3, src3f;
+int n_errs = 0;
+
+/* Helper function for packing/unpacking ph operands. */
+void NOINLINE
+unpack_ph_2twops(V512 src, V512 *op1, V512 *op2)
+{
+ V512 v1;
+
+ op1->zmm = _mm512_cvtph_ps(src.ymmi[0]);
+ v1.ymm[0] = _mm512_extractf32x8_ps(src.zmm, 1);
+ op2->zmm = _mm512_cvtph_ps(v1.ymmi[0]);
+}
+
+V512 NOINLINE
+pack_twops_2ph(V512 op1, V512 op2)
+{
+ V512 v1, v2, v3;
+
+ v1.ymmi[0] = _mm512_cvtps_ph(op1.zmm, _MM_FROUND_TO_NEAREST_INT);
+ v2.ymmi[0] = _mm512_cvtps_ph(op2.zmm, _MM_FROUND_TO_NEAREST_INT);
+
+ v3.zmm = _mm512_insertf32x8(v1.zmm, v2.ymm[0], 1);
+
+ return v3;
+}
+
+/* Helper function used for result debugging */
+#ifdef DEBUG
+void NOINLINE
+display_ps(const void *p, const char *banner, int n_elems)
+{
+ int i;
+ V512 *v = (V512*)p;
+
+ if (banner) {
+ printf("%s", banner);
+ }
+
+ for (i = 15; i >= n_elems; i--) {
+ printf(" --------");
+ if (i == 8) {
+ printf("\n");
+ if (banner) {
+ printf("%*s", (int)strlen(banner), "");
+ }
+ }
+ }
+
+ for (; i >= 0; i--) {
+ printf(" %x", v->u32[i]);
+ if (i == 8) {
+ printf("\n");
+ if (banner) {
+ printf("%*s", (int)strlen(banner), "");
+ }
+ }
+ }
+ printf("\n");
+}
+#endif
+
+/* Functions/macros used for init/result checking.
+ Only check components within AVX512F_LEN. */
+#define TO_STRING(x) #x
+#define STRINGIFY(x) TO_STRING(x)
+#define NAME_OF(NAME) STRINGIFY(INTRINSIC (NAME))
+
+#define CHECK_RESULT(res, exp, size, intrin) \
+ check_results ((void*)res, (void*)exp, size,\
+ NAME_OF(intrin))
+
+#define CHECK_RESULT_MASK(res, exp, size, intrin) \
+ check_results_mask ((__mmask32)res, (__mmask32)exp, size,\
+ NAME_OF(intrin))
+
+/* To evaluate whether result match _Float16 precision,
+ only the last bit of real/emulate result could be
+ different. */
+void NOINLINE
+check_results(void *got, void *exp, int n_elems, char *banner)
+{
+ int i;
+ V512 *v1 = (V512*)got;
+ V512 *v2 = (V512*)exp;
+
+ for (i = 0; i < n_elems; i++) {
+ if (v1->u16[i] != v2->u16[i] &&
+ ((v1->u16[i] > (v2->u16[i] + 1)) ||
+ (v1->u16[i] < (v2->u16[i] - 1)))) {
+
+#ifdef DEBUG
+ printf("ERROR: %s failed at %d'th element: %x(%f) != %x(%f)\n",
+ banner ? banner : "", i,
+ v1->u16[i], *(float *)(&v1->u16[i]),
+ v2->u16[i], *(float *)(&v2->u16[i]));
+ display_ps(got, "got:", n_elems);
+ display_ps(exp, "exp:", n_elems);
+#endif
+ n_errs++;
+ break;
+ }
+ }
+}
+
+void NOINLINE
+check_results_mask(__mmask32 got, __mmask32 exp, int n_elems, char *banner)
+{
+ if (got != exp) {
+#ifdef DEBUG
+ printf("ERROR: %s failed : got mask %x != exp mask %x\n",
+ banner ? banner : "", got, exp);
+#endif
+ n_errs++;
+ }
+}
+
+/* Functions for src/dest initialization */
+void NOINLINE
+init_src()
+{
+ V512 v1, v2, v3, v4;
+ int i;
+
+ for (i = 0; i < AVX512F_MAX_ELEM; i++) {
+ v1.f32[i] = i + 1;
+ v2.f32[i] = (i + 2) * 0.5f;
+ v3.f32[i] = i * 1.5f;
+ v4.f32[i] = i - 1.5f;
+
+ src3.u32[i] = (i + 1) * 10;
+ }
+
+ for (i = 0; i < 8; i++) {
+ src3f.f64[i] = (i + 1) * 7.5;
+ }
+
+ src1 = pack_twops_2ph(v1, v2);
+ src2 = pack_twops_2ph(v3, v4);
+}
+
+void NOINLINE
+init_src_nanf()
+{
+ V512 v1, v2, v3, v4;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ v1.f32[i] = i + 1 + 0.5;
+ v2.f32[i] = i + 17 + 0.5;
+ v3.f32[i] = i * 2 + 2 + 0.5;
+ v4.f32[i] = i * 2 + 34 + 0.5;
+
+ src3.u32[i] = (i + 1) * 10;
+ }
+
+ v1.f32[0] = __builtin_nanf("");
+ src1 = pack_twops_2ph(v1, v2);
+ src2 = pack_twops_2ph(v3, v4);
+}
+
+
+void NOINLINE
+init_dest(V512 * res, V512 * exp)
+{
+ int i;
+ V512 v1;
+
+ for (i = 0; i < AVX512F_MAX_ELEM; i++) {
+ v1.f32[i] = 12 + 0.5f * i;
+ }
+ *res = *exp = pack_twops_2ph(v1, v1);
+}
+
+#define EMULATE(NAME) EVAL(emulate_, NAME, AVX512F_LEN)
+
+#endif /* AVX512FP16_HELPER_INCLUDED */
+
+/* Macros for AVX512VL Testing. Include V512 component usage
+ and mask type for emulation. */
+
+#if AVX512F_LEN == 256
+#undef HF
+#undef SF
+#undef SI
+#undef DF
+#undef H_HF
+#undef NET_MASK
+#undef NET_CMASK
+#undef MASK_VALUE
+#undef HALF_MASK
+#undef ZMASK_VALUE
+#define NET_MASK 0xffff
+#define NET_CMASK 0xff
+#define MASK_VALUE 0xcccc
+#define ZMASK_VALUE 0xfcc1
+#define HALF_MASK 0xcc
+#define HF(x) x.ymmh[0]
+#define H_HF(x) x.xmmh[0]
+#define SF(x) x.ymm[0]
+#define DF(x) x.ymmd[0]
+#define SI(x) x.ymmi[0]
+#elif AVX512F_LEN == 128
+#undef HF
+#undef SF
+#undef DF
+#undef SI
+#undef H_HF
+#undef NET_MASK
+#undef NET_CMASK
+#undef MASK_VALUE
+#undef ZMASK_VALUE
+#undef HALF_MASK
+#define NET_MASK 0xff
+#define NET_CMASK 0xff
+#define MASK_VALUE 0xcc
+#define HALF_MASK MASK_VALUE
+#define ZMASK_VALUE 0xc1
+#define HF(x) x.xmmh[0]
+#define SF(x) x.xmm[0]
+#define DF(x) x.xmmd[0]
+#define SI(x) x.xmmi[0]
+#define H_HF(x) x.xmmh[0]
+#else
+#define NET_MASK 0xffffffff
+#define NET_CMASK 0xffff
+#define MASK_VALUE 0xcccccccc
+#define ZMASK_VALUE 0xfcc1fcc1
+#define HALF_MASK 0xcccc
+#define HF(x) x.zmmh
+#define SF(x) x.zmm
+#define DF(x) x.zmmd
+#define SI(x) x.zmmi
+#define H_HF(x) x.ymmh[0]
+#endif
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1a.c
new file mode 100644
index 0000000..bf7693e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1a.c
@@ -0,0 +1,19 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+/* { dg-final { scan-assembler-times "vpxord\[ \\t\]+\[^\n\r\]*%zmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vxorps\[ \\t\]+\[^\n\r\]*%xmm0" 1 } } */
+
+#include<immintrin.h>
+
+_Float16
+neghf (_Float16 a)
+{
+ return -a;
+}
+
+__m512h
+neghf512 (__m512h a)
+{
+ return -a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1b.c
new file mode 100644
index 0000000..770f7b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-neg-1b.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+static void
+test_512 (void)
+{
+ V512 v1, v2, v3, v4, exp, res;
+ int i;
+ init_src();
+
+ unpack_ph_2twops(src1, &v1, &v2);
+ v1.f32[0] = -v1.f32[0];
+ exp = pack_twops_2ph(v1, v2);
+ res.zmmh = src1.zmmh;
+ res.f16[0] = -res.f16[0];
+ check_results(&res, &exp, 32, "neg");
+
+ unpack_ph_2twops(src1, &v1, &v2);
+ for (i=0; i<16; i++)
+ {
+ v1.f32[i] = -v1.f32[i];
+ v2.f32[i] = -v2.f32[i];
+ }
+ exp = pack_twops_2ph(v1, v2);
+ res.zmmh = -src1.zmmh;
+ check_results(&res, &exp, 32, "neg");
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c b/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c
new file mode 100644
index 0000000..abd9156
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vpmovzxwd" "3" } } */
+/* { dg-final { scan-assembler-times "vpmovdw" "3" } } */
+
+typedef _Float16 v32hf __attribute__((vector_size (64)));
+typedef _Float16 v16hf __attribute__((vector_size (32)));
+typedef _Float16 v8hf __attribute__((vector_size (16)));
+typedef _Float16 v4hf __attribute__((vector_size (8)));
+typedef short v4hi __attribute__((vector_size (8)));
+typedef short v8hi __attribute__((vector_size (16)));
+
+#define PERM_CONST_INTERLEAVE_v32hi \
+0, 16, 1, 17, 2, 18, 3, 19, \
+4, 20, 5, 21, 6, 22, 7, 23, \
+8, 24, 9, 25, 10, 26, 11, 27, \
+12, 28, 13, 29, 14, 30, 15, 31
+
+#define PERM_CONST_INTERLEAVE_v16hi \
+0, 8, 1, 9, 2, 10, 3, 11, \
+4, 12, 5, 13, 6, 14, 7, 15
+
+#define PERM_CONST_INTERLEAVE_v8hi \
+0, 4, 1, 5, 2, 6, 3, 7
+
+#define PERM_CONST_TRUNCATE_v32hi \
+0, 2, 4, 6, 8, 10, 12, 14, \
+16, 18, 20, 22, 24, 26, 28, 30
+
+#define PERM_CONST_TRUNCATE_v16hi \
+0, 2, 4, 6, 8, 10, 12, 14
+
+#define PERM_CONST_TRUNCATE_v8hi \
+0, 2, 4, 6
+
+#define PERM_CONST_INTERLEAVE(size) \
+ PERM_CONST_INTERLEAVE_v##size##hi
+
+#define PERM_CONST_TRUNCATE(size) \
+ PERM_CONST_TRUNCATE_v##size##hi
+
+#define SHUFFLE_CONST_INTERLEAVE(type, rtype, size) \
+rtype foo_##type##shufflevector_const_interleave (type a) \
+{ \
+ return __builtin_shufflevector (a, (type) {}, \
+ PERM_CONST_INTERLEAVE (size)); \
+} \
+type foo_##type##shufflevector_const_trunc (rtype a) \
+{ \
+ return __builtin_shufflevector (a, a, \
+ PERM_CONST_TRUNCATE (size)); \
+}
+
+SHUFFLE_CONST_INTERLEAVE (v16hf, v32hf, 32)
+SHUFFLE_CONST_INTERLEAVE (v8hf, v16hf, 16)
+SHUFFLE_CONST_INTERLEAVE (v4hf, v8hf, 8)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-pr94680.c b/gcc/testsuite/gcc.target/i386/avx512fp16-pr94680.c
new file mode 100644
index 0000000..bfe1123
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-pr94680.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vmovdqa" 4 } } */
+/* { dg-final { scan-assembler-times "vmovq" 2 } } */
+
+typedef _Float16 v32hf __attribute__((vector_size (64)));
+typedef _Float16 v16hf __attribute__((vector_size (32)));
+typedef _Float16 v8hf __attribute__((vector_size (16)));
+typedef short v32hi __attribute__((vector_size (64)));
+typedef short v16hi __attribute__((vector_size (32)));
+typedef short v8hi __attribute__((vector_size (16)));
+
+
+#define PERM_CONST_CONCAT0_v32hi \
+{ 0, 1, 2, 3, 4, 5, 6, 7, \
+ 8, 9, 10, 11, 12, 13, 14, 15, \
+ 34, 53, 41, 55, 57, 43, 36, 39, \
+ 62, 48, 50, 51, 49, 44, 60, 37 }
+
+#define PERM_CONST_CONCAT0_v32hi_l \
+{ 32, 33, 34, 35, 36, 37, 38, 39, \
+ 40, 41, 42, 43, 44, 45, 46, 47, \
+ 31, 0, 29, 2, 27, 4, 25, 6, 23, \
+ 8, 21, 10, 19, 12, 17, 14 }
+
+#define PERM_CONST_CONCAT0_v16hi \
+{ 0, 1, 2, 3, 4, 5, 6, 7, \
+ 21, 26, 17, 31, 24, 22, 30, 19 }
+
+#define PERM_CONST_CONCAT0_v16hi_l \
+{ 16, 17, 18, 19, 20, 21, 22, 23, \
+ 15, 0, 13, 2, 11, 4, 9, 6 }
+
+#define PERM_CONST_CONCAT0_v8hi \
+{ 0, 1, 2, 3, 9, 11, 14, 12 }
+
+#define PERM_CONST_CONCAT0_v8hi_l \
+{ 8, 9, 10, 11, 3, 5, 1, 7 }
+
+#define PERM_CONST_CONCAT0(type) \
+ PERM_CONST_CONCAT0_##type
+
+#define PERM_CONST_CONCAT0_L(type) \
+ PERM_CONST_CONCAT0_##type##_l
+
+#define SHUFFLE_CONST_CONCAT0(type, itype) \
+type foo_##type##shuffle_const_concat0 (type a) \
+{ \
+ return __builtin_shuffle (a, (type) {0}, \
+ (itype) PERM_CONST_CONCAT0 (itype)); \
+} \
+type foo_##type##shuffle_const_concat0_l (type a) \
+{ \
+ return __builtin_shuffle ((type) {0}, a, \
+ (itype) PERM_CONST_CONCAT0_L (itype)); \
+}
+
+SHUFFLE_CONST_CONCAT0 (v32hf, v32hi)
+SHUFFLE_CONST_CONCAT0 (v16hf, v16hi)
+SHUFFLE_CONST_CONCAT0 (v8hf, v8hi)
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c
new file mode 100644
index 0000000..3556316
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-1.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+
+#include <immintrin.h>
+#include "avx512-check.h"
+
+__m512h a1 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+
+__m512h a2 = { 1.25f16, 2.25f16, -0.25f16, 4.0f16, -2.0f16, 4.0f16, -3.0f16, 2.0f16,
+ -0.5f16, -1.0f16, 1.0f16, -1.0f16, 1.0f16, 1.0f16, 2.0f16, 4.0f16,
+ 1.25f16, 2.25f16, -4.25f16, 4.0f16, -2.4f16, 4.0f16, -3.0f, 2.0f16,
+ -4.5f16, 7.6f16, 0.7f16, -8.2f16, 2.1f16, 2.4f16, -2.0f16, 19.4f16 };
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_add_ph (__m512h a)
+{
+ return _mm512_reduce_add_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_mul_ph (__m512h a)
+{
+ return _mm512_reduce_mul_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_max_ph (__m512h a)
+{
+ return _mm512_reduce_max_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_min_ph (__m512h a)
+{
+ return _mm512_reduce_min_ph (a);
+}
+
+#define SIZE 32
+#define REF_ADDMUL(op, a) \
+ __m256h __a1 = _mm256_setzero_ph (); \
+ for (int i =0; i < 16; i++) { \
+ __a1[i] = (_Float16) a[i] op (_Float16) a[i + 16]; \
+ } \
+ __m128h __a2 = _mm_setzero_ph (); \
+ for (int i =0; i < 8; i++) { \
+ __a2[i] = (_Float16) __a1[i] op (_Float16) __a1[i + 8]; \
+ } \
+ _Float16 __c0 = __a2[0] op __a2[4]; \
+ _Float16 __c1 = __a2[1] op __a2[5]; \
+ _Float16 __c2 = __a2[2] op __a2[6]; \
+ _Float16 __c3 = __a2[3] op __a2[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm512_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+ static void
+ test_512_addmul_ph (void)
+ {
+ TEST_ADDMUL_PH (a1);
+ TEST_ADDMUL_PH (a2);
+ }
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm512_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op a[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_MINMAX_PH(a) \
+ do { \
+ TESTOP (min, < a[i] ? r3 :, a); \
+ TESTOP (max, > a[i] ? r3 :, a); \
+ } while (0)
+
+static void
+test_512_minmax_ph (void)
+{
+ TEST_MINMAX_PH (a1);
+ TEST_MINMAX_PH (a2);
+}
+
+static void
+do_test (void)
+{
+ test_512_addmul_ph();
+ test_512_minmax_ph();
+}
+
+#undef SIZE
+#undef REF_ADDMUL
+#undef TESTOP
+#undef TEST_ADDMUL_PH
+#undef TEST_MINMAX_PH
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c
new file mode 100644
index 0000000..593340e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-2.c
@@ -0,0 +1,96 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mprefer-vector-width=512 -fdump-tree-optimized" } */
+
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MIN" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MAX" 3 "optimized" } } */
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_128 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 8; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_256 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 16; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_add_512 (_Float16* p)
+{
+ _Float16 sum = 0;
+ for (int i = 0; i != 32; i++)
+ sum += p[i];
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_128 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 8; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_256 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 16; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_min_512 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 32; i++)
+ sum = sum > p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_128 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 8; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_256 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 16; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
+
+_Float16
+__attribute__((noipa, target("avx512fp16,avx512vl"), optimize("Ofast")))
+reduc_max_512 (_Float16* p)
+{
+ _Float16 sum = p[0];
+ for (int i = 0; i != 32; i++)
+ sum = sum < p[i] ? p[i] : sum;
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c
new file mode 100644
index 0000000..9281a3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-reduce-op-3.c
@@ -0,0 +1,91 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512FP16
+#define AVX512VL
+
+#include "avx512f-helper.h"
+
+#include "avx512fp16-reduce-op-2.c"
+
+void
+test_256 (void)
+{
+ _Float16 a[32];
+ int sign = 1;
+ _Float16 res1 = 0, exp1;
+ _Float16 res2 = 0, exp2;
+ _Float16 res3 = 0, exp3;
+
+ for (int i = 0; i != 32; i++)
+ {
+ a[i] = sign * (4.0 * i);
+ sign *= -1;
+ if (i < 8)
+ res1 += a[i];
+ if (i < 16)
+ res2 += a[i];
+ res3 += a[i];
+ }
+
+ exp1 = reduc_add_128 (a);
+ exp2 = reduc_add_256 (a);
+ exp3 = reduc_add_512 (a);
+ if (exp1 != res1 || exp2 != res2 || exp3 != res3)
+ abort();
+}
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+void
+test_128 ()
+{
+ _Float16 a[32];
+ int sign = 1;
+ _Float16 min_res1, min_exp1, max_res1, max_exp1;
+ _Float16 min_res2, min_exp2, max_res2, max_exp2;
+ _Float16 min_res3, min_exp3, max_res3, max_exp3;
+
+ for (int i = 0; i != 32; i++)
+ {
+ a[i] = sign * (4.9 * i * i - 8.3 * i + 14.8);
+ sign *= -1;
+ }
+
+ min_res1 = max_res1 = a[0];
+ for (int i = 0 ; i != 8; i++)
+ {
+ min_res1 = MIN (min_res1, a[i]);
+ max_res1 = MAX (max_res1, a[i]);
+ }
+
+ min_res2 = min_res1;
+ max_res2 = max_res1;
+ for (int i = 8 ; i != 16; i++)
+ {
+ min_res2 = MIN (min_res2, a[i]);
+ max_res2 = MAX (max_res2, a[i]);
+ }
+
+ min_res3 = min_res2;
+ max_res3 = max_res2;
+ for (int i = 16 ; i != 32; i++)
+ {
+ min_res3 = MIN (min_res3, a[i]);
+ max_res3 = MAX (max_res3, a[i]);
+ }
+
+ min_exp1 = reduc_min_128 (a);
+ min_exp2 = reduc_min_256 (a);
+ min_exp3 = reduc_min_512 (a);
+ max_exp1 = reduc_max_128 (a);
+ max_exp2 = reduc_max_256 (a);
+ max_exp3 = reduc_max_512 (a);
+
+ if (min_exp1 != min_res1 || min_exp2 != min_res2 || min_exp3 != min_res3
+ || max_exp1 != max_res1 || max_exp2 != max_res2 || max_exp3 != max_res3)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1a.c
new file mode 100644
index 0000000..a9e45fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1a.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+_Float16
+f1 (_Float16 x)
+{
+ return __builtin_fabsf16 (x);
+}
+
+_Float16
+f2 (_Float16 x, _Float16 y)
+{
+ return __builtin_copysignf16 (x, y);
+}
+
+_Float16
+f3 (_Float16 x)
+{
+ return -x;
+}
+
+_Float16
+f4 (_Float16 x, _Float16 y)
+{
+ return x * __builtin_copysignf16 (1, y);
+}
+
+
+/* { dg-final { scan-assembler-times "vandps\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vpternlogd\[^\n\r\]*xmm\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "vxorps\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1b.c
new file mode 100644
index 0000000..7a29251
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-scalar-bitwise-1b.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+void NOINLINE
+emulate_absneg_ph (V512 * dest, V512 op1, int abs)
+{
+ V512 v1, v2, v3, v4;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v3, &v4);
+
+ for (i = 0; i != 16; i++) {
+ if (abs) {
+ v3.f32[i] = __builtin_fabsf (v1.f32[i]);
+ v4.f32[i] = __builtin_fabsf (v2.f32[i]);
+ }
+ else {
+ v3.f32[i] = -v1.f32[i];
+ v4.f32[i] = -v2.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v3, v4);
+}
+
+void NOINLINE
+emulate_copysign_ph (V512 * dest, V512 op1, V512 op2, int xorsign)
+{
+ V512 v1, v2, v3, v4, v5, v6;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v5, &v6);
+
+ for (i = 0; i != 16; i++) {
+ if (xorsign) {
+ v5.f32[i] = v1.f32[i] * __builtin_copysignf (1, v3.f32[i]);
+ v6.f32[i] = v2.f32[i] * __builtin_copysignf (1, v4.f32[i]);
+ }
+ else {
+ v5.f32[i] = __builtin_copysignf (v1.f32[i], v3.f32[i]);
+ v6.f32[i] = __builtin_copysignf (v2.f32[i], v4.f32[i]);
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res, exp;
+
+ init_src ();
+
+ /* Abs for float16. */
+ emulate_absneg_ph (&exp, src1, 1);
+ res.f16[0] = __builtin_fabsf16 (src1.f16[0]);
+ check_results (&res, &exp, 1, "abs_float16");
+
+ /* Neg for float16. */
+ emulate_absneg_ph (&exp, src1, 0);
+ res.f16[0] = -(src1.f16[0]);
+ check_results (&res, &exp, 1, "neg_float16");
+
+ /* Copysign for float16. */
+ emulate_copysign_ph (&exp, src1, src2, 0);
+ res.f16[0] = __builtin_copysignf16 (src1.f16[0], src2.f16[0]);
+ check_results (&res, &exp, 1, "copysign_float16");
+
+ /* Xorsign for float16. */
+ emulate_copysign_ph (&exp, src1, src2, 1);
+ res.f16[0] = src1.f16[0] * __builtin_copysignf16 (1, src2.f16[0]);
+ check_results (&res, &exp, 1, "xorsign_float16");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c
new file mode 100644
index 0000000..2ef901a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-trunc-extendvnhf.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern double df[8];
+extern float sf[16];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define TRUNCHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+truncv##size##mode##v##size##hf () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ hf[i] = mode[i]; \
+}
+
+#define EXTENDHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+extendv##size##hf##v##size##mode () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ mode[i] = hf[i]; \
+}
+
+TRUNCHFVV(8, df)
+TRUNCHFVV(4, df)
+TRUNCHFVV(2, df)
+TRUNCHFVV(16, sf)
+TRUNCHFVV(8, sf)
+TRUNCHFVV(4, sf)
+EXTENDHFVV(8, df)
+EXTENDHFVV(4, df)
+EXTENDHFVV(2, df)
+EXTENDHFVV(16, sf)
+EXTENDHFVV(8, sf)
+EXTENDHFVV(4, sf)
+
+/* { dg-final { scan-assembler-times "vcvtpd2phz\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxy\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c
new file mode 100644
index 0000000..2c025b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-trunchf.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*(?:%xmm\[0-9\]|\\(%esp\\))+, %eax(?:\n|\[ \\t\]+#)" 3 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*(?:%xmm\[0-9\]|\\(%esp\\))+, %eax(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+, %rax(?:\n|\[ \\t\]+#)" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+, %rax(?:\n|\[ \\t\]+#)" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xorl\[ \\t\]+%edx, %edx" { target ia32 } } } */
+
+#include <immintrin.h>
+
+short
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si16 (_Float16 f)
+{
+ return f;
+}
+
+unsigned short
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su16 (_Float16 f)
+{
+ return f;
+}
+
+int
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si32 (_Float16 f)
+{
+ return f;
+}
+
+unsigned int
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su32 (_Float16 f)
+{
+ return f;
+}
+
+long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_si64 (_Float16 f)
+{
+ return f;
+}
+
+unsigned long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su64 (_Float16 f)
+{
+ return f;
+}
+
+unsigned long long
+__attribute__ ((noinline, noclone))
+trunc_f16_to_su64_zext (_Float16 f)
+{
+ return (unsigned int) f;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c b/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c
new file mode 100644
index 0000000..7a51c9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-truncvnhf.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-slp-vectorize -mprefer-vector-width=512" } */
+
+extern long long di[8];
+extern unsigned long long udi[8];
+extern int si[16];
+extern unsigned int usi[16];
+extern short hi[32];
+extern unsigned short uhi[32];
+extern _Float16 hf[32];
+
+#define DO_PRAGMA(X) _Pragma(#X)
+
+#define FIX_TRUNCHFVV(size, mode) \
+ void __attribute__ ((noinline, noclone)) \
+fix_trunc##size##hf##v##size##mode () \
+{\
+ int i; \
+ DO_PRAGMA (GCC unroll size) \
+ for (i = 0; i < size; i++) \
+ mode[i] = hf[i]; \
+}
+
+FIX_TRUNCHFVV(32, hi)
+FIX_TRUNCHFVV(16, hi)
+FIX_TRUNCHFVV(8, hi)
+FIX_TRUNCHFVV(16, si)
+FIX_TRUNCHFVV(8, si)
+FIX_TRUNCHFVV(4, si)
+FIX_TRUNCHFVV(8, di)
+FIX_TRUNCHFVV(4, di)
+FIX_TRUNCHFVV(2, di)
+
+FIX_TRUNCHFVV(32, uhi)
+FIX_TRUNCHFVV(16, uhi)
+FIX_TRUNCHFVV(8, uhi)
+FIX_TRUNCHFVV(16, usi)
+FIX_TRUNCHFVV(8, usi)
+FIX_TRUNCHFVV(4, usi)
+FIX_TRUNCHFVV(8, udi)
+FIX_TRUNCHFVV(4, udi)
+FIX_TRUNCHFVV(2, udi)
+
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-1.c
new file mode 100644
index 0000000..cf0cc74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+void
+test_512 (void)
+{
+ V512 res;
+
+ res.ymmh[0] = _mm512_castph512_ph256 (src1.zmmh);
+ check_results (&res, &src1, 16, "_mm512_castph512_ph256");
+
+ res.xmmh[0] = _mm512_castph512_ph128 (src1.zmmh);
+ check_results (&res, &src1, 8, "_mm512_castph512_ph128");
+
+ res.zmmh = _mm512_castph256_ph512 (src1.ymmh[0]);
+ check_results (&res, &src1, 16, "_mm512_castph256_ph512");
+
+ res.zmmh = _mm512_castph128_ph512 (src1.xmmh[0]);
+ check_results (&res, &src1, 8, "_mm512_castph128_ph512");
+
+ res.zmm = _mm512_castph_ps (src1.zmmh);
+ check_results (&res, &src1, 32, "_mm512_castph_ps");
+
+ res.zmmd = _mm512_castph_pd (src1.zmmh);
+ check_results (&res, &src1, 32, "_mm512_castph_pd");
+
+ res.zmmi = _mm512_castph_si512 (src1.zmmh);
+ check_results (&res, &src1, 32, "_mm512_castph_si512");
+
+ res.zmmh = _mm512_castps_ph (src1.zmm);
+ check_results (&res, &src1, 32, "_mm512_castps_ph");
+
+ res.zmmh = _mm512_castpd_ph (src1.zmmd);
+ check_results (&res, &src1, 32, "_mm512_castpd_ph");
+
+ res.zmmh = _mm512_castsi512_ph (src1.zmmi);
+ check_results (&res, &src1, 32, "_mm512_castsi512_ph");
+
+ if (n_errs != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-2.c
new file mode 100644
index 0000000..a29f1db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-typecast-2.c
@@ -0,0 +1,43 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512f-check.h"
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+void
+do_test (void)
+{
+ union512i_d zero;
+ union512h ad;
+ union256h b,bd;
+ union128h c;
+
+ int i;
+
+ for (i = 0; i < 16; i++)
+ {
+ b.a[i] = 65.43f + i;
+ zero.a[i] = 0;
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ c.a[i] = 32.01f + i;
+ }
+
+ ad.x = _mm512_zextph256_ph512 (b.x);
+ if (memcmp (ad.a, b.a, 32)
+ || memcmp (&ad.a[16], &zero.a, 32))
+ abort ();
+
+ ad.x = _mm512_zextph128_ph512 (c.x);
+ if (memcmp (ad.a, c.a, 16)
+ || memcmp (&ad.a[8], &zero.a, 48))
+ abort ();
+
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-v4hf-concat.c b/gcc/testsuite/gcc.target/i386/avx512fp16-v4hf-concat.c
new file mode 100644
index 0000000..3b8a7f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-v4hf-concat.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vpunpcklqdq" 1 } } */
+
+typedef _Float16 v8hf __attribute__((vector_size (16)));
+typedef _Float16 v4hf __attribute__((vector_size (8)));
+
+v8hf foov (v4hf a, v4hf b)
+{
+ return __builtin_shufflevector (a, b, 0, 1, 2, 3, 4, 5, 6, 7);
+}
+
+v8hf foov2 (v4hf a)
+{
+ return __builtin_shufflevector (a, (v4hf){0}, 0, 1, 2, 3, 4, 5, 6, 7);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1a.c
new file mode 100644
index 0000000..0590c34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_add_ph (x1, x2);
+ res1 = _mm512_mask_add_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_add_ph (m32, x1, x2);
+
+ res = _mm512_add_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_add_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_add_round_ph (m32, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1b.c
new file mode 100644
index 0000000..1c412b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddph-1b.c
@@ -0,0 +1,92 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(add_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] + v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] + v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(add_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_add_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _add_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(add_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_add_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_add_ph);
+
+ EMULATE(add_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_add_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_add_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(add_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_add_round_ph) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _add_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(add_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_add_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_add_round_ph);
+
+ EMULATE(add_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_add_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_add_round_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1a.c
new file mode 100644
index 0000000..97aac3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_add_sh (x1, x2);
+ res = _mm_mask_add_sh (res, m8, x1, x2);
+ res = _mm_maskz_add_sh (m8, x1, x2);
+
+ res = _mm_add_round_sh (x1, x2, 8);
+ res = _mm_mask_add_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_add_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1b.c
new file mode 100644
index 0000000..724112c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vaddsh-1b.c
@@ -0,0 +1,104 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_add_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] + v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_add_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_add_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_add_sh");
+
+ //DEST.fp16[0] := SRC1.fp16[0] + SRC2.fp16[0]
+ emulate_add_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_add_sh(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_add_sh");
+
+ //dest.fp16[0] remains unchanged
+ init_dest(&res, &exp);
+ emulate_add_sh(&exp, src1, src2, 0x2, 0);
+ res.xmmh[0] = _mm_mask_add_sh(res.xmmh[0], 0x2,
+ src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_add_sh");
+
+ //dest.fp16[0] = 0
+ emulate_add_sh(&exp, src1, src2, 0x2, 1);
+ res.xmmh[0] = _mm_maskz_add_sh(0x2, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_add_sh");
+
+ //DEST.fp16[0] := SRC1.fp16[0] + SRC2.fp16[0]
+ emulate_add_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_add_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_add_sh");
+
+ //DEST.fp16[0] := SRC1.fp16[0] + SRC2.fp16[0]
+ emulate_add_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_add_round_sh(src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_add_round_sh");
+
+ //DEST.fp16[0] := SRC1.fp16[0] + SRC2.fp16[0]
+ emulate_add_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_add_round_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_add_round_sh");
+
+ //dest.fp16[0] remains unchanged
+ init_dest(&res, &exp);
+ emulate_add_sh(&exp, src1, src2, 0x2, 0);
+ res.xmmh[0] = _mm_mask_add_round_sh(res.xmmh[0], 0x2, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_add_round_sh");
+
+ //dest.fp16[0] = 0
+ emulate_add_sh(&exp, src1, src2, 0x2, 1);
+ res.xmmh[0] = _mm_maskz_add_round_sh(0x2, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_add_round_sh");
+
+ //DEST.fp16[0] := SRC1.fp16[0] + SRC2.fp16[0]
+ emulate_add_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_add_round_sh(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_add_round_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-1.c
new file mode 100644
index 0000000..9bd3668
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-1.c
@@ -0,0 +1,122 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-options "-mavx512fp16" } */
+
+#include <stdarg.h>
+#include <assert.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+struct m256h
+{
+ __m256h v;
+};
+
+__m128 n1 = { -283.3, -23.3, 213.4, 1119.03 };
+struct m256h n2 = { { -93.83f16, 893.318f16, 3994.3f16, -39484.0f16, 213.4f16, 323.4f16, 42.5f16, -43.4f16,
+ 234.4f16, 93.9f16, 34.5f16, -14.5f16, -34.9f16, -421.0f16, 234.5f16, 214.5f16 } };
+__m128h n3 = { 11.5f16, -31.80f16, 242.3f16, 136.4f16, 42.8f16, -22.8f16, 343.8f16, 215.4f16 } ;
+_Float16 n4 = 32.4f16;
+double n5 = 103.3;
+__m128h n6 = { -12.3f16, 2.0f16, 245.9f16, -432.1f16, 53.5f16, -13.4f16, 432.5f16, 482.4f16 };
+__m128d n7 = { -91.387, -8193.518 };
+struct m256h n8 = { { -93.83f16, 893.318f16, 3994.3f16, -39484.0f16, 213.4f16, 323.4f16, 42.5f16, -43.4f16,
+ 234.4f16, 93.9f16, 34.5f16, -14.5f16, -34.9f16, -421.0f16, 234.5f16, 214.5f16 } };
+__m128 n9 = { -123.3, 2.3, 3.4, -10.03 };
+__m128h n10 = { 123.3f16, -100.0f16, 246.9f16, 13.4f16, -134.4f16, 35.4f16, 156.5f16, 953.1f16 };
+_Float16 n11 = 40.7f16;
+double n12 = 304.9;
+__m128h n13 = { 23.3f16, -11.0f16, 24.5f16, -24.5f16, 535.4f16, 35.4f16, -13.4f16, 14.5f16 };
+__m256h n14 = { -123.3f16, 23.9f16, 34.4f16, -100.3f16, 284.4f16, 352.5f16, 131.5f16, -13.2f16,
+ 131.4f16, 382.5f16, 38.5f16, 99.6f16, 423.2f16, -12.44f16, 43.2f16, -34.45f16 };
+__m512h n15 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+__m128d n16 = { 73.0, 63.18 };
+__m256 n17 = { -183.3, -22.3, 13.9, -119.3, 483.1, 122.3, -33.4, -9.37 };
+__m128 n18 = { -183.3, 22.3, 13.4, -19.03 };
+
+__m128 e1;
+struct m256h e2;
+__m128h e3;
+_Float16 e4;
+double e5;
+__m128h e6;
+__m128d e7;
+struct m256h e8;
+__m128 e9;
+__m128h e10;
+_Float16 e11;
+double e12;
+__m128h e13;
+__m256h e14;
+__m512h e15;
+__m128d e16;
+__m256 e17;
+__m128 e18;
+
+static void
+__attribute__((noinline))
+foo (va_list va_arglist)
+{
+ e4 = va_arg (va_arglist, _Float16);
+ e5 = va_arg (va_arglist, double);
+ e6 = va_arg (va_arglist, __m128h);
+ e7 = va_arg (va_arglist, __m128d);
+ e8 = va_arg (va_arglist, struct m256h);
+ e9 = va_arg (va_arglist, __m128);
+ e10 = va_arg (va_arglist, __m128h);
+ e11 = va_arg (va_arglist, _Float16);
+ e12 = va_arg (va_arglist, double);
+ e13 = va_arg (va_arglist, __m128h);
+ e14 = va_arg (va_arglist, __m256h);
+ e15 = va_arg (va_arglist, __m512h);
+ e16 = va_arg (va_arglist, __m128d);
+ e17 = va_arg (va_arglist, __m256);
+ e18 = va_arg (va_arglist, __m128);
+ va_end (va_arglist);
+}
+
+static void
+__attribute__((noinline))
+test (__m128 a1, struct m256h a2, __m128h a3, ...)
+{
+ va_list va_arglist;
+
+ e1 = a1;
+ e2 = a2;
+ e3 = a3;
+ va_start (va_arglist, a3);
+ foo (va_arglist);
+ va_end (va_arglist);
+}
+
+static void
+do_test (void)
+{
+ test (n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12,
+ n13, n14, n15, n16, n17, n18);
+ assert (__builtin_memcmp (&e1, &n1, sizeof (e1)) == 0);
+ assert (__builtin_memcmp (&e2, &n2, sizeof (e2)) == 0);
+ assert (__builtin_memcmp (&e3, &n3, sizeof (e3)) == 0);
+ assert (n4 == e4);
+ assert (n5 == e5);
+ assert (__builtin_memcmp (&e6, &n6, sizeof (e6)) == 0);
+ assert (__builtin_memcmp (&e7, &n7, sizeof (e7)) == 0);
+ assert (__builtin_memcmp (&e8, &n8, sizeof (e8)) == 0);
+ assert (__builtin_memcmp (&e9, &n9, sizeof (e9)) == 0);
+ assert (__builtin_memcmp (&e10, &n10, sizeof (e10)) == 0);
+ assert (n11 == e11);
+ assert (n12 == e12);
+ assert (__builtin_memcmp (&e13, &n13, sizeof (e13)) == 0);
+ assert (__builtin_memcmp (&e14, &n14, sizeof (e14)) == 0);
+ assert (__builtin_memcmp (&e15, &n15, sizeof (e15)) == 0);
+ assert (__builtin_memcmp (&e16, &n16, sizeof (e16)) == 0);
+ assert (__builtin_memcmp (&e17, &n17, sizeof (e17)) == 0);
+ assert (__builtin_memcmp (&e18, &n18, sizeof (e18)) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-2.c
new file mode 100644
index 0000000..043f1c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-2.c
@@ -0,0 +1,107 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-options "-mavx512fp16" } */
+
+#include <stdarg.h>
+#include <assert.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+__m128 n1 = { -283.3, -23.3, 213.4, 1119.03 };
+__m256d n2 = { -93.83, 893.318, 3994.3, -39484.0 };
+__m128h n3 = { 11.5f16, -31.80f16, 242.3f16, 136.4f16, 42.8f16, -22.8f16, 343.8f16, 215.4f16 } ;
+_Float16 n4 = 32.4f16;
+double n5 = 103.3;
+__m128h n6 = { -12.3f16, 2.0f16, 245.9f16, -432.1f16, 53.5f16, -13.4f16, 432.5f16, 482.4f16 };
+__m128d n7 = { -91.387, -8193.518 };
+__m256d n8 = { -123.3, 2.3, 3.4, -10.03 };
+__m128 n9 = { -123.3, 2.3, 3.4, -10.03 };
+__m128h n10 = { 123.3f16, -100.0f16, 246.9f16, 13.4f16, -134.4f16, 35.4f16, 156.5f16, 953.1f16 };
+_Float16 n11 = 40.7f16;
+double n12 = 304.9;
+__m128h n13 = { 23.3f16, -11.0f16, 24.5f16, -24.5f16, 535.4f16, 35.4f16, -13.4f16, 14.5f16 };
+__m256h n14 = { -123.3f16, 23.9f16, 34.4f16, -100.3f16, 284.4f16, 352.5f16, 131.5f16, -13.2f16,
+ 131.4f16, 382.5f16, 38.5f16, 99.6f16, 423.2f16, -12.44f16, 43.2f16, -34.45f16 };
+__m512h n15 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+__m128d n16 = { 73.0, 63.18 };
+__m256 n17 = { -183.3, -22.3, 13.9, -119.3, 483.1, 122.3, -33.4, -9.37 };
+__m128 n18 = { -183.3, 22.3, 13.4, -19.03 };
+
+__m128 e1;
+__m256d e2;
+__m128h e3;
+_Float16 e4;
+double e5;
+__m128h e6;
+__m128d e7;
+__m256d e8;
+__m128 e9;
+__m128h e10;
+_Float16 e11;
+double e12;
+__m128h e13;
+__m256h e14;
+__m512h e15;
+__m128d e16;
+__m256 e17;
+__m128 e18;
+
+static void
+__attribute__((noinline))
+test (__m128 a1, __m256d a2, __m128h a3, ...)
+{
+ va_list va_arglist;
+
+ e1 = a1;
+ e2 = a2;
+ e3 = a3;
+ va_start (va_arglist, a3);
+ e4 = va_arg (va_arglist, _Float16);
+ e5 = va_arg (va_arglist, double);
+ e6 = va_arg (va_arglist, __m128h);
+ e7 = va_arg (va_arglist, __m128d);
+ e8 = va_arg (va_arglist, __m256d);
+ e9 = va_arg (va_arglist, __m128);
+ e10 = va_arg (va_arglist, __m128h);
+ e11 = va_arg (va_arglist, _Float16);
+ e12 = va_arg (va_arglist, double);
+ e13 = va_arg (va_arglist, __m128h);
+ e14 = va_arg (va_arglist, __m256h);
+ e15 = va_arg (va_arglist, __m512h);
+ e16 = va_arg (va_arglist, __m128d);
+ e17 = va_arg (va_arglist, __m256);
+ e18 = va_arg (va_arglist, __m128);
+ va_end (va_arglist);
+}
+
+static void
+do_test (void)
+{
+ test (n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12,
+ n13, n14, n15, n16, n17, n18);
+ assert (__builtin_memcmp (&e1, &n1, sizeof (e1)) == 0);
+ assert (__builtin_memcmp (&e2, &n2, sizeof (e2)) == 0);
+ assert (__builtin_memcmp (&e3, &n3, sizeof (e3)) == 0);
+ assert (n4 == e4);
+ assert (n5 == e5);
+ assert (__builtin_memcmp (&e6, &n6, sizeof (e6)) == 0);
+ assert (__builtin_memcmp (&e7, &n7, sizeof (e7)) == 0);
+ assert (__builtin_memcmp (&e8, &n8, sizeof (e8)) == 0);
+ assert (__builtin_memcmp (&e9, &n9, sizeof (e9)) == 0);
+ assert (__builtin_memcmp (&e10, &n10, sizeof (e10)) == 0);
+ assert (n11 == e11);
+ assert (n12 == e12);
+ assert (__builtin_memcmp (&e13, &n13, sizeof (e13)) == 0);
+ assert (__builtin_memcmp (&e14, &n14, sizeof (e14)) == 0);
+ assert (__builtin_memcmp (&e15, &n15, sizeof (e15)) == 0);
+ assert (__builtin_memcmp (&e16, &n16, sizeof (e16)) == 0);
+ assert (__builtin_memcmp (&e17, &n17, sizeof (e17)) == 0);
+ assert (__builtin_memcmp (&e18, &n18, sizeof (e18)) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-3.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-3.c
new file mode 100644
index 0000000..cb414a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-3.c
@@ -0,0 +1,114 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-options "-mavx512fp16" } */
+
+#include <stdarg.h>
+#include <assert.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+struct m256h
+{
+ __m256h v;
+};
+
+__m128 n1 = { -283.3, -23.3, 213.4, 1119.03 };
+struct m256h n2 = { { -93.83f16, 893.318f16, 3994.3f16, -39484.0f16, 213.4f16, 323.4f16, 42.5f16, -43.4f16,
+ 234.4f16, 93.9f16, 34.5f16, -14.5f16, -34.9f16, -421.0f16, 234.5f16, 214.5f16 } };
+__m128h n3 = { 11.5f16, -31.80f16, 242.3f16, 136.4f16, 42.8f16, -22.8f16, 343.8f16, 215.4f16 } ;
+_Float16 n4 = 32.4f16;
+double n5 = 103.3;
+__m128h n6 = { -12.3f16, 2.0f16, 245.9f16, -432.1f16, 53.5f16, -13.4f16, 432.5f16, 482.4f16 };
+__m128d n7 = { -91.387, -8193.518 };
+struct m256h n8 = { { -93.83f16, 893.318f16, 3994.3f16, -39484.0f16, 213.4f16, 323.4f16, 42.5f16, -43.4f16,
+ 234.4f16, 93.9f16, 34.5f16, -14.5f16, -34.9f16, -421.0f16, 234.5f16, 214.5f16 } };
+__m128 n9 = { -123.3, 2.3, 3.4, -10.03 };
+__m128h n10 = { 123.3f16, -100.0f16, 246.9f16, 13.4f16, -134.4f16, 35.4f16, 156.5f16, 953.1f16 };
+_Float16 n11 = 40.7f16;
+double n12 = 304.9;
+__m128h n13 = { 23.3f16, -11.0f16, 24.5f16, -24.5f16, 535.4f16, 35.4f16, -13.4f16, 14.5f16 };
+__m256h n14 = { -123.3f16, 23.9f16, 34.4f16, -100.3f16, 284.4f16, 352.5f16, 131.5f16, -13.2f16,
+ 131.4f16, 382.5f16, 38.5f16, 99.6f16, 423.2f16, -12.44f16, 43.2f16, -34.45f16 };
+__m512h n15 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+__m128d n16 = { 73.0, 63.18 };
+__m256 n17 = { -183.3, -22.3, 13.9, -119.3, 483.1, 122.3, -33.4, -9.37 };
+__m128 n18 = { -183.3, 22.3, 13.4, -19.03 };
+
+__m128 e1;
+struct m256h e2;
+__m128h e3;
+_Float16 e4;
+double e5;
+__m128h e6;
+__m128d e7;
+struct m256h e8;
+__m128 e9;
+__m128h e10;
+_Float16 e11;
+double e12;
+__m128h e13;
+__m256h e14;
+__m512h e15;
+__m128d e16;
+__m256 e17;
+__m128 e18;
+
+static void
+__attribute__((noinline))
+test (__m128 a1, struct m256h a2, __m128h a3, ...)
+{
+ va_list va_arglist;
+
+ e1 = a1;
+ e2 = a2;
+ e3 = a3;
+ va_start (va_arglist, a3);
+ e4 = va_arg (va_arglist, _Float16);
+ e5 = va_arg (va_arglist, double);
+ e6 = va_arg (va_arglist, __m128h);
+ e7 = va_arg (va_arglist, __m128d);
+ e8 = va_arg (va_arglist, struct m256h);
+ e9 = va_arg (va_arglist, __m128);
+ e10 = va_arg (va_arglist, __m128h);
+ e11 = va_arg (va_arglist, _Float16);
+ e12 = va_arg (va_arglist, double);
+ e13 = va_arg (va_arglist, __m128h);
+ e14 = va_arg (va_arglist, __m256h);
+ e15 = va_arg (va_arglist, __m512h);
+ e16 = va_arg (va_arglist, __m128d);
+ e17 = va_arg (va_arglist, __m256);
+ e18 = va_arg (va_arglist, __m128);
+ va_end (va_arglist);
+}
+
+static void
+do_test (void)
+{
+ test (n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12,
+ n13, n14, n15, n16, n17, n18);
+ assert (__builtin_memcmp (&e1, &n1, sizeof (e1)) == 0);
+ assert (__builtin_memcmp (&e2, &n2, sizeof (e2)) == 0);
+ assert (__builtin_memcmp (&e3, &n3, sizeof (e3)) == 0);
+ assert (n4 == e4);
+ assert (n5 == e5);
+ assert (__builtin_memcmp (&e6, &n6, sizeof (e6)) == 0);
+ assert (__builtin_memcmp (&e7, &n7, sizeof (e7)) == 0);
+ assert (__builtin_memcmp (&e8, &n8, sizeof (e8)) == 0);
+ assert (__builtin_memcmp (&e9, &n9, sizeof (e9)) == 0);
+ assert (__builtin_memcmp (&e10, &n10, sizeof (e10)) == 0);
+ assert (n11 == e11);
+ assert (n12 == e12);
+ assert (__builtin_memcmp (&e13, &n13, sizeof (e13)) == 0);
+ assert (__builtin_memcmp (&e14, &n14, sizeof (e14)) == 0);
+ assert (__builtin_memcmp (&e15, &n15, sizeof (e15)) == 0);
+ assert (__builtin_memcmp (&e16, &n16, sizeof (e16)) == 0);
+ assert (__builtin_memcmp (&e17, &n17, sizeof (e17)) == 0);
+ assert (__builtin_memcmp (&e18, &n18, sizeof (e18)) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-4.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-4.c
new file mode 100644
index 0000000..962c2bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vararg-4.c
@@ -0,0 +1,115 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-options "-mavx512fp16" } */
+
+#include <stdarg.h>
+#include <assert.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+__m128 n1 = { -283.3, -23.3, 213.4, 1119.03 };
+__m256d n2 = { -93.83, 893.318, 3994.3, -39484.0 };
+__m128h n3 = { 11.5f16, -31.80f16, 242.3f16, 136.4f16, 42.8f16, -22.8f16, 343.8f16, 215.4f16 } ;
+_Float16 n4 = 32.4f16;
+double n5 = 103.3;
+__m128h n6 = { -12.3f16, 2.0f16, 245.9f16, -432.1f16, 53.5f16, -13.4f16, 432.5f16, 482.4f16 };
+__m128d n7 = { -91.387, -8193.518 };
+__m256d n8 = { -123.3, 2.3, 3.4, -10.03 };
+__m128 n9 = { -123.3, 2.3, 3.4, -10.03 };
+__m128h n10 = { 123.3f16, -100.0f16, 246.9f16, 13.4f16, -134.4f16, 35.4f16, 156.5f16, 953.1f16 };
+_Float16 n11 = 40.7f16;
+double n12 = 304.9;
+__m128h n13 = { 23.3f16, -11.0f16, 24.5f16, -24.5f16, 535.4f16, 35.4f16, -13.4f16, 14.5f16 };
+__m256h n14 = { -123.3f16, 23.9f16, 34.4f16, -100.3f16, 284.4f16, 352.5f16, 131.5f16, -13.2f16,
+ 131.4f16, 382.5f16, 38.5f16, 99.6f16, 423.2f16, -12.44f16, 43.2f16, -34.45f16 };
+__m512h n15 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16,
+ 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+__m128d n16 = { 73.0, 63.18 };
+__m256 n17 = { -183.3, -22.3, 13.9, -119.3, 483.1, 122.3, -33.4, -9.37 };
+__m128 n18 = { -183.3, 22.3, 13.4, -19.03 };
+
+__m128 e1;
+__m256d e2;
+__m128h e3;
+_Float16 e4;
+double e5;
+__m128h e6;
+__m128d e7;
+__m256d e8;
+__m128 e9;
+__m128h e10;
+_Float16 e11;
+double e12;
+__m128h e13;
+__m256h e14;
+__m512h e15;
+__m128d e16;
+__m256 e17;
+__m128 e18;
+
+static void
+__attribute__((noinline))
+foo (va_list va_arglist)
+{
+ e4 = va_arg (va_arglist, _Float16);
+ e5 = va_arg (va_arglist, double);
+ e6 = va_arg (va_arglist, __m128h);
+ e7 = va_arg (va_arglist, __m128d);
+ e8 = va_arg (va_arglist, __m256d);
+ e9 = va_arg (va_arglist, __m128);
+ e10 = va_arg (va_arglist, __m128h);
+ e11 = va_arg (va_arglist, _Float16);
+ e12 = va_arg (va_arglist, double);
+ e13 = va_arg (va_arglist, __m128h);
+ e14 = va_arg (va_arglist, __m256h);
+ e15 = va_arg (va_arglist, __m512h);
+ e16 = va_arg (va_arglist, __m128d);
+ e17 = va_arg (va_arglist, __m256);
+ e18 = va_arg (va_arglist, __m128);
+ va_end (va_arglist);
+}
+
+static void
+__attribute__((noinline))
+test (__m128 a1, __m256d a2, __m128h a3, ...)
+{
+ va_list va_arglist;
+
+ e1 = a1;
+ e2 = a2;
+ e3 = a3;
+ va_start (va_arglist, a3);
+ foo (va_arglist);
+ va_end (va_arglist);
+}
+
+static void
+do_test (void)
+{
+ test (n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12,
+ n13, n14, n15, n16, n17, n18);
+ assert (__builtin_memcmp (&e1, &n1, sizeof (e1)) == 0);
+ assert (__builtin_memcmp (&e2, &n2, sizeof (e2)) == 0);
+ assert (__builtin_memcmp (&e3, &n3, sizeof (e3)) == 0);
+ assert (n4 == e4);
+ assert (n5 == e5);
+ assert (__builtin_memcmp (&e6, &n6, sizeof (e6)) == 0);
+ assert (__builtin_memcmp (&e7, &n7, sizeof (e7)) == 0);
+ assert (__builtin_memcmp (&e8, &n8, sizeof (e8)) == 0);
+ assert (__builtin_memcmp (&e9, &n9, sizeof (e9)) == 0);
+ assert (__builtin_memcmp (&e10, &n10, sizeof (e10)) == 0);
+ assert (n11 == e11);
+ assert (n12 == e12);
+ assert (__builtin_memcmp (&e13, &n13, sizeof (e13)) == 0);
+ assert (__builtin_memcmp (&e14, &n14, sizeof (e14)) == 0);
+ assert (__builtin_memcmp (&e15, &n15, sizeof (e15)) == 0);
+ assert (__builtin_memcmp (&e16, &n16, sizeof (e16)) == 0);
+ assert (__builtin_memcmp (&e17, &n17, sizeof (e17)) == 0);
+ assert (__builtin_memcmp (&e18, &n18, sizeof (e18)) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1a.c
new file mode 100644
index 0000000..6425c46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1a.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$1\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%k\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$2\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$3\[^\n\r]*\{sae\}\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\[^\{\n\]*\\\$4\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __mmask32 res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cmp_ph_mask (x1, x2, 1);
+ res1 = _mm512_mask_cmp_ph_mask (m32, x1, x2, 2);
+ res = _mm512_cmp_round_ph_mask (x1, x2, 3, 8);
+ res1 = _mm512_mask_cmp_round_ph_mask (m32, x1, x2, 4, 4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1b.c
new file mode 100644
index 0000000..ec5eccf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpph-1b.c
@@ -0,0 +1,70 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+__mmask32 NOINLINE
+EMULATE(cmp_ph) (V512 op1, V512 op2,
+ __mmask32 k, int predicate)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i, j;
+ __mmask16 mr1 = 0, mr2 = 0;
+ __mmask16 m1, m2;
+ __mmask32 mr = 0;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) != 0) {
+ j = v1.f32[i] == v3.f32[i] ? 1 : 0;
+ mr1 = mr1 | (j << i);
+ }
+
+ if (((1 << i) & m2) != 0) {
+ j = v2.f32[i] == v4.f32[i] ? 1 : 0;
+ mr2 = mr2 | (j << i);
+ }
+ }
+
+ mr = mr1 | (mr2 << 16);
+ return mr;
+}
+
+void
+TEST (void)
+{
+ __mmask32 res, exp;
+
+ init_src();
+
+ exp = EMULATE(cmp_ph) (src1, src2, NET_MASK, 0);
+ res = INTRINSIC (_cmp_ph_mask) (HF(src1), HF(src2), 0);
+ CHECK_RESULT_MASK (res, exp, N_ELEMS, _cmp_ph_mask);
+
+ exp = EMULATE(cmp_ph) (src1, src2, MASK_VALUE, 0);
+ res = INTRINSIC (_mask_cmp_ph_mask) (MASK_VALUE, HF(src1), HF(src2), 0);
+ CHECK_RESULT_MASK (res, exp, N_ELEMS, _mask_cmp_ph_mask);
+
+#if AVX512F_LEN == 512
+ exp = EMULATE(cmp_ph) (src1, src2, NET_MASK, 0);
+ res = INTRINSIC (_cmp_round_ph_mask) (HF(src1), HF(src2), 0, 8);
+ CHECK_RESULT_MASK (res, exp, N_ELEMS, _cmp_round_ph_mask);
+
+ exp = EMULATE(cmp_ph) (src1, src2, MASK_VALUE, 0);
+ res = INTRINSIC (_mask_cmp_round_ph_mask) (MASK_VALUE, HF(src1), HF(src2), 0, 8);
+ CHECK_RESULT_MASK (res, exp, N_ELEMS, _mask_cmp_round_ph_mask);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1a.c
new file mode 100644
index 0000000..5cce097
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1a.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$3\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\[^\{\n\]*\\\$4\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$3\[^\n\r]*\{sae\}\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\[^\{\n\]*\\\$4\[^\n\r]*\{sae\}\[^\n\r\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __mmask8 res, res1, res2;
+volatile __m128h x1, x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_cmp_sh_mask (x1, x2, 3);
+ res = _mm_mask_cmp_sh_mask (m8, x1, x2, 4);
+ res = _mm_cmp_round_sh_mask (x1, x2, 3, 8);
+ res1 = _mm_mask_cmp_round_sh_mask (m8, x1, x2, 4, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1b.c
new file mode 100644
index 0000000..9deae52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcmpsh-1b.c
@@ -0,0 +1,45 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+__mmask8 NOINLINE
+emulate_cmp_sh(V512 op1, V512 op2,
+ __mmask8 k, int predicate)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ __mmask8 mr = 0;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+
+ if ((k&1) || !k)
+ mr = v1.f32[0] == v3.f32[0] ? 1 : 0;
+
+ return mr;
+}
+
+void
+test_512 (void)
+{
+ __mmask8 res, exp;
+
+ init_src();
+
+ exp = emulate_cmp_sh(src1, src2, 0x1, 0);
+ res = _mm_cmp_round_sh_mask(src1.xmmh[0], src2.xmmh[0], 0, 8);
+ check_results_mask(res, exp, 1, "_mm_cmp_round_sh_mask");
+
+ exp = emulate_cmp_sh(src1, src2, 0x1, 0);
+ res = _mm_mask_cmp_round_sh_mask(0x1, src1.xmmh[0], src2.xmmh[0], 0, 8);
+ check_results_mask(res, exp, 1, "_mm_mask_cmp_round_sh_mask");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1a.c
new file mode 100644
index 0000000..b87ffd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1a.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$3\[^\n\r]*\{sae\}\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$7\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$16\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$1\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$2\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$14\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$13\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$20\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$0\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$17\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$18\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$30\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$29\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpsh\[ \\t\]+\\\$4\[^\n\r0-9]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x, y;
+volatile int res;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_comi_round_sh (x, y, 3, 8);
+ res = _mm_comi_sh (x, y, 7);
+ res = _mm_comieq_sh (x, y);
+ res = _mm_comilt_sh (x, y);
+ res = _mm_comile_sh (x, y);
+ res = _mm_comigt_sh (x, y);
+ res = _mm_comige_sh (x, y);
+ res = _mm_comineq_sh (x, y);
+ res = _mm_ucomieq_sh (x, y);
+ res = _mm_ucomilt_sh (x, y);
+ res = _mm_ucomile_sh (x, y);
+ res = _mm_ucomigt_sh (x, y);
+ res = _mm_ucomige_sh (x, y);
+ res = _mm_ucomineq_sh (x, y);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1b.c
new file mode 100644
index 0000000..8c39800
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1b.c
@@ -0,0 +1,66 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+
+#define CMP(imm, rel) \
+ dst_ref = 0; \
+ dst_ref = ((int) rel) | dst_ref; \
+ dst = _mm_comi_round_sh(src1.xmmh[0], src2.xmmh[0], imm, \
+ _MM_FROUND_NO_EXC); \
+ if (dst_ref != dst) abort(); \
+
+void
+test_512 (void)
+{
+ V512 v1,v2,v3,v4;
+ float s1,s2;
+ int res,exp,dst;
+ __mmask8 dst_ref;
+
+ init_src();
+ unpack_ph_2twops(src1, &v1, &v2);
+ unpack_ph_2twops(src2, &v3, &v4);
+ s1 = v1.f32[0];
+ s2 = v3.f32[0];
+
+ CMP(_CMP_EQ_OQ, !isunordered(s1, s2) && s1 == s2);
+ CMP(_CMP_LT_OS, !isunordered(s1, s2) && s1 < s2);
+ CMP(_CMP_LE_OS, !isunordered(s1, s2) && s1 <= s2);
+ CMP(_CMP_UNORD_Q, isunordered(s1, s2));
+ CMP(_CMP_NEQ_UQ, isunordered(s1, s2) || s1 != s2);
+ CMP(_CMP_NLT_US, isunordered(s1, s2) || s1 >= s2);
+ CMP(_CMP_NLE_US, isunordered(s1, s2) || s1 > s2);
+ CMP(_CMP_ORD_Q, !isunordered(s1, s2));
+
+ CMP(_CMP_EQ_UQ, isunordered(s1, s2) || s1 == s2);
+ CMP(_CMP_NGE_US, isunordered(s1, s2) || s1 < s2);
+ CMP(_CMP_NGT_US, isunordered(s1, s2) || s1 <= s2);
+
+ CMP(_CMP_FALSE_OQ, 0);
+ CMP(_CMP_NEQ_OQ, !isunordered(s1, s2) && s1 != s2);
+ CMP(_CMP_GE_OS, !isunordered(s1, s2) && s1 >= s2);
+ CMP(_CMP_GT_OS, !isunordered(s1, s2) && s1 > s2);
+ CMP(_CMP_TRUE_UQ, 1);
+
+ CMP(_CMP_EQ_OS, !isunordered(s1, s2) && s1 == s2);
+ CMP(_CMP_LT_OQ, !isunordered(s1, s2) && s1 < s2);
+ CMP(_CMP_LE_OQ, !isunordered(s1, s2) && s1 <= s2);
+ CMP(_CMP_UNORD_S, isunordered(s1, s2));
+ CMP(_CMP_NEQ_US, isunordered(s1, s2) || s1 != s2);
+ CMP(_CMP_NLT_UQ, isunordered(s1, s2) || s1 >= s2);
+ CMP(_CMP_NLE_UQ, isunordered(s1, s2) || s1 > s2);
+ CMP(_CMP_ORD_S, !isunordered(s1, s2));
+ CMP(_CMP_EQ_US, isunordered(s1, s2) || s1 == s2);
+ CMP(_CMP_NGE_UQ, isunordered(s1, s2) || s1 < s2);
+ CMP(_CMP_NGT_UQ, isunordered(s1, s2) || s1 <= s2);
+ CMP(_CMP_FALSE_OS, 0);
+ CMP(_CMP_NEQ_OS, !isunordered(s1, s2) && s1 != s2);
+ CMP(_CMP_GE_OQ, !isunordered(s1, s2) && s1 >= s2);
+ CMP(_CMP_GT_OQ, !isunordered(s1, s2) && s1 > s2);
+ CMP(_CMP_TRUE_US, 1);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1c.c
new file mode 100644
index 0000000..77366a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcomish-1c.c
@@ -0,0 +1,66 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+
+#define CMP(imm, rel) \
+ dst_ref = 0; \
+ dst_ref = ((int) rel) | dst_ref; \
+ dst = _mm_comi_round_sh(src1.xmmh[0], src2.xmmh[0], imm, \
+ _MM_FROUND_NO_EXC); \
+ if (dst_ref != dst) abort(); \
+
+void
+test_512 (void)
+{
+ V512 v1,v2,v3,v4;
+ float s1,s2;
+ int res,exp,dst;
+ __mmask8 dst_ref;
+
+ init_src_nanf();
+ unpack_ph_2twops(src1, &v1, &v2);
+ unpack_ph_2twops(src2, &v3, &v4);
+ s1 = v1.f32[0];
+ s2 = v3.f32[0];
+
+ CMP(_CMP_EQ_OQ, !isunordered(s1, s2) && s1 == s2);
+ CMP(_CMP_LT_OS, !isunordered(s1, s2) && s1 < s2);
+ CMP(_CMP_LE_OS, !isunordered(s1, s2) && s1 <= s2);
+ CMP(_CMP_UNORD_Q, isunordered(s1, s2));
+ CMP(_CMP_NEQ_UQ, isunordered(s1, s2) || s1 != s2);
+ CMP(_CMP_NLT_US, isunordered(s1, s2) || s1 >= s2);
+ CMP(_CMP_NLE_US, isunordered(s1, s2) || s1 > s2);
+ CMP(_CMP_ORD_Q, !isunordered(s1, s2));
+
+ CMP(_CMP_EQ_UQ, isunordered(s1, s2) || s1 == s2);
+ CMP(_CMP_NGE_US, isunordered(s1, s2) || s1 < s2);
+ CMP(_CMP_NGT_US, isunordered(s1, s2) || s1 <= s2);
+
+ CMP(_CMP_FALSE_OQ, 0);
+ CMP(_CMP_NEQ_OQ, !isunordered(s1, s2) && s1 != s2);
+ CMP(_CMP_GE_OS, !isunordered(s1, s2) && s1 >= s2);
+ CMP(_CMP_GT_OS, !isunordered(s1, s2) && s1 > s2);
+ CMP(_CMP_TRUE_UQ, 1);
+
+ CMP(_CMP_EQ_OS, !isunordered(s1, s2) && s1 == s2);
+ CMP(_CMP_LT_OQ, !isunordered(s1, s2) && s1 < s2);
+ CMP(_CMP_LE_OQ, !isunordered(s1, s2) && s1 <= s2);
+ CMP(_CMP_UNORD_S, isunordered(s1, s2));
+ CMP(_CMP_NEQ_US, isunordered(s1, s2) || s1 != s2);
+ CMP(_CMP_NLT_UQ, isunordered(s1, s2) || s1 >= s2);
+ CMP(_CMP_NLE_UQ, isunordered(s1, s2) || s1 > s2);
+ CMP(_CMP_ORD_S, !isunordered(s1, s2));
+ CMP(_CMP_EQ_US, isunordered(s1, s2) || s1 == s2);
+ CMP(_CMP_NGE_UQ, isunordered(s1, s2) || s1 < s2);
+ CMP(_CMP_NGT_UQ, isunordered(s1, s2) || s1 <= s2);
+ CMP(_CMP_FALSE_OS, 0);
+ CMP(_CMP_NEQ_OS, !isunordered(s1, s2) && s1 != s2);
+ CMP(_CMP_GE_OQ, !isunordered(s1, s2) && s1 >= s2);
+ CMP(_CMP_GT_OQ, !isunordered(s1, s2) && s1 > s2);
+ CMP(_CMP_TRUE_US, 1);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c
new file mode 100644
index 0000000..e8745ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=512" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 27 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpw|vpcmpeqw)" 12 } } */
+/* { dg-final { scan-assembler-times "vpcmpuw" 6 } } */
+
+typedef unsigned short u16;
+typedef short s16;
+
+#define CONDMOV_LOOP(size, type, ptype, op, name) \
+void \
+__attribute__ ((noinline, noclone, optimize("tree-vectorize"))) \
+loop_cond_##size##ptype##type##name ( \
+ ptype * restrict a, ptype * restrict b, \
+ type * restrict c, type * restrict d) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ { \
+ if (a[i] op b[i]) \
+ d[i] = c[i]; \
+ } \
+}
+
+CONDMOV_LOOP (32, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (32, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (32, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (16, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (16, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (16, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (8, _Float16, _Float16, <, lt)
+CONDMOV_LOOP (8, _Float16, _Float16, >, gt)
+CONDMOV_LOOP (8, _Float16, _Float16, ==, eq)
+CONDMOV_LOOP (32, _Float16, s16, <, lt)
+CONDMOV_LOOP (32, _Float16, s16, >, gt)
+CONDMOV_LOOP (32, _Float16, s16, ==, eq)
+CONDMOV_LOOP (16, _Float16, s16, <, lt)
+CONDMOV_LOOP (16, _Float16, s16, >, gt)
+CONDMOV_LOOP (16, _Float16, s16, ==, eq)
+CONDMOV_LOOP (8, _Float16, s16, <, lt)
+CONDMOV_LOOP (8, _Float16, s16, >, gt)
+CONDMOV_LOOP (8, _Float16, s16, ==, eq)
+CONDMOV_LOOP (32, s16, _Float16, <, lt)
+CONDMOV_LOOP (32, s16, _Float16, >, gt)
+CONDMOV_LOOP (32, s16, _Float16, ==, eq)
+CONDMOV_LOOP (16, s16, _Float16, <, lt)
+CONDMOV_LOOP (16, s16, _Float16, >, gt)
+CONDMOV_LOOP (16, s16, _Float16, ==, eq)
+CONDMOV_LOOP (8, s16, _Float16, <, lt)
+CONDMOV_LOOP (8, s16, _Float16, >, gt)
+CONDMOV_LOOP (8, s16, _Float16, ==, eq)
+CONDMOV_LOOP (32, _Float16, u16, <, lt)
+CONDMOV_LOOP (32, _Float16, u16, >, gt)
+CONDMOV_LOOP (32, _Float16, u16, ==, eq)
+CONDMOV_LOOP (16, _Float16, u16, <, lt)
+CONDMOV_LOOP (16, _Float16, u16, >, gt)
+CONDMOV_LOOP (16, _Float16, u16, ==, eq)
+CONDMOV_LOOP (8, _Float16, u16, <, lt)
+CONDMOV_LOOP (8, _Float16, u16, >, gt)
+CONDMOV_LOOP (8, _Float16, u16, ==, eq)
+CONDMOV_LOOP (32, u16, _Float16, <, lt)
+CONDMOV_LOOP (32, u16, _Float16, >, gt)
+CONDMOV_LOOP (32, u16, _Float16, ==, eq)
+CONDMOV_LOOP (16, u16, _Float16, <, lt)
+CONDMOV_LOOP (16, u16, _Float16, >, gt)
+CONDMOV_LOOP (16, u16, _Float16, ==, eq)
+CONDMOV_LOOP (8, u16, _Float16, <, lt)
+CONDMOV_LOOP (8, u16, _Float16, >, gt)
+CONDMOV_LOOP (8, u16, _Float16, ==, eq)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c
new file mode 100644
index 0000000..a0d5f98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcondmn-loop-2.c
@@ -0,0 +1,143 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=512" } */
+
+static void condmov_test (void);
+#define DO_TEST condmov_test
+#define AVX512FP16
+#define AVX512VL
+#include "avx512f-check.h"
+#include "avx512fp16-vcondmn-loop-1.c"
+
+_Float16 a[32], b[32], c[32], fexp[32], fref[32];
+s16 sa[32], sb[32], sc[32], sexp[32], sref[32];
+u16 ua[32], ub[32], uc[32], uexp[32], uref[32];
+
+#define EMULATE_CONDMOV_LOOP(size, type, ptype, op, name) \
+void \
+__attribute__ ((noinline, noclone)) \
+scalar_cond_##size##ptype##type##name ( \
+ ptype * restrict a, ptype * restrict b, \
+ type * restrict c, type * restrict d) \
+{ \
+ int i; \
+ for (i = 0; i < size; i++) \
+ { \
+ if (a[i] op b[i]) \
+ d[i] = c[i]; \
+ } \
+}
+
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, s16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, s16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (32, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (16, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, <, lt)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, >, gt)
+EMULATE_CONDMOV_LOOP (8, _Float16, u16, ==, eq)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (32, u16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (16, u16, _Float16, ==, eq)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, <, lt)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, >, gt)
+EMULATE_CONDMOV_LOOP (8, u16, _Float16, ==, eq)
+
+void init()
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ ua[i] = sa[i] = a[i] = i;
+ ub[i] = sb[i] = b[i] = i;
+ uc[i] = sc[i] = c[i] = (32 - i) * 2;
+ uexp[i] = sexp[i] = fexp[i] = -1;
+ uref[i] = sref[i] = fref[i] = -1;
+ }
+}
+
+int check_cond(void *a, void *b, int size)
+{
+ int i;
+ u16 *pa = (u16 *)a, *pb = (u16 *)b;
+ for (i = 0; i < size; i++)
+ if (pa[i] != pb[i])
+ return 0;
+ return 1;
+}
+
+#define TEST_CONDMOV_LOOP(size, name) \
+{ \
+ init (); \
+ scalar_cond_##size##_Float16_Float16##name (a, b, c, fexp); \
+ loop_cond_##size##_Float16_Float16##name (a, b, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##_Float16s16##name (a, b, sc, sexp); \
+ loop_cond_##size##_Float16s16##name (a, b, sc, sref); \
+ if (!check_cond ((void *)sexp, (void *)sref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##s16_Float16##name (sa, sb, c, fexp); \
+ loop_cond_##size##s16_Float16##name (sa, sb, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##_Float16u16##name (a, b, uc, uexp); \
+ loop_cond_##size##_Float16u16##name (a, b, uc, uref); \
+ if (!check_cond ((void *)uexp, (void *)uref, size)) \
+ abort(); \
+ \
+ init (); \
+ scalar_cond_##size##u16_Float16##name (ua, ub, c, fexp); \
+ loop_cond_##size##u16_Float16##name (ua, ub, c, fref); \
+ if (!check_cond ((void *)fexp, (void *)fref, size)) \
+ abort(); \
+}
+
+static void condmov_test()
+{
+ TEST_CONDMOV_LOOP (32, lt)
+ TEST_CONDMOV_LOOP (32, gt)
+ TEST_CONDMOV_LOOP (32, eq)
+ TEST_CONDMOV_LOOP (16, lt)
+ TEST_CONDMOV_LOOP (16, gt)
+ TEST_CONDMOV_LOOP (16, eq)
+ TEST_CONDMOV_LOOP (8, lt)
+ TEST_CONDMOV_LOOP (8, gt)
+ TEST_CONDMOV_LOOP (8, eq)
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1a.c
new file mode 100644
index 0000000..45697d94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res, res1, res2;
+volatile __m512i x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepi32_ph (x1);
+ res1 = _mm512_mask_cvtepi32_ph (res, m16, x2);
+ res2 = _mm512_maskz_cvtepi32_ph (m16, x3);
+ res = _mm512_cvt_roundepi32_ph (x1, 4);
+ res1 = _mm512_mask_cvt_roundepi32_ph (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvt_roundepi32_ph (m16, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1b.c
new file mode 100644
index 0000000..a2bb56c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtdq2ph-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 32)
+
+void NOINLINE
+EMULATE(cvtd2_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v5);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtd2_ph)(&exp, src3, NET_MASK, 0);
+ H_HF(res) = INTRINSIC (_cvtepi32_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtepi32_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 0);
+ H_HF(res) = INTRINSIC (_mask_cvtepi32_ph) (H_HF(res), HALF_MASK, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtepi32_ph);
+
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvtepi32_ph) (HALF_MASK, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtepi32_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtd2_ph)(&exp, src3, NET_MASK, 0);
+ H_HF(res) = INTRINSIC (_cvt_roundepi32_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundepi32_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 0);
+ H_HF(res) = INTRINSIC (_mask_cvt_roundepi32_ph) (H_HF(res), HALF_MASK, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundepi32_ph);
+
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvt_roundepi32_ph) (HALF_MASK, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundepi32_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c
new file mode 100644
index 0000000..8f74405
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtpd2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m512d x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtpd_ph (x1);
+ res1 = _mm512_mask_cvtpd_ph (res, m8, x2);
+ res2 = _mm512_maskz_cvtpd_ph (m8, x3);
+ res = _mm512_cvt_roundpd_ph (x1, 4);
+ res1 = _mm512_mask_cvt_roundpd_ph (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundpd_ph (m8, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1b.c
new file mode 100644
index 0000000..dde364b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtpd2ph-1b.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 64)
+
+void NOINLINE
+EMULATE(cvtpd2_ph) (V512 * dest, V512 op1, int n_el,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < n_el; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.f64[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v5);
+ for (i = n_el; i < 8; i++)
+ dest->u16[i] = 0;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvtpd_ph) (DF(src3f));
+ CHECK_RESULT (&res, &exp, 8, _cvtpd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvtpd_ph) (res.xmmh[0], 0xcc,
+ DF(src3f));
+ CHECK_RESULT (&res, &exp, 8, _mask_cvtpd_ph);
+
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, 0xf1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvtpd_ph) (0xf1, DF(src3f));
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvtpd_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvt_roundpd_ph) (DF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _cvt_roundpd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvt_roundpd_ph) (res.xmmh[0], 0xcc,
+ DF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _mask_cvt_roundpd_ph);
+
+ EMULATE(cvtpd2_ph)(&exp, src3f, N_ELEMS, 0xf1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvt_roundpd_ph) (0xf1, DF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvt_roundpd_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1a.c
new file mode 100644
index 0000000..31a5639
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\{rn-sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\{rz-sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m256h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epi32 (x1);
+ res1 = _mm512_mask_cvtph_epi32 (res, m16, x2);
+ res2 = _mm512_maskz_cvtph_epi32 (m16, x3);
+ res = _mm512_cvt_roundph_epi32 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epi32 (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epi32 (m16, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1b.c
new file mode 100644
index 0000000..80a8582
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2dq-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_d) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epi32) (H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epi32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epi32) (SI(res), HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epi32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epi32) (HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epi32);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epi32) (H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epi32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epi32) (SI(res), HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epi32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epi32) (HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epi32);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1a.c
new file mode 100644
index 0000000..b7bb3b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512d res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_pd (x1);
+ res1 = _mm512_mask_cvtph_pd (res, m8, x2);
+ res2 = _mm512_maskz_cvtph_pd (m8, x3);
+ res = _mm512_cvt_roundph_pd (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_pd (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_pd (m8, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1b.c
new file mode 100644
index 0000000..c20888b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2pd-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_pd) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.f64[i] = v1.f32[i];
+ }
+ }
+
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_pd)(&exp, src1, NET_MASK, 0);
+ DF(res) = INTRINSIC (_cvtph_pd) (src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_pd);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_pd)(&exp, src1, 0xcc, 0);
+ DF(res) = INTRINSIC (_mask_cvtph_pd) (DF(res), 0xcc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_pd);
+
+ EMULATE(cvtph2_pd)(&exp, src1, 0xc1, 1);
+ DF(res) = INTRINSIC (_maskz_cvtph_pd) (0xc1, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_pd);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_pd)(&exp, src1, NET_MASK, 0);
+ DF(res) = INTRINSIC (_cvt_roundph_pd) (src1.xmmh[0], _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_pd);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_pd)(&exp, src1, 0xcc, 0);
+ DF(res) = INTRINSIC (_mask_cvt_roundph_pd) (DF(res), 0xcc, src1.xmmh[0], _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_pd);
+
+ EMULATE(cvtph2_pd)(&exp, src1, 0xc1, 1);
+ DF(res) = INTRINSIC (_maskz_cvt_roundph_pd) (0xc1, src1.xmmh[0], _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_pd);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+}
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1a.c
new file mode 100644
index 0000000..c79549f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512 res, res1, res2;
+volatile __m256h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtxph_ps (x1);
+ res1 = _mm512_mask_cvtxph_ps (res, m16, x2);
+ res2 = _mm512_maskz_cvtxph_ps (m16, x3);
+ res = _mm512_cvtx_roundph_ps (x1, 4);
+ res1 = _mm512_mask_cvtx_roundph_ps (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvtx_roundph_ps (m16, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1b.c
new file mode 100644
index 0000000..a2f20c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2psx-1b.c
@@ -0,0 +1,81 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 32)
+#define CHECK_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtxph2_ps) (V512 * dest, V512 op1, int n_el,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < n_el; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i];
+ }
+ }
+
+ for (i = n_el; i < 16; i++)
+ v5.u32[i] = 0;
+
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xffff, 0);
+ SF(res) = INTRINSIC (_cvtxph_ps) (H_HF(src1));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _cvtxph_ps);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xcc, 0);
+ SF(res) = INTRINSIC (_mask_cvtxph_ps) (SF(res), 0xcc, H_HF(src1));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _mask_cvtxph_ps);
+
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xc1, 1);
+ SF(res) = INTRINSIC (_maskz_cvtxph_ps) (0xc1, H_HF(src1));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _maskz_cvtxph_ps);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xffff, 0);
+ SF(res) = INTRINSIC (_cvtx_roundph_ps) (H_HF(src1), _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _cvtx_roundph_ps);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xcc, 0);
+ SF(res) = INTRINSIC (_mask_cvtx_roundph_ps) (SF(res), 0xcc, H_HF(src1), _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _mask_cvtx_roundph_ps);
+
+ EMULATE(cvtxph2_ps)(&exp, src1, N_ELEMS, 0xc1, 1);
+ SF(res) = INTRINSIC (_maskz_cvtx_roundph_ps) (0xc1, H_HF(src1), _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _maskz_cvtx_roundph_ps);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1a.c
new file mode 100644
index 0000000..d80ee61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epi64 (x1);
+ res1 = _mm512_mask_cvtph_epi64 (res, m8, x2);
+ res2 = _mm512_maskz_cvtph_epi64 (m8, x3);
+ res = _mm512_cvt_roundph_epi64 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epi64 (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epi64 (m8, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1b.c
new file mode 100644
index 0000000..42b21cf2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2qq-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_q) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epi64) (src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epi64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epi64) (SI(res), 0xcc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epi64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfa, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epi64) (0xfa, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epi64);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epi64) (src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epi64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epi64) (SI(res), 0xcc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epi64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfa, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epi64) (0xfa, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epi64);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1a.c
new file mode 100644
index 0000000..b4a833a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\{rn-sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\{rz-sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m256h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epu32 (x1);
+ res1 = _mm512_mask_cvtph_epu32 (res, m16, x2);
+ res2 = _mm512_maskz_cvtph_epu32 (m16, x3);
+ res = _mm512_cvt_roundph_epu32 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epu32 (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epu32 (m16, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1b.c
new file mode 100644
index 0000000..15fa0ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2udq-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_d) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epu32) (H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epu32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epu32) (SI(res), HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epu32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epu32) (HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epu32);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epu32) (H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epu32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epu32) (SI(res), HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epu32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epu32) (HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epu32);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c
new file mode 100644
index 0000000..b408779
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epu64 (x1);
+ res1 = _mm512_mask_cvtph_epu64 (res, m8, x2);
+ res2 = _mm512_maskz_cvtph_epu64 (m8, x3);
+ res = _mm512_cvt_roundph_epu64 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epu64 (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epu64 (m8, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1b.c
new file mode 100644
index 0000000..7f34772
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uqq-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_q) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epu64) (src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epu64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epu64) (SI(res), 0xcc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epu64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfc, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epu64) (0xfc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epu64);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epu64) (src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epu64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epu64) (SI(res), 0xcc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epu64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfc, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epu64) (0xfc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epu64);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1a.c
new file mode 100644
index 0000000..2622745
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epu16 (x1);
+ res1 = _mm512_mask_cvtph_epu16 (res, m32, x2);
+ res2 = _mm512_maskz_cvtph_epu16 (m32, x3);
+ res = _mm512_cvt_roundph_epu16 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epu16 (res, m32, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epu16 (m32, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1b.c
new file mode 100644
index 0000000..437a1f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2uw-1b.c
@@ -0,0 +1,84 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_w) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ dest->u16[i] = 0;
+ }
+ }
+ else {
+ dest->u16[i] = v1.f32[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ dest->u16[i+16] = 0;
+ }
+ }
+ else {
+ dest->u16[i+16] = v2.f32[i];
+ }
+ }
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epu16) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epu16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epu16) (SI(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epu16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epu16) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epu16);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epu16) (HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epu16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epu16) (SI(res), MASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epu16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epu16) (ZMASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epu16);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1a.c
new file mode 100644
index 0000000..bcaa744
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtph_epi16 (x1);
+ res1 = _mm512_mask_cvtph_epi16 (res, m32, x2);
+ res2 = _mm512_maskz_cvtph_epi16 (m32, x3);
+ res = _mm512_cvt_roundph_epi16 (x1, 4);
+ res1 = _mm512_mask_cvt_roundph_epi16 (res, m32, x2, 8);
+ res2 = _mm512_maskz_cvt_roundph_epi16 (m32, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1b.c
new file mode 100644
index 0000000..dfa2052
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtph2w-1b.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_w) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ dest->u16[i] = 0;
+ }
+ }
+ else {
+ dest->u16[i] = v1.f32[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ dest->u16[i+16] = 0;
+ }
+ }
+ else {
+ dest->u16[i+16] = v2.f32[i];
+ }
+ }
+}
+
+void
+TEST (void)
+{
+ V512 res, exp;
+
+ init_src();
+
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtph_epi16) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtph_epi16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvtph_epi16) (SI(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtph_epi16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvtph_epi16) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtph_epi16);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvt_roundph_epi16) (HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundph_epi16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvt_roundph_epi16) (SI(res), MASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundph_epi16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvt_roundph_epi16) (ZMASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundph_epi16);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1a.c
new file mode 100644
index 0000000..cb957f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phx\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res, res1, res2;
+volatile __m512 x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtxps_ph (x1);
+ res1 = _mm512_mask_cvtxps_ph (res, m16, x2);
+ res2 = _mm512_maskz_cvtxps_ph (m16, x3);
+ res = _mm512_cvtx_roundps_ph (x1, 4);
+ res1 = _mm512_mask_cvtx_roundps_ph (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvtx_roundps_ph (m16, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1b.c
new file mode 100644
index 0000000..e316e76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtps2ph-1b.c
@@ -0,0 +1,84 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 32)
+#define CHECK_ELEMS (AVX512F_LEN_HALF / 16)
+
+void NOINLINE
+EMULATE(cvtxps2_ph) (V512 * dest, V512 op1, int n_el,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < n_el; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v5);
+ for (i = n_el; i < 16; i++)
+ dest->u16[i] = 0;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, NET_MASK, 0);
+ H_HF(res) = INTRINSIC (_cvtxps_ph) (SF(src3f));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _cvtxps_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, 0xcc, 0);
+ H_HF(res) = INTRINSIC (_mask_cvtxps_ph) (H_HF(res), 0xcc,
+ SF(src3f));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _mask_cvtxps_ph);
+
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, 0xf1, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvtxps_ph) (0xf1, SF(src3f));
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _maskz_cvtxps_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, NET_MASK, 0);
+ H_HF(res) = INTRINSIC (_cvtx_roundps_ph) (SF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _cvtx_roundps_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, 0xcc, 0);
+ H_HF(res) = INTRINSIC (_mask_cvtx_roundps_ph) (H_HF(res), 0xcc,
+ SF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _mask_cvtx_roundps_ph);
+
+ EMULATE(cvtxps2_ph)(&exp, src3f, N_ELEMS, 0xf1, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvtx_roundps_ph) (0xf1, SF(src3f), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, CHECK_ELEMS, _maskz_cvtx_roundps_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c
new file mode 100644
index 0000000..4e8515e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m512i x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepi64_ph (x1);
+ res1 = _mm512_mask_cvtepi64_ph (res, m8, x2);
+ res2 = _mm512_maskz_cvtepi64_ph (m8, x3);
+ res = _mm512_cvt_roundepi64_ph (x1, 4);
+ res1 = _mm512_mask_cvt_roundepi64_ph (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundepi64_ph (m8, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1b.c
new file mode 100644
index 0000000..cb213b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtqq2ph-1b.c
@@ -0,0 +1,84 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 64)
+
+void NOINLINE
+EMULATE(cvtq2_ph) (V512 * dest, V512 op1, int n_el,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < n_el; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u64[i];
+ }
+ }
+
+ // The left part should be zero
+ for (i = n_el; i < 16; i++)
+ v5.f32[i] = 0;
+
+ *dest = pack_twops_2ph(v5, v5);
+}
+
+void
+TEST (void)
+{
+
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvtepi64_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _cvtepi64_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvtepi64_ph) (res.xmmh[0], 0xcc, SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _mask_cvtepi64_ph);
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xf1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvtepi64_ph) (0xf1, SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvtepi64_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvt_roundepi64_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _cvt_roundepi64_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvt_roundepi64_ph) (res.xmmh[0], 0xcc, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _mask_cvt_roundepi64_ph);
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xf1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvt_roundepi64_ph) (0xf1, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvt_roundepi64_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1a.c
new file mode 100644
index 0000000..b663ca5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsd2sh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1;
+volatile __m128d x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_cvtsd_sh (x1, x2);
+ res = _mm_mask_cvtsd_sh (res, m8, x1, x2);
+ res = _mm_maskz_cvtsd_sh (m8, x1, x2);
+ res = _mm_cvt_roundsd_sh (x1, x2, 8);
+ res = _mm_mask_cvt_roundsd_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_cvt_roundsd_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1b.c
new file mode 100644
index 0000000..5523620
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsd2sh-1b.c
@@ -0,0 +1,60 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtsd2sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = (float)op2.f64[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtsd2sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_cvt_roundsd_sh(src1.xmmh[0], src2.xmmd[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsd_sh");
+
+ init_dest(&res, &exp);
+ emulate_vcvtsd2sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_cvt_roundsd_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmd[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_mask_cvt_roundsd_sh");
+
+ emulate_vcvtsd2sh(&exp, src1, src2, 0x2, 1);
+ res.xmmh[0] = _mm_maskz_cvt_roundsd_sh(0x2, src1.xmmh[0],
+ src2.xmmd[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_maskz_cvt_roundsd_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1a.c
new file mode 100644
index 0000000..59719ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsh2sd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2sd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2sd\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2sd\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2sd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m128d res;
+volatile __m128d x1;
+volatile __m128h x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_cvtsh_sd (x1, x2);
+ res = _mm_mask_cvtsh_sd (res, m8, x1, x2);
+ res = _mm_maskz_cvtsh_sd (m8, x1, x2);
+ res = _mm_cvt_roundsh_sd (x1, x2, 8);
+ res = _mm_mask_cvt_roundsh_sd (res, m8, x1, x2, 8);
+ res = _mm_maskz_cvt_roundsh_sd (m8, x1, x2, 4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1b.c
new file mode 100644
index 0000000..e6bdc95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2sd-1b.c
@@ -0,0 +1,57 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtsh2sd(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+
+ unpack_ph_2twops(op2, &v3, &v4);
+
+ if ((k&1) || !k)
+ v5.f64[0] = v3.f32[0];
+ else if (zero_mask)
+ v5.f64[0] = 0;
+ else
+ v5.f64[0] = dest->f64[0];
+
+ v5.f64[1] = op1.f64[1];
+
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtsh2sd(&exp, src1, src2, 0x1, 0);
+ res.xmmd[0] = _mm_cvt_roundsh_sd(src1.xmmd[0], src2.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsh_sd");
+
+ init_dest(&res, &exp);
+ emulate_vcvtsh2sd(&exp, src1, src2, 0x1, 0);
+ res.xmmd[0] = _mm_mask_cvt_roundsh_sd(res.xmmd[0], 0x1, src1.xmmd[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_mask_cvt_roundsh_sd");
+
+ emulate_vcvtsh2sd(&exp, src1, src2, 0x2, 1);
+ res.xmmd[0] = _mm_maskz_cvt_roundsh_sd(0x2, src1.xmmd[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_maskz_cvt_roundsh_sd");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c
new file mode 100644
index 0000000..f29c953
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile int res1;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm_cvtsh_i32 (x1);
+ res1 = _mm_cvt_roundsh_i32 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1b.c
new file mode 100644
index 0000000..89c492c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1b.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 2
+
+void NOINLINE
+emulate_cvtph2_d(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_d(&exp, src1, NET_MASK, 0);
+ res.i32[0] = _mm_cvt_roundsh_i32(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsh_i32");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1a.c
new file mode 100644
index 0000000..0289ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile long long res2;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm_cvtsh_i64 (x1);
+ res2 = _mm_cvt_roundsh_i64 (x1, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1b.c
new file mode 100644
index 0000000..6a5e836
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si64-1b.c
@@ -0,0 +1,52 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 4
+
+void NOINLINE
+emulate_cvtph2_q(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_q(&exp, src1, NET_MASK, 0);
+ res.s64[0] = _mm_cvt_roundsh_i64(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsh_i64");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1a.c
new file mode 100644
index 0000000..e6c369c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsh2ss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2ss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2ss\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2ss\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2ss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m128 res;
+volatile __m128 x1;
+volatile __m128h x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_cvtsh_ss (x1, x2);
+ res = _mm_mask_cvtsh_ss (res, m8, x1, x2);
+ res = _mm_maskz_cvtsh_ss (m8, x1, x2);
+ res = _mm_cvt_roundsh_ss (x1, x2, 8);
+ res = _mm_mask_cvt_roundsh_ss (res, m8, x1, x2, 8);
+ res = _mm_maskz_cvt_roundsh_ss (m8, x1, x2, 4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1b.c
new file mode 100644
index 0000000..3195983
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2ss-1b.c
@@ -0,0 +1,59 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+ void NOINLINE
+emulate_vcvtsh2ss(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op2, &v3, &v4);
+ if ((k&1) || !k)
+ v5.f32[0] = v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = dest->f32[0];
+
+ for (i = 1; i < 4; i++)
+ v5.f32[i] = op1.f32[i];
+
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtsh2ss(&exp, src1, src2, 0x1, 0);
+ res.xmm[0] = _mm_cvt_roundsh_ss(src1.xmm[0], src2.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsh_ss");
+
+ init_dest(&res, &exp);
+ emulate_vcvtsh2ss(&exp, src1, src2, 0x1, 0);
+ res.xmm[0] = _mm_mask_cvt_roundsh_ss(res.xmm[0], 0x1, src1.xmm[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_mask_cvt_roundsh_ss");
+
+ emulate_vcvtsh2ss(&exp, src1, src2, 0x2, 1);
+ res.xmm[0] = _mm_maskz_cvt_roundsh_ss(0x2, src1.xmm[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_maskz_cvt_roundsh_ss");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c
new file mode 100644
index 0000000..7d00867
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile unsigned int res1;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm_cvtsh_u32 (x1);
+ res1 = _mm_cvt_roundsh_u32 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1b.c
new file mode 100644
index 0000000..466ce6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1b.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 2
+
+void NOINLINE
+emulate_cvtph2_d(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_d(&exp, src1, NET_MASK, 0);
+ res.u32[0] = _mm_cvt_roundsh_i32(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundsh_u32");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1a.c
new file mode 100644
index 0000000..363252d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2 " } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile unsigned long long res2;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm_cvtsh_u64 (x1);
+ res2 = _mm_cvt_roundsh_u64 (x1, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1b.c
new file mode 100644
index 0000000..74643ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi64-1b.c
@@ -0,0 +1,53 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 4
+
+void NOINLINE
+emulate_cvtph2_q(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_q(&exp, src1, NET_MASK, 0);
+ res.u64[0] = _mm_cvt_roundsh_i64(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, 4, "_mm_cvt_roundsh_u64");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1a.c
new file mode 100644
index 0000000..19d1b96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsi2shl\[ \\t\]+\[^%\n\]*%e\[^\{\n\]*\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsi2shl\[ \\t\]+\[^%\n\]*%e\[^\{\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x;
+volatile int n;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_cvti32_sh (x, n);
+ x = _mm_cvt_roundi32_sh (x, n, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1b.c
new file mode 100644
index 0000000..d9c9a85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh-1b.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtsi2sh(V512 *dest, V512 op1,
+ int value_32, __int64_t value_64, int bits)
+{
+ V512 v1,v2,v5,v6;
+ unpack_ph_2twops(op1, &v1, &v2);
+ if (bits == 32)
+ v5.xmm[0] = _mm_cvt_roundi32_ss (v1.xmm[0], value_32, _ROUND_NINT);
+#ifdef __x86_64__
+ else
+ v5.xmm[0] = _mm_cvt_roundi64_ss (v1.xmm[0], value_64, _ROUND_NINT);
+#endif
+ v5.xmm[1] = v1.xmm[1];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtsi2sh(&exp, src1, 99, 0, 32);
+ res.xmmh[0] = _mm_cvt_roundi32_sh(src1.xmmh[0], 99, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundi32_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1a.c
new file mode 100644
index 0000000..7781e36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtsi2shq\[ \\t\]+\[^%\n\]*%r\[^\{\n\]*\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsi2shq\[ \\t\]+\[^%\n\]*%r\[^\{\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x;
+volatile long long n;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_cvti64_sh (x, n);
+ x = _mm_cvt_roundi64_sh (x, n, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1b.c
new file mode 100644
index 0000000..6f66a87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsi2sh64-1b.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtsi2sh(V512 *dest, V512 op1,
+ int value_32, __int64_t value_64, int bits)
+{
+ V512 v1,v2,v5,v6;
+ unpack_ph_2twops(op1, &v1, &v2);
+ if (bits == 32)
+ v5.xmm[0] = _mm_cvt_roundi32_ss (v1.xmm[0], value_32, _ROUND_NINT);
+#ifdef __x86_64__
+ else
+ v5.xmm[0] = _mm_cvt_roundi64_ss (v1.xmm[0], value_64, _ROUND_NINT);
+#endif
+ v5.xmm[1] = v1.xmm[1];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtsi2sh(&exp, src1, 0, 99, 64);
+ res.xmmh[0] = _mm_cvt_roundi64_sh(src1.xmmh[0], 99, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundi64_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1a.c
new file mode 100644
index 0000000..63ad090
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtss2sh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1;
+volatile __m128 x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_cvtss_sh (x1, x2);
+ res = _mm_mask_cvtss_sh (res, m8, x1, x2);
+ res = _mm_maskz_cvtss_sh (m8, x1, x2);
+ res = _mm_cvt_roundss_sh (x1, x2, 8);
+ res = _mm_mask_cvt_roundss_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_cvt_roundss_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1b.c
new file mode 100644
index 0000000..94981bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtss2sh-1b.c
@@ -0,0 +1,60 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtss2sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = op2.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtss2sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_cvt_roundss_sh(src1.xmmh[0], src2.xmm[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundss_sh");
+
+ init_dest(&res, &exp);
+ emulate_vcvtss2sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_cvt_roundss_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmm[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_mask_cvt_roundss_sh");
+
+ emulate_vcvtss2sh(&exp, src1, src2, 0x2, 1);
+ res.xmmh[0] = _mm_maskz_cvt_roundss_sh(0x2, src1.xmmh[0],
+ src2.xmm[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "mm_maskz_cvt_roundss_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1a.c
new file mode 100644
index 0000000..0e44aaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m256h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epi32 (x1);
+ res1 = _mm512_mask_cvttph_epi32 (res, m16, x2);
+ res2 = _mm512_maskz_cvttph_epi32 (m16, x3);
+ res = _mm512_cvtt_roundph_epi32 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epi32 (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epi32 (m16, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1b.c
new file mode 100644
index 0000000..c18fefb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2dq-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_d) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epi32) (H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epi32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epi32) (SI(res), HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epi32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epi32) (HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epi32);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epi32) (H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epi32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epi32) (SI(res), HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epi32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epi32) (HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epi32);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1a.c
new file mode 100644
index 0000000..1241694
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epi64 (x1);
+ res1 = _mm512_mask_cvttph_epi64 (res, m8, x2);
+ res2 = _mm512_maskz_cvttph_epi64 (m8, x3);
+ res = _mm512_cvtt_roundph_epi64 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epi64 (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epi64 (m8, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1b.c
new file mode 100644
index 0000000..2a9a2ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2qq-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_q) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epi64) (src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epi64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epi64) (SI(res), 0xcc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epi64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfa, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epi64) (0xfa, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epi64);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epi64) (src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epi64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epi64) (SI(res), 0xcc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epi64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfa, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epi64) (0xfa, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epi64);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1a.c
new file mode 100644
index 0000000..0fd60f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\{sae\}\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m256h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epu32 (x1);
+ res1 = _mm512_mask_cvttph_epu32 (res, m16, x2);
+ res2 = _mm512_maskz_cvttph_epu32 (m16, x3);
+ res = _mm512_cvtt_roundph_epu32 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epu32 (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epu32 (m16, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1b.c
new file mode 100644
index 0000000..98bce37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2udq-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_d) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epu32) (H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epu32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epu32) (SI(res), HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epu32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epu32) (HALF_MASK, H_HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epu32);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_d)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epu32) (H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epu32);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epu32) (SI(res), HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epu32);
+
+ EMULATE(cvtph2_d)(&exp, src1, HALF_MASK, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epu32) (HALF_MASK, H_HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epu32);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c
new file mode 100644
index 0000000..04fee29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epu64 (x1);
+ res1 = _mm512_mask_cvttph_epu64 (res, m8, x2);
+ res2 = _mm512_maskz_cvttph_epu64 (m8, x3);
+ res = _mm512_cvtt_roundph_epu64 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epu64 (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epu64 (m8, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1b.c
new file mode 100644
index 0000000..31879ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uqq-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_q) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epu64) (src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epu64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epu64) (SI(res), 0xcc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epu64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfc, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epu64) (0xfc, src1.xmmh[0]);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epu64);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_q)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epu64) (src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epu64);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_q)(&exp, src1, 0xcc, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epu64) (SI(res), 0xcc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epu64);
+
+ EMULATE(cvtph2_q)(&exp, src1, 0xfc, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epu64) (0xfc, src1.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epu64);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1a.c
new file mode 100644
index 0000000..b31af84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epu16 (x1);
+ res1 = _mm512_mask_cvttph_epu16 (res, m32, x2);
+ res2 = _mm512_maskz_cvttph_epu16 (m32, x3);
+ res = _mm512_cvtt_roundph_epu16 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epu16 (res, m32, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epu16 (m32, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1b.c
new file mode 100644
index 0000000..34e94e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2uw-1b.c
@@ -0,0 +1,84 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_w) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ dest->u16[i] = 0;
+ }
+ }
+ else {
+ dest->u16[i] = v1.f32[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ dest->u16[i+16] = 0;
+ }
+ }
+ else {
+ dest->u16[i+16] = v2.f32[i];
+ }
+ }
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epu16) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epu16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epu16) (SI(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epu16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epu16) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epu16);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epu16) (HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epu16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epu16) (SI(res), MASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epu16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epu16) (ZMASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epu16);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1a.c
new file mode 100644
index 0000000..a918594
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512i res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvttph_epi16 (x1);
+ res1 = _mm512_mask_cvttph_epi16 (res, m32, x2);
+ res2 = _mm512_maskz_cvttph_epi16 (m32, x3);
+ res = _mm512_cvtt_roundph_epi16 (x1, 4);
+ res1 = _mm512_mask_cvtt_roundph_epi16 (res, m32, x2, 8);
+ res2 = _mm512_maskz_cvtt_roundph_epi16 (m32, x3, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1b.c
new file mode 100644
index 0000000..23bc8e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttph2w-1b.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtph2_w) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ dest->u16[i] = 0;
+ }
+ }
+ else {
+ dest->u16[i] = v1.f32[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ dest->u16[i+16] = 0;
+ }
+ }
+ else {
+ dest->u16[i+16] = v2.f32[i];
+ }
+ }
+}
+
+void
+TEST (void)
+{
+ V512 res, exp;
+
+ init_src();
+
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvttph_epi16) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvttph_epi16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvttph_epi16) (SI(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvttph_epi16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvttph_epi16) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvttph_epi16);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtph2_w)(&exp, src1, NET_MASK, 0);
+ SI(res) = INTRINSIC (_cvtt_roundph_epi16) (HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtt_roundph_epi16);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtph2_w)(&exp, src1, MASK_VALUE, 0);
+ SI(res) = INTRINSIC (_mask_cvtt_roundph_epi16) (SI(res), MASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtt_roundph_epi16);
+
+ EMULATE(cvtph2_w)(&exp, src1, ZMASK_VALUE, 1);
+ SI(res) = INTRINSIC (_maskz_cvtt_roundph_epi16) (ZMASK_VALUE, HF(src1), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtt_roundph_epi16);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c
new file mode 100644
index 0000000..80d84fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile int res1;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm_cvttsh_i32 (x1);
+ res1 = _mm_cvtt_roundsh_i32 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1b.c
new file mode 100644
index 0000000..c5b0a64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1b.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 2
+
+void NOINLINE
+emulate_cvtph2_d(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_d(&exp, src1, NET_MASK, 0);
+ res.i32[0] = _mm_cvtt_roundsh_i32(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvtt_roundsh_i32");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1a.c
new file mode 100644
index 0000000..76a9053
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile long long res2;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm_cvttsh_i64 (x1);
+ res2 = _mm_cvtt_roundsh_i64 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1b.c
new file mode 100644
index 0000000..4e0fe5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si64-1b.c
@@ -0,0 +1,52 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 4
+
+void NOINLINE
+emulate_cvtph2_q(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_q(&exp, src1, NET_MASK, 0);
+ res.s64[0] = _mm_cvtt_roundsh_i64(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvtt_roundsh_i64");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c
new file mode 100644
index 0000000..5956457
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile unsigned int res1;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm_cvttsh_u32 (x1);
+ res1 = _mm_cvtt_roundsh_u32 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1b.c
new file mode 100644
index 0000000..214e3e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1b.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 2
+
+void NOINLINE
+emulate_cvtph2_d(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u32[i] = 0;
+ }
+ else {
+ v5.u32[i] = dest->u32[i];
+ }
+ }
+ else {
+ v5.u32[i] = v1.f32[i];
+
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_d(&exp, src1, NET_MASK, 0);
+ res.u32[0] = _mm_cvtt_roundsh_i32(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvtt_roundsh_u32");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1a.c
new file mode 100644
index 0000000..23e8e70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2 " } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%rax" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x1;
+volatile unsigned long long res2;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm_cvttsh_u64 (x1);
+ res2 = _mm_cvtt_roundsh_u64 (x1, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1b.c
new file mode 100644
index 0000000..863fb6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi64-1b.c
@@ -0,0 +1,53 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 4
+
+void NOINLINE
+emulate_cvtph2_q(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.u64[i] = 0;
+ }
+ else {
+ v5.u64[i] = dest->u64[i];
+ }
+ }
+ else {
+ v5.u64[i] = v1.f32[i];
+ }
+ }
+ *dest = v5;
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_cvtph2_q(&exp, src1, NET_MASK, 0);
+ res.u64[0] = _mm_cvtt_roundsh_i64(src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, 4, "_mm_cvtt_roundsh_u64");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1a.c
new file mode 100644
index 0000000..8d90ef6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res, res1, res2;
+volatile __m512i x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepu32_ph (x1);
+ res1 = _mm512_mask_cvtepu32_ph (res, m16, x2);
+ res2 = _mm512_maskz_cvtepu32_ph (m16, x3);
+ res = _mm512_cvt_roundepu32_ph (x1, 4);
+ res1 = _mm512_mask_cvt_roundepu32_ph (res, m16, x2, 8);
+ res2 = _mm512_maskz_cvt_roundepu32_ph (m16, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1b.c
new file mode 100644
index 0000000..e9c1cd1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtudq2ph-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 32)
+
+void NOINLINE
+EMULATE(cvtd2_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v5);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtd2_ph)(&exp, src3, NET_MASK, 0);
+ H_HF(res)= INTRINSIC (_cvtepu32_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtepu32_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 0);
+ H_HF(res) = INTRINSIC (_mask_cvtepu32_ph) (H_HF(res), HALF_MASK, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtepu32_ph);
+
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvtepu32_ph) (HALF_MASK, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtepu32_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtd2_ph)(&exp, src3, NET_MASK, 0);
+ H_HF(res)= INTRINSIC (_cvt_roundepu32_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundepu32_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 0);
+ H_HF(res) = INTRINSIC (_mask_cvt_roundepu32_ph) (H_HF(res), HALF_MASK, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundepu32_ph);
+
+ EMULATE(cvtd2_ph)(&exp, src3, HALF_MASK, 1);
+ H_HF(res) = INTRINSIC (_maskz_cvt_roundepu32_ph) (HALF_MASK, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundepu32_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c
new file mode 100644
index 0000000..a234bb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m512i x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepu64_ph (x1);
+ res1 = _mm512_mask_cvtepu64_ph (res, m8, x2);
+ res2 = _mm512_maskz_cvtepu64_ph (m8, x3);
+ res = _mm512_cvt_roundepu64_ph (x1, 4);
+ res1 = _mm512_mask_cvt_roundepu64_ph (res, m8, x2, 8);
+ res2 = _mm512_maskz_cvt_roundepu64_ph (m8, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1b.c
new file mode 100644
index 0000000..873d910
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuqq2ph-1b.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 64)
+
+void NOINLINE
+EMULATE(cvtq2_ph) (V512 * dest, V512 op1, int n_el,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < n_el; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u64[i];
+ }
+ }
+
+ // The left part should be zero
+ for (i = n_el; i < 16; i++)
+ v5.f32[i] = 0;
+
+ *dest = pack_twops_2ph(v5, v5);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvtepu64_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _cvtepu64_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvtepu64_ph) (res.xmmh[0], 0xcc, SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _mask_cvtepu64_ph);
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xc1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvtepu64_ph) (0xc1, SI(src3));
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvtepu64_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, NET_MASK, 0);
+ res.xmmh[0] = INTRINSIC (_cvt_roundepu64_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _cvt_roundepu64_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xcc, 0);
+ res.xmmh[0] = INTRINSIC (_mask_cvt_roundepu64_ph) (res.xmmh[0], 0xcc, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _mask_cvt_roundepu64_ph);
+
+ EMULATE(cvtq2_ph)(&exp, src3, N_ELEMS, 0xc1, 1);
+ res.xmmh[0] = INTRINSIC (_maskz_cvt_roundepu64_ph) (0xc1, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, 8, _maskz_cvt_roundepu64_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1a.c
new file mode 100644
index 0000000..3b6d095
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtusi2shl\[ \\t\]+\[^%\n\]*%e\[^\{\n\]*\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtusi2shl\[ \\t\]+\[^%\n\]*%e\[^\{\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x;
+volatile unsigned n;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_cvtu32_sh (x, n);
+ x = _mm_cvt_roundu32_sh (x, n, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1b.c
new file mode 100644
index 0000000..d339f0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh-1b.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtusi2sh(V512 *dest, V512 op1,
+ int value_32, __int64_t value_64, int bits)
+{
+ V512 v1,v2,v5,v6;
+ unpack_ph_2twops(op1, &v1, &v2);
+ if (bits == 32)
+ v5.xmm[0] = _mm_cvt_roundu32_ss (v1.xmm[0], value_32, _ROUND_NINT);
+#ifdef __x86_64__
+ else
+ v5.xmm[0] = _mm_cvt_roundu64_ss (v1.xmm[0], value_64, _ROUND_NINT);
+#endif
+ v5.xmm[1] = v1.xmm[1];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtusi2sh(&exp, src1, 99, 0, 32);
+ res.xmmh[0] = _mm_cvt_roundu32_sh(src1.xmmh[0], 99, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundu32_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1a.c
new file mode 100644
index 0000000..30fcdc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtusi2shq\[ \\t\]+\[^%\n\]*%r\[^\{\n\]*\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtusi2shq\[ \\t\]+\[^%\n\]*%r\[^\{\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x;
+volatile unsigned long long n;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_cvtu64_sh (x, n);
+ x = _mm_cvt_roundu64_sh (x, n, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1b.c
new file mode 100644
index 0000000..20e711e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtusi2sh64-1b.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target { { ! ia32 } && avx512fp16 } } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_vcvtusi2sh(V512 *dest, V512 op1,
+ int value_32, __int64_t value_64, int bits)
+{
+ V512 v1,v2,v5,v6;
+ unpack_ph_2twops(op1, &v1, &v2);
+ if (bits == 32)
+ v5.xmm[0] = _mm_cvt_roundu32_ss (v1.xmm[0], value_32, _ROUND_NINT);
+#ifdef __x86_64__
+ else
+ v5.xmm[0] = _mm_cvt_roundu64_ss (v1.xmm[0], value_64, _ROUND_NINT);
+#endif
+ v5.xmm[1] = v1.xmm[1];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_vcvtusi2sh(&exp, src1, 0, 99, 64);
+ res.xmmh[0] = _mm_cvt_roundu64_sh(src1.xmmh[0], 99, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_cvt_roundu64_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1a.c
new file mode 100644
index 0000000..43c96a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res;
+volatile __m512i x1;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepu16_ph (x1);
+ res = _mm512_mask_cvtepu16_ph (res, m32, x1);
+ res = _mm512_maskz_cvtepu16_ph (m32, x1);
+ res = _mm512_cvt_roundepu16_ph (x1, 4);
+ res = _mm512_mask_cvt_roundepu16_ph (res, m32, x1, 8);
+ res = _mm512_maskz_cvt_roundepu16_ph (m32, x1, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1b.c
new file mode 100644
index 0000000..6d6b6da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtuw2ph-1b.c
@@ -0,0 +1,93 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtw2_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.f32[i] = v7.f32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u16[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.f32[i] = v8.f32[i];
+ }
+ }
+ else {
+ v6.f32[i] = op1.u16[i+16];
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtw2_ph)(&exp, src3, NET_MASK, 0);
+ HF(res) = INTRINSIC (_cvtepu16_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtepu16_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtw2_ph)(&exp, src3, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_cvtepu16_ph) (HF(res), MASK_VALUE, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtepu16_ph);
+
+ EMULATE(cvtw2_ph)(&exp, src3, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_cvtepu16_ph) (ZMASK_VALUE, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtepu16_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtw2_ph)(&exp, src3, NET_MASK, 0);
+ HF(res) = INTRINSIC (_cvt_roundepu16_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundepu16_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtw2_ph)(&exp, src3, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_cvt_roundepu16_ph) (HF(res), MASK_VALUE, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundepu16_ph);
+
+ EMULATE(cvtw2_ph)(&exp, src3, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_cvt_roundepu16_ph) (ZMASK_VALUE, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundepu16_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1a.c
new file mode 100644
index 0000000..c6eaee1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res;
+volatile __m512i x1;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_cvtepi16_ph (x1);
+ res = _mm512_mask_cvtepi16_ph (res, m32, x1);
+ res = _mm512_maskz_cvtepi16_ph (m32, x1);
+ res = _mm512_cvt_roundepi16_ph (x1, 4);
+ res = _mm512_mask_cvt_roundepi16_ph (res, m32, x1, 8);
+ res = _mm512_maskz_cvt_roundepi16_ph (m32, x1, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1b.c
new file mode 100644
index 0000000..e02b6fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtw2ph-1b.c
@@ -0,0 +1,92 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(cvtw2_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.f32[i] = v7.f32[i];
+ }
+ }
+ else {
+ v5.f32[i] = op1.u16[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.f32[i] = v8.f32[i];
+ }
+ }
+ else {
+ v6.f32[i] = op1.u16[i+16];
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(cvtw2_ph)(&exp, src3, NET_MASK, 0);
+ HF(res) = INTRINSIC (_cvtepi16_ph) (SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvtepi16_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtw2_ph)(&exp, src3, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_cvtepi16_ph) (HF(res), MASK_VALUE, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvtepi16_ph);
+
+ EMULATE(cvtw2_ph)(&exp, src3, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_cvtepi16_ph) (ZMASK_VALUE, SI(src3));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvtepi16_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(cvtw2_ph)(&exp, src3, NET_MASK, 0);
+ HF(res) = INTRINSIC (_cvt_roundepi16_ph) (SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _cvt_roundepi16_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(cvtw2_ph)(&exp, src3, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_cvt_roundepi16_ph) (HF(res), MASK_VALUE, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_cvt_roundepi16_ph);
+
+ EMULATE(cvtw2_ph)(&exp, src3, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_cvt_roundepi16_ph) (ZMASK_VALUE, SI(src3), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_cvt_roundepi16_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1a.c
new file mode 100644
index 0000000..63f111f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_div_ph (x1, x2);
+ res1 = _mm512_mask_div_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_div_ph (m32, x1, x2);
+
+ res = _mm512_div_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_div_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_div_round_ph (m32, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1b.c
new file mode 100644
index 0000000..c8b3821
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivph-1b.c
@@ -0,0 +1,97 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(div_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] / v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] / v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(div_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_div_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _div_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(div_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_div_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_div_ph);
+
+ EMULATE(div_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_div_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_div_ph);
+
+#if AVX512F_LEN == 512
+#if AVX512F_LEN == 512
+ EMULATE(div_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_div_round_ph) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _div_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(div_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_div_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_div_ph);
+
+ EMULATE(div_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_div_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_div_ph);
+#endif
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1a.c
new file mode 100644
index 0000000..39f26f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_div_sh (x1, x2);
+ res = _mm_mask_div_sh (res, m8, x1, x2);
+ res = _mm_maskz_div_sh (m8, x1, x2);
+
+ res = _mm_div_round_sh (x1, x2, 8);
+ res = _mm_mask_div_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_div_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1b.c
new file mode 100644
index 0000000..467f5d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vdivsh-1b.c
@@ -0,0 +1,76 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_div_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] / v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_div_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_div_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_div_sh");
+
+ init_dest(&res, &exp);
+ emulate_div_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_div_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_div_sh");
+
+ emulate_div_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_div_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_div_sh");
+
+ emulate_div_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_div_round_sh(src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_div_sh");
+
+ init_dest(&res, &exp);
+ emulate_div_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_div_round_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_div_sh");
+
+ emulate_div_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_div_round_sh(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_div_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c
new file mode 100644
index 0000000..ef9f853
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_cmpmn.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vcmpph" 15 } } */
+
+typedef _Float16 v8hf __attribute__ ((vector_size (16)));
+typedef _Float16 v16hf __attribute__ ((vector_size (32)));
+typedef _Float16 v32hf __attribute__ ((vector_size (64)));
+
+#define VCMPMN(type, op, name) \
+type \
+__attribute__ ((noinline, noclone)) \
+vec_cmp_##type##type##name (type a, type b) \
+{ \
+ return a op b; \
+}
+
+VCMPMN (v8hf, <, lt)
+VCMPMN (v16hf, <, lt)
+VCMPMN (v32hf, <, lt)
+VCMPMN (v8hf, <=, le)
+VCMPMN (v16hf, <=, le)
+VCMPMN (v32hf, <=, le)
+VCMPMN (v8hf, >, gt)
+VCMPMN (v16hf, >, gt)
+VCMPMN (v32hf, >, gt)
+VCMPMN (v8hf, >=, ge)
+VCMPMN (v16hf, >=, ge)
+VCMPMN (v32hf, >=, ge)
+VCMPMN (v8hf, ==, eq)
+VCMPMN (v16hf, ==, eq)
+VCMPMN (v32hf, ==, eq)
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vec_set_var.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_set_var.c
new file mode 100644
index 0000000..6a2e820
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vec_set_var.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mno-avx512vl -O2" } */
+/* { dg-final { scan-assembler-times {(?n)vpblendvb[ \t]+%xmm[0-9]} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)vpblendvb[ \t]+%ymm[0-9]} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)(?:vpbroadcastw|vmovdq[ua]16)[ \t].*%zmm[0-9].*%k[0-7]} 1 } } */
+
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef _Float16 v16hf __attribute__((vector_size(32)));
+typedef _Float16 v8hf __attribute__((vector_size(16)));
+
+v8hf
+foo1 (v8hf a, _Float16 b, int c)
+{
+ a[c] = b;
+ return a;
+}
+
+v16hf
+foo2 (v16hf a, _Float16 b, int c)
+{
+ a[c] = b;
+ return a;
+}
+
+v32hf
+foo3 (v32hf a, _Float16 b, int c)
+{
+ a[c] = b;
+ return a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1a.c
new file mode 100644
index 0000000..758aec1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1a.c
@@ -0,0 +1,121 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512vl -mavx512fp16 -mprefer-vector-width=512" } */
+
+#include<immintrin.h>
+__m128h
+f1 (__m128h x)
+{
+ int i = 0;
+ __m128h y;
+ for (; i != 8; i++)
+ y[i] = __builtin_fabsf16 (x[i]);
+ return y;
+}
+
+__m256h
+f2 (__m256h x)
+{
+ int i = 0;
+ __m256h y;
+ for (; i != 16; i++)
+ y[i] = __builtin_fabsf16 (x[i]);
+ return y;
+}
+
+__m512h
+f3 (__m512h x)
+{
+ int i = 0;
+ __m512h y;
+ for (; i != 32; i++)
+ y[i] = __builtin_fabsf16 (x[i]);
+ return y;
+}
+
+__m128h
+f4 (__m128h x)
+{
+ return -x;
+}
+
+__m256h
+f5 (__m256h x)
+{
+ return -x;
+}
+
+__m512h
+f6 (__m512h x)
+{
+ return -x;
+}
+
+__m128h
+f7 (__m128h x, __m128h y)
+{
+ int i = 0;
+ __m128h z;
+ for (; i != 8; i++)
+ z[i] = __builtin_copysignf16 (x[i], y[i]);
+ return z;
+}
+
+__m256h
+f8 (__m256h x, __m256h y)
+{
+ int i = 0;
+ __m256h z;
+ for (; i != 16; i++)
+ z[i] = __builtin_copysignf16 (x[i], y[i]);
+ return z;
+}
+
+__m512h
+f9 (__m512h x, __m512h y)
+{
+ int i = 0;
+ __m512h z;
+ for (; i != 32; i++)
+ z[i] = __builtin_copysignf16 (x[i], y[i]);
+ return z;
+}
+
+__m128h
+f10 (__m128h x, __m128h y)
+{
+ int i = 0;
+ __m128h z;
+ for (; i != 8; i++)
+ z[i] = x[i] * __builtin_copysignf16 (1, y[i]);
+ return z;
+}
+
+__m256h
+f11 (__m256h x, __m256h y)
+{
+ int i = 0;
+ __m256h z;
+ for (; i != 16; i++)
+ z[i] = x[i] * __builtin_copysignf16 (1, y[i]);
+ return z;
+}
+
+__m512h
+f12 (__m512h x, __m512h y)
+{
+ int i = 0;
+ __m512h z;
+ for (; i != 32; i++)
+ z[i] = x[i] * __builtin_copysignf16 (1, y[i]);
+ return z;
+}
+
+/* { dg-final { scan-assembler "vandps\[^\n\r\]*xmm0" } } */
+/* { dg-final { scan-assembler "vandps\[^\n\r\]*ymm0" } } */
+/* { dg-final { scan-assembler "vpandd\[^\n\r\]*zmm0" } } */
+/* { dg-final { scan-assembler-times "vxorps\[^\n\r\]*xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vxorps\[^\n\r\]*ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vpxord\[^\n\r\]*zmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vpternlogd\[^\n\r\]*xmm\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "vpternlogd\[^\n\r\]*ymm\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "vpternlogd\[^\n\r\]*zmm\[0-9\]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1b.c
new file mode 100644
index 0000000..1398b36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vector-bitwise-1b.c
@@ -0,0 +1,119 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+void NOINLINE
+emulate_absneg_ph (V512 * dest, V512 op1, int abs)
+{
+ V512 v1, v2, v3, v4;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v3, &v4);
+
+ for (i = 0; i != 16; i++) {
+ if (abs) {
+ v3.f32[i] = __builtin_fabsf (v1.f32[i]);
+ v4.f32[i] = __builtin_fabsf (v2.f32[i]);
+ }
+ else {
+ v3.f32[i] = -v1.f32[i];
+ v4.f32[i] = -v2.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v3, v4);
+}
+
+void NOINLINE
+emulate_copysign_ph (V512 * dest, V512 op1, V512 op2, int xorsign)
+{
+ V512 v1, v2, v3, v4, v5, v6;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v5, &v6);
+
+ for (i = 0; i != 16; i++) {
+ if (xorsign) {
+ v5.f32[i] = v1.f32[i] * __builtin_copysignf (1, v3.f32[i]);
+ v6.f32[i] = v2.f32[i] * __builtin_copysignf (1, v4.f32[i]);
+ }
+ else {
+ v5.f32[i] = __builtin_copysignf (v1.f32[i], v3.f32[i]);
+ v6.f32[i] = __builtin_copysignf (v2.f32[i], v4.f32[i]);
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+
+void
+test_512 (void)
+{
+ V512 res, exp;
+
+ init_src ();
+
+ /* Abs for vector float16. */
+ emulate_absneg_ph (&exp, src1, 1);
+ for (int i = 0; i != 8; i++)
+ res.f16[i] = __builtin_fabsf16 (src1.f16[i]);
+ check_results (&res, &exp, 8, "abs_m128h");
+
+ for (int i = 0; i != 16; i++)
+ res.f16[i] = __builtin_fabsf16 (src1.f16[i]);
+ check_results (&res, &exp, 16, "abs_m256h");
+
+ for (int i = 0; i != 32; i++)
+ res.f16[i] = __builtin_fabsf16 (src1.f16[i]);
+ check_results (&res, &exp, 32, "abs_m512h");
+
+ /* Neg for vector float16. */
+ emulate_absneg_ph (&exp, src1, 0);
+ for (int i = 0; i != 8; i++)
+ res.f16[i] = -(src1.f16[i]);
+ check_results (&res, &exp, 8, "neg_m128h");
+
+ for (int i = 0; i != 16; i++)
+ res.f16[i] = -(src1.f16[i]);
+ check_results (&res, &exp, 16, "neg_m256h");
+
+ for (int i = 0; i != 32; i++)
+ res.f16[i] = -(src1.f16[i]);
+ check_results (&res, &exp, 32, "neg_m512h");
+
+ /* Copysign for vector float16. */
+ emulate_copysign_ph (&exp, src1, src2, 0);
+ for (int i = 0; i != 8; i++)
+ res.f16[i] = __builtin_copysignf16 (src1.f16[i], src2.f16[i]);
+ check_results (&res, &exp, 8, "copysign_m128h");
+
+ for (int i = 0; i != 16; i++)
+ res.f16[i] = __builtin_copysignf16 (src1.f16[i], src2.f16[i]);
+ check_results (&res, &exp, 16, "copysign_m256h");
+
+ for (int i = 0; i != 32; i++)
+ res.f16[i] = __builtin_copysignf16 (src1.f16[i], src2.f16[i]);
+ check_results (&res, &exp, 32, "copysign_m512h");
+
+ /* Xorsign for vector float16. */
+ emulate_copysign_ph (&exp, src1, src2, 1);
+ for (int i = 0; i != 8; i++)
+ res.f16[i] = src1.f16[i] * __builtin_copysignf16 (1, src2.f16[i]);
+ check_results (&res, &exp, 8, "xorsign_m128h");
+
+ for (int i = 0; i != 16; i++)
+ res.f16[i] = src1.f16[i] * __builtin_copysignf16 (1, src2.f16[i]);
+ check_results (&res, &exp, 16, "xorsign_m256h");
+
+ for (int i = 0; i != 32; i++)
+ res.f16[i] = src1.f16[i] * __builtin_copysignf16 (1, src2.f16[i]);
+ check_results (&res, &exp, 32, "xorsign_m512h");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c
new file mode 100644
index 0000000..cd39b7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fcmadd_pch (x1, x2, x3);
+ res1 = _mm512_mask_fcmadd_pch (res1, m16, x1, x2);
+ res1 = _mm512_mask3_fcmadd_pch (res1, x1, x2, m16);
+ res2 = _mm512_maskz_fcmadd_pch (m16, x1, x2, x3);
+ res = _mm512_fcmadd_round_pch (x1, x2, x3, 8);
+ res1 = _mm512_mask_fcmadd_round_pch (res1, m16, x1, x2, 8);
+ res1 = _mm512_mask3_fcmadd_round_pch (res1, x1, x2, m16, 8);
+ res2 = _mm512_maskz_fcmadd_round_pch (m16, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c
new file mode 100644
index 0000000..835699b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcph-1b.c
@@ -0,0 +1,133 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmadd_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = is_mask3 ? v3.u32[i] : v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i]
+ - invert * (v1.f32[i+1] * v7.f32[i+1]) + v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v7.f32[i]
+ + invert * (v1.f32[i] * v7.f32[i-1]) + v3.f32[i];
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = is_mask3 ? v4.u32[i] : v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i]
+ - invert * (v2.f32[i+1] * v8.f32[i+1]) + v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v8.f32[i]
+ + invert * (v2.f32[i] * v8.f32[i-1]) + v4.f32[i];
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_fcmadd_pch) (HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_mask_fcmadd_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 1);
+ HF(res) = INTRINSIC (_mask3_fcmadd_pch) (HF(res), HF(src1),
+ HF(src2), HALF_MASK);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fcmadd_pch);
+
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fcmadd_pch) (HALF_MASK, HF(res),
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmadd_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_fcmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 0);
+ HF(res) = INTRINSIC (_mask_fcmadd_round_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 1, 1);
+ HF(res) = INTRINSIC (_mask3_fcmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), HALF_MASK, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fcmadd_pch);
+
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fcmadd_round_pch) (HALF_MASK, HF(res),
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmadd_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c
new file mode 100644
index 0000000..eb96588
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mno-avx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendvps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vmovss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx128f_test (void)
+{
+ res = _mm_fcmadd_sch (x1, x2, x3);
+ res1 = _mm_mask_fcmadd_sch (res1, m8, x1, x2);
+ res1 = _mm_mask3_fcmadd_sch (res1, x1, x2, m8);
+ res2 = _mm_maskz_fcmadd_sch (m8, x1, x2, x3);
+ res = _mm_fcmadd_round_sch (x1, x2, x3, 8);
+ res1 = _mm_mask_fcmadd_round_sch (res1, m8, x1, x2, 8);
+ res1 = _mm_mask3_fcmadd_round_sch (res1, x1, x2, m8, 8);
+ res2 = _mm_maskz_fcmadd_round_sch (m8, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c
new file mode 100644
index 0000000..c479068
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmadd_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v7.f32[0]
+ - invert * (v1.f32[1] * v7.f32[1]) + v3.f32[0];
+ v5.f32[1] = v1.f32[0] * v7.f32[1]
+ + invert * (v1.f32[1] * v7.f32[0]) + v3.f32[1];
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = is_mask3? v3.f32[i] : v7.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 0);
+ res.xmmh[0] = _mm_fcmadd_round_sch(res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 0);
+ res.xmmh[0] = _mm_mask_fcmadd_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 1, 1);
+ res.xmmh[0] = _mm_mask3_fcmadd_round_sch(res.xmmh[0], src1.xmmh[0], src2.xmmh[0],
+ 0x1, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask3_fcmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x3, 1, 1, 0);
+ res.xmmh[0] = _mm_maskz_fcmadd_round_sch(0x3, res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fcmadd_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1c.c
new file mode 100644
index 0000000..79a295f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmaddcsh-1c.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vmovss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include "avx512fp16-vfcmaddcsh-1a.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
new file mode 100644
index 0000000..ca2f140
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fcmul_pch (x1, x2);
+ res1 = _mm512_mask_fcmul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_fcmul_pch (m16, x1, x2);
+ res = _mm512_fcmul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_fcmul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_fcmul_round_pch (m16, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c
new file mode 100644
index 0000000..ee41f6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1b.c
@@ -0,0 +1,111 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmul_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i]
+ - invert * (v1.f32[i+1] * v3.f32[i+1]);
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i-1]
+ + invert * (v1.f32[i-1] * v3.f32[i]);
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i]
+ - invert * (v2.f32[i+1] * v4.f32[i+1]);
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i-1]
+ + invert * (v2.f32[i-1] * v4.f32[i]);
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 1);
+ HF(res) = INTRINSIC (_fcmul_pch) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 1);
+ HF(res) = INTRINSIC (_mask_fcmul_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmul_pch);
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 1);
+ HF(res) = INTRINSIC (_maskz_fcmul_pch) ( HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmul_pch);
+
+#if AVX512F_LEN == 512
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 1);
+ HF(res) = INTRINSIC (_fcmul_round_pch) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fcmul_round_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 1);
+ HF(res) = INTRINSIC (_mask_fcmul_round_pch) (HF(res) ,HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fcmul_round_pch);
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 1);
+ HF(res) = INTRINSIC (_maskz_fcmul_round_pch) ( HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fcmul_round_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
new file mode 100644
index 0000000..872d91a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_fcmul_sch (x1, x2);
+ res1 = _mm_mask_fcmul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_fcmul_sch (m8, x1, x2);
+ res = _mm_fcmul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_fcmul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_fcmul_round_sch (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c
new file mode 100644
index 0000000..995df84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1b.c
@@ -0,0 +1,71 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmul_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v3.f32[0]
+ - invert * (v1.f32[1] * v3.f32[1]);
+ v5.f32[1] = v1.f32[1] * v3.f32[0]
+ + invert * (v1.f32[0] * v3.f32[1]);
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0 , 1);
+ res.xmmh[0] = _mm_fcmul_round_sch(src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fcmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask_fcmul_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fcmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x3, 1, 1);
+ res.xmmh[0] = _mm_maskz_fcmul_round_sch(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fcmul_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1a.c
new file mode 100644
index 0000000..f9e2777
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fmadd_ph (x1, x2, x3);
+ x1 = _mm512_mask_fmadd_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fmadd_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fmadd_ph (m, x1, x2, x3);
+ x1 = _mm512_fmadd_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fmadd_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fmadd_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fmadd_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1b.c
new file mode 100644
index 0000000..71c2b8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXph-1b.c
@@ -0,0 +1,160 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fmadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] + v7.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] + v8.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fmadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v7.f32[i] * v1.f32[i] + v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v8.f32[i] * v2.f32[i] + v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fmadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmadd_ph) (HF(src1), HF(src2),
+ HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmadd_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmadd_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_ph);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(fmadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmadd_round_ph) (HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_round_ph) (HF(res), MASK_VALUE, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_ph);
+
+ EMULATE(fmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmadd_round_ph) (HF(src1), HF(src2), HF(res),
+ MASK_VALUE, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmadd_round_ph) (ZMASK_VALUE, HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1a.c
new file mode 100644
index 0000000..472454d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmadd231sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd231sh\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...sh\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h a, b, c;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ a = _mm_fmadd_sh (a, b, c);
+ a = _mm_mask_fmadd_sh (a, m, b, c);
+ c = _mm_mask3_fmadd_sh (a, b, c, m);
+ a = _mm_maskz_fmadd_sh (m, a, b, c);
+ a = _mm_fmadd_round_sh (a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ a = _mm_mask_fmadd_round_sh (a, m, b, c, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ c = _mm_mask3_fmadd_round_sh (a, b, c, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ a = _mm_maskz_fmadd_round_sh (m, a, b, c, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1b.c
new file mode 100644
index 0000000..a0eca9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddXXXsh-1b.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_fmadd_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] * v3.f32[0] + v7.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++){
+ if (mask3)
+ v5.f32[i] = v7.f32[i];
+ else
+ v5.f32[i] = v1.f32[i];
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fmadd_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmadd_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ 0x1);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmadd_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmadd_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fmadd_sh");
+
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fmadd_round_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmadd_round_sh(src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], 0x1, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmadd_round_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fmadd_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmadd_round_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fmadd_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c
new file mode 100644
index 0000000..859b215
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fmadd_pch (x1, x2, x3);
+ res1 = _mm512_mask_fmadd_pch (res1, m16, x1, x2);
+ res1 = _mm512_mask3_fmadd_pch (res1, x1, x2, m16);
+ res2 = _mm512_maskz_fmadd_pch (m16, x1, x2, x3);
+ res = _mm512_fmadd_round_pch (x1, x2, x3, 8);
+ res1 = _mm512_mask_fmadd_round_pch (res1, m16, x1, x2, 8);
+ res1 = _mm512_mask3_fmadd_round_pch (res1, x1, x2, m16, 8);
+ res2 = _mm512_maskz_fmadd_round_pch (m16, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c
new file mode 100644
index 0000000..1da6f01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcph-1b.c
@@ -0,0 +1,131 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmadd_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = is_mask3 ? v3.u32[i] : v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i]
+ - invert * (v1.f32[i+1] * v7.f32[i+1]) + v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v7.f32[i]
+ + invert * (v1.f32[i] * v7.f32[i-1]) + v3.f32[i];
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = is_mask3 ? v4.u32[i] : v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i]
+ - invert * (v2.f32[i+1] * v8.f32[i+1]) + v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v8.f32[i]
+ + invert * (v2.f32[i] * v8.f32[i-1]) + v4.f32[i];
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_fmadd_pch) (HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_pch) (HF(res), HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 1);
+ HF(res) = INTRINSIC (_mask3_fmadd_pch) (HF(res), HF(src1), HF(src2),
+ HALF_MASK);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 0, 0);
+ HF(res) = INTRINSIC (_maskz_fmadd_pch) (HALF_MASK, HF(res), HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, NET_CMASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_fmadd_round_pch) (HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmadd_round_pch) (HF(res), HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 0, 0, 1);
+ HF(res) = INTRINSIC (_mask3_fmadd_round_pch) (HF(res), HF(src1), HF(src2),
+ HALF_MASK, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmadd_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_pch)(&exp, src1, src2, HALF_MASK, 1, 0, 0);
+ HF(res) = INTRINSIC (_maskz_fmadd_round_pch) (HALF_MASK, HF(res), HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmadd_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c
new file mode 100644
index 0000000..288d1c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mno-avx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendvps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vmovss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx128f_test (void)
+{
+ res = _mm_fmadd_sch (x1, x2, x3);
+ res1 = _mm_mask_fmadd_sch (res1, m8, x1, x2);
+ res1 = _mm_mask3_fmadd_sch (res1, x1, x2, m8);
+ res2 = _mm_maskz_fmadd_sch (m8, x1, x2, x3);
+ res = _mm_fmadd_round_sch (x1, x2, x3, 8);
+ res1 = _mm_mask_fmadd_round_sch (res1, m8, x1, x2, 8);
+ res1 = _mm_mask3_fmadd_round_sch (res1, x1, x2, m8, 8);
+ res2 = _mm_maskz_fmadd_round_sch (m8, x1, x2, x3, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c
new file mode 100644
index 0000000..4c74e01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1b.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmadd_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag,
+ int is_mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v7.f32[0]
+ - invert * (v1.f32[1] * v7.f32[1]) + v3.f32[0];
+ v5.f32[1] = v1.f32[0] * v7.f32[1]
+ + invert * (v1.f32[1] * v7.f32[0]) + v3.f32[1];
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = is_mask3? v3.f32[i] : v7.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 0);
+ res.xmmh[0] = _mm_fmadd_round_sch(res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 0);
+ res.xmmh[0] = _mm_mask_fmadd_round_sch(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fmadd_sch);
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x1, 0, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmadd_round_sch(res.xmmh[0], src1.xmmh[0], src2.xmmh[0],
+ 0x1, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask3_fmadd_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmadd_csh)(&exp, src1, src2, 0x3, 1, 0, 0);
+ res.xmmh[0] = _mm_maskz_fmadd_round_sch(0x3, res.xmmh[0], src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fmadd_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1c.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1c.c
new file mode 100644
index 0000000..7863f8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddcsh-1c.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vmovss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+
+#include "avx512fp16-vfmaddcsh-1a.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1a.c
new file mode 100644
index 0000000..7063646
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fmaddsub_ph (x1, x2, x3);
+ x1 = _mm512_mask_fmaddsub_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fmaddsub_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fmaddsub_ph (m, x1, x2, x3);
+ x1 = _mm512_fmaddsub_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fmaddsub_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fmaddsub_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fmaddsub_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1b.c
new file mode 100644
index 0000000..16cf0af1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmaddsubXXXph-1b.c
@@ -0,0 +1,171 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fmaddsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] + v7.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] - v7.f32[i];
+ }
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] + v8.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] - v8.f32[i];
+ }
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fmaddsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i] + v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v7.f32[i] - v3.f32[i];
+ }
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i] + v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v8.f32[i] - v4.f32[i];
+ }
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmaddsub_ph) (HF(src1), HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmaddsub_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(m_fmaddsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmaddsub_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmaddsub_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmaddsub_ph);
+
+ init_dest(&res, &exp);
+#if AVX512F_LEN == 512
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmaddsub_round_ph) (HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmaddsub_round_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(m_fmaddsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmaddsub_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmaddsub_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmaddsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmaddsub_round_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmaddsub_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1a.c
new file mode 100644
index 0000000..3b1147a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1a.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fmsub_ph (x1, x2, x3);
+ x1 = _mm512_mask_fmsub_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fmsub_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fmsub_ph (m, x1, x2, x3);
+ x1 = _mm512_fmsub_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT
+ | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fmsub_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF
+ | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fmsub_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF
+ | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fmsub_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO
+ | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1b.c
new file mode 100644
index 0000000..abb9a9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXph-1b.c
@@ -0,0 +1,155 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fmsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] - v7.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] - v8.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fmsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v7.f32[i] * v1.f32[i] - v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v8.f32[i] * v2.f32[i] - v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fmsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmsub_ph) (HF(src1), HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmsub_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmsub_ph) (HF(src1), HF(src2), HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmsub_ph) (ZMASK_VALUE, HF(src1), HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmsub_ph);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(fmsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmsub_round_ph) (HF(src1), HF(src2), HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmsub_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmsub_ph);
+
+ EMULATE(fmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmsub_round_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fmsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmsub_round_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmsub_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1a.c
new file mode 100644
index 0000000..335b9e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsub231sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub231sh\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...sh\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h a, b, c;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ a = _mm_fmsub_sh (a, b, c);
+ a = _mm_mask_fmsub_sh (a, m, b, c);
+ c = _mm_mask3_fmsub_sh (a, b, c, m);
+ a = _mm_maskz_fmsub_sh (m, a, b, c);
+ a = _mm_fmsub_round_sh (a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ a = _mm_mask_fmsub_round_sh (a, m, b, c, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ c = _mm_mask3_fmsub_round_sh (a, b, c, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ a = _mm_maskz_fmsub_round_sh (m, a, b, c, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1b.c
new file mode 100644
index 0000000..a2563fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubXXXsh-1b.c
@@ -0,0 +1,89 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_fmsub_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] * v3.f32[0] - v7.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+ for (i = 1; i < 8; i++){
+ if (mask3)
+ v5.f32[i] = v7.f32[i];
+ else
+ v5.f32[i] = v1.f32[i];
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fmsub_sh(src1.xmmh[0],
+ src2.xmmh[0], res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmsub_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ 0x1);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmsub_sh(src1.xmmh[0], 0x1, src2.xmmh[0], res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmsub_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fmsub_sh");
+
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fmsub_round_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fmsub_round_sh(src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], 0x1, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmsub_round_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fmsub_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmsub_round_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fmsub_sh");
+
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1a.c
new file mode 100644
index 0000000..87087c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fmsubadd_ph (x1, x2, x3);
+ x1 = _mm512_mask_fmsubadd_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fmsubadd_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fmsubadd_ph (m, x1, x2, x3);
+ x1 = _mm512_fmsubadd_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fmsubadd_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fmsubadd_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fmsubadd_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1b.c
new file mode 100644
index 0000000..159cae4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmsubaddXXXph-1b.c
@@ -0,0 +1,175 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fmsubadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] - v7.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i] + v7.f32[i];
+ }
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] - v8.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i] + v8.f32[i];
+ }
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fmsubadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v5.f32[i] = v1.f32[i] * v7.f32[i] - v3.f32[i];
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v7.f32[i] + v3.f32[i];
+ }
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if (i % 2 == 1) {
+ v6.f32[i] = v2.f32[i] * v8.f32[i] - v4.f32[i];
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v8.f32[i] + v4.f32[i];
+ }
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmsubadd_ph) (HF(src1), HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmsubadd_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(m_fmsubadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmsubadd_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmsubadd_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmsubadd_ph);
+
+ init_dest(&res, &exp);
+#if AVX512F_LEN == 512
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fmsubadd_round_ph) (HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fmsubadd_round_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE,
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(m_fmsubadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fmsubadd_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2),
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmsubadd_ph);
+ init_dest(&res, &exp);
+ EMULATE(fmsubadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fmsubadd_round_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res),
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmsubadd_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
new file mode 100644
index 0000000..f31cbca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2, x3;
+volatile __mmask16 m16;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_fmul_pch (x1, x2);
+ res1 = _mm512_mask_fmul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_fmul_pch (m16, x1, x2);
+ res = _mm512_fmul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_fmul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_fmul_round_pch (m16, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c
new file mode 100644
index 0000000..d9bb1b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1b.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(c_fmul_pch) (V512 * dest, V512 op1, V512 op2,
+ __mmask16 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << (i / 2)) & k) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v5.f32[i] = v1.f32[i] * v3.f32[i]
+ - invert * (v1.f32[i+1] * v3.f32[i+1]);
+ }
+ else {
+ v5.f32[i] = v1.f32[i-1] * v3.f32[i]
+ + invert * (v1.f32[i] * v3.f32[i-1]);
+
+ }
+ }
+ if (((1 << (i / 2 + 8)) & k) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ if ((i % 2) == 0) {
+ v6.f32[i] = v2.f32[i] * v4.f32[i]
+ - invert * (v2.f32[i+1] * v4.f32[i+1]);
+ }
+ else {
+ v6.f32[i] = v2.f32[i-1] * v4.f32[i]
+ + invert * (v2.f32[i] * v4.f32[i-1]);
+ }
+
+ }
+ }
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 0);
+ HF(res) = INTRINSIC (_fmul_pch) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmul_pch) (HF(res),HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fmul_pch) (HALF_MASK, HF(src1),
+ HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmul_pch);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, NET_CMASK, 0, 0);
+ HF(res) = INTRINSIC (_fmul_round_pch) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 0, 0);
+ HF(res) = INTRINSIC (_mask_fmul_round_pch) (HF(res),HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fmul_pch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_pch)(&exp, src1, src2, HALF_MASK, 1, 0);
+ HF(res) = INTRINSIC (_maskz_fmul_round_pch) (HALF_MASK, HF(src1),
+ HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fmul_pch);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
new file mode 100644
index 0000000..5d48874
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, res1, res2;
+volatile __m128h x1, x2, x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_fmul_sch (x1, x2);
+ res1 = _mm_mask_fmul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_fmul_sch (m8, x1, x2);
+ res = _mm_fmul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_fmul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_fmul_round_sch (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c
new file mode 100644
index 0000000..45840d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1b.c
@@ -0,0 +1,71 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+EMULATE(c_fmul_csh) (V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int c_flag)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ int invert = 1;
+ if (c_flag == 1)
+ invert = -1;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k) {
+ v5.f32[0] = v1.f32[0] * v3.f32[0]
+ - invert * (v1.f32[1] * v3.f32[1]);
+ v5.f32[1] = v1.f32[0] * v3.f32[1]
+ + invert * (v1.f32[1] * v3.f32[0]);
+ }
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 2; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0 , 0);
+ res.xmmh[0] = _mm_fmul_round_sch(src1.xmmh[0], src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_fmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fmul_round_sch(res.xmmh[0], 0x1,
+ src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_mask_fmul_sch);
+
+ init_dest(&res, &exp);
+ EMULATE(c_fmul_csh)(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fmul_round_sch(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mm_maskz_fmul_sch);
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1a.c
new file mode 100644
index 0000000..20e77ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fnmadd_ph (x1, x2, x3);
+ x1 = _mm512_mask_fnmadd_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fnmadd_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fnmadd_ph (m, x1, x2, x3);
+ x1 = _mm512_fnmadd_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fnmadd_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fnmadd_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fnmadd_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1b.c
new file mode 100644
index 0000000..b15b1bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXph-1b.c
@@ -0,0 +1,159 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fnmadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = -(v1.f32[i] * v3.f32[i]) + v7.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = -(v2.f32[i] * v4.f32[i]) + v8.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fnmadd_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = -(v1.f32[i] * v7.f32[i]) + v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = -(v2.f32[i] * v8.f32[i]) + v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fnmadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fnmadd_ph) (HF(src1), HF(src2),
+ HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fnmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fnmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fnmadd_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fnmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fnmadd_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fnmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fnmadd_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fnmadd_ph);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(fnmadd_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fnmadd_round_ph) (HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fnmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fnmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fnmadd_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fnmadd_ph);
+
+ EMULATE(fnmadd_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fnmadd_round_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fnmadd_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmadd_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fnmadd_round_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fnmadd_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1a.c
new file mode 100644
index 0000000..77106aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1a.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231sh\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...sh\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h a, b, c;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ a = _mm_fnmadd_sh (a, b, c);
+ a = _mm_mask_fnmadd_sh (a, m, b, c);
+ c = _mm_mask3_fnmadd_sh (a, b, c, m);
+ a = _mm_maskz_fnmadd_sh (m, a, b, c);
+ a = _mm_fnmadd_round_sh (a, b, c, _MM_FROUND_TO_NEAREST_INT
+ | _MM_FROUND_NO_EXC);
+ a = _mm_mask_fnmadd_round_sh (a, m, b, c, _MM_FROUND_TO_NEG_INF
+ | _MM_FROUND_NO_EXC);
+ c = _mm_mask3_fnmadd_round_sh (a, b, c, m, _MM_FROUND_TO_POS_INF
+ | _MM_FROUND_NO_EXC);
+ a = _mm_maskz_fnmadd_round_sh (m, a, b, c, _MM_FROUND_TO_ZERO
+ | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1b.c
new file mode 100644
index 0000000..9200150
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmaddXXXsh-1b.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_fnmadd_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = -(v1.f32[0] * v3.f32[0]) + v7.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++){
+ if (mask3)
+ v5.f32[i] = v7.f32[i];
+ else
+ v5.f32[i] = v1.f32[i];
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fnmadd_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fnmadd_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ 0x1);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fnmadd_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fnmadd_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fnmadd_sh");
+
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fnmadd_round_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fnmadd_round_sh(src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], 0x1, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fnmadd_round_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fnmadd_sh");
+ init_dest(&res, &exp);
+ emulate_fnmadd_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fnmadd_round_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fnmadd_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1a.c
new file mode 100644
index 0000000..eb05de4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1a.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x1, x2, x3;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm512_fnmsub_ph (x1, x2, x3);
+ x1 = _mm512_mask_fnmsub_ph (x1, m, x2, x3);
+ x3 = _mm512_mask3_fnmsub_ph (x1, x2, x3, m);
+ x1 = _mm512_maskz_fnmsub_ph (m, x1, x2, x3);
+ x1 = _mm512_fnmsub_round_ph (x1, x2, x3, _MM_FROUND_TO_NEAREST_INT
+ | _MM_FROUND_NO_EXC);
+ x1 = _mm512_mask_fnmsub_round_ph (x1, m, x2, x3, _MM_FROUND_TO_NEG_INF
+ | _MM_FROUND_NO_EXC);
+ x3 = _mm512_mask3_fnmsub_round_ph (x1, x2, x3, m, _MM_FROUND_TO_POS_INF
+ | _MM_FROUND_NO_EXC);
+ x1 = _mm512_maskz_fnmsub_round_ph (m, x1, x2, x3, _MM_FROUND_TO_ZERO
+ | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1b.c
new file mode 100644
index 0000000..73f0172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXph-1b.c
@@ -0,0 +1,157 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(fnmsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = -(v1.f32[i] * v3.f32[i]) - v7.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = -(v2.f32[i] * v4.f32[i]) - v8.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+EMULATE(m_fnmsub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = -(v1.f32[i] * v7.f32[i]) - v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = -(v2.f32[i] * v8.f32[i]) - v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ EMULATE(fnmsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fnmsub_ph) (HF(src1), HF(src2),
+ HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fnmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fnmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fnmsub_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fnmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fnmsub_ph) (HF(src1), HF(src2), HF(res), MASK_VALUE);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fnmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fnmsub_ph) (ZMASK_VALUE, HF(src1), HF(src2), HF(res));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fnmsub_ph);
+
+#if AVX512F_LEN == 512
+ init_dest(&res, &exp);
+ EMULATE(fnmsub_ph)(&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_fnmsub_round_ph) (HF(src1), HF(src2),
+ HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _fnmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(m_fnmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_fnmsub_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_fnmsub_ph);
+
+ EMULATE(fnmsub_ph)(&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask3_fnmsub_round_ph) (HF(src1), HF(src2),
+ HF(res), MASK_VALUE, _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask3_fnmsub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(fnmsub_ph)(&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_fnmsub_round_ph) (ZMASK_VALUE, HF(src1),
+ HF(src2), HF(res), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_fnmsub_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1a.c
new file mode 100644
index 0000000..5d14608
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\n\]*\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\n\]*\{rd-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231sh\[ \\t\]+\[^\n\]*\{ru-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...sh\[ \\t\]+\[^\n\]*\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h a, b, c;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ a = _mm_fnmsub_sh (a, b, c);
+ a = _mm_mask_fnmsub_sh (a, m, b, c);
+ c = _mm_mask3_fnmsub_sh (a, b, c, m);
+ a = _mm_maskz_fnmsub_sh (m, a, b, c);
+ a = _mm_fnmsub_round_sh (a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
+ a = _mm_mask_fnmsub_round_sh (a, m, b, c, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);
+ c = _mm_mask3_fnmsub_round_sh (a, b, c, m, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);
+ a = _mm_maskz_fnmsub_round_sh (m, a, b, c, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1b.c
new file mode 100644
index 0000000..7bdb861
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfnmsubXXXsh-1b.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_fnmsub_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask, int mask3)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = -(v1.f32[0] * v3.f32[0]) - v7.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++){
+ if (mask3)
+ v5.f32[i] = v7.f32[i];
+ else
+ v5.f32[i] = v1.f32[i];
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fnmsub_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fnmsub_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ 0x1);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fnmsub_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fnmsub_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fnmsub_sh");
+
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_fnmsub_round_sh(src1.xmmh[0], src2.xmmh[0], res.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 1);
+ res.xmmh[0] = _mm_mask3_fnmsub_round_sh(src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], 0x1, _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask3_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x1, 0, 0);
+ res.xmmh[0] = _mm_mask_fnmsub_round_sh(src1.xmmh[0], 0x1, src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_fnmsub_sh");
+ init_dest(&res, &exp);
+ emulate_fnmsub_sh(&exp, src1, src2, 0x3, 1, 0);
+ res.xmmh[0] = _mm_maskz_fnmsub_round_sh(0x3, src1.xmmh[0], src2.xmmh[0],
+ res.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_fnmsub_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1a.c
new file mode 100644
index 0000000..a97dddf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfpclassphz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclassphz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x512;
+volatile __mmask16 m32;
+
+void extern
+avx512dq_test (void)
+{
+ m32 = _mm512_fpclass_ph_mask (x512, 13);
+ m32 = _mm512_mask_fpclass_ph_mask (2, x512, 13);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1b.c
new file mode 100644
index 0000000..9ffb560
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclassph-1b.c
@@ -0,0 +1,77 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "avx512f-helper.h"
+
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include "avx512f-mask-type.h"
+#define SIZE (AVX512F_LEN / 16)
+
+#ifndef __FPCLASSPH__
+#define __FPCLASSPH__
+int check_fp_class_hp (_Float16 src, int imm)
+{
+ int qNaN_res = isnan (src);
+ int sNaN_res = isnan (src);
+ int Pzero_res = (src == 0.0);
+ int Nzero_res = (src == -0.0);
+ int PInf_res = (isinf (src) == 1);
+ int NInf_res = (isinf (src) == -1);
+ int Denorm_res = (fpclassify (src) == FP_SUBNORMAL);
+ int FinNeg_res = __builtin_finite (src) && (src < 0);
+
+ int result = (((imm & 1) && qNaN_res)
+ || (((imm >> 1) & 1) && Pzero_res)
+ || (((imm >> 2) & 1) && Nzero_res)
+ || (((imm >> 3) & 1) && PInf_res)
+ || (((imm >> 4) & 1) && NInf_res)
+ || (((imm >> 5) & 1) && Denorm_res)
+ || (((imm >> 6) & 1) && FinNeg_res)
+ || (((imm >> 7) & 1) && sNaN_res));
+ return result;
+}
+#endif
+
+MASK_TYPE
+CALC (_Float16 *s1, int imm)
+{
+ int i;
+ MASK_TYPE res = 0;
+
+ for (i = 0; i < SIZE; i++)
+ if (check_fp_class_hp(s1[i], imm))
+ res = res | (1 << i);
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ int i;
+ UNION_TYPE (AVX512F_LEN, h) src;
+ MASK_TYPE res1, res2, res_ref = 0;
+ MASK_TYPE mask = MASK_VALUE;
+
+ src.a[0] = NAN;
+ src.a[1] = 1.0 / 0.0;
+ for (i = 1; i < SIZE; i++)
+ {
+ src.a[i] = -24.43 + 0.6 * i;
+ }
+
+ res1 = INTRINSIC (_fpclass_ph_mask) (src.x, 0xFF);
+ res2 = INTRINSIC (_mask_fpclass_ph_mask) (mask, src.x, 0xFF);
+
+ res_ref = CALC (src.a, 0xFF);
+
+ if (res_ref != res1)
+ abort ();
+
+ if ((mask & res_ref) != res2)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1a.c
new file mode 100644
index 0000000..7a31fd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfpclasssh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasssh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x128;
+volatile __mmask8 m8;
+
+void extern
+avx512dq_test (void)
+{
+ m8 = _mm_fpclass_sh_mask (x128, 13);
+ m8 = _mm_mask_fpclass_sh_mask (m8, x128, 13);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1b.c
new file mode 100644
index 0000000..bdc6f9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfpclasssh-1b.c
@@ -0,0 +1,76 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "avx512f-helper.h"
+
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include "avx512f-mask-type.h"
+#define SIZE (128 / 16)
+
+#ifndef __FPCLASSSH__
+#define __FPCLASSSH__
+int check_fp_class_hp (_Float16 src, int imm)
+{
+ int qNaN_res = isnan (src);
+ int sNaN_res = isnan (src);
+ int Pzero_res = (src == 0.0);
+ int Nzero_res = (src == -0.0);
+ int PInf_res = (isinf (src) == 1);
+ int NInf_res = (isinf (src) == -1);
+ int Denorm_res = (fpclassify (src) == FP_SUBNORMAL);
+ int FinNeg_res = __builtin_finite (src) && (src < 0);
+
+ int result = (((imm & 1) && qNaN_res)
+ || (((imm >> 1) & 1) && Pzero_res)
+ || (((imm >> 2) & 1) && Nzero_res)
+ || (((imm >> 3) & 1) && PInf_res)
+ || (((imm >> 4) & 1) && NInf_res)
+ || (((imm >> 5) & 1) && Denorm_res)
+ || (((imm >> 6) & 1) && FinNeg_res)
+ || (((imm >> 7) & 1) && sNaN_res));
+ return result;
+}
+#endif
+
+__mmask8
+CALC (_Float16 *s1, int imm)
+{
+ int i;
+ __mmask8 res = 0;
+
+ if (check_fp_class_hp(s1[0], imm))
+ res = res | 1;
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ int i;
+ union128h src;
+ __mmask8 res1, res2, res_ref = 0;
+ __mmask8 mask = MASK_VALUE;
+
+ src.a[0] = 1.0 / 0.0;
+ for (i = 1; i < SIZE; i++)
+ {
+ src.a[i] = -24.43 + 0.6 * i;
+ }
+
+ res1 = _mm_fpclass_sh_mask (src.x, 0xFF);
+ res2 = _mm_mask_fpclass_sh_mask (mask, src.x, 0xFF);
+
+
+ res_ref = CALC (src.a, 0xFF);
+
+ if (res_ref != res1)
+ abort ();
+
+ if ((mask & res_ref) != res2)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1a.c
new file mode 100644
index 0000000..993cbd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1} } */
+
+#include <immintrin.h>
+
+volatile __m512h x;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm512_getexp_ph (x);
+ x = _mm512_mask_getexp_ph (x, m, x);
+ x = _mm512_maskz_getexp_ph (m, x);
+ x = _mm512_getexp_round_ph (x, _MM_FROUND_NO_EXC);
+ x = _mm512_mask_getexp_round_ph (x, m, x, _MM_FROUND_NO_EXC);
+ x = _mm512_maskz_getexp_round_ph (m, x, _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1b.c
new file mode 100644
index 0000000..3483c95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpph-1b.c
@@ -0,0 +1,99 @@
+ /* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(getexp_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ float emu[32];
+ __mmask16 m1, m2;
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ v3.zmm = _mm512_getexp_round_ps(v1.zmm, _ROUND_CUR);
+ v4.zmm = _mm512_getexp_round_ps(v2.zmm, _ROUND_CUR);
+ for (i=0; i<16; i++)
+ {
+ emu[i] = v3.f32[i];
+ emu[i+16] = v4.f32[i];
+ }
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = emu[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = emu[i+16];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(getexp_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_getexp_ph) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _getexp_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(getexp_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_getexp_ph) (HF(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_getexp_ph);
+
+ EMULATE(getexp_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_getexp_ph) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_getexp_ph);
+#if AVX512F_LEN == 512
+ EMULATE(getexp_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_getexp_round_ph) (HF(src1), _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _getexp_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(getexp_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_getexp_round_ph) (HF(res), MASK_VALUE, HF(src1),
+ _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_getexp_round_ph);
+
+ EMULATE(getexp_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_getexp_round_ph) (ZMASK_VALUE, HF(src1), _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_getexp_round_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1a.c
new file mode 100644
index 0000000..397fd3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\{\n\]\[^\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\{\n\]\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\{\n\]\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_getexp_sh (x, x);
+ x = _mm_mask_getexp_sh (x, m, x, x);
+ x = _mm_maskz_getexp_sh (m, x, x);
+ x = _mm_getexp_round_sh (x, x, _MM_FROUND_NO_EXC);
+ x = _mm_mask_getexp_round_sh (x, m, x, x, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getexp_round_sh (m, x, x, _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1b.c
new file mode 100644
index 0000000..ca9834d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetexpsh-1b.c
@@ -0,0 +1,61 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_getexp_sh(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v0, v1, v2, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ v0.xmm[0] = _mm_getexp_round_ss (v1.xmm[0], v1.xmm[0], _ROUND_CUR);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v0.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_getexp_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_getexp_round_sh(exp.xmmh[0], src1.xmmh[0], _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_getexp_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_getexp_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_getexp_round_sh(res.xmmh[0], 0x1, exp.xmmh[0],
+ src1.xmmh[0], _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_getexp_round_sh");
+
+ emulate_getexp_sh(&exp, src1, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_getexp_round_sh(0x3, exp.xmmh[0], src1.xmmh[0],
+ _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_getexp_round_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1a.c
new file mode 100644
index 0000000..69e0c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h x, y;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm512_getmant_ph (y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm512_mask_getmant_ph (x, m, y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm512_maskz_getmant_ph (m, y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm512_getmant_round_ph (y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm512_mask_getmant_round_ph (x, m, y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm512_maskz_getmant_round_ph (m, y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1b.c
new file mode 100644
index 0000000..c18d1aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantph-1b.c
@@ -0,0 +1,102 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(getmant_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ float emu[32];
+ __mmask16 m1, m2;
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ v3.zmm = _mm512_getmant_round_ps(v1.zmm, 2, 0, _ROUND_CUR);
+ v4.zmm = _mm512_getmant_round_ps(v2.zmm, 2, 0, _ROUND_CUR);
+ for (i=0; i<16; i++)
+ {
+ emu[i] = v3.f32[i];
+ emu[i+16] = v4.f32[i];
+ }
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = emu[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = emu[i+16];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(getmant_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_getmant_ph) (HF(src1), 2, 0);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _getmant_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(getmant_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_getmant_ph) (HF(res), MASK_VALUE,
+ HF(src1), 2, 0);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_getmant_ph);
+
+ EMULATE(getmant_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_getmant_ph) (ZMASK_VALUE, HF(src1),
+ 2, 0);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_getmant_ph);
+#if AVX512F_LEN == 512
+ EMULATE(getmant_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_getmant_round_ph) (HF(src1), 2, 0, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _getmant_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(getmant_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_getmant_round_ph) (HF(res), MASK_VALUE,
+ HF(src1), 2, 0, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_getmant_round_ph);
+
+ EMULATE(getmant_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_getmant_round_ph) (ZMASK_VALUE, HF(src1),
+ 2, 0, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_getmant_round_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1a.c
new file mode 100644
index 0000000..b533f20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h x, y, z;
+volatile __mmask8 m;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm_getmant_sh (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_mask_getmant_sh (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_maskz_getmant_sh (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_getmant_round_sh (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm_mask_getmant_round_sh (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getmant_round_sh (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1b.c
new file mode 100644
index 0000000..bee8b04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vgetmantsh-1b.c
@@ -0,0 +1,62 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_getmant_sh(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v0, v1, v2, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ v0.xmm[0] = _mm_getmant_round_ss (v1.xmm[0], v1.xmm[0], 2, 0, _ROUND_CUR);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v0.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_getmant_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_getmant_round_sh(src1.xmmh[0], exp.xmmh[0],
+ 2, 0, _ROUND_CUR);
+ check_results(&res, &exp, 1, "_mm_getmant_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_getmant_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_getmant_round_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ exp.xmmh[0], 2, 0, _ROUND_CUR);
+ check_results(&res, &exp, 1, "_mm_mask_getmant_round_sh");
+
+ emulate_getmant_sh(&exp, src1, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_getmant_round_sh(0x3, src1.xmmh[0], exp.xmmh[0],
+ 2, 0, _ROUND_CUR);
+ check_results(&res, &exp, 1, "_mm_maskz_getmant_round_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1a.c
new file mode 100644
index 0000000..b91f4bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_max_ph (x1, x2);
+ res1 = _mm512_mask_max_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_max_ph (m32, x1, x2);
+
+ res = _mm512_max_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_max_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_max_round_ph (m32, x1, x2, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1b.c
new file mode 100644
index 0000000..0dd4c11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxph-1b.c
@@ -0,0 +1,94 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(max_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] > v3.f32[i] ? v1.f32[i] : v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] > v4.f32[i] ? v2.f32[i] : v4.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(max_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_max_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _max_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(max_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_max_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_max_ph);
+
+ EMULATE(max_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_max_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_max_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(max_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_max_round_ph) (HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _max_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(max_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_max_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_max_ph);
+
+ EMULATE(max_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_max_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_max_ph);
+
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1.c
new file mode 100644
index 0000000..d5198dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_max_sh (x1, x2);
+ res = _mm_mask_max_sh (res, m8, x1, x2);
+ res = _mm_maskz_max_sh (m8, x1, x2);
+
+ res = _mm_max_round_sh (x1, x2, 8);
+ res = _mm_mask_max_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_max_round_sh (m8, x1, x2, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1b.c
new file mode 100644
index 0000000..fe49de3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmaxsh-1b.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_max_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[i] = v1.f32[i] > v3.f32[i] ? v1.f32[i] : v3.f32[i];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_max_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_max_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_max_sh");
+
+ init_dest(&res, &exp);
+ emulate_max_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_max_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_max_sh");
+
+ emulate_max_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_max_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_max_sh");
+
+ emulate_max_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_max_round_sh(src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_max_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_max_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_max_round_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_max_round_sh");
+
+ emulate_max_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_max_round_sh(0x3, src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_max_round_sh");
+
+ if (n_errs != 0)
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1a.c
new file mode 100644
index 0000000..810a93e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+\{sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_min_ph (x1, x2);
+ res1 = _mm512_mask_min_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_min_ph (m32, x1, x2);
+
+ res = _mm512_min_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_min_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_min_round_ph (m32, x1, x2, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1b.c
new file mode 100644
index 0000000..3315ce1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vminph-1b.c
@@ -0,0 +1,93 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(min_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] < v3.f32[i] ? v1.f32[i] : v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] < v4.f32[i] ? v2.f32[i] : v4.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(min_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_min_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _min_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(min_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_min_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_min_ph);
+
+ EMULATE(min_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_min_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_min_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(min_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_min_round_ph) (HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _min_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(min_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_min_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_min_ph);
+
+ EMULATE(min_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_min_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_min_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1.c
new file mode 100644
index 0000000..9f1d6e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminsh\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_min_sh (x1, x2);
+ res = _mm_mask_min_sh (res, m8, x1, x2);
+ res = _mm_maskz_min_sh (m8, x1, x2);
+
+ res = _mm_min_round_sh (x1, x2, 8);
+ res = _mm_mask_min_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_min_round_sh (m8, x1, x2, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1b.c
new file mode 100644
index 0000000..13b8d86
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vminsh-1b.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_min_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[i] = v1.f32[i] < v3.f32[i] ? v1.f32[i] : v3.f32[i];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_min_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_min_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_min_sh");
+
+ init_dest(&res, &exp);
+ emulate_min_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_min_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_min_sh");
+
+ emulate_min_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_min_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_min_sh");
+
+ emulate_min_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_min_round_sh(src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_min_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_min_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_min_round_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_min_round_sh");
+
+ emulate_min_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_min_round_sh(0x3, src1.xmmh[0], src2.xmmh[0], 8);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_min_round_sh");
+
+ if (n_errs != 0)
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c
new file mode 100644
index 0000000..e35be10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^z\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+extern _Float16 const* p;
+volatile __m128h x1, x2, res;
+volatile __mmask8 m8;
+
+void
+avx512f_test (void)
+{
+ x2 = _mm_mask_load_sh (x1, m8, p);
+ x2 = _mm_maskz_load_sh (m8, p);
+ _mm_mask_store_sh (p, m8, x1);
+
+ res = _mm_move_sh (x1, x2);
+ res = _mm_mask_move_sh (res, m8, x1, x2);
+ res = _mm_maskz_move_sh (m8, x1, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1b.c
new file mode 100644
index 0000000..cea224a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1b.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+void NOINLINE
+emulate_mov2_load_sh(V512 * dest, V512 op1,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0]; //remains unchanged
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = 0;
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+emulate_mov3_load_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0]; //remains unchanged
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void NOINLINE
+emulate_mov2_store_sh(V512 * dest, V512 op1, __mmask8 k)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0];
+ else
+ v5.f32[0] = v7.f32[0]; //remains unchanged
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ // no mask
+ emulate_mov2_load_sh (&exp, src1, 0x0, 0);
+ res.xmmh[0] = _mm_load_sh((const void *)&(src1.u16[0]));
+ check_results(&res, &exp, 8, "_mm_load_sh");
+
+ // with mask and mask bit is set
+ emulate_mov2_load_sh (&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_load_sh(res.xmmh[0], 0x1, (const void *)&(src1.u16[0]));
+ check_results(&res, &exp, 8, "_mm__mask_load_sh");
+
+ // with zero-mask
+ emulate_mov2_load_sh (&exp, src1, 0x0, 1);
+ res.xmmh[0] = _mm_maskz_load_sh(0x1, (const void *)&(src1.u16[0]));
+ check_results(&res, &exp, 8, "_mm_maskz_load_sh");
+
+ emulate_mov3_load_sh (&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_move_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, 8, "_mm_mask_move_sh");
+
+ emulate_mov3_load_sh (&exp, src1, src2, 0x1, 1);
+ res.xmmh[0] = _mm_maskz_move_sh(0x1, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, 8, "_mm_maskz_move_sh");
+
+ // no mask
+ emulate_mov2_store_sh (&exp, src1, 0x0);
+ _mm_store_sh((void *)&(res.u16[0]), src1.xmmh[0]);
+ check_results(&exp, &res, 1, "_mm_store_sh");
+
+ // with mask
+ emulate_mov2_store_sh (&exp, src1, 0x1);
+ _mm_mask_store_sh((void *)&(res.u16[0]), 0x1, src1.xmmh[0]);
+ check_results(&exp, &res, 1, "_mm_mask_store_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1a.c
new file mode 100644
index 0000000..177802c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1a.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmovw\[^-]" 1 } } */
+/* { dg-final { scan-assembler-times "vpextrw" 1 } } */
+#include <immintrin.h>
+
+volatile __m128i x1;
+volatile short x2;
+
+void extern
+avx512f_test (void)
+{
+ x1 = _mm_cvtsi16_si128 (x2);
+ x2 = _mm_cvtsi128_si16 (x1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1b.c
new file mode 100644
index 0000000..a96007d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-1b.c
@@ -0,0 +1,27 @@
+/* { dg-do run {target avx512fp16} } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+static void
+do_test (void)
+{
+ union128i_w u;
+ short b = 128;
+ short e[8] = {0,0,0,0,0,0,0,0};
+
+ u.x = _mm_cvtsi16_si128 (b);
+
+ e[0] = b;
+
+ if (check_union128i_w (u, e))
+ abort ();
+ u.a[0] = 123;
+ b = _mm_cvtsi128_si16 (u.x);
+ if (u.a[0] != b)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2a.c
new file mode 100644
index 0000000..efa24e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2a.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef short __v8hi __attribute__ ((__vector_size__ (16)));
+typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__));
+
+__m128i
+__attribute__ ((noinline, noclone))
+foo1 (short x)
+{
+ return __extension__ (__m128i)(__v8hi) { x, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+__m128i
+__attribute__ ((noinline, noclone))
+foo2 (short *x)
+{
+ return __extension__ (__m128i)(__v8hi) { *x, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^-\n\r]*xmm0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2b.c
new file mode 100644
index 0000000..b680a16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-2b.c
@@ -0,0 +1,53 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-vmovw-2a.c"
+
+__m128i
+__attribute__ ((noinline,noclone))
+foo3 (__m128i x)
+{
+ return foo1 (((__v8hi) x)[0]);
+}
+
+static void
+do_test (void)
+{
+ short x;
+ union128i_w u = { -1, -1,};
+ union128i_w exp = { 0, 0};
+ __m128i v;
+ union128i_w a;
+
+ x = 25;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union128i_w (a, exp.a))
+ abort ();
+
+ x = 33;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union128i_w (a, exp.a))
+ abort ();
+
+ x = -33;
+ u.a[0] = x;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union128i_w (a, exp.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3a.c
new file mode 100644
index 0000000..c603107
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3a.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef short __v16hi __attribute__ ((__vector_size__ (32)));
+typedef long long __m256i __attribute__ ((__vector_size__ (32), __may_alias__));
+
+__m256i
+__attribute__ ((noinline, noclone))
+foo1 (short x)
+{
+ return __extension__ (__m256i)(__v16hi) { x, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+__m256i
+__attribute__ ((noinline, noclone))
+foo2 (short *x)
+{
+ return __extension__ (__m256i)(__v16hi) { *x, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^-\n\r]*xmm0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3b.c
new file mode 100644
index 0000000..13c1f65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-3b.c
@@ -0,0 +1,52 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-vmovw-3a.c"
+
+__m256i
+__attribute__ ((noinline,noclone))
+foo3 (__m256i x)
+{
+ return foo1 (((__v16hi) x)[0]);
+}
+
+static void
+do_test (void)
+{
+ short x;
+ union256i_w u = { -1, -1, -1, -1 };
+ union256i_w exp = { 0, 0, 0, 0 };
+
+ __m256i v;
+ union256i_w a;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union256i_w (a, exp.a))
+ abort ();
+
+ x = 33;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union256i_w (a, exp.a))
+ abort ();
+
+ x = -23;
+ u.a[0] = x;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union256i_w (a, exp.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4a.c
new file mode 100644
index 0000000..2ba198d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef short __v32hi __attribute__ ((__vector_size__ (64)));
+typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
+
+__m512i
+__attribute__ ((noinline, noclone))
+foo1 (short x)
+{
+ return __extension__ (__m512i)(__v32hi) { x, 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 };
+}
+
+__m512i
+__attribute__ ((noinline, noclone))
+foo2 (short *x)
+{
+ return __extension__ (__m512i)(__v32hi) { *x, 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 };
+}
+
+/* { dg-final { scan-assembler-times "vmovw\[^-\n\r]*xmm0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4b.c
new file mode 100644
index 0000000..ec6477b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovw-4b.c
@@ -0,0 +1,52 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#include <string.h>
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512fp16-vmovw-4a.c"
+
+__m512i
+__attribute__ ((noinline,noclone))
+foo3 (__m512i x)
+{
+ return foo1 (((__v32hi) x)[0]);
+}
+
+static void
+do_test (void)
+{
+ short x = 25;
+ union512i_w u = { -1, -1, -1, -1, -1, -1, -1, -1 };
+ union512i_w exp = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ __m512i v;
+ union512i_w a;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo1 (x);
+ a.x = v;
+ if (check_union512i_w (a, exp.a))
+ abort ();
+
+ x = 55;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo2 (&x);
+ a.x = v;
+ if (check_union512i_w (a, exp.a))
+ abort ();
+
+ x = 33;
+ u.a[0] = x;
+ exp.a[0] = x;
+ memset (&v, -1, sizeof (v));
+ v = foo3 (u.x);
+ a.x = v;
+ if (check_union512i_w (a, exp.a))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1a.c
new file mode 100644
index 0000000..1088e25
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_mul_ph (x1, x2);
+ res1 = _mm512_mask_mul_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_mul_ph (m32, x1, x2);
+
+ res = _mm512_mul_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_mul_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_mul_round_ph (m32, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1b.c
new file mode 100644
index 0000000..0d67e87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulph-1b.c
@@ -0,0 +1,92 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(mul_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(mul_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_mul_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mul_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(mul_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_mul_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_mul_ph);
+
+ EMULATE(mul_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_mul_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_mul_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(mul_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_mul_round_ph) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mul_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(mul_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_mul_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_mul_ph);
+
+ EMULATE(mul_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_mul_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_mul_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1a.c
new file mode 100644
index 0000000..85707b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_mul_sh (x1, x2);
+ res = _mm_mask_mul_sh (res, m8, x1, x2);
+ res = _mm_maskz_mul_sh (m8, x1, x2);
+
+ res = _mm_mul_round_sh (x1, x2, 8);
+ res = _mm_mask_mul_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_mul_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1b.c
new file mode 100644
index 0000000..36b6930
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmulsh-1b.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_mul_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] * v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_mul_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mul_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mul_sh");
+
+ init_dest(&res, &exp);
+ emulate_mul_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_mul_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_mul_sh");
+
+ emulate_mul_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_mul_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_mul_sh");
+
+ emulate_mul_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mul_round_sh(src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mul_sh");
+
+ init_dest(&res, &exp);
+ emulate_mul_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_mul_round_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_mul_sh");
+
+ emulate_mul_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_mul_round_sh(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_mul_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1a.c
new file mode 100644
index 0000000..6a5c642
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1a.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res;
+volatile __m512h x1;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_rcp_ph (x1);
+ res = _mm512_mask_rcp_ph (res, m32, x1);
+ res = _mm512_maskz_rcp_ph (m32, x1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1b.c
new file mode 100644
index 0000000..4a65451
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpph-1b.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(rcp_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = 1. / v1.f32[i];
+
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = 1. / v2.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(rcp_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_rcp_ph) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _rcp_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(rcp_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_rcp_ph) (HF(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_rcp_ph);
+
+ EMULATE(rcp_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_rcp_ph) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_rcp_ph);
+
+ if (n_errs != 0)
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1a.c
new file mode 100644
index 0000000..0a5a18e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrcpsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrcpsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrcpsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1, x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_rcp_sh (x1, x2);
+ res = _mm_mask_rcp_sh (res, m8, x1, x2);
+ res = _mm_maskz_rcp_sh (m8, x1, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1b.c
new file mode 100644
index 0000000..5316895
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrcpsh-1b.c
@@ -0,0 +1,57 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_rcp_sh(V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = 1. / v1.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_rcp_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_rcp_sh(exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_rcp_sh");
+
+ init_dest(&res, &exp);
+ emulate_rcp_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_rcp_sh(res.xmmh[0], 0x1, exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_rcp_sh");
+
+ emulate_rcp_sh(&exp, src1, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_rcp_sh(0x3, exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_rcp_sh");
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1a.c
new file mode 100644
index 0000000..536c1ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m512h x1;
+volatile __mmask32 m;
+
+void extern
+avx512fp16_test (void)
+{
+ x1 = _mm512_reduce_ph (x1, IMM);
+ x1 = _mm512_mask_reduce_ph (x1, m, x1, IMM);
+ x1 = _mm512_maskz_reduce_ph (m, x1, IMM);
+ x1 = _mm512_reduce_round_ph (x1, IMM, 8);
+ x1 = _mm512_mask_reduce_round_ph (x1, m, x1, IMM, 8);
+ x1 = _mm512_maskz_reduce_round_ph (m, x1, IMM, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1b.c
new file mode 100644
index 0000000..20d1ba5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vreduceph-1b.c
@@ -0,0 +1,116 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+#ifndef __REDUCEPH__
+#define __REDUCEPH__
+V512 borrow_reduce_ps(V512 v, int imm8)
+{
+ V512 temp;
+ switch (imm8)
+ {
+ case 1: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 1);break;
+ case 2: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 2);break;
+ case 3: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 3);break;
+ case 4: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 4);break;
+ case 5: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 5);break;
+ case 6: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 6);break;
+ case 7: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 7);break;
+ case 8: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 8);break;
+ }
+ return temp;
+}
+#endif
+
+void NOINLINE
+EMULATE(reduce_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int imm8, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ V512 t1,t2;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ t1 = borrow_reduce_ps(v1, imm8);
+ t2 = borrow_reduce_ps(v2, imm8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = t1.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = t2.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(reduce_ph) (&exp, src1, NET_MASK, 6, 0);
+ HF(res) = INTRINSIC (_reduce_ph) (HF(src1), 6);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _reduce_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(reduce_ph) (&exp, src1, MASK_VALUE, 5, 0);
+ HF(res) = INTRINSIC (_mask_reduce_ph) (HF(res), MASK_VALUE, HF(src1), 5);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_reduce_ph);
+
+ EMULATE(reduce_ph) (&exp, src1, ZMASK_VALUE, 4, 1);
+ HF(res) = INTRINSIC (_maskz_reduce_ph) (ZMASK_VALUE, HF(src1), 4);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_reduce_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(reduce_ph) (&exp, src1, NET_MASK, 6, 0);
+ HF(res) = INTRINSIC (_reduce_round_ph) (HF(src1), 6, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _reduce_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(reduce_ph) (&exp, src1, MASK_VALUE, 5, 0);
+ HF(res) = INTRINSIC (_mask_reduce_round_ph) (HF(res), MASK_VALUE, HF(src1), 5, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_reduce_round_ph);
+
+ EMULATE(reduce_ph) (&exp, src1, ZMASK_VALUE, 4, 1);
+ HF(res) = INTRINSIC (_maskz_reduce_round_ph) (ZMASK_VALUE, HF(src1), 4, _ROUND_CUR);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_reduce_round_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1a.c
new file mode 100644
index 0000000..8036991
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vreducesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vreducesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreducesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreducesh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreducesh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m128h x1, x2;
+volatile __mmask8 m;
+
+void extern
+avx512fp16_test (void)
+{
+ x1 = _mm_reduce_sh (x1, x2, IMM);
+ x1 = _mm_mask_reduce_sh(x1, m, x1, x2, IMM);
+ x1 = _mm_maskz_reduce_sh(m, x1, x2, IMM);
+ x1 = _mm_reduce_round_sh (x1, x2, IMM, 4);
+ x1 = _mm_mask_reduce_round_sh(x1, m, x1, x2, IMM, 8);
+ x1 = _mm_maskz_reduce_round_sh(m, x1, x2, IMM, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1b.c
new file mode 100644
index 0000000..4c5dfe7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vreducesh-1b.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+V512 borrow_reduce_ps(V512 v, int imm8)
+{
+ V512 temp;
+ switch (imm8)
+ {
+ case 1: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 1);break;
+ case 2: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 2);break;
+ case 3: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 3);break;
+ case 4: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 4);break;
+ case 5: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 5);break;
+ case 6: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 6);break;
+ case 7: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 7);break;
+ case 8: temp.zmm = _mm512_mask_reduce_ps (v.zmm, 0xffff, v.zmm, 8);break;
+ }
+ return temp;
+}
+
+void NOINLINE
+emulate_reduce_sh(V512 * dest, V512 op1,
+ __mmask32 k, int imm8, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ V512 t1;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ t1 = borrow_reduce_ps(v1, imm8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = t1.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_reduce_sh(&exp, src1, 0x1, 8, 0);
+ res.xmmh[0] = _mm_reduce_round_sh(src1.xmmh[0], exp.xmmh[0], 8, _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_reduce_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_reduce_sh(&exp, src1, 0x1, 7, 0);
+ res.xmmh[0] = _mm_mask_reduce_round_sh(res.xmmh[0], 0x1, src1.xmmh[0], exp.xmmh[0], 7, _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_reduce_round_sh");
+
+ emulate_reduce_sh(&exp, src1, 0x3, 6, 1);
+ res.xmmh[0] = _mm_maskz_reduce_round_sh(0x3, src1.xmmh[0], exp.xmmh[0], 6, _ROUND_CUR);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_reduce_round_sh");
+
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1a.c
new file mode 100644
index 0000000..8a30727
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m512h x1;
+volatile __mmask32 m;
+
+void extern
+avx512fp16_test (void)
+{
+ x1 = _mm512_roundscale_ph (x1, IMM);
+ x1 = _mm512_mask_roundscale_ph (x1, m, x1, IMM);
+ x1 = _mm512_maskz_roundscale_ph (m, x1, IMM);
+ x1 = _mm512_roundscale_round_ph (x1, IMM, 8);
+ x1 = _mm512_mask_roundscale_round_ph (x1, m, x1, IMM, 8);
+ x1 = _mm512_maskz_roundscale_round_ph (m, x1, IMM, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1b.c
new file mode 100644
index 0000000..d50e755
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscaleph-1b.c
@@ -0,0 +1,101 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(roundscale_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask, int round)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+ V512 t1, t2;
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ if (round==0)
+ {
+ t1.zmm = _mm512_maskz_roundscale_ps (0xffff, v1.zmm, 0x11);
+ t2.zmm = _mm512_maskz_roundscale_ps (0xffff, v2.zmm, 0x11);
+ }
+ else
+ {
+ t1.zmm = _mm512_maskz_roundscale_ps (0xffff, v1.zmm, 0x14);
+ t2.zmm = _mm512_maskz_roundscale_ps (0xffff, v2.zmm, 0x14);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = t1.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = t2.f32[i];
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res, exp;
+
+ init_src();
+
+ EMULATE(roundscale_ph) (&exp, src1, NET_MASK, 0, 1);
+ HF(res) = INTRINSIC (_roundscale_ph) (HF(src1), 0x13);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _roundscale_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(roundscale_ph) (&exp, src1, MASK_VALUE, 0, 1);
+ HF(res) = INTRINSIC (_mask_roundscale_ph) (HF(res), MASK_VALUE, HF(src1), 0x14);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_roundscale_ph);
+
+ EMULATE(roundscale_ph) (&exp, src1, ZMASK_VALUE, 1, 1);
+ HF(res) = INTRINSIC (_maskz_roundscale_ph) (ZMASK_VALUE, HF(src1), 0x14);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_roundscale_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(roundscale_ph) (&exp, src1, NET_MASK, 0, 1);
+ HF(res) = INTRINSIC (_roundscale_round_ph) (HF(src1), 0x13, 0x08);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _roundscale_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(roundscale_ph) (&exp, src1, MASK_VALUE, 0, 1);
+ HF(res) = INTRINSIC (_mask_roundscale_round_ph) (HF(res), MASK_VALUE, HF(src1), 0x14, 0x08);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_roundscale_round_ph);
+
+ EMULATE(roundscale_ph) (&exp, src1, ZMASK_VALUE, 1, 1);
+ HF(res) = INTRINSIC (_maskz_roundscale_round_ph) (ZMASK_VALUE, HF(src1), 0x14, 0x08);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_roundscale_round_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1a.c
new file mode 100644
index 0000000..bd41b63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m128h x1, x2;
+volatile __mmask8 m;
+
+void extern
+avx512fp16_test (void)
+{
+ x1 = _mm_roundscale_sh (x1, x2, IMM);
+ x1 = _mm_mask_roundscale_sh(x1, m, x1, x2, IMM);
+ x1 = _mm_maskz_roundscale_sh(m, x1, x2, IMM);
+ x1 = _mm_roundscale_round_sh (x1, x2, IMM, 4);
+ x1 = _mm_mask_roundscale_round_sh(x1, m, x1, x2, IMM, 8);
+ x1 = _mm_maskz_roundscale_round_sh(m, x1, x2, IMM, 8);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1b.c
new file mode 100644
index 0000000..c103389
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrndscalesh-1b.c
@@ -0,0 +1,62 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_roundscale_sh(V512 * dest, V512 op1,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ V512 t1,t2;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+ t1.zmm = _mm512_maskz_roundscale_ps (0xffff, v1.zmm, 0x14);
+ t2.zmm = _mm512_maskz_roundscale_ps (0xffff, v2.zmm, 0x14);
+
+ if ((k&1) || !k)
+ v5.f32[0] = t1.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_roundscale_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_roundscale_round_sh(src1.xmmh[0], src1.xmmh[0], 0x1, 0x08);
+ check_results(&res, &exp, N_ELEMS, "_mm_roundscale_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_roundscale_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_roundscale_round_sh(res.xmmh[0],
+ 0x1, src1.xmmh[0], src1.xmmh[0], 0x1, 0x08);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_roundscale_round_sh");
+
+ emulate_roundscale_sh(&exp, src1, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_roundscale_round_sh(0x3, src1.xmmh[0], src1.xmmh[0], 0x1, 0x08);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_roundscale_round_sh");
+
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1a.c
new file mode 100644
index 0000000..c9671e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1a.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res;
+volatile __m512h x1;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_rsqrt_ph (x1);
+ res = _mm512_mask_rsqrt_ph (res, m32, x1);
+ res = _mm512_maskz_rsqrt_ph (m32, x1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1b.c
new file mode 100644
index 0000000..237971d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtph-1b.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(rsqrt_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = 1. / sqrtf(v1.f32[i]);
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = 1. / sqrtf(v2.f32[i]);
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(rsqrt_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_rsqrt_ph) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _rsqrt_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(rsqrt_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_rsqrt_ph) (HF(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_rsqrt_ph);
+
+ EMULATE(rsqrt_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_rsqrt_ph) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_rsqrt_ph);
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1a.c
new file mode 100644
index 0000000..060ce33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vrsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1, x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_rsqrt_sh (x1, x2);
+ res = _mm_mask_rsqrt_sh (res, m8, x1, x2);
+ res = _mm_maskz_rsqrt_sh (m8, x1, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1b.c
new file mode 100644
index 0000000..5f20de7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vrsqrtsh-1b.c
@@ -0,0 +1,59 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_rsqrt_sh(V512 * dest, V512 op1,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = 1.0 / sqrtf(v1.f32[0]);
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_rsqrt_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_rsqrt_sh(exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_rsqrt_sh");
+
+ init_dest(&res, &exp);
+ emulate_rsqrt_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_rsqrt_sh(res.xmmh[0], 0x1, exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_rsqrt_sh");
+
+ emulate_rsqrt_sh(&exp, src1, 0x1, 1);
+ res.xmmh[0] = _mm_maskz_rsqrt_sh(0x1, exp.xmmh[0], src1.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_rsqrt_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1a.c
new file mode 100644
index 0000000..f3d2789
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_scalef_ph (x1, x2);
+ res1 = _mm512_mask_scalef_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_scalef_ph (m32, x1, x2);
+ res = _mm512_scalef_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_scalef_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_scalef_round_ph (m32, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1b.c
new file mode 100644
index 0000000..7c7288d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefph-1b.c
@@ -0,0 +1,94 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define DEBUG
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(scalef_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] * powf(2.0f, floorf(v3.f32[i]));
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] * powf(2.0f, floorf(v4.f32[i]));
+ }
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(scalef_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_scalef_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _scalef_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(scalef_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_scalef_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_scalef_ph);
+
+ EMULATE(scalef_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_scalef_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_scalef_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(scalef_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_scalef_round_ph) (HF(src1), HF(src2), 0x04);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _scalef_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(scalef_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_scalef_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), 0x04);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_scalef_round_ph);
+
+ EMULATE(scalef_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_scalef_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), 0x04);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_scalef_round_ph);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1a.c
new file mode 100644
index 0000000..999c048
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1a.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vscalefsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vscalefsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1, x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_scalef_sh (x1, x2);
+ res = _mm_mask_scalef_sh (res, m8, x1, x2);
+ res = _mm_maskz_scalef_sh (m8, x1, x2);
+ res = _mm_scalef_round_sh (x1, x2, 4);
+ res = _mm_mask_scalef_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_scalef_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1b.c
new file mode 100644
index 0000000..5db7be0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vscalefsh-1b.c
@@ -0,0 +1,58 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_scalef_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] * powf(2.0f, floorf(v3.f32[0]));
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+ emulate_scalef_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_scalef_round_sh(src1.xmmh[0], src2.xmmh[0], (0x00 | 0x08));
+ check_results(&res, &exp, N_ELEMS, "_mm_scalef_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_scalef_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_scalef_round_sh(res.xmmh[0], 0x1, src1.xmmh[0], src2.xmmh[0], (0x00 | 0x08));
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_scalef_round_sh");
+
+ emulate_scalef_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_scalef_round_sh(0x3, src1.xmmh[0], src2.xmmh[0], (0x00 | 0x08));
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_scalef_round_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1a.c
new file mode 100644
index 0000000..497b5ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res;
+volatile __m512h x1;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_sqrt_ph (x1);
+ res = _mm512_mask_sqrt_ph (res, m32, x1);
+ res = _mm512_maskz_sqrt_ph (m32, x1);
+ res = _mm512_sqrt_round_ph (x1, 4);
+ res = _mm512_mask_sqrt_round_ph (res, m32, x1, 8);
+ res = _mm512_maskz_sqrt_round_ph (m32, x1, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1b.c
new file mode 100644
index 0000000..d4d047b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtph-1b.c
@@ -0,0 +1,92 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(sqrt_ph) (V512 * dest, V512 op1,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = sqrtf(v1.f32[i]);
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = sqrtf(v2.f32[i]);
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(sqrt_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_sqrt_ph) (HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _sqrt_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(sqrt_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_sqrt_ph) (HF(res), MASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_sqrt_ph);
+
+ EMULATE(sqrt_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_sqrt_ph) (ZMASK_VALUE, HF(src1));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_sqrt_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(sqrt_ph) (&exp, src1, NET_MASK, 0);
+ HF(res) = INTRINSIC (_sqrt_round_ph) (HF(src1), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _sqrt_round_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(sqrt_ph) (&exp, src1, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_sqrt_round_ph) (HF(res), MASK_VALUE, HF(src1), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_sqrt_round_ph);
+
+ EMULATE(sqrt_ph) (&exp, src1, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_sqrt_round_ph) (ZMASK_VALUE, HF(src1), 8);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_sqrt_round_ph);
+#endif
+
+ if (n_errs != 0)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1a.c
new file mode 100644
index 0000000..dd44534
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1a.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res, x1, x2;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_sqrt_sh (x1, x2);
+ res = _mm_mask_sqrt_sh (res, m8, x1, x2);
+ res = _mm_maskz_sqrt_sh (m8, x1, x2);
+ res = _mm_sqrt_round_sh (x1, x2, 4);
+ res = _mm_mask_sqrt_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_sqrt_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1b.c
new file mode 100644
index 0000000..4744c6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsqrtsh-1b.c
@@ -0,0 +1,60 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_sqrt_sh(V512 * dest, V512 op1,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = sqrtf(v1.f32[0]);
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_sqrt_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_sqrt_round_sh(exp.xmmh[0], src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_sqrt_round_sh");
+
+ init_dest(&res, &exp);
+ emulate_sqrt_sh(&exp, src1, 0x1, 0);
+ res.xmmh[0] = _mm_mask_sqrt_round_sh(res.xmmh[0], 0x1, exp.xmmh[0],
+ src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_sqrt_round_sh");
+
+ emulate_sqrt_sh(&exp, src1, 0x1, 1);
+ res.xmmh[0] = _mm_maskz_sqrt_round_sh(0x1, exp.xmmh[0], src1.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_sqrt_round_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1a.c
new file mode 100644
index 0000000..bb5eda6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m512h res, res1, res2;
+volatile __m512h x1, x2;
+volatile __mmask32 m32;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm512_sub_ph (x1, x2);
+ res1 = _mm512_mask_sub_ph (res1, m32, x1, x2);
+ res2 = _mm512_maskz_sub_ph (m32, x1, x2);
+
+ res = _mm512_sub_round_ph (x1, x2, 8);
+ res1 = _mm512_mask_sub_round_ph (res1, m32, x1, x2, 8);
+ res2 = _mm512_maskz_sub_round_ph (m32, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1b.c
new file mode 100644
index 0000000..bd31d98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubph-1b.c
@@ -0,0 +1,93 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS (AVX512F_LEN / 16)
+
+void NOINLINE
+EMULATE(sub_ph) (V512 * dest, V512 op1, V512 op2,
+ __mmask32 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+ __mmask16 m1, m2;
+
+ m1 = k & 0xffff;
+ m2 = (k >> 16) & 0xffff;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ for (i = 0; i < 16; i++) {
+ if (((1 << i) & m1) == 0) {
+ if (zero_mask) {
+ v5.f32[i] = 0;
+ }
+ else {
+ v5.u32[i] = v7.u32[i];
+ }
+ }
+ else {
+ v5.f32[i] = v1.f32[i] - v3.f32[i];
+ }
+
+ if (((1 << i) & m2) == 0) {
+ if (zero_mask) {
+ v6.f32[i] = 0;
+ }
+ else {
+ v6.u32[i] = v8.u32[i];
+ }
+ }
+ else {
+ v6.f32[i] = v2.f32[i] - v4.f32[i];
+ }
+
+ }
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+
+void
+TEST (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ EMULATE(sub_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_sub_ph) (HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _sub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(sub_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_sub_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_sub_ph);
+
+ EMULATE(sub_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_sub_ph) (ZMASK_VALUE, HF(src1), HF(src2));
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_sub_ph);
+
+#if AVX512F_LEN == 512
+ EMULATE(sub_ph) (&exp, src1, src2, NET_MASK, 0);
+ HF(res) = INTRINSIC (_sub_round_ph) (HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _sub_ph);
+
+ init_dest(&res, &exp);
+ EMULATE(sub_ph) (&exp, src1, src2, MASK_VALUE, 0);
+ HF(res) = INTRINSIC (_mask_sub_round_ph) (HF(res), MASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _mask_sub_ph);
+
+ EMULATE(sub_ph) (&exp, src1, src2, ZMASK_VALUE, 1);
+ HF(res) = INTRINSIC (_maskz_sub_round_ph) (ZMASK_VALUE, HF(src1), HF(src2), _ROUND_NINT);
+ CHECK_RESULT (&res, &exp, N_ELEMS, _maskz_sub_ph);
+#endif
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1a.c
new file mode 100644
index 0000000..8ea1eea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res;
+volatile __m128h x1, x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm_sub_sh (x1, x2);
+ res = _mm_mask_sub_sh (res, m8, x1, x2);
+ res = _mm_maskz_sub_sh (m8, x1, x2);
+
+ res = _mm_sub_round_sh (x1, x2, 8);
+ res = _mm_mask_sub_round_sh (res, m8, x1, x2, 8);
+ res = _mm_maskz_sub_round_sh (m8, x1, x2, 11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1b.c
new file mode 100644
index 0000000..df3680e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vsubsh-1b.c
@@ -0,0 +1,76 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512dq" } */
+
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+#define N_ELEMS 8
+
+void NOINLINE
+emulate_sub_sh(V512 * dest, V512 op1, V512 op2,
+ __mmask8 k, int zero_mask)
+{
+ V512 v1, v2, v3, v4, v5, v6, v7, v8;
+ int i;
+
+ unpack_ph_2twops(op1, &v1, &v2);
+ unpack_ph_2twops(op2, &v3, &v4);
+ unpack_ph_2twops(*dest, &v7, &v8);
+
+ if ((k&1) || !k)
+ v5.f32[0] = v1.f32[0] - v3.f32[0];
+ else if (zero_mask)
+ v5.f32[0] = 0;
+ else
+ v5.f32[0] = v7.f32[0];
+
+ for (i = 1; i < 8; i++)
+ v5.f32[i] = v1.f32[i];
+
+ *dest = pack_twops_2ph(v5, v6);
+}
+
+void
+test_512 (void)
+{
+ V512 res;
+ V512 exp;
+
+ init_src();
+
+ emulate_sub_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_sub_sh(src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_sub_sh");
+
+ init_dest(&res, &exp);
+ emulate_sub_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_sub_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_sub_sh");
+
+ emulate_sub_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_sub_sh(0x3, src1.xmmh[0], src2.xmmh[0]);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_sub_sh");
+
+ emulate_sub_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_sub_round_sh(src1.xmmh[0], src2.xmmh[0],
+ _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_sub_sh");
+
+ init_dest(&res, &exp);
+ emulate_sub_sh(&exp, src1, src2, 0x1, 0);
+ res.xmmh[0] = _mm_mask_sub_round_sh(res.xmmh[0], 0x1, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_mask_sub_sh");
+
+ emulate_sub_sh(&exp, src1, src2, 0x3, 1);
+ res.xmmh[0] = _mm_maskz_sub_round_sh(0x3, src1.xmmh[0],
+ src2.xmmh[0], _ROUND_NINT);
+ check_results(&res, &exp, N_ELEMS, "_mm_maskz_sub_sh");
+
+ if (n_errs != 0) {
+ abort ();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-xorsign-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-xorsign-1.c
new file mode 100644
index 0000000..a22a6ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-xorsign-1.c
@@ -0,0 +1,41 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -ftree-vectorize -fdump-tree-vect-details -save-temps" } */
+
+extern void abort ();
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+
+#define N 16
+_Float16 a[N] = {-0.1f, -3.2f, -6.3f, -9.4f,
+ -12.5f, -15.6f, -18.7f, -21.8f,
+ 24.9f, 27.1f, 30.2f, 33.3f,
+ 36.4f, 39.5f, 42.6f, 45.7f};
+_Float16 b[N] = {-1.2f, 3.4f, -5.6f, 7.8f,
+ -9.0f, 1.0f, -2.0f, 3.0f,
+ -4.0f, -5.0f, 6.0f, 7.0f,
+ -8.0f, -9.0f, 10.0f, 11.0f};
+_Float16 r[N];
+
+static void
+__attribute__ ((noinline, noclone))
+do_test (void)
+{
+ int i;
+
+ for (i = 0; i < N; i++)
+ r[i] = a[i] * __builtin_copysignf16 (1.0f, b[i]);
+
+ /* check results: */
+ for (i = 0; i < N; i++)
+ if (r[i] != a[i] * __builtin_copysignf16 (1.0f, b[i]))
+ abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-assembler "\[ \t\]xor" } } */
+/* { dg-final { scan-assembler "\[ \t\]and" } } */
+/* { dg-final { scan-assembler-not "copysign" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c
new file mode 100644
index 0000000..08deb3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-builtin-sqrt-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+void
+f1 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 8; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+void
+f2 (_Float16* __restrict psrc, _Float16* __restrict pdst)
+{
+ for (int i = 0; i != 16; i++)
+ pdst[i] = __builtin_sqrtf16 (psrc[i]);
+}
+
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[^\n\r\]*ymm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c
new file mode 100644
index 0000000..d8fdab7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-conjugation-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#include <immintrin.h>
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_conj_pch (__m256h __A)
+{
+ return _mm256_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxor\[^\n\]*%ymm\[0-9\]+" 3 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_conj_pch (__m128h __A)
+{
+ return _mm_conj_pch (__A);
+}
+
+/* { dg-final { scan-assembler-times "vpxor\[^\n\]*%xmm\[0-9\]+" 3 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_mask_conj_pch (__m256h __W, __mmask8 __U, __m256h __A)
+{
+ return _mm256_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[^\n\]*%ymm\[0-9\]+" 2 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_mask_conj_pch (__m128h __W, __mmask8 __U, __m128h __A)
+{
+ return _mm_mask_conj_pch (__W, __U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[^\n\]*%xmm\[0-9\]+" 2 } } */
+
+__m256h
+__attribute__ ((noinline, noclone))
+test_mm256_maskz_conj_pch (__mmask8 __U, __m256h __A)
+{
+ return _mm256_maskz_conj_pch (__U, __A);
+}
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+__m128h
+__attribute__ ((noinline, noclone))
+test_mm_maskz_conj_pch (__mmask8 __U, __m128h __A) {
+ return _mm_maskz_conj_pch (__U, __A);
+}
+
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c
new file mode 100644
index 0000000..1a832f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-1.c
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+typedef _Float16 v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 v16hf __attribute__ ((__vector_size__ (32)));
+
+v8hf
+foo1 (v8hf a, v8hf b, v8hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo2 (v8hf a, v8hf b, v8hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo3 (v8hf a, v8hf b, v8hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v8hf
+foo4 (v8hf a, v8hf b, v8hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+v16hf
+foo5 (v16hf a, v16hf b, v16hf c)
+{
+ return a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo6 (v16hf a, v16hf b, v16hf c)
+{
+ return -a * b + c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo7 (v16hf a, v16hf b, v16hf c)
+{
+ return a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
+v16hf
+foo8 (v16hf a, v16hf b, v16hf c)
+{
+ return -a * b - c;
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*ymm\[0-9\]" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c
new file mode 100644
index 0000000..d0b8bec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-fma-vectorize-1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mavx512fp16 -mavx512vl" } */
+
+typedef _Float16 v8hf __attribute__ ((__vector_size__ (16)));
+typedef _Float16 v16hf __attribute__ ((__vector_size__ (32)));
+
+void
+foo1 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = pa[i] * pb[i] + pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo2 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = -pa[i] * pb[i] + pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo3 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = pa[i] * pb[i] - pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
+
+void
+foo4 (_Float16* __restrict pa, _Float16* __restrict pb,
+ _Float16* __restrict pc, _Float16* __restrict pd)
+{
+ for (int i = 0; i != 8; i++)
+ pd[i] = -pa[i] * pb[i] - pc[i];
+}
+
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1a.c
new file mode 100644
index 0000000..a40a0d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+/* { dg-final { scan-assembler-times "vxorps\[ \\t\]+\[^\n\r\]*%xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vxorps\[ \\t\]+\[^\n\r\]*%ymm0" 1 } } */
+#include<immintrin.h>
+
+__m128h
+neghf128 (__m128h a)
+{
+ return -a;
+}
+
+__m256h
+neghf256 (__m256h a)
+{
+ return -a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1b.c
new file mode 100644
index 0000000..d8f65fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-neg-1b.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+static void
+test_512 (void)
+{
+ V512 v1, v2, v3, v4, exp, res;
+ int i;
+ init_src();
+
+ unpack_ph_2twops(src1, &v1, &v2);
+ v1.f32[0] = -v1.f32[0];
+ exp = pack_twops_2ph(v1, v2);
+ res.zmmh = src1.zmmh;
+ res.f16[0] = -res.f16[0];
+ check_results(&res, &exp, 32, "neg");
+
+ unpack_ph_2twops(src1, &v1, &v2);
+ for (i=0; i<16; i++)
+ {
+ v1.f32[i] = -v1.f32[i];
+ v2.f32[i] = -v2.f32[i];
+ }
+ exp = pack_twops_2ph(v1, v2);
+ res.zmmh = -src1.zmmh;
+ check_results(&res, &exp, 32, "neg");
+ if (n_errs != 0) {
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c
new file mode 100644
index 0000000..70485d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-reduce-op-1.c
@@ -0,0 +1,244 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+
+#include <immintrin.h>
+#include "avx512-check.h"
+
+__m256h a1 = { -39.3f16, -180.9f16, 13.4f16, 35.4f16, -41.1f16, -14.4f16, 24.5f16, 53.54f16,
+ 238.4f16, -134.8f16, 24.5f16, 35.6f16, -346.7f16, -43.4f16, -535.3f16, 324.7f16 };
+__m256h a2 = { 82.5f16, 21.4f16, 24.4f16, 53.4f16, 23.5f16, -24.4f16, -34.5f16, -32.5f16,
+ 23.6f16, -13.4f16, 24.5f16, 35.5f16, -34.4f16, -24.5f16, -34.5f16, 13.5f16 };
+
+__m128h b1 = { 1.25f16, 2.25f16, -0.25f16, 4.0f16, -2.0f16, 4.0f16, -3.0f16, 2.0f16 };
+__m128h b2 = { -0.5f16, -1.0f16, 1.0f16, -1.0f16, 1.0f16, 1.0f16, 2.0f16, 4.0f16 };
+__m128h b3 = { 1.25f16, 2.25f16, -4.25f16, 4.0f16, -2.4f16, 4.0f16, -3.0f, 2.0f16 };
+__m128h b4 = { -4.5f16, 7.6f16, 0.7f16, -8.2f16, 2.1f16, 2.4f16, -2.0f16, 1.4f16 };
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_add_ph (__m256h a)
+{
+ return _mm256_reduce_add_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_mul_ph (__m256h a)
+{
+ return _mm256_reduce_mul_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_max_ph (__m256h a)
+{
+ return _mm256_reduce_max_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_256_min_ph (__m256h a)
+{
+ return _mm256_reduce_min_ph (a);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_add_ph (__m128h b)
+{
+ return _mm_reduce_add_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_mul_ph (__m128h b)
+{
+ return _mm_reduce_mul_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_max_ph (__m128h b)
+{
+ return _mm_reduce_max_ph (b);
+}
+
+__attribute__((noinline, noclone)) _Float16
+test_reduce_min_ph (__m128h b)
+{
+ return _mm_reduce_min_ph (b);
+}
+
+#define SIZE 16
+#define REF_ADDMUL(op, a) \
+ __m128h __a1 = _mm_setzero_ph (); \
+ for (int i = 0; i < 8; i++) { \
+ __a1[i] = (_Float16) a[i] op (_Float16) a[i + 8]; \
+ } \
+ _Float16 __c0 = __a1[0] op __a1[4]; \
+ _Float16 __c1 = __a1[1] op __a1[5]; \
+ _Float16 __c2 = __a1[2] op __a1[6]; \
+ _Float16 __c3 = __a1[3] op __a1[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm256_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_256_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+static void
+test_256_addmul_ph (void)
+{
+ TEST_ADDMUL_PH (a1);
+ TEST_ADDMUL_PH (a2);
+}
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm256_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_256_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op a[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#define TEST_MINMAX_PH(a) \
+ do { \
+ TESTOP (min, < a[i] ? r3 :, a); \
+ TESTOP (max, > a[i] ? r3 :, a); \
+ } while (0)
+
+static void
+test_256_minmax_ph (void)
+{
+ TEST_MINMAX_PH (a1);
+ TEST_MINMAX_PH (a2);
+}
+
+static void
+test_256_ph (void)
+{
+ test_256_addmul_ph ();
+ test_256_minmax_ph ();
+}
+
+#undef SIZE
+#define SIZE 8
+
+#undef REF_ADDMUL
+#define REF_ADDMUL(op, a) \
+ _Float16 __c0 = a[0] op a[4]; \
+ _Float16 __c1 = a[1] op a[5]; \
+ _Float16 __c2 = a[2] op a[6]; \
+ _Float16 __c3 = a[3] op a[7]; \
+ _Float16 __d0 = __c0 op __c2; \
+ _Float16 __d1 = __c1 op __c3; \
+ _Float16 __e0 = __d0 op __d1; \
+ r3 = __e0
+
+#undef TESTOP
+#define TESTOP(opname, op, a) \
+ do { \
+ _Float16 r1 = _mm_reduce_##opname##_ph (a); \
+ _Float16 r2 = test_reduce_##opname##_ph (a); \
+ _Float16 r3 = a[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ REF_ADDMUL (op, a); \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#undef TEST_ADDMUL_PH
+#define TEST_ADDMUL_PH(a) \
+ do { \
+ TESTOP (add, +, a); \
+ TESTOP (mul, *, a); \
+ } while (0)
+
+static void
+test_128_addmul_ph (void)
+{
+ TEST_ADDMUL_PH (b1);
+ TEST_ADDMUL_PH (b2);
+ TEST_ADDMUL_PH (b3);
+ TEST_ADDMUL_PH (b4);
+}
+
+#undef TESTOP
+#define TESTOP(opname, op, b) \
+ do { \
+ _Float16 r1 = _mm_reduce_##opname##_ph (b); \
+ _Float16 r2 = test_reduce_##opname##_ph (b); \
+ _Float16 r3 = b[0]; \
+ if (r1 != r2) { \
+ __builtin_abort (); \
+ } \
+ for (int i = 1; i < SIZE; i++) \
+ r3 = r3 op b[i]; \
+ if (r1 != r3) { \
+ __builtin_abort (); \
+ } \
+ } while (0)
+
+#undef TEST_MINMAX_PH
+#define TEST_MINMAX_PH(b) \
+ do { \
+ TESTOP (min, < b[i] ? r3 :, b); \
+ TESTOP (max, > b[i] ? r3 :, b); \
+ } while (0)
+
+static void
+test_128_minmax_ph (void)
+{
+ TEST_MINMAX_PH (b1);
+ TEST_MINMAX_PH (b2);
+ TEST_MINMAX_PH (b3);
+ TEST_MINMAX_PH (b4);
+}
+
+static void
+test_128_ph (void)
+{
+ test_128_addmul_ph ();
+ test_128_minmax_ph ();
+}
+
+static void
+do_test (void)
+{
+ test_256_ph ();
+ test_128_ph ();
+}
+
+
+#undef SIZE
+#undef REF_ADDMUL
+#undef TESTOP
+#undef TEST_ADDMUL_PH
+#undef TEST_MINMAX_PH
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-1.c
new file mode 100644
index 0000000..3621bb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512FP16
+#include "avx512fp16-helper.h"
+
+void
+test_512 (void)
+{
+ V512 res;
+ res.xmm[0] = _mm_castph_ps (src1.xmmh[0]);
+ check_results (&res, &src1, 8, "_mm_castph_ps");
+
+ res.xmmd[0] = _mm_castph_pd (src1.xmmh[0]);
+ check_results (&res, &src1, 8, "_mm_castph_pd");
+
+ res.xmmi[0] = _mm_castph_si128 (src1.xmmh[0]);
+ check_results (&res, &src1, 8, "_mm_castph_si128");
+
+ res.xmmh[0] = _mm_castps_ph (src1.xmm[0]);
+ check_results (&res, &src1, 8, "_mm_castps_ph");
+
+ res.xmmh[0] = _mm_castpd_ph (src1.xmmd[0]);
+ check_results (&res, &src1, 8, "_mm_castpd_ph");
+
+ res.xmmh[0] = _mm_castsi128_ph (src1.xmmi[0]);
+ check_results (&res, &src1, 8, "_mm_castsi128_ph");
+
+ res.ymm[0] = _mm256_castph_ps (src1.ymmh[0]);
+ check_results (&res, &src1, 16, "_mm256_castph_ps");
+
+ res.ymmd[0] = _mm256_castph_pd (src1.ymmh[0]);
+ check_results (&res, &src1, 16, "_mm256_castph_pd");
+
+ res.ymmi[0] = _mm256_castph_si256 (src1.ymmh[0]);
+ check_results (&res, &src1, 16, "_mm256_castph_si256");
+
+ res.ymmh[0] = _mm256_castps_ph (src1.ymm[0]);
+ check_results (&res, &src1, 16, "_mm256_castps_ph");
+
+ res.ymmh[0] = _mm256_castpd_ph (src1.ymmd[0]);
+ check_results (&res, &src1, 16, "_mm256_castpd_ph");
+
+ res.ymmh[0] = _mm256_castsi256_ph (src1.ymmi[0]);
+ check_results (&res, &src1, 16, "_mm256_castsi256_ph");
+
+ res.xmmh[0] = _mm256_castph256_ph128 (src1.ymmh[0]);
+ check_results (&res, &src1, 8, "_mm256_castph256_ph128");
+
+ res.ymmh[0] = _mm256_castph128_ph256 (src1.xmmh[0]);
+ check_results (&res, &src1, 8, "_mm256_castph128_ph256");
+
+ if (n_errs != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-2.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-2.c
new file mode 100644
index 0000000..dce387f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-typecast-2.c
@@ -0,0 +1,37 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512f-check.h"
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+void
+do_test (void)
+{
+ union512i_d zero;
+ union512h ad;
+ union256h b,bd;
+ union128h c;
+
+ int i;
+
+ for (i = 0; i < 16; i++)
+ {
+ b.a[i] = 65.43f + i;
+ zero.a[i] = 0;
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ c.a[i] = 32.01f + i;
+ }
+
+ bd.x = _mm256_zextph128_ph256 (c.x);
+ if (memcmp (bd.a, c.a, 16)
+ || memcmp (&bd.a[8], &zero.a, 16))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1a.c
new file mode 100644
index 0000000..354d897
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_add_ph (x1, x2);
+ res1 = _mm256_mask_add_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_add_ph (m16, x1, x2);
+
+ res2 = _mm_add_ph (x3, x4);
+ res2 = _mm_mask_add_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_add_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1b.c
new file mode 100644
index 0000000..fcf6a90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vaddph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vaddph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vaddph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1a.c
new file mode 100644
index 0000000..31da2b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1a.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$1\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%k\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$2\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$3\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcmpph\[ \\t\]+\\\$4\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%k\[0-9\]\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __mmask16 res;
+volatile __mmask8 res1;
+volatile __m256h x1, x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res = _mm256_cmp_ph_mask (x1, x2, 1);
+ res = _mm256_mask_cmp_ph_mask (m16, x1, x2, 2);
+ res1 = _mm_cmp_ph_mask (x3, x4, 3);
+ res1 = _mm_mask_cmp_ph_mask (m8, x3, x4, 4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1b.c
new file mode 100644
index 0000000..c201a92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcmpph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcmpph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcmpph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1a.c
new file mode 100644
index 0000000..ab0541d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtdq2phy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtdq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtepi32_ph (x2);
+ res3 = _mm256_mask_cvtepi32_ph (res3, m8, x2);
+ res3 = _mm256_maskz_cvtepi32_ph (m8, x2);
+
+ res3 = _mm_cvtepi32_ph (x3);
+ res3 = _mm_mask_cvtepi32_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepi32_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1b.c
new file mode 100644
index 0000000..033587a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtdq2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtdq2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtdq2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c
new file mode 100644
index 0000000..57604a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtpd2phy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtpd2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256d x2;
+volatile __m128d x3;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtpd_ph (x2);
+ res3 = _mm256_mask_cvtpd_ph (res3, m16, x2);
+ res3 = _mm256_maskz_cvtpd_ph (m16, x2);
+
+ res3 = _mm_cvtpd_ph (x3);
+ res3 = _mm_mask_cvtpd_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtpd_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1b.c
new file mode 100644
index 0000000..ea4b200
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtpd2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtpd2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtpd2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c
new file mode 100644
index 0000000..df653b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epi32 (x3);
+ res1 = _mm256_mask_cvtph_epi32 (res1, m8, x3);
+ res1 = _mm256_maskz_cvtph_epi32 (m8, x3);
+
+ res2 = _mm_cvtph_epi32 (x3);
+ res2 = _mm_mask_cvtph_epi32 (res2, m8, x3);
+ res2 = _mm_maskz_cvtph_epi32 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1b.c
new file mode 100644
index 0000000..93a3e90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2dq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2dq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2dq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1a.c
new file mode 100644
index 0000000..80010c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2pd\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256d res1;
+volatile __m128d res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_pd (x3);
+ res1 = _mm256_mask_cvtph_pd (res1, m8, x3);
+ res1 = _mm256_maskz_cvtph_pd (m8, x3);
+
+ res2 = _mm_cvtph_pd (x3);
+ res2 = _mm_mask_cvtph_pd (res2, m8, x3);
+ res2 = _mm_maskz_cvtph_pd (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1b.c
new file mode 100644
index 0000000..a384905
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2pd-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2pd-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2pd-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c
new file mode 100644
index 0000000..e8c4c8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2psx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256 res1;
+volatile __m128 res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtxph_ps (x3);
+ res1 = _mm256_mask_cvtxph_ps (res1, m8, x3);
+ res1 = _mm256_maskz_cvtxph_ps (m8, x3);
+
+ res2 = _mm_cvtxph_ps (x3);
+ res2 = _mm_mask_cvtxph_ps (res2, m8, x3);
+ res2 = _mm_maskz_cvtxph_ps (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1b.c
new file mode 100644
index 0000000..ad91de8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2psx-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2psx-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2psx-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c
new file mode 100644
index 0000000..ddc6f2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epi64 (x3);
+ res1 = _mm256_mask_cvtph_epi64 (res1, m8, x3);
+ res1 = _mm256_maskz_cvtph_epi64 (m8, x3);
+
+ res2 = _mm_cvtph_epi64 (x3);
+ res2 = _mm_mask_cvtph_epi64 (res2, m8, x3);
+ res2 = _mm_maskz_cvtph_epi64 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1b.c
new file mode 100644
index 0000000..5afc5a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2qq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2qq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2qq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c
new file mode 100644
index 0000000..d07d766
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epu32 (x3);
+ res1 = _mm256_mask_cvtph_epu32 (res1, m8, x3);
+ res1 = _mm256_maskz_cvtph_epu32 (m8, x3);
+
+ res2 = _mm_cvtph_epu32 (x3);
+ res2 = _mm_mask_cvtph_epu32 (res2, m8, x3);
+ res2 = _mm_maskz_cvtph_epu32 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1b.c
new file mode 100644
index 0000000..d869a0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2udq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2udq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2udq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c
new file mode 100644
index 0000000..26dbf22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epu64 (x3);
+ res1 = _mm256_mask_cvtph_epu64 (res1, m8, x3);
+ res1 = _mm256_maskz_cvtph_epu64 (m8, x3);
+
+ res2 = _mm_cvtph_epu64 (x3);
+ res2 = _mm_mask_cvtph_epu64 (res2, m8, x3);
+ res2 = _mm_maskz_cvtph_epu64 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1b.c
new file mode 100644
index 0000000..d9b10a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uqq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2uqq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2uqq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c
new file mode 100644
index 0000000..0f9fd27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m256h x3;
+volatile __m128h x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epu16 (x3);
+ res1 = _mm256_mask_cvtph_epu16 (res1, m16, x3);
+ res1 = _mm256_maskz_cvtph_epu16 (m16, x3);
+
+ res2 = _mm_cvtph_epu16 (x4);
+ res2 = _mm_mask_cvtph_epu16 (res2, m8, x4);
+ res2 = _mm_maskz_cvtph_epu16 (m8, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1b.c
new file mode 100644
index 0000000..280dcd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2uw-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2uw-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2uw-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c
new file mode 100644
index 0000000..8dee4ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m256h x3;
+volatile __m128h x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvtph_epi16 (x3);
+ res1 = _mm256_mask_cvtph_epi16 (res1, m16, x3);
+ res1 = _mm256_maskz_cvtph_epi16 (m16, x3);
+
+ res2 = _mm_cvtph_epi16 (x4);
+ res2 = _mm_mask_cvtph_epi16 (res2, m8, x4);
+ res2 = _mm_maskz_cvtph_epi16 (m8, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1b.c
new file mode 100644
index 0000000..739ba64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtph2w-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2w-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtph2w-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c
new file mode 100644
index 0000000..a89f8c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtps2phxy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtps2phxx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256 x2;
+volatile __m128 x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtxps_ph (x2);
+ res3 = _mm256_mask_cvtxps_ph (res3, m8, x2);
+ res3 = _mm256_maskz_cvtxps_ph (m8, x2);
+
+ res3 = _mm_cvtxps_ph (x3);
+ res3 = _mm_mask_cvtxps_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtxps_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1b.c
new file mode 100644
index 0000000..a339d0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtps2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtps2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtps2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c
new file mode 100644
index 0000000..8e42a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtqq2phy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtepi64_ph (x2);
+ res3 = _mm256_mask_cvtepi64_ph (res3, m16, x2);
+ res3 = _mm256_maskz_cvtepi64_ph (m16, x2);
+
+ res3 = _mm_cvtepi64_ph (x3);
+ res3 = _mm_mask_cvtepi64_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepi64_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1b.c
new file mode 100644
index 0000000..6a4a329
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtqq2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtqq2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtqq2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c
new file mode 100644
index 0000000..b4c0840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2dq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epi32 (x3);
+ res1 = _mm256_mask_cvttph_epi32 (res1, m8, x3);
+ res1 = _mm256_maskz_cvttph_epi32 (m8, x3);
+
+ res2 = _mm_cvttph_epi32 (x3);
+ res2 = _mm_mask_cvttph_epi32 (res2, m8, x3);
+ res2 = _mm_maskz_cvttph_epi32 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1b.c
new file mode 100644
index 0000000..f9d82f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2dq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2dq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2dq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1a.c
new file mode 100644
index 0000000..421c688
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2qq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epi64 (x3);
+ res1 = _mm256_mask_cvttph_epi64 (res1, m8, x3);
+ res1 = _mm256_maskz_cvttph_epi64 (m8, x3);
+
+ res2 = _mm_cvttph_epi64 (x3);
+ res2 = _mm_mask_cvttph_epi64 (res2, m8, x3);
+ res2 = _mm_maskz_cvttph_epi64 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1b.c
new file mode 100644
index 0000000..323ab74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2qq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2qq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2qq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c
new file mode 100644
index 0000000..60f4318
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2udq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epu32 (x3);
+ res1 = _mm256_mask_cvttph_epu32 (res1, m8, x3);
+ res1 = _mm256_maskz_cvttph_epu32 (m8, x3);
+
+ res2 = _mm_cvttph_epu32 (x3);
+ res2 = _mm_mask_cvttph_epu32 (res2, m8, x3);
+ res2 = _mm_maskz_cvttph_epu32 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1b.c
new file mode 100644
index 0000000..61365d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2udq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2udq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2udq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1a.c
new file mode 100644
index 0000000..37008f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uqq\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epu64 (x3);
+ res1 = _mm256_mask_cvttph_epu64 (res1, m8, x3);
+ res1 = _mm256_maskz_cvttph_epu64 (m8, x3);
+
+ res2 = _mm_cvttph_epu64 (x3);
+ res2 = _mm_mask_cvttph_epu64 (res2, m8, x3);
+ res2 = _mm_maskz_cvttph_epu64 (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1b.c
new file mode 100644
index 0000000..6360402
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uqq-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2uqq-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2uqq-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c
new file mode 100644
index 0000000..eafa31a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2uw\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m256h x3;
+volatile __m128h x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epu16 (x3);
+ res1 = _mm256_mask_cvttph_epu16 (res1, m16, x3);
+ res1 = _mm256_maskz_cvttph_epu16 (m16, x3);
+
+ res2 = _mm_cvttph_epu16 (x4);
+ res2 = _mm_mask_cvttph_epu16 (res2, m8, x4);
+ res2 = _mm_maskz_cvttph_epu16 (m8, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1b.c
new file mode 100644
index 0000000..dd5ed9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2uw-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2uw-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2uw-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c
new file mode 100644
index 0000000..7476d3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttph2w\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256i res1;
+volatile __m128i res2;
+volatile __m256h x3;
+volatile __m128h x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_cvttph_epi16 (x3);
+ res1 = _mm256_mask_cvttph_epi16 (res1, m16, x3);
+ res1 = _mm256_maskz_cvttph_epi16 (m16, x3);
+
+ res2 = _mm_cvttph_epi16 (x4);
+ res2 = _mm_mask_cvttph_epi16 (res2, m8, x4);
+ res2 = _mm_maskz_cvttph_epi16 (m8, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1b.c
new file mode 100644
index 0000000..7a04a6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvttph2w-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2w-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvttph2w-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1a.c
new file mode 100644
index 0000000..4fa2ab9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1a.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtudq2phy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtudq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtepu32_ph (x2);
+ res3 = _mm256_mask_cvtepu32_ph (res3, m8, x2);
+ res3 = _mm256_maskz_cvtepu32_ph (m8, x2);
+
+ res3 = _mm_cvtepu32_ph (x3);
+ res3 = _mm_mask_cvtepu32_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepu32_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1b.c
new file mode 100644
index 0000000..4ea2c26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtudq2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtudq2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtudq2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c
new file mode 100644
index 0000000..a3ee951
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phy\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuqq2phx\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res3 = _mm256_cvtepu64_ph (x2);
+ res3 = _mm256_mask_cvtepu64_ph (res3, m16, x2);
+ res3 = _mm256_maskz_cvtepu64_ph (m16, x2);
+
+ res3 = _mm_cvtepu64_ph (x3);
+ res3 = _mm_mask_cvtepu64_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepu64_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1b.c
new file mode 100644
index 0000000..c747e8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtuqq2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtuqq2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1a.c
new file mode 100644
index 0000000..59393dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtuw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res2;
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm256_cvtepu16_ph (x2);
+ res2 = _mm256_mask_cvtepu16_ph (res2, m16, x2);
+ res2 = _mm256_maskz_cvtepu16_ph (m16, x2);
+
+ res3 = _mm_cvtepu16_ph (x3);
+ res3 = _mm_mask_cvtepu16_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepu16_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1b.c
new file mode 100644
index 0000000..89d94df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtuw2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtuw2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtuw2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1a.c
new file mode 100644
index 0000000..ff5530f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtw2ph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res2;
+volatile __m128h res3;
+volatile __m256i x2;
+volatile __m128i x3;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res2 = _mm256_cvtepi16_ph (x2);
+ res2 = _mm256_mask_cvtepi16_ph (res2, m16, x2);
+ res2 = _mm256_maskz_cvtepi16_ph (m16, x2);
+
+ res3 = _mm_cvtepi16_ph (x3);
+ res3 = _mm_mask_cvtepi16_ph (res3, m8, x3);
+ res3 = _mm_maskz_cvtepi16_ph (m8, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1b.c
new file mode 100644
index 0000000..243e45b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vcvtw2ph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtw2ph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vcvtw2ph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1a.c
new file mode 100644
index 0000000..038d9e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_div_ph (x1, x2);
+ res1 = _mm256_mask_div_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_div_ph (m16, x1, x2);
+
+ res2 = _mm_div_ph (x3, x4);
+ res2 = _mm_mask_div_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_div_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1b.c
new file mode 100644
index 0000000..48965c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vdivph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vdivph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vdivph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c
new file mode 100644
index 0000000..627241c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fcmadd_pch (x1, x2, x3);
+ res1 = _mm256_mask_fcmadd_pch (res1, m8, x1, x2);
+ res1 = _mm256_mask3_fcmadd_pch (res1, x1, x2, m8);
+ res1 = _mm256_maskz_fcmadd_pch (m8, x1, x2, x3);
+
+ res2 = _mm_fcmadd_pch (x4, x5, x6);
+ res2 = _mm_mask_fcmadd_pch (res2, m8, x4, x5);
+ res2 = _mm_mask3_fcmadd_pch (res2, x4, x5, m8);
+ res2 = _mm_maskz_fcmadd_pch (m8, x4, x5, x6);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c
new file mode 100644
index 0000000..5e3a54e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmaddcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmaddcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmaddcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
new file mode 100644
index 0000000..4e48e9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fcmul_pch (x1, x2);
+ res1 = _mm256_mask_fcmul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_fcmul_pch (m8, x1, x2);
+
+ res2 = _mm_fcmul_pch (x4, x5);
+ res2 = _mm_mask_fcmul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_fcmul_pch (m8, x4, x5);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c
new file mode 100644
index 0000000..19564a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmulcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfcmulcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1a.c
new file mode 100644
index 0000000..eea38b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fmadd_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fmadd_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fmadd_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fmadd_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fmadd_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fmadd_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1b.c
new file mode 100644
index 0000000..f6e4a9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c
new file mode 100644
index 0000000..75cba83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vblendmps\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fmadd_pch (x1, x2, x3);
+ res1 = _mm256_mask_fmadd_pch (res1, m8, x1, x2);
+ res1 = _mm256_mask3_fmadd_pch (res1, x1, x2, m8);
+ res1 = _mm256_maskz_fmadd_pch (m8, x1, x2, x3);
+
+ res2 = _mm_fmadd_pch (x4, x5, x6);
+ res2 = _mm_mask_fmadd_pch (res2, m8, x4, x5);
+ res2 = _mm_mask3_fmadd_pch (res2, x4, x5, m8);
+ res2 = _mm_maskz_fmadd_pch (m8, x4, x5, x6);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c
new file mode 100644
index 0000000..bf85fea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1a.c
new file mode 100644
index 0000000..963fbb6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmaddsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fmaddsub_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fmaddsub_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fmaddsub_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fmaddsub_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fmaddsub_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fmaddsub_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1b.c
new file mode 100644
index 0000000..7f9748b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmaddsubXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddsubXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmaddsubXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1a.c
new file mode 100644
index 0000000..add1abc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fmsub_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fmsub_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fmsub_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fmsub_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fmsub_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fmsub_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1b.c
new file mode 100644
index 0000000..b9c2085
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmsubXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmsubXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1a.c
new file mode 100644
index 0000000..0316b8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsubadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fmsubadd_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fmsubadd_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fmsubadd_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fmsubadd_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fmsubadd_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fmsubadd_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1b.c
new file mode 100644
index 0000000..c8caca1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmsubaddXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmsubaddXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmsubaddXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
new file mode 100644
index 0000000..54e58c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1, x2, x3;
+volatile __m128h x4, x5, x6;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_fmul_pch (x1, x2);
+ res1 = _mm256_mask_fmul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_fmul_pch (m8, x1, x2);
+
+ res2 = _mm_fmul_pch (x4, x5);
+ res2 = _mm_mask_fmul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_fmul_pch (m8, x4, x5);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c
new file mode 100644
index 0000000..f88d842
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmulcph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfmulcph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1a.c
new file mode 100644
index 0000000..6dad901
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fnmadd_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fnmadd_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fnmadd_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fnmadd_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fnmadd_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fnmadd_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1b.c
new file mode 100644
index 0000000..6c615d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmaddXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfnmaddXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfnmaddXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1a.c
new file mode 100644
index 0000000..1a7fd09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1a.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub...ph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h yy, y2, y3;
+volatile __m128h xx, x2, x3;
+volatile __mmask8 m;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ yy = _mm256_mask_fnmsub_ph (yy, m16, y2, y3);
+ xx = _mm_mask_fnmsub_ph (xx, m, x2, x3);
+
+ y3 = _mm256_mask3_fnmsub_ph (yy, y2, y3, m16);
+ x3 = _mm_mask3_fnmsub_ph (xx, x2, x3, m);
+
+ yy = _mm256_maskz_fnmsub_ph (m16, yy, y2, y3);
+ xx = _mm_maskz_fnmsub_ph (m, xx, x2, x3);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1b.c
new file mode 100644
index 0000000..6d72b3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfnmsubXXXph-1b.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfnmsubXXXph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfnmsubXXXph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1a.c
new file mode 100644
index 0000000..897a3c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1a.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vfpclassphy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclassphx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclassphy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclassphx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h x256;
+volatile __m128h x128;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512dq_test (void)
+{
+ m16 = _mm256_fpclass_ph_mask (x256, 13);
+ m8 = _mm_fpclass_ph_mask (x128, 13);
+ m16 = _mm256_mask_fpclass_ph_mask (2, x256, 13);
+ m8 = _mm_mask_fpclass_ph_mask (2, x128, 13);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1b.c
new file mode 100644
index 0000000..6745f13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfpclassph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfpclassph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vfpclassph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1a.c
new file mode 100644
index 0000000..82c23b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512fp16 -O2" } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1} } */
+/* { dg-final { scan-assembler-times "vgetexpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1} } */
+
+#include <immintrin.h>
+
+volatile __m256h xx;
+volatile __m128h x2;
+volatile __mmask8 m8;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ xx = _mm256_getexp_ph (xx);
+ xx = _mm256_mask_getexp_ph (xx, m16, xx);
+ xx = _mm256_maskz_getexp_ph (m16, xx);
+ x2 = _mm_getexp_ph (x2);
+ x2 = _mm_mask_getexp_ph (x2, m8, x2);
+ x2 = _mm_maskz_getexp_ph (m8, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1b.c
new file mode 100644
index 0000000..7eb4fa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetexpph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vgetexpph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vgetexpph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1a.c
new file mode 100644
index 0000000..4ce6ed5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1a.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vl -mavx512fp16 " } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h x, y;
+volatile __m128h a, b;
+volatile __mmask8 m8;
+volatile __mmask16 m16;
+
+void extern
+avx512vl_test (void)
+{
+ x = _mm256_getmant_ph (y, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm256_mask_getmant_ph (x, m16, y, _MM_MANT_NORM_p75_1p5,
+ _MM_MANT_SIGN_src);
+ x = _mm256_maskz_getmant_ph (m16, y, _MM_MANT_NORM_p75_1p5,
+ _MM_MANT_SIGN_src);
+ a = _mm_getmant_ph (b, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ a = _mm_mask_getmant_ph (a, m8, b, _MM_MANT_NORM_p75_1p5,
+ _MM_MANT_SIGN_src);
+ a = _mm_maskz_getmant_ph (m8, b, _MM_MANT_NORM_p75_1p5,
+ _MM_MANT_SIGN_src);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1b.c
new file mode 100644
index 0000000..e5f8740
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vgetmantph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vgetmantph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vgetmantph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1a.c
new file mode 100644
index 0000000..adadc4e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmaxph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_max_ph (x1, x2);
+ res1 = _mm256_mask_max_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_max_ph (m16, x1, x2);
+
+ res2 = _mm_max_ph (x3, x4);
+ res2 = _mm_mask_max_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_max_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1b.c
new file mode 100644
index 0000000..f9a3b70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmaxph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vmaxph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vmaxph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1a.c
new file mode 100644
index 0000000..7909541
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vminph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_min_ph (x1, x2);
+ res1 = _mm256_mask_min_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_min_ph (m16, x1, x2);
+
+ res2 = _mm_min_ph (x3, x4);
+ res2 = _mm_mask_min_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_min_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1b.c
new file mode 100644
index 0000000..98808b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vminph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vminph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vminph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1a.c
new file mode 100644
index 0000000..26663c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_mul_ph (x1, x2);
+ res1 = _mm256_mask_mul_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_mul_ph (m16, x1, x2);
+
+ res2 = _mm_mul_ph (x3, x4);
+ res2 = _mm_mask_mul_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_mul_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1b.c
new file mode 100644
index 0000000..2b3ba050
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vmulph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vmulph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vmulph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1a.c
new file mode 100644
index 0000000..5894dbc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrcpph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1;
+volatile __m128h x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_rcp_ph (x1);
+ res1 = _mm256_mask_rcp_ph (res1, m16, x1);
+ res1 = _mm256_maskz_rcp_ph (m16, x1);
+
+ res2 = _mm_rcp_ph (x2);
+ res2 = _mm_mask_rcp_ph (res2, m8, x2);
+ res2 = _mm_maskz_rcp_ph (m8, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1b.c
new file mode 100644
index 0000000..a6b1e37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrcpph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrcpph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrcpph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1a.c
new file mode 100644
index 0000000..4f43abd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1a.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vreduceph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m256h x2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+volatile __mmask16 m16;
+
+void extern
+avx512fp16_test (void)
+{
+ x2 = _mm256_reduce_ph (x2, IMM);
+ x3 = _mm_reduce_ph (x3, IMM);
+
+ x2 = _mm256_mask_reduce_ph (x2, m16, x2, IMM);
+ x3 = _mm_mask_reduce_ph (x3, m8, x3, IMM);
+
+ x2 = _mm256_maskz_reduce_ph (m8, x2, IMM);
+ x3 = _mm_maskz_reduce_ph (m16, x3, IMM);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1b.c
new file mode 100644
index 0000000..3851597
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vreduceph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vreduceph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vreduceph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1a.c
new file mode 100644
index 0000000..9fcf7e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1a.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrndscaleph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+#define IMM 123
+
+volatile __m256h x2;
+volatile __m128h x3;
+volatile __mmask8 m8;
+volatile __mmask16 m16;
+
+void extern
+avx512fp16_test (void)
+{
+ x2 = _mm256_roundscale_ph (x2, IMM);
+ x3 = _mm_roundscale_ph (x3, IMM);
+
+ x2 = _mm256_mask_roundscale_ph (x2, m16, x2, IMM);
+ x3 = _mm_mask_roundscale_ph (x3, m8, x3, IMM);
+
+ x2 = _mm256_maskz_roundscale_ph (m8, x2, IMM);
+ x3 = _mm_maskz_roundscale_ph (m16, x3, IMM);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1b.c
new file mode 100644
index 0000000..04b00e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrndscaleph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrndscaleph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrndscaleph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c
new file mode 100644
index 0000000..a5edc17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vrsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1;
+volatile __m128h x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_rsqrt_ph (x1);
+ res1 = _mm256_mask_rsqrt_ph (res1, m16, x1);
+ res1 = _mm256_maskz_rsqrt_ph (m16, x1);
+
+ res2 = _mm_rsqrt_ph (x2);
+ res2 = _mm_mask_rsqrt_ph (res2, m8, x2);
+ res2 = _mm_maskz_rsqrt_ph (m8, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1b.c
new file mode 100644
index 0000000..a5e796b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vrsqrtph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrsqrtph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vrsqrtph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1a.c
new file mode 100644
index 0000000..22231d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vscalefph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_scalef_ph (x1, x2);
+ res1 = _mm256_mask_scalef_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_scalef_ph (m16, x1, x2);
+
+ res2 = _mm_scalef_ph (x3, x4);
+ res2 = _mm_mask_scalef_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_scalef_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1b.c
new file mode 100644
index 0000000..5c12d08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vscalefph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vscalefph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vscalefph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1a.c
new file mode 100644
index 0000000..4acb137
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vsqrtph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1;
+volatile __m128h x2;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_sqrt_ph (x1);
+ res1 = _mm256_mask_sqrt_ph (res1, m16, x1);
+ res1 = _mm256_maskz_sqrt_ph (m16, x1);
+
+ res2 = _mm_sqrt_ph (x2);
+ res2 = _mm_mask_sqrt_ph (res2, m8, x2);
+ res2 = _mm_maskz_sqrt_ph (m8, x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1b.c
new file mode 100644
index 0000000..9b0a91d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsqrtph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vsqrtph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vsqrtph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1a.c
new file mode 100644
index 0000000..10e5cbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1a.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include <immintrin.h>
+
+volatile __m256h res1;
+volatile __m128h res2;
+volatile __m256h x1,x2;
+volatile __m128h x3, x4;
+volatile __mmask16 m16;
+volatile __mmask8 m8;
+
+void extern
+avx512f_test (void)
+{
+ res1 = _mm256_sub_ph (x1, x2);
+ res1 = _mm256_mask_sub_ph (res1, m16, x1, x2);
+ res1 = _mm256_maskz_sub_ph (m16, x1, x2);
+
+ res2 = _mm_sub_ph (x3, x4);
+ res2 = _mm_mask_sub_ph (res2, m8, x3, x4);
+ res2 = _mm_maskz_sub_ph (m8, x3, x4);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1b.c
new file mode 100644
index 0000000..fa16218
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vsubph-1b.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+
+#define DEBUG
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vsubph-1b.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512fp16-vsubph-1b.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-abs-copysign-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-abs-copysign-1.c
index b375c5f..b27335b 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-abs-copysign-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-abs-copysign-1.c
@@ -64,8 +64,8 @@ f6 (double x)
}
/* { dg-final { scan-assembler "vpandd\[^\n\r\]*xmm16" } } */
-/* { dg-final { scan-assembler "vpord\[^\n\r\]*xmm16" } } */
+/* { dg-final { scan-assembler "vpternlogd\[^\n\r\]*xmm16" } } */
/* { dg-final { scan-assembler "vpxord\[^\n\r\]*xmm16" } } */
/* { dg-final { scan-assembler "vpandq\[^\n\r\]*xmm18" } } */
-/* { dg-final { scan-assembler "vporq\[^\n\r\]*xmm18" } } */
+/* { dg-final { scan-assembler "vpternlogq\[^\n\r\]*xmm18" } } */
/* { dg-final { scan-assembler "vpxorq\[^\n\r\]*xmm18" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c b/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c
new file mode 100644
index 0000000..02204d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-pr95046.c
@@ -0,0 +1,10 @@
+/* PR target/95046 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O3 -mavx512vl" } */
+
+#include "pr95046-3.c"
+
+/* { dg-final { scan-assembler "\tvfmadd\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfmsub\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfnmadd\[123\]+ps" } } */
+/* { dg-final { scan-assembler "\tvfnmsub\[123\]+ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqd-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqd-1.c
index 863bad9..4322c5d 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqd-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqq-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqq-1.c
index 35ddeeb..69b200a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpeqq-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpeqq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpeqq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$0)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtd-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtd-1.c
index 95ec53d..2278a27 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtd-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtd\[ \\t\]+|vpcmpd\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtq-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtq-1.c
index a83a901..26cac3a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpcmpgtq-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vpcmpgtq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "(?:vpcmpgtq\[ \\t\]+|vpcmpq\[ \\t\]+\\\$6)\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512vlfp16-11a.c b/gcc/testsuite/gcc.target/i386/avx512vlfp16-11a.c
new file mode 100644
index 0000000..a8c6296
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vlfp16-11a.c
@@ -0,0 +1,68 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+#include <immintrin.h>
+__m128h
+__attribute__ ((noinline, noclone))
+vadd128 (__m128h a, __m128h b)
+{
+ return a + b;
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+vadd256 (__m256h a, __m256h b)
+{
+ return a + b;
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+vsub128 (__m128h a, __m128h b)
+{
+ return a - b;
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+vsub256 (__m256h a, __m256h b)
+{
+ return a - b;
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+vmul128 (__m128h a, __m128h b)
+{
+ return a * b;
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+vmul256 (__m256h a, __m256h b)
+{
+ return a * b;
+}
+
+__m128h
+__attribute__ ((noinline, noclone))
+vdiv128 (__m128h a, __m128h b)
+{
+ return a / b;
+}
+
+__m256h
+__attribute__ ((noinline, noclone))
+vdiv256 (__m256h a, __m256h b)
+{
+ return a / b;
+}
+
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\[^\n\r\]*%xmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vaddph\[ \\t\]+\[^\n\r\]*%ymm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\[^\n\r\]*%xmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vsubph\[ \\t\]+\[^\n\r\]*%ymm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\[^\n\r\]*%xmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vmulph\[ \\t\]+\[^\n\r\]*%ymm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\[^\n\r\]*%xmm\[01\]" 1 } } */
+/* { dg-final { scan-assembler-times "vdivph\[ \\t\]+\[^\n\r\]*%ymm\[01\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vlfp16-11b.c b/gcc/testsuite/gcc.target/i386/avx512vlfp16-11b.c
new file mode 100644
index 0000000..b8d3e8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vlfp16-11b.c
@@ -0,0 +1,96 @@
+/* { dg-do run { target avx512fp16 } } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
+
+#include <string.h>
+#include <stdlib.h>
+static void do_test (void);
+
+#define DO_TEST do_test
+#define AVX512FP16
+#include "avx512-check.h"
+#include "avx512vlfp16-11a.c"
+
+/* Get random float16 between -50.x to 50.x. */
+_Float16
+get_float16_noround()
+{
+ return ((int) (100.0 * rand ()/ (RAND_MAX + 1.0)) - 50)
+ + 0.1f * (int) (10 * rand() / (RAND_MAX + 1.0));
+}
+
+static void
+do_test (void)
+{
+ _Float16 x[16];
+ _Float16 y[16];
+ _Float16 res_add[16];
+ _Float16 res_sub[16];
+ _Float16 res_mul[16];
+ _Float16 res_div[16];
+ for (int i = 0 ; i != 16; i++)
+ {
+ x[i] = get_float16_noround ();
+ y[i] = get_float16_noround ();
+ if (y[i] == 0)
+ y[i] = 1.0f;
+ res_add[i] = x[i] + y[i];
+ res_sub[i] = x[i] - y[i];
+ res_mul[i] = x[i] * y[i];
+ res_div[i] = x[i] / y[i];
+
+ }
+
+ union128h u128 = { x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] };
+ union128h u128_1 = { y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7] };
+ union256h u256 = { x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15] };
+ union256h u256_1 = { y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7],
+ y[8], y[9], y[10], y[11], y[12], y[13], y[14], y[15]};
+
+ __m128h v128;
+ __m256h v256;
+ union128h a128;
+ union256h a256;
+
+ memset (&v128, -1, sizeof (v128));
+ v128 = vadd128 (u128.x, u128_1.x);
+ a128.x = v128;
+ if (check_union128h (a128, res_add))
+ abort ();
+ memset (&v128, -1, sizeof (v128));
+ v128 = vsub128 (u128.x, u128_1.x);
+ a128.x = v128;
+ if (check_union128h (a128, res_sub))
+ abort ();
+ memset (&v128, -1, sizeof (v128));
+ v128 = vmul128 (u128.x, u128_1.x);
+ a128.x = v128;
+ if (check_union128h (a128, res_mul))
+ abort ();
+ memset (&v128, -1, sizeof (v128));
+ v128 = vdiv128 (u128.x, u128_1.x);
+ a128.x = v128;
+ if (check_union128h (a128, res_div))
+ abort ();
+
+ memset (&v256, -1, sizeof (v256));
+ v256 = vadd256 (u256.x, u256_1.x);
+ a256.x = v256;
+ if (check_union256h (a256, res_add))
+ abort ();
+ memset (&v256, -1, sizeof (v256));
+ v256 = vsub256 (u256.x, u256_1.x);
+ a256.x = v256;
+ if (check_union256h (a256, res_sub))
+ abort ();
+ memset (&v256, -1, sizeof (v256));
+ v256 = vmul256 (u256.x, u256_1.x);
+ a256.x = v256;
+ if (check_union256h (a256, res_mul))
+ abort ();
+ memset (&v256, -1, sizeof (v256));
+ v256 = vdiv256 (u256.x, u256_1.x);
+ a256.x = v256;
+ if (check_union256h (a256, res_div))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c b/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c
index 709cd21..a732bc4 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-vpopcntd-1.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -mavx512vpopcntdq -mavx512bw -mavx512vl" } */
+/* { dg-options "-O2 -fno-tree-vectorize -mavx512vpopcntdq -mavx512bw -mavx512vl" } */
/* { dg-require-effective-target avx512vl } */
/* { dg-require-effective-target avx512vpopcntdqvl } */
/* { dg-require-effective-target avx512bw } */
diff --git a/gcc/testsuite/gcc.target/i386/bitwise_mask_op-1.c b/gcc/testsuite/gcc.target/i386/bitwise_mask_op-1.c
index 61f71ab..826ed69 100644
--- a/gcc/testsuite/gcc.target/i386/bitwise_mask_op-1.c
+++ b/gcc/testsuite/gcc.target/i386/bitwise_mask_op-1.c
@@ -150,8 +150,6 @@ foo_notq (__m512i a, __m512i b, __m512i c, __m512i d)
return _mm512_mask_add_epi8 (c, ~m1, a, d);
}
-/* { dg-final { scan-assembler-times "knotq" "2" { target { ! ia32 } } } } */
-
__m512i
foo_notd (__m512i a, __m512i b, __m512i c, __m512i d)
{
@@ -159,8 +157,6 @@ foo_notd (__m512i a, __m512i b, __m512i c, __m512i d)
return _mm512_mask_add_epi16 (c, ~m1, a, d);
}
-/* { dg-final { scan-assembler-times "knotd" "2" { target { ! ia32 } } } } */
-
__m512i
foo_notw (__m512i a, __m512i b, __m512i c, __m512i d)
{
@@ -174,5 +170,3 @@ foo_notb (__m512i a, __m512i b, __m512i c, __m512i d)
__mmask8 m1 = _mm512_cmpeq_epi64_mask (a, b);
return _mm512_mask_add_epi64 (c, ~m1, a, d);
}
-
-/* { dg-final { scan-assembler-times "knotw" "4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/bitwise_mask_op-2.c b/gcc/testsuite/gcc.target/i386/bitwise_mask_op-2.c
index 850f0b4..e93269b 100644
--- a/gcc/testsuite/gcc.target/i386/bitwise_mask_op-2.c
+++ b/gcc/testsuite/gcc.target/i386/bitwise_mask_op-2.c
@@ -1,7 +1,6 @@
/* PR target/88808 */
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512dq -O2" } */
-/* { dg-final { scan-assembler-times "knotb" "2" } } */
/* { dg-final { scan-assembler-times "korb" "1" } } */
/* { dg-final { scan-assembler-times "kxorb" "1" } } */
#include "bitwise_mask_op-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index aa96805..3e7505a 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include "cpuid.h"
#define CHECK___builtin_cpu_is(cpu) assert (__builtin_cpu_is (cpu))
+#define CHECK___builtin_cpu_supports(isa) \
+ assert (__builtin_cpu_supports (isa))
#define gcc_assert(a) assert (a)
#define gcc_unreachable() abort ()
#define inline
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c
new file mode 100644
index 0000000..b503b75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-vect" } */
+/* { dg-final { scan-tree-dump ".COND_ADD" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_SUB" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_MUL" "vect" } } */
+/* { dg-final { scan-tree-dump ".COND_RDIV" "vect" } } */
+
+#include "cond_op_addsubmuldiv_double-1.c"
+
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c
new file mode 100644
index 0000000..e8397bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_addsubmuldiv__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "cond_op_addsubmuldiv_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c
new file mode 100644
index 0000000..9ea45d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-optimized -D__BUILTIN_FMA=__builtin_fmaf16" } */
+/* { dg-final { scan-tree-dump-times ".COND_FMA" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FNMA" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FMS" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times ".COND_FNMS" 3 "optimized" } } */
+/* { dg-final { scan-assembler-times "vfmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+#include "cond_op_fma_double-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c
new file mode 100644
index 0000000..b384ab8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_fma__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16 -D__BUILTIN_FMA=__builtin_fmaf16 -DNUM=100" } */
+/* { dg-require-effective-target avx512fp16 } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512FP16
+#include "cond_op_fma_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c
new file mode 100644
index 0000000..b094102
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -DTYPE=_Float16 -fdump-tree-optimized -DFN_MAX=__builtin_fmaxf16 -DFN_MIN=__builtin_fminf16" } */
+/* { dg-final { scan-tree-dump ".COND_MAX" "optimized" } } */
+/* { dg-final { scan-tree-dump ".COND_MIN" "optimized" } } */
+/* { dg-final { scan-assembler-times "vmaxph" 1 } } */
+/* { dg-final { scan-assembler-times "vminph" 1 } } */
+
+#include "cond_op_maxmin_double-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c
new file mode 100644
index 0000000..b07d044
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cond_op_maxmin__Float16-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mprefer-vector-width=256 -DTYPE=_Float16 -DFN_MAX=__builtin_fmaxf16 -DFN_MIN=__builtin_fminf16 -ffast-math" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512FP16
+#include "cond_op_maxmin_double-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/eh_return-1.c b/gcc/testsuite/gcc.target/i386/eh_return-1.c
index 671ba63..b21fd75 100644
--- a/gcc/testsuite/gcc.target/i386/eh_return-1.c
+++ b/gcc/testsuite/gcc.target/i386/eh_return-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=haswell -mno-avx512f" } */
+/* { dg-options "-O2 -march=haswell -mno-avx512f -mtune-ctrl=avx256_move_by_pieces" } */
struct _Unwind_Context
{
diff --git a/gcc/testsuite/gcc.target/i386/float16-3a.c b/gcc/testsuite/gcc.target/i386/float16-3a.c
new file mode 100644
index 0000000..3846c8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-3a.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "vcvtsi2shl\[ \t\]+\[^\n\r]*%xmm0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/float16-3b.c b/gcc/testsuite/gcc.target/i386/float16-3b.c
new file mode 100644
index 0000000..247dd6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-3b.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+foo (unsigned int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "vcvtusi2shl\[ \t\]+\[^\n\r]*%xmm0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/float16-4a.c b/gcc/testsuite/gcc.target/i386/float16-4a.c
new file mode 100644
index 0000000..6310825
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-4a.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+foo (long long x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "vcvtsi2shq\[ \t\]+\[^\n\r]*%xmm0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/float16-4b.c b/gcc/testsuite/gcc.target/i386/float16-4b.c
new file mode 100644
index 0000000..828d853
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-4b.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+foo (unsigned long long x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "vcvtusi2shq\[ \t\]+\[^\n\r]*%xmm0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/float16-5.c b/gcc/testsuite/gcc.target/i386/float16-5.c
new file mode 100644
index 0000000..ebc0af1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-5.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+_Float16
+foo (int a)
+{
+ union {
+ int a;
+ _Float16 b;
+ }c;
+ c.a = a;
+ return c.b;
+}
diff --git a/gcc/testsuite/gcc.target/i386/float16-6.c b/gcc/testsuite/gcc.target/i386/float16-6.c
new file mode 100644
index 0000000..3d2503c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-6.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2 -mfpmath=sse -fdump-tree-gimple -fexcess-precision=16" } */
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "gimple" } } */
+_Float16
+foo (_Float16 a, _Float16 b, _Float16 c)
+{
+ return a + b + c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/float16-7.c b/gcc/testsuite/gcc.target/i386/float16-7.c
new file mode 100644
index 0000000..86641af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-7.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
+/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with '-mfpmath=387'" } */
+_Float16
+foo (_Float16 a, _Float16 b)
+{
+ return a + b;/* { dg-error "'-fexcess-precision=16' is not compatible with '-mfpmath=387'" } */
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
index 79265c7..8499fdf 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
@@ -79,6 +79,7 @@ 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_avx512fp16 (void) __attribute__((__target__("avx512fp16")));
extern void test_no_sgx (void) __attribute__((__target__("no-sgx")));
extern void test_no_avx5124fmaps(void) __attribute__((__target__("no-avx5124fmaps")));
@@ -159,6 +160,7 @@ 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_no_avx512fp16 (void) __attribute__((__target__("no-avx512fp16")));
extern void test_arch_nocona (void) __attribute__((__target__("arch=nocona")));
extern void test_arch_core2 (void) __attribute__((__target__("arch=core2")));
diff --git a/gcc/testsuite/gcc.target/i386/m512-check.h b/gcc/testsuite/gcc.target/i386/m512-check.h
index 6befaf0..68e74fc 100644
--- a/gcc/testsuite/gcc.target/i386/m512-check.h
+++ b/gcc/testsuite/gcc.target/i386/m512-check.h
@@ -60,7 +60,24 @@ typedef union
__m512i x;
unsigned long long a[8];
} union512i_uq;
-
+
+typedef union
+{
+ __m128h x;
+ _Float16 a[8];
+} union128h;
+
+typedef union
+{
+ __m256h x;
+ _Float16 a[16];
+} union256h;
+
+typedef union
+{
+ __m512h x;
+ _Float16 a[32];
+} union512h;
CHECK_EXP (union512i_b, char, "%d")
CHECK_EXP (union512i_w, short, "%d")
@@ -115,3 +132,22 @@ CHECK_ROUGH_EXP (union256, float, "%f")
CHECK_ROUGH_EXP (union256d, double, "%f")
CHECK_ROUGH_EXP (union128, float, "%f")
CHECK_ROUGH_EXP (union128d, double, "%f")
+
+#ifdef AVX512FP16
+
+CHECK_EXP (union128h, _Float16, "%f")
+CHECK_EXP (union256h, _Float16, "%f")
+CHECK_EXP (union512h, _Float16, "%f")
+
+#ifndef ESP_FLOAT16
+#define ESP_FLOAT16 0.27
+#endif
+
+CHECK_FP_EXP (union128h, _Float16, ESP_FLOAT16, "%f")
+CHECK_FP_EXP (union256h, _Float16, ESP_FLOAT16, "%f")
+CHECK_FP_EXP (union512h, _Float16, ESP_FLOAT16, "%f")
+
+CHECK_ROUGH_EXP (union128h, _Float16, "%f")
+CHECK_ROUGH_EXP (union256h, _Float16, "%f")
+CHECK_ROUGH_EXP (union512h, _Float16, "%f")
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/mmx-reduce-op-1.c b/gcc/testsuite/gcc.target/i386/mmx-reduce-op-1.c
new file mode 100644
index 0000000..ac20ed0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mmx-reduce-op-1.c
@@ -0,0 +1,58 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MIN" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MAX" 2 "optimized" } } */
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+short
+__attribute__((noipa, optimize("Ofast"),target("sse2")))
+reduce_add (short* __restrict pa)
+{
+ short sum = 0;
+ for (int i = 0; i != 4; i++)
+ sum += pa[i];
+ return sum;
+}
+
+short
+__attribute__((noipa, optimize("Ofast"),target("sse2")))
+reduce_smax (short* __restrict pa)
+{
+ short sum = pa[0];
+ for (int i = 0; i != 4; i++)
+ sum = MAX(sum, pa[i]);
+ return sum;
+}
+
+short
+__attribute__((noipa, optimize("Ofast"),target("sse2")))
+reduce_smin (short* __restrict pa)
+{
+ short sum = pa[0];
+ for (int i = 0; i != 4; i++)
+ sum = MIN(sum, pa[i]);
+ return sum;
+}
+
+unsigned short
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_umax (unsigned short* __restrict pa)
+{
+ unsigned short sum = pa[0];
+ for (int i = 0; i != 4; i++)
+ sum = MAX(sum, pa[i]);
+ return sum;
+}
+
+unsigned short
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_umin (unsigned short* __restrict pa)
+{
+ unsigned short sum = pa[0];
+ for (int i = 0; i != 4; i++)
+ sum = MIN(sum, pa[i]);
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.target/i386/mmx-reduce-op-2.c b/gcc/testsuite/gcc.target/i386/mmx-reduce-op-2.c
new file mode 100644
index 0000000..0896cd6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mmx-reduce-op-2.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O2 -msse4.1" } */
+
+#include "sse4_1-check.h"
+
+#include "mmx-reduce-op-1.c"
+
+static void
+sse4_1_test ()
+{
+ short p[4] = { -103, 23, 41, 200 };
+ unsigned short up[4] = { 100, 30, 299, 1000 };
+
+ if (reduce_add (p) != 161)
+ abort ();
+ if (reduce_smin (p) != -103)
+ abort ();
+ if (reduce_smax (p) != 200)
+ abort ();
+ if (reduce_umin (up) != 30)
+ abort ();
+ if (reduce_umax (up) != 1000)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/mvc16.c b/gcc/testsuite/gcc.target/i386/mvc16.c
new file mode 100644
index 0000000..def6581
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mvc16.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("arch=x86-64", "arch=x86-64-v2", "arch=x86-64-v3", "arch=x86-64-v4", "default")))
+int
+foo ()
+{
+ return 0;
+}
+
+int
+main ()
+{
+ return foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-12.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-12.c
index f1432eb..8a82baf 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memcpy-12.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_move_by_pieces" } */
extern char *dst, *src;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memcpy-15.c b/gcc/testsuite/gcc.target/i386/pieces-memcpy-15.c
index 695e8c3..4fb94ce 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memcpy-15.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memcpy-15.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_move_by_pieces" } */
extern char *dst, *src;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-11.c b/gcc/testsuite/gcc.target/i386/pieces-memset-11.c
index 3fb9038..3802eb7 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-11.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-14.c b/gcc/testsuite/gcc.target/i386/pieces-memset-14.c
index 45ece48..10bc085 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-14.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-14.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-2.c b/gcc/testsuite/gcc.target/i386/pieces-memset-2.c
index 649f344..4ebfc4d 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-2.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-20.c b/gcc/testsuite/gcc.target/i386/pieces-memset-20.c
index b8747e6..1dc4db1 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-20.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-20.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-23.c b/gcc/testsuite/gcc.target/i386/pieces-memset-23.c
index a3b4ffc..9232864 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-23.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-23.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-29.c b/gcc/testsuite/gcc.target/i386/pieces-memset-29.c
index 650e6fe..3b07a64 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-29.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-29.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-30.c b/gcc/testsuite/gcc.target/i386/pieces-memset-30.c
index dcec2c7..59595e6 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-30.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-30.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-33.c b/gcc/testsuite/gcc.target/i386/pieces-memset-33.c
index a87d1b8..6864622 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-33.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-33.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-34.c b/gcc/testsuite/gcc.target/i386/pieces-memset-34.c
index 0c2f1ee..52a16a0 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-34.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-34.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-37.c b/gcc/testsuite/gcc.target/i386/pieces-memset-37.c
index ec59497..fd09bd1 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-37.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-37.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune=generic" } */
+/* { dg-options "-O2 -mno-avx512f -mavx2 -mtune-ctrl=avx256_store_by_pieces" } */
void
foo (int a1, int a2, int a3, int a4, int a5, int a6, int x, char *dst)
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-44.c b/gcc/testsuite/gcc.target/i386/pieces-memset-44.c
index ecc31be..5986f8e 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-44.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-44.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pieces-memset-5.c b/gcc/testsuite/gcc.target/i386/pieces-memset-5.c
index 3e95db5..e2379df 100644
--- a/gcc/testsuite/gcc.target/i386/pieces-memset-5.c
+++ b/gcc/testsuite/gcc.target/i386/pieces-memset-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-avx2 -mavx -mtune=haswell" } */
+/* { dg-options "-O2 -mno-avx2 -mavx -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-10a.c b/gcc/testsuite/gcc.target/i386/pr100865-10a.c
index 98b6dfb..1d849a3 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-10a.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-10a.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target int128 } } */
-/* { dg-options "-O3 -march=skylake" } */
+/* { dg-options "-O3 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern __int128 array[16];
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-4a.c b/gcc/testsuite/gcc.target/i386/pr100865-4a.c
index 3654873..8609d11 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-4a.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-4a.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern char array[64];
diff --git a/gcc/testsuite/gcc.target/i386/pr101282.c b/gcc/testsuite/gcc.target/i386/pr101282.c
new file mode 100644
index 0000000..2148b92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101282.c
@@ -0,0 +1,18 @@
+/* { dg-do run { target { ia32 } } } */
+/* { dg-options "-Os -march=i686 -mfpmath=sse -msse2" } */
+
+#include<stdlib.h>
+int
+main (void)
+{
+ static volatile unsigned int ivin, ivout;
+ static volatile _Float16 fv1, fv2;
+ ivin = ((unsigned int)1);
+ fv1 = ((unsigned int)1);
+ fv2 = ivin;
+ ivout = fv2;
+ if (ivout != ((unsigned int)1))
+ abort ();
+
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr101900-1.c b/gcc/testsuite/gcc.target/i386/pr101900-1.c
new file mode 100644
index 0000000..0a45f8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101900-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=use_vector_fp_converts" } */
+
+extern float f;
+extern double d;
+extern int i;
+
+void
+foo (void)
+{
+ d = f;
+ f = i;
+}
+
+/* { dg-final { scan-assembler "vcvtps2pd" } } */
+/* { dg-final { scan-assembler "vcvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "vcvtss2sd" } } */
+/* { dg-final { scan-assembler-times "vxorps\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr101900-2.c b/gcc/testsuite/gcc.target/i386/pr101900-2.c
new file mode 100644
index 0000000..c8b2d1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101900-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=use_vector_converts" } */
+
+extern float f;
+extern double d;
+extern int i;
+
+void
+foo (void)
+{
+ d = f;
+ f = i;
+}
+
+/* { dg-final { scan-assembler "vcvtss2sd" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps" } } */
+/* { dg-final { scan-assembler-not "vcvtsi2ssl" } } */
+/* { dg-final { scan-assembler-times "vxorps\[^\n\r\]*xmm\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr101900-3.c b/gcc/testsuite/gcc.target/i386/pr101900-3.c
new file mode 100644
index 0000000..6ee565b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101900-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=skylake -mfpmath=sse -mtune-ctrl=use_vector_fp_converts,use_vector_converts" } */
+
+extern float f;
+extern double d;
+extern int i;
+
+void
+foo (void)
+{
+ d = f;
+ f = i;
+}
+
+/* { dg-final { scan-assembler "vcvtps2pd" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps" } } */
+/* { dg-final { scan-assembler-not "vcvtss2sd" } } */
+/* { dg-final { scan-assembler-not "vcvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "vxorps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102080.c b/gcc/testsuite/gcc.target/i386/pr102080.c
new file mode 100644
index 0000000..4c5ee32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102080.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include<immintrin.h>
+typedef float __m256 __attribute__((__vector_size__(32)));
+__m256 _mm256_blendv_ps___Y, _mm256_blendv_ps___M, _mm256_mul_ps___A,
+ _mm256_mul_ps___B, IfThenElse___trans_tmp_9;
+
+void
+__attribute__ ((target("avx")))
+IfThenElse (__m256 no) {
+ IfThenElse___trans_tmp_9 = _mm256_blendv_ps (no, _mm256_blendv_ps___Y, _mm256_blendv_ps___M);
+}
+void
+__attribute__ ((target("avx512vl")))
+EncodedFromDisplay() {
+ __m256 __trans_tmp_11 = _mm256_mul_ps___A * _mm256_mul_ps___B;
+ IfThenElse(__trans_tmp_11);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102230.c b/gcc/testsuite/gcc.target/i386/pr102230.c
new file mode 100644
index 0000000..ad37f4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102230.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+typedef _Float16 v4hf __attribute__ ((vector_size (8)));
+typedef _Float16 v2hf __attribute__ ((vector_size (4)));
+
+v4hf
+v4hf_abi_1 (v4hf a)
+{
+ return a;
+}
+
+v4hf
+v4hf_abi_3 (v4hf a, v4hf b, v4hf c)
+{
+ return c;
+}
+
+/* { dg-final { scan-assembler-times "movq\[\\t \]*%mm2, %mm0" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm2, %xmm0" 1 { target { ! ia32 } } } } */
+
+v4hf
+v4hf_abi_4 (v4hf a, v4hf b, v4hf c, v4hf d)
+{
+ return d;
+}
+
+/* { dg-final { scan-assembler-times "movq\[\\t \]*4\\(%esp\\), %mm0" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm3, %xmm0" 1 { target { ! ia32 } } } } */
+
+v2hf
+v2hf_test (v2hf a, v2hf b, v2hf c, v2hf d)
+{
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "movl\[\\t \]*8\\(%esp\\), %eax" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "vmovaps\[\\t \]*%xmm1, %xmm0" 1 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102327-1.c b/gcc/testsuite/gcc.target/i386/pr102327-1.c
new file mode 100644
index 0000000..4743926
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102327-1.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+
+typedef _Float16 v8hf __attribute__((vector_size (16)));
+typedef _Float16 v16hf __attribute__((vector_size (32)));
+typedef _Float16 v32hf __attribute__((vector_size (64)));
+
+#define VEC_EXTRACT(V,S,IDX) \
+ S \
+ __attribute__((noipa)) \
+ vec_extract_##V##_##IDX (V v) \
+ { \
+ return v[IDX]; \
+ }
+
+#define VEC_SET(V,S,IDX) \
+ V \
+ __attribute__((noipa)) \
+ vec_set_##V##_##IDX (V v, S s) \
+ { \
+ v[IDX] = s; \
+ return v; \
+ }
+
+v8hf
+vec_init_v8hf (_Float16 a1, _Float16 a2, _Float16 a3, _Float16 a4, _Float16 a5,
+_Float16 a6, _Float16 a7, _Float16 a8)
+{
+ return __extension__ (v8hf) {a1, a2, a3, a4, a5, a6, a7, a8};
+}
+
+/* { dg-final { scan-assembler-times "vpunpcklwd" 4 } } */
+/* { dg-final { scan-assembler-times "vpunpckldq" 2 } } */
+/* { dg-final { scan-assembler-times "vpunpcklqdq" 1 } } */
+
+VEC_EXTRACT (v8hf, _Float16, 4);
+VEC_EXTRACT (v16hf, _Float16, 3);
+VEC_EXTRACT (v16hf, _Float16, 8);
+VEC_EXTRACT (v16hf, _Float16, 15);
+VEC_EXTRACT (v32hf, _Float16, 5);
+VEC_EXTRACT (v32hf, _Float16, 8);
+VEC_EXTRACT (v32hf, _Float16, 14);
+VEC_EXTRACT (v32hf, _Float16, 16);
+VEC_EXTRACT (v32hf, _Float16, 24);
+VEC_EXTRACT (v32hf, _Float16, 28);
+/* { dg-final { scan-assembler-times "vpsrldq\[\t ]*\\\$8" 2 } } */
+/* { dg-final { scan-assembler-times "vpsrldq\[\t ]*\\\$6" 1 } } */
+/* { dg-final { scan-assembler-times "vpsrldq\[\t ]*\\\$14" 1 } } */
+/* { dg-final { scan-assembler-times "vpsrldq\[\t ]*\\\$10" 1 } } */
+/* { dg-final { scan-assembler-times "vpsrldq\[\t ]*\\\$12" 1 } } */
+/* { dg-final { scan-assembler-times "vextract" 9 } } */
+
+VEC_SET (v8hf, _Float16, 4);
+VEC_SET (v16hf, _Float16, 3);
+VEC_SET (v16hf, _Float16, 8);
+VEC_SET (v16hf, _Float16, 15);
+VEC_SET (v32hf, _Float16, 5);
+VEC_SET (v32hf, _Float16, 8);
+VEC_SET (v32hf, _Float16, 14);
+VEC_SET (v32hf, _Float16, 16);
+VEC_SET (v32hf, _Float16, 24);
+VEC_SET (v32hf, _Float16, 28);
+/* { dg-final { scan-assembler-times "vpbroadcastw" 10 } } */
+/* { dg-final { scan-assembler-times "vpblendw" 4 } } */
+/* { dg-final { scan-assembler-times "vpblendd" 3 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102327-2.c b/gcc/testsuite/gcc.target/i386/pr102327-2.c
new file mode 100644
index 0000000..363e4b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102327-2.c
@@ -0,0 +1,95 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vl -mavx512fp16" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512fp16 } */
+
+#define AVX512VL
+#define AVX512FP16
+
+#ifndef CHECK
+#define CHECK "avx512f-helper.h"
+#endif
+
+#include CHECK
+#include "pr102327-1.c"
+
+#define RUNCHECK_VEC_EXTRACT(U,V,S,IDX) \
+ do \
+ { \
+ S tmp = vec_extract_##V##_##IDX ((V)U.x); \
+ if (tmp != U.a[IDX]) \
+ abort(); \
+ } \
+ while (0)
+
+#define RUNCHECK_VEC_SET(UTYPE,U,V,S,IDX,NUM) \
+ do \
+ { \
+ S tmp = 3.0f; \
+ UTYPE res; \
+ res.x = vec_set_##V##_##IDX ((V)U.x, tmp); \
+ for (int i = 0; i != NUM; i++) \
+ if (i == IDX) \
+ { \
+ if (res.a[i] != tmp) \
+ abort (); \
+ } \
+ else if (res.a[i] != U.a[i]) \
+ abort(); \
+ } \
+ while (0)
+
+void
+test_256 (void)
+{
+ union512h g1;
+ union256h t1;
+ union128h x1;
+ int sign = 1;
+
+ int i = 0;
+ for (i = 0; i < 32; i++)
+ {
+ g1.a[i] = 56.78 * (i - 30) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i != 16; i++)
+ {
+ t1.a[i] = 90.12 * (i + 40) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i != 8; i++)
+ {
+ x1.a[i] = 90.12 * (i + 40) * sign;
+ sign = -sign;
+ }
+
+ RUNCHECK_VEC_EXTRACT (x1, v8hf, _Float16, 4);
+ RUNCHECK_VEC_EXTRACT (t1, v16hf, _Float16, 3);
+ RUNCHECK_VEC_EXTRACT (t1, v16hf, _Float16, 8);
+ RUNCHECK_VEC_EXTRACT (t1, v16hf, _Float16, 15);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 5);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 8);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 14);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 16);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 24);
+ RUNCHECK_VEC_EXTRACT (g1, v32hf, _Float16, 28);
+
+ RUNCHECK_VEC_SET (union128h, x1, v8hf, _Float16, 4, 8);
+ RUNCHECK_VEC_SET (union256h, t1, v16hf, _Float16, 3, 16);
+ RUNCHECK_VEC_SET (union256h, t1, v16hf, _Float16, 8, 16);
+ RUNCHECK_VEC_SET (union256h, t1, v16hf, _Float16, 15, 16);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 5, 32);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 8, 32);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 14, 32);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 16, 32);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 24, 32);
+ RUNCHECK_VEC_SET (union512h, g1, v32hf, _Float16, 28, 32);
+}
+
+void
+test_128()
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102464.c b/gcc/testsuite/gcc.target/i386/pr102464.c
new file mode 100644
index 0000000..e3e060e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102464.c
@@ -0,0 +1,39 @@
+/* PR target/102464. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+#define FOO(FUNC,SUFFIX) \
+ _Float16 \
+ foo_##FUNC##_##SUFFIX (_Float16 a) \
+ { \
+ return __builtin_##FUNC##SUFFIX (a); \
+ }
+
+FOO (roundeven, f16);
+FOO (roundeven, f);
+FOO (roundeven, );
+FOO (roundeven, l);
+FOO (trunc, f16);
+FOO (trunc, f);
+FOO (trunc, );
+FOO (trunc, l);
+FOO (ceil, f16);
+FOO (ceil, f);
+FOO (ceil, );
+FOO (ceil, l);
+FOO (floor, f16);
+FOO (floor, f);
+FOO (floor, );
+FOO (floor, l);
+FOO (nearbyint, f16);
+FOO (nearbyint, f);
+FOO (nearbyint, );
+FOO (nearbyint, l);
+FOO (rint, f16);
+FOO (rint, f);
+FOO (rint, );
+FOO (rint, l);
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-not "extendhfxf" } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[^\n\r\]*xmm\[0-9\]" 24 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr102483-2.c b/gcc/testsuite/gcc.target/i386/pr102483-2.c
new file mode 100644
index 0000000..d477c53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102483-2.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O2 -msse4.1" } */
+
+#include "sse4_1-check.h"
+
+#include "pr102483.c"
+
+static void
+sse4_1_test ()
+{
+ char p[4] = { -103, 23, 41, -56 };
+ unsigned char up[4] = { 100, 30, 255, 9 };
+
+ char res = reduce_add (p);
+ if (res != -95)
+ abort ();
+ if (reduce_smin (p) != -103)
+ abort ();
+ if (reduce_smax (p) != 41)
+ abort ();
+ if (reduce_umin (up) != 9)
+ abort ();
+ if (reduce_umax (up) != 255)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102483.c b/gcc/testsuite/gcc.target/i386/pr102483.c
new file mode 100644
index 0000000..681b575
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102483.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse4.1 -ftree-vectorize -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MIN" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_MAX" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 1 "optimized" } } */
+
+char
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_add (char* p)
+{
+ char sum = 0;
+ for (int i = 0; i != 4; i++)
+ sum += p[i];
+ return sum;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+unsigned char
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_umax (unsigned char* p)
+{
+ unsigned char sum = p[0];
+ for (int i = 0; i != 4; i++)
+ sum = MAX(sum, p[i]);
+ return sum;
+}
+
+unsigned char
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_umin (unsigned char* p)
+{
+ unsigned char sum = p[0];
+ for (int i = 0; i != 4; i++)
+ sum = MIN(sum, p[i]);
+ return sum;
+}
+
+char
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_smax (char* p)
+{
+ char sum = p[0];
+ for (int i = 0; i != 4; i++)
+ sum = MAX(sum, p[i]);
+ return sum;
+}
+
+char
+__attribute__((noipa, optimize("Ofast"),target("sse4.1")))
+reduce_smin (char* p)
+{
+ char sum = p[0];
+ for (int i = 0; i != 4; i++)
+ sum = MIN(sum, p[i]);
+ return sum;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102498.c b/gcc/testsuite/gcc.target/i386/pr102498.c
new file mode 100644
index 0000000..44161c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102498.c
@@ -0,0 +1,59 @@
+/* PR target/102498 */
+/* { dg-do run { target fenv } } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+__attribute__((noipa)) long double
+fldlg2 (void)
+{
+ return 0.3010299956639811952256464283594894482L;
+}
+
+__attribute__((noipa)) long double
+fldln2 (void)
+{
+ return 0.6931471805599453094286904741849753009L;
+}
+
+__attribute__((noipa)) long double
+fldl2e (void)
+{
+ return 1.4426950408889634073876517827983434472L;
+}
+
+__attribute__((noipa)) long double
+fldl2t (void)
+{
+ return 3.3219280948873623478083405569094566090L;
+}
+
+__attribute__((noipa)) long double
+fldpi (void)
+{
+ return 3.1415926535897932385128089594061862044L;
+}
+
+int
+main ()
+{
+ long double a = fldlg2 ();
+ long double b = fldln2 ();
+ long double c = fldl2e ();
+ long double d = fldl2t ();
+ long double e = fldpi ();
+ static int f[] = { FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD };
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ fesetround (f[i]);
+ if (a != fldlg2 ()
+ || b != fldln2 ()
+ || c != fldl2e ()
+ || d != fldl2t ()
+ || e != fldpi ())
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102627.c b/gcc/testsuite/gcc.target/i386/pr102627.c
new file mode 100644
index 0000000..8ab9aca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102627.c
@@ -0,0 +1,41 @@
+/* PR rtl-optimization/102627 */
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+int a, f, l, m, q, c, d, g;
+long b, e;
+struct g {
+ signed h;
+ signed i;
+ unsigned j;
+ unsigned k;
+};
+unsigned n;
+char o;
+int *p = &m;
+long r(int s) { return s && b ?: b; }
+long __attribute__((noipa)) v() {
+ l = 0 || r(n & o);
+ return q;
+}
+void w(int, unsigned, struct g x) {
+ c ?: a;
+ for (; d < 2; d++)
+ *p = x.k;
+}
+struct g __attribute__((noipa)) y() {
+ struct g h = {3, 908, 1, 20};
+ for (; g; g++)
+ ;
+ return h;
+}
+int main() {
+ long t;
+ struct g u = y();
+ t = e << f;
+ w(0, t, u);
+ v(0, 4, 4, 4);
+ if (m != 20)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr34012.c b/gcc/testsuite/gcc.target/i386/pr34012.c
index d0cffa05..1c1f0ee 100644
--- a/gcc/testsuite/gcc.target/i386/pr34012.c
+++ b/gcc/testsuite/gcc.target/i386/pr34012.c
@@ -1,7 +1,7 @@
/* PR rtl-optimization/34012 */
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-O2 -fno-store-merging" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fno-store-merging" } */
void bar (long int *);
void
diff --git a/gcc/testsuite/gcc.target/i386/pr49781-1.c b/gcc/testsuite/gcc.target/i386/pr49781-1.c
index 60f9d50..d5a2e32 100644
--- a/gcc/testsuite/gcc.target/i386/pr49781-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr49781-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fpic -mtune=generic" } */
+/* { dg-options "-O2 -fno-tree-vectorize -fpic -mtune=generic" } */
/* { dg-require-effective-target fpic } */
static int heap[2*(256 +1+29)+1];
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-11.c b/gcc/testsuite/gcc.target/i386/pr54855-11.c
new file mode 100644
index 0000000..0d7d739
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-11.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vaddsh\[ \\t\]" 1 } } */
+/* { dg-final { scan-assembler-not "vpextrw\[ \\t\]" } } */
+/* { dg-final { scan-assembler-not "vmovd\[ \\t\]" } } */
+/* { dg-final { scan-assembler-not "vpunpckldq\[ \\t\]" } } */
+/* { dg-final { scan-assembler-not "vpunpcklqdq\[ \\t\]" } } */
+
+#include <immintrin.h>
+
+__m128h
+foo (__m128h x, __m128h y)
+{
+ return _mm_add_sh (x, y);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-12.c b/gcc/testsuite/gcc.target/i386/pr54855-12.c
new file mode 100644
index 0000000..2f8af39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-12.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]" 1 } } */
+/* { dg-final { scan-assembler-not "vcomish\[ \\t\]" } } */
+/* { dg-final { scan-assembler-not "vmovsh\[ \\t\]" { target { ! ia32 } } } } */
+
+#include <immintrin.h>
+
+_Float16
+foo (_Float16 x, _Float16 y)
+{
+ x = x > y ? x : y;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-13.c b/gcc/testsuite/gcc.target/i386/pr54855-13.c
new file mode 100644
index 0000000..87b4f45
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-13.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+/* { dg-final { scan-assembler-times "vmaxsh\[ \\t\]" 1 } } */
+/* { dg-final { scan-assembler-not "vcomish\[ \\t\]" } } */
+/* { dg-final { scan-assembler-not "vmovsh\[ \\t\]" { target { ! ia32 } } } } */
+
+#include <immintrin.h>
+
+__m128h
+foo (__m128h x, __m128h y)
+{
+ x[0] = x[0] > y[0] ? x[0] : y[0];
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr85730.c b/gcc/testsuite/gcc.target/i386/pr85730.c
new file mode 100644
index 0000000..b279016
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85730.c
@@ -0,0 +1,95 @@
+/* PR target/85730 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse4" } */
+
+typedef char V __attribute__((vector_size(4)));
+
+V
+test_and (V v, char c)
+{
+ v[0] &= c;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+V
+test_or (V v, char c)
+{
+ v[0] |= c;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+V
+test_xor (V v, char c)
+{
+ v[0] ^= c;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+V
+test_not (V v)
+{
+ v[0] = ~v[0];
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]notb" } } */
+
+V
+test_sal (V v)
+{
+ v[0] <<= 3;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]salb" } } */
+
+V
+test_sar (V v)
+{
+ v[0] >>= 3;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]sarb" } } */
+
+V
+test_add (V v, char c)
+{
+ v[0] += c;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+V
+test_sub (V v, char c)
+{
+ v[0] -= c;
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */
+
+V
+test_neg (V v)
+{
+ v[0] = -v[0];
+
+ return v;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]negb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-1a.c b/gcc/testsuite/gcc.target/i386/pr85819-1a.c
new file mode 100644
index 0000000..db02282
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-1a.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx512f -mfma -mfpmath=sse" } */
+
+float
+foo (unsigned int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler "vfmadd132ss" { target ia32 } } } */
+/* { dg-final { scan-assembler "vcvtsi2ssq" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-1b.c b/gcc/testsuite/gcc.target/i386/pr85819-1b.c
new file mode 100644
index 0000000..f1408c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-1b.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f -mfpmath=sse" } */
+
+#include "pr85819-1a.c"
+
+/* { dg-final { scan-assembler "vcvtusi2ss" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-2a.c b/gcc/testsuite/gcc.target/i386/pr85819-2a.c
new file mode 100644
index 0000000..cea599f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-2a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx512f -mavx2 -mfma -mfpmath=sse" } */
+
+typedef float To __attribute__ ((__vector_size__ (32)));
+typedef unsigned int From __attribute__ ((__vector_size__ (32)));
+
+#define A2(I) (float)a[I], (float)a[1+I]
+#define A4(I) A2(I), A2(2+I)
+#define A8(I) A4(I), A4(4+I)
+
+To
+f(From a)
+{
+ return __extension__ (To) {A8(0)};
+}
+
+/* { dg-final { scan-assembler "vfmadd132ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-2b.c b/gcc/testsuite/gcc.target/i386/pr85819-2b.c
new file mode 100644
index 0000000..0750e56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-2b.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vl -mfpmath=sse" } */
+
+#include "pr85819-2a.c"
+
+/* { dg-final { scan-assembler "vcvtudq2ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-2c.c b/gcc/testsuite/gcc.target/i386/pr85819-2c.c
new file mode 100644
index 0000000..8211669
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-2c.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-fma -mno-avx2 -mno-avx512vl -mavx512f -mfpmath=sse" } */
+
+#include "pr85819-2a.c"
+
+/* { dg-final { scan-assembler-not "vcvtudq2ps" } } */
+/* { dg-final { scan-assembler-not "vfmadd132ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85819-3.c b/gcc/testsuite/gcc.target/i386/pr85819-3.c
new file mode 100644
index 0000000..cd3bf9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85819-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f -mfpmath=sse" } */
+
+typedef float To __attribute__ ((__vector_size__ (64)));
+typedef unsigned int From __attribute__ ((__vector_size__ (64)));
+
+#define A2(I) (float)a[I], (float)a[1+I]
+#define A4(I) A2(I), A2(2+I)
+#define A8(I) A4(I), A4(4+I)
+#define A16(I) A8(I), A8(8+I)
+
+To
+f(From a)
+{
+ return __extension__ (To) {A16(0)};
+}
+
+/* { dg-final { scan-assembler "vcvtudq2ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr89954.c b/gcc/testsuite/gcc.target/i386/pr89954.c
new file mode 100644
index 0000000..c1e9f3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89954.c
@@ -0,0 +1,45 @@
+/* PR target/89954 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+signed char ab;
+
+short aw;
+
+int al;
+
+short sext_andbw (void) { return ab & -2; }
+short sext_orbw (void) { return ab | -3; }
+short sext_xorbw (void) { return ab ^ -4; }
+
+int sext_andbl (void) { return ab & -2; }
+int sext_orbl (void) { return ab | -3; }
+int sext_xorbl (void) { return ab ^ -4; }
+
+int sext_andwl (void) { return aw & -2; }
+int sext_orwl (void) { return aw | -3; }
+int sext_xorwl (void) { return aw ^ -4; }
+
+#ifdef __x86_64__
+
+long long sext_andbq (void) { return ab & -2; }
+long long sext_orbq (void) { return ab | -3; }
+long long sext_xorbq (void) { return ab ^ -4; }
+
+long long sext_andwq (void) { return aw & -2; }
+long long sext_orwq (void) { return aw | -3; }
+long long sext_xorwq (void) { return aw ^ -4; }
+
+long long sext_andlq (void) { return al & -2; }
+long long sext_orlq (void) { return al | -3; }
+long long sext_xorlq (void) { return al ^ -4; }
+
+#endif
+
+/* { dg-final { scan-assembler-times "movsbw" 3 } } */
+/* { dg-final { scan-assembler-times "movsbl" 3 } } */
+/* { dg-final { scan-assembler-times "movswl" 3 } } */
+
+/* { dg-final { scan-assembler-times "movsbq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movswq" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movslq" 3 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr89984-1.c b/gcc/testsuite/gcc.target/i386/pr89984-1.c
new file mode 100644
index 0000000..d77691c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89984-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-avx -msse2" } */
+
+float
+check_f_pos (float x, float y)
+{
+ return x * __builtin_copysignf (1.0f, y);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr89984-2.c b/gcc/testsuite/gcc.target/i386/pr89984-2.c
new file mode 100644
index 0000000..ff6a8e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89984-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mavx" } */
+
+float
+check_f_pos (float x, float y)
+{
+ return x * __builtin_copysignf (1.0f, y);
+}
+
+/* { dg-final { scan-assembler-not "vmovaps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-20.c b/gcc/testsuite/gcc.target/i386/pr90773-20.c
index e61e405..884a550 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-20.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-20.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-21.c b/gcc/testsuite/gcc.target/i386/pr90773-21.c
index 16ad17f..5bbb387 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-21.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-21.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-22.c b/gcc/testsuite/gcc.target/i386/pr90773-22.c
index 45a8ff6..245a436 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-22.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-22.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-23.c b/gcc/testsuite/gcc.target/i386/pr90773-23.c
index 9256ce1..ca4a86f 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-23.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-23.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-26.c b/gcc/testsuite/gcc.target/i386/pr90773-26.c
index b2513c3..76fb79f 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-26.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-26.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=skylake" } */
+/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_move_by_pieces" } */
struct S
{
diff --git a/gcc/testsuite/gcc.target/i386/pr91103-1.c b/gcc/testsuite/gcc.target/i386/pr91103-1.c
new file mode 100644
index 0000000..2d78a6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91103-1.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "valign\[dq\]" 8 } } */
+/* { dg-final { scan-assembler-times "vextract" 12 } } */
+
+typedef float v8sf __attribute__((vector_size(32)));
+typedef float v16sf __attribute__((vector_size(64)));
+typedef int v8si __attribute__((vector_size(32)));
+typedef int v16si __attribute__((vector_size(64)));
+typedef double v4df __attribute__((vector_size(32)));
+typedef double v8df __attribute__((vector_size(64)));
+typedef long long v4di __attribute__((vector_size(32)));
+typedef long long v8di __attribute__((vector_size(64)));
+
+#define EXTRACT(V,S,IDX) \
+ S \
+ __attribute__((noipa)) \
+ foo_##V##_##IDX (V v) \
+ { \
+ return v[IDX]; \
+ } \
+
+EXTRACT (v8sf, float, 4);
+EXTRACT (v8sf, float, 7);
+EXTRACT (v8si, int, 4);
+EXTRACT (v8si, int, 7);
+EXTRACT (v16sf, float, 4);
+EXTRACT (v16sf, float, 8);
+EXTRACT (v16sf, float, 12);
+EXTRACT (v16sf, float, 15);
+EXTRACT (v16si, int, 4);
+EXTRACT (v16si, int, 8);
+EXTRACT (v16si, int, 12);
+EXTRACT (v16si, int, 15);
+EXTRACT (v4df, double, 2);
+EXTRACT (v4df, double, 3);
+EXTRACT (v4di, long long, 2);
+EXTRACT (v4di, long long, 3);
+EXTRACT (v8df, double, 4);
+EXTRACT (v8df, double, 7);
+EXTRACT (v8di, long long, 4);
+EXTRACT (v8di, long long, 7);
diff --git a/gcc/testsuite/gcc.target/i386/pr91103-2.c b/gcc/testsuite/gcc.target/i386/pr91103-2.c
new file mode 100644
index 0000000..a928d87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91103-2.c
@@ -0,0 +1,85 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vl" } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512VL
+
+#ifndef CHECK
+#define CHECK "avx512f-helper.h"
+#endif
+
+#include CHECK
+#include "pr91103-1.c"
+
+#define RUNCHECK(U,V,S,IDX) \
+ do \
+ { \
+ S tmp = foo_##V##_##IDX ((V)U.x); \
+ if (tmp != U.a[IDX]) \
+ abort(); \
+ } \
+ while (0)
+
+void
+test_256 (void)
+{
+ union512i_d di1;
+ union256i_d di2;
+ union512i_q q1;
+ union256i_q q2;
+ union512 f1;
+ union256 f2;
+ union512d d1;
+ union256d d2;
+ int sign = 1;
+
+ int i = 0;
+ for (i = 0; i < 16; i++)
+ {
+ di1.a[i] = 30 * (i - 30) * sign;
+ f1.a[i] = 56.78 * (i - 30) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i != 8; i++)
+ {
+ di2.a[i] = 15 * (i + 40) * sign;
+ f2.a[i] = 90.12 * (i + 40) * sign;
+ q1.a[i] = 15 * (i + 40) * sign;
+ d1.a[i] = 90.12 * (i + 40) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i != 4; i++)
+ {
+ q2.a[i] = 15 * (i + 40) * sign;
+ d2.a[i] = 90.12 * (i + 40) * sign;
+ sign = -sign;
+ }
+
+RUNCHECK (f2, v8sf, float, 4);
+RUNCHECK (f2, v8sf, float, 7);
+RUNCHECK (di2, v8si, int, 4);
+RUNCHECK (di2, v8si, int, 7);
+RUNCHECK (f1, v16sf, float, 4);
+RUNCHECK (f1, v16sf, float, 8);
+RUNCHECK (f1, v16sf, float, 12);
+RUNCHECK (f1, v16sf, float, 15);
+RUNCHECK (di1, v16si, int, 4);
+RUNCHECK (di1, v16si, int, 8);
+RUNCHECK (di1, v16si, int, 12);
+RUNCHECK (di1, v16si, int, 15);
+RUNCHECK (d2, v4df, double, 2);
+RUNCHECK (d2, v4df, double, 3);
+RUNCHECK (q2, v4di, long long, 2);
+RUNCHECK (q2, v4di, long long, 3);
+RUNCHECK (d1, v8df, double, 4);
+RUNCHECK (d1, v8df, double, 7);
+RUNCHECK (q1, v8di, long long, 4);
+RUNCHECK (q1, v8di, long long, 7);
+}
+
+void
+test_128()
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
index e26b06e..9afb195 100644
--- a/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512f.c
@@ -48,6 +48,10 @@ truncqb (v8qi * dst, v8di * __restrict src)
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] = *(v8qi *) tem;
}
@@ -100,7 +104,7 @@ truncdb (v16qi * dst, v16si * __restrict src)
/* { dg-final { scan-assembler-times "vpmovqd" 1 } } */
/* { dg-final { scan-assembler-times "vpmovqw" 1 } } */
-/* { dg-final { scan-assembler-times "vpmovqb" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpmovqb" 1 } } */
/* { dg-final { scan-assembler-times "vpmovdw" 1 } } */
/* { dg-final { scan-assembler-times "vpmovdb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
index 7ff9c19..ae6959e 100644
--- a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c
@@ -123,6 +123,7 @@ truncdb_128 (v16qi * dst, v4si * __restrict src)
/* { dg-final { scan-assembler-times "vpmovqd" 2 } } */
/* { dg-final { scan-assembler-times "vpmovqw" 2 } } */
-/* { dg-final { scan-assembler-times "vpmovqb" 2 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpmovqb\[ \t]*%ymm" 1 } } */
+/* { dg-final { scan-assembler-times "vpmovqb\[ \t]*%xmm" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "vpmovdw" 2 } } */
/* { dg-final { scan-assembler-times "vpmovdb" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95798-1.c b/gcc/testsuite/gcc.target/i386/pr95798-1.c
index 9a7e32d..526f489 100644
--- a/gcc/testsuite/gcc.target/i386/pr95798-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr95798-1.c
@@ -1,6 +1,6 @@
/* PR target/95798 */
/* { dg-do compile } */
-/* { dg-options "-O2 -masm=att -fomit-frame-pointer" } */
+/* { dg-options "-O2 -fno-tree-vectorize -masm=att -fomit-frame-pointer" } */
/* { dg-final { scan-assembler "1, 8\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "2, 16\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "3, 24\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95798-2.c b/gcc/testsuite/gcc.target/i386/pr95798-2.c
index c670d37..6b5c5a7 100644
--- a/gcc/testsuite/gcc.target/i386/pr95798-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr95798-2.c
@@ -1,6 +1,6 @@
/* PR target/95798 */
/* { dg-do compile } */
-/* { dg-options "-O2 -masm=att -fomit-frame-pointer" } */
+/* { dg-options "-O2 -fno-tree-vectorize -masm=att -fomit-frame-pointer" } */
/* { dg-final { scan-assembler "1, 8\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "2, 16\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
/* { dg-final { scan-assembler "3, 24\\\(%rsp,%r\[a-z0-9]*,8\\\)" { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr97950.c b/gcc/testsuite/gcc.target/i386/pr97950.c
index 277311d..185d733 100644
--- a/gcc/testsuite/gcc.target/i386/pr97950.c
+++ b/gcc/testsuite/gcc.target/i386/pr97950.c
@@ -1,10 +1,10 @@
/* PR target/95950 */
/* { dg-do compile } */
/* { dg-options "-O2 -mtune=generic" } */
-/* { dg-final { scan-assembler-times "\tseta\t" 4 } } */
+/* { dg-final { scan-assembler-times "\tset\[ab]\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?\[ab]\t" } } */
/* { dg-final { scan-assembler-not "\tjn?o\t" } } */
/* { dg-final { scan-assembler-not "\tjn?c\t" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr99591.c b/gcc/testsuite/gcc.target/i386/pr99591.c
new file mode 100644
index 0000000..01d8485
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99591.c
@@ -0,0 +1,32 @@
+/* PR tree-optimization/99591 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "\tmovs\[bw]l\t" } } */
+
+int
+foo (signed char a, signed char b)
+{
+ signed char r;
+ return __builtin_add_overflow (a, b, &r);
+}
+
+int
+bar (short a, short b)
+{
+ short r;
+ return __builtin_add_overflow (a, b, &r);
+}
+
+int
+baz (signed char a, signed char b)
+{
+ signed char r;
+ return __builtin_add_overflow ((int) a, (int) b, &r);
+}
+
+int
+qux (short a, short b)
+{
+ short r;
+ return __builtin_add_overflow ((int) a, (int) b, &r);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index 7029771..e285c30 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 -mkl -mwidekl -mavxvnni" } */
+/* { 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 -mavx512fp16" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
@@ -702,6 +702,141 @@
#define __builtin_ia32_vpshld_v2di(A, B, C) __builtin_ia32_vpshld_v2di(A, B, 1)
#define __builtin_ia32_vpshld_v2di_mask(A, B, C, D, E) __builtin_ia32_vpshld_v2di_mask(A, B, 1, D, E)
+/* avx512fp16intrin.h */
+#define __builtin_ia32_addph512_mask_round(A, B, C, D, E) __builtin_ia32_addph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subph512_mask_round(A, B, C, D, E) __builtin_ia32_subph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulph512_mask_round(A, B, C, D, E) __builtin_ia32_mulph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divph512_mask_round(A, B, C, D, E) __builtin_ia32_divph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_addsh_mask_round(A, B, C, D, E) __builtin_ia32_addsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subsh_mask_round(A, B, C, D, E) __builtin_ia32_subsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulsh_mask_round(A, B, C, D, E) __builtin_ia32_mulsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divsh_mask_round(A, B, C, D, E) __builtin_ia32_divsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxph512_mask_round(A, B, C, D, E) __builtin_ia32_maxph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minph512_mask_round(A, B, C, D, E) __builtin_ia32_minph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxsh_mask_round(A, B, C, D, E) __builtin_ia32_maxsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minsh_mask_round(A, B, C, D, E) __builtin_ia32_minsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_cmpph512_mask(A, B, C, D) __builtin_ia32_cmpph512_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph512_mask_round(A, B, C, D, E) __builtin_ia32_cmpph512_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_cmpsh_mask_round(A, B, C, D, E) __builtin_ia32_cmpsh_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_sqrtph512_mask_round(C, A, B, D) __builtin_ia32_sqrtph512_mask_round(C, A, B, 8)
+#define __builtin_ia32_sqrtsh_mask_round(D, C, A, B, E) __builtin_ia32_sqrtsh_mask_round(D, C, A, B, 8)
+#define __builtin_ia32_scalefph512_mask_round(A, B, C, D, E) __builtin_ia32_scalefph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_scalefsh_mask_round(A, B, C, D, E) __builtin_ia32_scalefsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_reduceph512_mask_round(A, B, C, D, E) __builtin_ia32_reduceph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_reduceph128_mask(A, B, C, D) __builtin_ia32_reduceph128_mask(A, 123, C, D)
+#define __builtin_ia32_reduceph256_mask(A, B, C, D) __builtin_ia32_reduceph256_mask(A, 123, C, D)
+#define __builtin_ia32_reducesh_mask_round(A, B, C, D, E, F) __builtin_ia32_reducesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_rndscaleph512_mask_round(A, B, C, D, E) __builtin_ia32_rndscaleph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_rndscaleph128_mask(A, B, C, D) __builtin_ia32_rndscaleph128_mask(A, 123, C, D)
+#define __builtin_ia32_rndscaleph256_mask(A, B, C, D) __builtin_ia32_rndscaleph256_mask(A, 123, C, D)
+#define __builtin_ia32_rndscalesh_mask_round(A, B, C, D, E, F) __builtin_ia32_rndscalesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_fpclassph512_mask(A, D, C) __builtin_ia32_fpclassph512_mask(A, 1, C)
+#define __builtin_ia32_fpclasssh_mask(A, D, U) __builtin_ia32_fpclasssh_mask(A, 1, U)
+#define __builtin_ia32_getexpph512_mask(A, B, C, D) __builtin_ia32_getexpph512_mask(A, B, C, 8)
+#define __builtin_ia32_getexpsh_mask_round(A, B, C, D, E) __builtin_ia32_getexpsh_mask_round(A, B, C, D, 4)
+#define __builtin_ia32_getmantph512_mask(A, F, C, D, E) __builtin_ia32_getmantph512_mask(A, 1, C, D, 8)
+#define __builtin_ia32_getmantsh_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsh_mask_round(A, B, 1, W, U, 4)
+#define __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2si32_round(A, B) __builtin_ia32_vcvtsh2si32_round(A, 8)
+#define __builtin_ia32_vcvtsh2si64_round(A, B) __builtin_ia32_vcvtsh2si64_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi32_round(A, B) __builtin_ia32_vcvtsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi64_round(A, B) __builtin_ia32_vcvtsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvttsh2si32_round(A, B) __builtin_ia32_vcvttsh2si32_round(A, 8)
+#define __builtin_ia32_vcvttsh2si64_round(A, B) __builtin_ia32_vcvttsh2si64_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi32_round(A, B) __builtin_ia32_vcvttsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi64_round(A, B) __builtin_ia32_vcvttsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvtsi2sh32_round(A, B, C) __builtin_ia32_vcvtsi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtsi2sh64_round(A, B, C) __builtin_ia32_vcvtsi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh32_round(A, B, C) __builtin_ia32_vcvtusi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh64_round(A, B, C) __builtin_ia32_vcvtusi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, D) __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
+
+/* avx512fp16vlintrin.h */
+#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph256_mask(A, B, C, D) __builtin_ia32_cmpph256_mask(A, B, 1, D)
+#define __builtin_ia32_fpclassph256_mask(A, D, C) __builtin_ia32_fpclassph256_mask(A, 1, C)
+#define __builtin_ia32_fpclassph128_mask(A, D, C) __builtin_ia32_fpclassph128_mask(A, 1, C)
+#define __builtin_ia32_getmantph256_mask(A, E, C, D) __builtin_ia32_getmantph256_mask(A, 1, C, D)
+#define __builtin_ia32_getmantph128_mask(A, E, C, D) __builtin_ia32_getmantph128_mask(A, 1, C, D)
+
/* vpclmulqdqintrin.h */
#define __builtin_ia32_vpclmulqdq_v4di(A, B, C) __builtin_ia32_vpclmulqdq_v4di(A, B, 1)
#define __builtin_ia32_vpclmulqdq_v2di(A, B, C) __builtin_ia32_vpclmulqdq_v2di(A, B, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index 4ce0fff..956a9d1 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 -mkl -mwidekl -mavxvnni" } */
+/* { 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 -mavx512fp16" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
@@ -286,6 +286,7 @@ test_2 (_mm_add_round_sd, __m128d, __m128d, __m128d, 9)
test_2 (_mm_add_round_ss, __m128, __m128, __m128, 9)
test_2 (_mm_cmp_sd_mask, __mmask8, __m128d, __m128d, 1)
test_2 (_mm_cmp_ss_mask, __mmask8, __m128, __m128, 1)
+test_2 (_mm_cmp_sh_mask, __mmask8, __m128h, __m128h, 1)
#ifdef __x86_64__
test_2 (_mm_cvt_roundi64_sd, __m128d, __m128d, long long, 9)
test_2 (_mm_cvt_roundi64_ss, __m128, __m128, long long, 9)
@@ -470,6 +471,7 @@ test_3 (_mm256_maskz_shldi_epi64, __m256i, __mmask8, __m256i, __m256i, 1)
test_3 (_mm_maskz_shldi_epi16, __m128i, __mmask8, __m128i, __m128i, 1)
test_3 (_mm_maskz_shldi_epi32, __m128i, __mmask8, __m128i, __m128i, 1)
test_3 (_mm_maskz_shldi_epi64, __m128i, __mmask8, __m128i, __m128i, 1)
+test_3 (_mm_mask_cmp_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1)
test_3v (_mm512_i32scatter_epi32, void *, __m512i, __m512i, 1)
test_3v (_mm512_i32scatter_epi64, void *, __m256i, __m512i, 1)
test_3v (_mm512_i32scatter_pd, void *, __m256i, __m512d, 1)
@@ -667,6 +669,284 @@ test_3 (_mm512_mask_rcp28_round_ps, __m512, __m512, __mmask16, __m512, 8)
test_3 (_mm512_mask_rsqrt28_round_pd, __m512d, __m512d, __mmask8, __m512d, 8)
test_3 (_mm512_mask_rsqrt28_round_ps, __m512, __m512, __mmask16, __m512, 8)
+/* avx512fp16intrin.h */
+test_1 (_mm512_sqrt_round_ph, __m512h, __m512h, 8)
+test_1 (_mm_reduce_ph, __m128h, __m128h, 123)
+test_1 (_mm256_reduce_ph, __m256h, __m256h, 123)
+test_1 (_mm512_reduce_ph, __m512h, __m512h, 123)
+test_1 (_mm_roundscale_ph, __m128h, __m128h, 123)
+test_1 (_mm256_roundscale_ph, __m256h, __m256h, 123)
+test_1 (_mm512_roundscale_ph, __m512h, __m512h, 123)
+test_1 (_mm512_getexp_round_ph, __m512h, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epi16, __m512i, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epu16, __m512i, __m512h, 8)
+test_1 (_mm512_cvtt_roundph_epi16, __m512i, __m512h, 8)
+test_1 (_mm512_cvtt_roundph_epu16, __m512i, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epi32, __m512i, __m256h, 8)
+test_1 (_mm512_cvt_roundph_epu32, __m512i, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epi32, __m512i, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epu32, __m512i, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epi64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundph_pd, __m512d, __m128h, 8)
+test_1 (_mm512_cvtx_roundph_ps, __m512, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epu64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundph_epi64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundph_epu64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundepi16_ph, __m512h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu16_ph, __m512h, __m512i, 8)
+test_1 (_mm512_cvt_roundepi32_ph, __m256h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu32_ph, __m256h, __m512i, 8)
+test_1 (_mm512_cvt_roundepi64_ph, __m128h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu64_ph, __m128h, __m512i, 8)
+test_1 (_mm512_cvtx_roundps_ph, __m256h, __m512, 8)
+test_1 (_mm512_cvt_roundpd_ph, __m128h, __m512d, 8)
+test_1 (_mm_cvt_roundsh_i32, int, __m128h, 8)
+test_1 (_mm_cvt_roundsh_u32, unsigned, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_i32, int, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_u32, unsigned, __m128h, 8)
+#ifdef __x86_64__
+test_1 (_mm_cvt_roundsh_i64, long long, __m128h, 8)
+test_1 (_mm_cvt_roundsh_u64, unsigned long long, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_i64, long long, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_u64, unsigned long long, __m128h, 8)
+test_2 (_mm_cvt_roundi64_sh, __m128h, __m128h, long long, 8)
+test_2 (_mm_cvt_roundu64_sh, __m128h, __m128h, unsigned long long, 8)
+#endif
+test_1x (_mm512_reduce_round_ph, __m512h, __m512h, 123, 8)
+test_1x (_mm512_roundscale_round_ph, __m512h, __m512h, 123, 8)
+test_1x (_mm512_getmant_ph, __m512h, __m512h, 1, 1)
+test_1y (_mm512_getmant_round_ph, __m512h, __m512h, 1, 1, 8)
+test_2 (_mm512_add_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_sub_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_mul_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_div_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_add_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_sub_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_mul_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_div_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_max_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_min_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_max_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_min_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_cmp_ph_mask, __mmask32, __m512h, __m512h, 1)
+test_2 (_mm_comi_sh, int, __m128h, __m128h, 1)
+test_2 (_mm512_maskz_sqrt_round_ph, __m512h, __mmask32, __m512h, 8)
+test_2 (_mm_sqrt_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_scalef_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_scalef_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_maskz_reduce_ph, __m128h, __mmask8, __m128h, 123)
+test_2 (_mm256_maskz_reduce_ph, __m256h, __mmask16, __m256h, 123)
+test_2 (_mm512_maskz_reduce_ph, __m512h, __mmask32, __m512h, 123)
+test_2 (_mm_reduce_sh, __m128h, __m128h, __m128h, 123)
+test_2 (_mm_maskz_roundscale_ph, __m128h, __mmask8, __m128h, 123)
+test_2 (_mm256_maskz_roundscale_ph, __m256h, __mmask16, __m256h, 123)
+test_2 (_mm512_maskz_roundscale_ph, __m512h, __mmask32, __m512h, 123)
+test_2 (_mm_roundscale_sh, __m128h, __m128h, __m128h, 123)
+test_2 (_mm512_maskz_getexp_round_ph, __m512h, __mmask32, __m512h, 8)
+test_2 (_mm_getexp_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_pd, __m512d, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvtx_roundph_ps, __m512, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundepi16_ph, __m512h, __mmask32, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu16_ph, __m512h, __mmask32, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepi32_ph, __m256h, __mmask16, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu32_ph, __m256h, __mmask16, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepi64_ph, __m128h, __mmask8, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu64_ph, __m128h, __mmask8, __m512i, 8)
+test_2 (_mm512_maskz_cvtx_roundps_ph, __m256h, __mmask16, __m512, 8)
+test_2 (_mm512_maskz_cvt_roundpd_ph, __m128h, __mmask8, __m512d, 8)
+test_2 (_mm_cvt_roundsh_ss, __m128, __m128, __m128h, 8)
+test_2 (_mm_cvt_roundsh_sd, __m128d, __m128d, __m128h, 8)
+test_2 (_mm_cvt_roundss_sh, __m128h, __m128h, __m128, 8)
+test_2 (_mm_cvt_roundsd_sh, __m128h, __m128h, __m128d, 8)
+test_2 (_mm_cvt_roundi32_sh, __m128h, __m128h, int, 8)
+test_2 (_mm_cvt_roundu32_sh, __m128h, __m128h, unsigned, 8)
+test_2 (_mm512_fmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_fcmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_fmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_fcmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2x (_mm512_cmp_round_ph_mask, __mmask32, __m512h, __m512h, 1, 8)
+test_2x (_mm_cmp_round_sh_mask, __mmask8, __m128h, __m128h, 1, 8)
+test_2x (_mm_comi_round_sh, int, __m128h, __m128h, 1, 8)
+test_2x (_mm512_maskz_reduce_round_ph, __m512h, __mmask32, __m512h, 123, 8)
+test_2x (_mm512_maskz_roundscale_round_ph, __m512h, __mmask32, __m512h, 123, 8)
+test_2x (_mm_reduce_round_sh, __m128h, __m128h, __m128h, 123, 8)
+test_2x (_mm_roundscale_round_sh, __m128h, __m128h, __m128h, 123, 8)
+test_2x (_mm512_maskz_getmant_ph, __m512h, __mmask32, __m512h, 1, 1)
+test_2x (_mm_getmant_sh, __m128h, __m128h, __m128h, 1, 1)
+test_2y (_mm512_maskz_getmant_round_ph, __m512h, __mmask32, __m512h, 1, 1, 8)
+test_2y (_mm_getmant_round_sh, __m128h, __m128h, __m128h, 1, 1, 8)
+test_3 (_mm512_maskz_add_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_sub_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_mul_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_div_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_maskz_add_round_sh, __m128h, __mmask32, __m128h, __m128h, 8)
+test_3 (_mm_maskz_sub_round_sh, __m128h, __mmask32, __m128h, __m128h, 8)
+test_3 (_mm_maskz_mul_round_sh, __m128h, __mmask32, __m128h, __m128h, 8)
+test_3 (_mm_maskz_div_round_sh, __m128h, __mmask32, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_max_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_min_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_maskz_max_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_min_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_mask_cmp_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1)
+test_3 (_mm512_mask_sqrt_round_ph, __m512h, __m512h, __mmask32, __m512h, 8)
+test_3 (_mm_maskz_sqrt_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_scalef_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_maskz_scalef_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_mask_reduce_ph, __m128h, __m128h, __mmask8, __m128h, 123)
+test_3 (_mm256_mask_reduce_ph, __m256h, __m256h, __mmask16, __m256h, 123)
+test_3 (_mm512_mask_reduce_ph, __m512h, __m512h, __mmask32, __m512h, 123)
+test_3 (_mm_maskz_reduce_sh, __m128h, __mmask8, __m128h, __m128h, 123)
+test_3 (_mm_mask_roundscale_ph, __m128h, __m128h, __mmask8, __m128h, 123)
+test_3 (_mm256_mask_roundscale_ph, __m256h, __m256h, __mmask16, __m256h, 123)
+test_3 (_mm512_mask_roundscale_ph, __m512h, __m512h, __mmask32, __m512h, 123)
+test_3 (_mm_maskz_roundscale_sh, __m128h, __mmask8, __m128h, __m128h, 123)
+test_3 (_mm_maskz_getexp_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_mask_getexp_round_ph, __m512h, __m512h, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundph_pd, __m512d, __m512d, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvtx_roundph_ps, __m512, __m512, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundepi16_ph, __m512h, __m512h, __mmask32, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu16_ph, __m512h, __m512h, __mmask32, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepi32_ph, __m256h, __m256h, __mmask16, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu32_ph, __m256h, __m256h, __mmask16, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepi64_ph, __m128h, __m128h, __mmask8, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu64_ph, __m128h, __m128h, __mmask8, __m512i, 8)
+test_3 (_mm512_mask_cvtx_roundps_ph, __m256h, __m256h, __mmask16, __m512, 8)
+test_3 (_mm512_mask_cvt_roundpd_ph, __m128h, __m128h, __mmask8, __m512d, 8)
+test_3 (_mm_maskz_cvt_roundsh_ss, __m128, __mmask8, __m128, __m128h, 8)
+test_3 (_mm_maskz_cvt_roundsh_sd, __m128d, __mmask8, __m128d, __m128h, 8)
+test_3 (_mm_maskz_cvt_roundss_sh, __m128h, __mmask8, __m128h, __m128, 8)
+test_3 (_mm_maskz_cvt_roundsd_sh, __m128h, __mmask8, __m128h, __m128d, 8)
+test_3 (_mm512_fmaddsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmsubadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fnmadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fnmsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm512_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_fmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_fcmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm_maskz_fmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_fcmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3x (_mm512_mask_cmp_round_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1, 8)
+test_3x (_mm_mask_cmp_round_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1, 8)
+test_3x (_mm512_mask_reduce_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
+test_3x (_mm512_mask_roundscale_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
+test_3x (_mm_maskz_reduce_round_sh, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_3x (_mm_maskz_roundscale_round_sh, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_3x (_mm512_mask_getmant_ph, __m512h, __m512h, __mmask32, __m512h, 1, 1)
+test_3x (_mm_maskz_getmant_sh, __m128h, __mmask8, __m128h, __m128h, 1, 1)
+test_3y (_mm_maskz_getmant_round_sh, __m128h, __mmask8, __m128h, __m128h, 1, 1, 8)
+test_3y (_mm512_mask_getmant_round_ph, __m512h, __m512h, __mmask32, __m512h, 1, 1, 8)
+test_4 (_mm512_mask_add_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_sub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_mul_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_div_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_add_round_sh, __m128h, __m128h, __mmask32, __m128h, __m128h, 8)
+test_4 (_mm_mask_sub_round_sh, __m128h, __m128h, __mmask32, __m128h, __m128h, 8)
+test_4 (_mm_mask_mul_round_sh, __m128h, __m128h, __mmask32, __m128h, __m128h, 8)
+test_4 (_mm_mask_div_round_sh, __m128h, __m128h, __mmask32, __m128h, __m128h, 8)
+test_4 (_mm512_mask_max_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_min_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_max_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_min_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_sqrt_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm512_mask_scalef_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_scalef_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_reduce_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123)
+test_4 (_mm_mask_roundscale_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123)
+test_4 (_mm_mask_getexp_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_cvt_roundsh_ss, __m128, __m128, __mmask8, __m128, __m128h, 8)
+test_4 (_mm_mask_cvt_roundsh_sd, __m128d, __m128d, __mmask8, __m128d, __m128h, 8)
+test_4 (_mm_mask_cvt_roundss_sh, __m128h, __m128h, __mmask8, __m128h, __m128, 8)
+test_4 (_mm_mask_cvt_roundsd_sh, __m128h, __m128h, __mmask8, __m128h, __m128d, 8)
+test_4 (_mm512_mask_fmaddsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmaddsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmaddsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmsubadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_mask_fmsubadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_maskz_fmsubadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fmadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fnmadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fnmadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fnmadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fmsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fnmsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fnmsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fnmsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm_mask_fmadd_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fmadd_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fnmadd_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fnmadd_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fnmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fnmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm512_mask_fmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask3_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_mask3_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_maskz_fmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm512_maskz_fcmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask3_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_mask3_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_maskz_fmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm_maskz_fcmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm512_mask_fmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4x (_mm_mask_reduce_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_4x (_mm_mask_roundscale_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_4x (_mm_mask_getmant_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1)
+test_4y (_mm_mask_getmant_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1, 8)
+
+/* avx512fp16vlintrin.h */
+test_2 (_mm_cmp_ph_mask, __mmask8, __m128h, __m128h, 1)
+test_2 (_mm256_cmp_ph_mask, __mmask16, __m256h, __m256h, 1)
+test_3 (_mm_mask_cmp_ph_mask, __mmask8, __mmask8, __m128h, __m128h, 1)
+test_3 (_mm256_mask_cmp_ph_mask, __mmask16, __mmask16, __m256h, __m256h, 1)
+
/* shaintrin.h */
test_2 (_mm_sha1rnds4_epu32, __m128i, __m128i, __m128i, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index 6e8b6f3..31492ef 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,kl,widekl,avxvnni")
+#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,avx512fp16")
#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,kl,widekl,avxvnni")
+#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,avx512fp16")
#endif
#include <immintrin.h>
test_1 (_cvtss_sh, unsigned short, float, 1)
@@ -457,6 +457,7 @@ test_2 (_mm256_shldi_epi64, __m256i, __m256i, __m256i, 1)
test_2 (_mm_shldi_epi16, __m128i, __m128i, __m128i, 1)
test_2 (_mm_shldi_epi32, __m128i, __m128i, __m128i, 1)
test_2 (_mm_shldi_epi64, __m128i, __m128i, __m128i, 1)
+test_2 (_mm_cmp_sh_mask, __mmask8, __m128h, __m128h, 1)
#ifdef __x86_64__
test_2 (_mm_cvt_roundi64_sd, __m128d, __m128d, long long, 9)
test_2 (_mm_cvt_roundi64_ss, __m128, __m128, long long, 9)
@@ -581,6 +582,7 @@ test_3 (_mm256_maskz_shldi_epi64, __m256i, __mmask8, __m256i, __m256i, 1)
test_3 (_mm_maskz_shldi_epi16, __m128i, __mmask8, __m128i, __m128i, 1)
test_3 (_mm_maskz_shldi_epi32, __m128i, __mmask8, __m128i, __m128i, 1)
test_3 (_mm_maskz_shldi_epi64, __m128i, __mmask8, __m128i, __m128i, 1)
+test_3 (_mm_mask_cmp_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1)
test_3v (_mm512_i32scatter_epi32, void *, __m512i, __m512i, 1)
test_3v (_mm512_i32scatter_epi64, void *, __m256i, __m512i, 1)
test_3v (_mm512_i32scatter_pd, void *, __m256i, __m512d, 1)
@@ -772,6 +774,281 @@ test_2 (_mm_rcp28_round_ss, __m128, __m128, __m128, 8)
test_2 (_mm_rsqrt28_round_sd, __m128d, __m128d, __m128d, 8)
test_2 (_mm_rsqrt28_round_ss, __m128, __m128, __m128, 8)
+/* avx512fp16intrin.h */
+test_1 (_mm512_sqrt_round_ph, __m512h, __m512h, 8)
+test_1 (_mm_reduce_ph, __m128h, __m128h, 123)
+test_1 (_mm256_reduce_ph, __m256h, __m256h, 123)
+test_1 (_mm512_reduce_ph, __m512h, __m512h, 123)
+test_1 (_mm_roundscale_ph, __m128h, __m128h, 123)
+test_1 (_mm256_roundscale_ph, __m256h, __m256h, 123)
+test_1 (_mm512_roundscale_ph, __m512h, __m512h, 123)
+test_1 (_mm512_getexp_round_ph, __m512h, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epi16, __m512i, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epu16, __m512i, __m512h, 8)
+test_1 (_mm512_cvtt_roundph_epi16, __m512i, __m512h, 8)
+test_1 (_mm512_cvtt_roundph_epu16, __m512i, __m512h, 8)
+test_1 (_mm512_cvt_roundph_epi32, __m512i, __m256h, 8)
+test_1 (_mm512_cvt_roundph_epu32, __m512i, __m256h, 8)
+test_1 (_mm512_cvt_roundph_epi64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundph_epu64, __m512i, __m128h, 8)
+test_1 (_mm512_cvtt_roundph_epi32, __m512i, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epu32, __m512i, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epi64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundph_pd, __m512d, __m128h, 8)
+test_1 (_mm512_cvtx_roundph_ps, __m512, __m256h, 8)
+test_1 (_mm512_cvtt_roundph_epu64, __m512i, __m128h, 8)
+test_1 (_mm512_cvt_roundepi16_ph, __m512h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu16_ph, __m512h, __m512i, 8)
+test_1 (_mm512_cvt_roundepi32_ph, __m256h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu32_ph, __m256h, __m512i, 8)
+test_1 (_mm512_cvt_roundepi64_ph, __m128h, __m512i, 8)
+test_1 (_mm512_cvt_roundepu64_ph, __m128h, __m512i, 8)
+test_1 (_mm512_cvtx_roundps_ph, __m256h, __m512, 8)
+test_1 (_mm512_cvt_roundpd_ph, __m128h, __m512d, 8)
+test_1 (_mm_cvt_roundsh_i32, int, __m128h, 8)
+test_1 (_mm_cvt_roundsh_u32, unsigned, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_i32, int, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_u32, unsigned, __m128h, 8)
+#ifdef __x86_64__
+test_1 (_mm_cvt_roundsh_i64, long long, __m128h, 8)
+test_1 (_mm_cvt_roundsh_u64, unsigned long long, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_i64, long long, __m128h, 8)
+test_1 (_mm_cvtt_roundsh_u64, unsigned long long, __m128h, 8)
+test_2 (_mm_cvt_roundi64_sh, __m128h, __m128h, long long, 8)
+test_2 (_mm_cvt_roundu64_sh, __m128h, __m128h, unsigned long long, 8)
+#endif
+test_1x (_mm512_reduce_round_ph, __m512h, __m512h, 123, 8)
+test_1x (_mm512_roundscale_round_ph, __m512h, __m512h, 123, 8)
+test_1x (_mm512_getmant_ph, __m512h, __m512h, 1, 1)
+test_1y (_mm512_getmant_round_ph, __m512h, __m512h, 1, 1, 8)
+test_2 (_mm512_add_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_sub_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_mul_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_div_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_add_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_sub_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_mul_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_div_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_max_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_min_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_max_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_min_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_cmp_ph_mask, __mmask32, __m512h, __m512h, 1)
+test_2 (_mm_comi_sh, int, __m128h, __m128h, 1)
+test_2 (_mm512_maskz_sqrt_round_ph, __m512h, __mmask32, __m512h, 8)
+test_2 (_mm_sqrt_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_scalef_round_ph, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_maskz_reduce_ph, __m128h, __mmask8, __m128h, 123)
+test_2 (_mm256_maskz_reduce_ph, __m256h, __mmask16, __m256h, 123)
+test_2 (_mm512_maskz_reduce_ph, __m512h, __mmask32, __m512h, 123)
+test_2 (_mm_reduce_sh, __m128h, __m128h, __m128h, 123)
+test_2 (_mm_maskz_roundscale_ph, __m128h, __mmask8, __m128h, 123)
+test_2 (_mm256_maskz_roundscale_ph, __m256h, __mmask16, __m256h, 123)
+test_2 (_mm512_maskz_roundscale_ph, __m512h, __mmask32, __m512h, 123)
+test_2 (_mm_roundscale_sh, __m128h, __m128h, __m128h, 123)
+test_2 (_mm512_maskz_getexp_round_ph, __m512h, __mmask32, __m512h, 8)
+test_2 (_mm_getexp_round_sh, __m128h, __m128h, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu16, __m512i, __mmask32, __m512h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epi64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_epu64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu32, __m512i, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epi64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundph_pd, __m512d, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvtx_roundph_ps, __m512, __mmask16, __m256h, 8)
+test_2 (_mm512_maskz_cvtt_roundph_epu64, __m512i, __mmask8, __m128h, 8)
+test_2 (_mm512_maskz_cvt_roundepi16_ph, __m512h, __mmask32, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu16_ph, __m512h, __mmask32, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepi32_ph, __m256h, __mmask16, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu32_ph, __m256h, __mmask16, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepi64_ph, __m128h, __mmask8, __m512i, 8)
+test_2 (_mm512_maskz_cvt_roundepu64_ph, __m128h, __mmask8, __m512i, 8)
+test_2 (_mm512_maskz_cvtx_roundps_ph, __m256h, __mmask16, __m512, 8)
+test_2 (_mm512_maskz_cvt_roundpd_ph, __m128h, __mmask8, __m512d, 8)
+test_2 (_mm_cvt_roundi32_sh, __m128h, __m128h, int, 8)
+test_2 (_mm_cvt_roundu32_sh, __m128h, __m128h, unsigned, 8)
+test_2 (_mm_cvt_roundsh_ss, __m128, __m128, __m128h, 8)
+test_2 (_mm_cvt_roundsh_sd, __m128d, __m128d, __m128h, 8)
+test_2 (_mm_cvt_roundss_sh, __m128h, __m128h, __m128, 8)
+test_2 (_mm_cvt_roundsd_sh, __m128h, __m128h, __m128d, 8)
+test_2 (_mm512_fmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm512_fcmul_round_pch, __m512h, __m512h, __m512h, 8)
+test_2 (_mm_fmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2 (_mm_fcmul_round_sch, __m128h, __m128h, __m128h, 8)
+test_2x (_mm512_cmp_round_ph_mask, __mmask32, __m512h, __m512h, 1, 8)
+test_2x (_mm_cmp_round_sh_mask, __mmask8, __m128h, __m128h, 1, 8)
+test_2x (_mm_comi_round_sh, int, __m128h, __m128h, 1, 8)
+test_2x (_mm512_maskz_reduce_round_ph, __m512h, __mmask32, __m512h, 123, 8)
+test_2x (_mm512_maskz_roundscale_round_ph, __m512h, __mmask32, __m512h, 123, 8)
+test_2x (_mm_reduce_round_sh, __m128h, __m128h, __m128h, 123, 8)
+test_2x (_mm_roundscale_round_sh, __m128h, __m128h, __m128h, 123, 8)
+test_2x (_mm512_maskz_getmant_ph, __m512h, __mmask32, __m512h, 1, 1)
+test_2x (_mm_getmant_sh, __m128h, __m128h, __m128h, 1, 1)
+test_2y (_mm512_maskz_getmant_round_ph, __m512h, __mmask32, __m512h, 1, 1, 8)
+test_2y (_mm_getmant_round_sh, __m128h, __m128h, __m128h, 1, 1, 8)
+test_3 (_mm512_maskz_add_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_sub_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_mul_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_div_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_maskz_add_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_sub_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_mul_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_div_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_max_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_min_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_maskz_max_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_min_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_mask_cmp_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1)
+test_3 (_mm512_mask_sqrt_round_ph, __m512h, __m512h, __mmask32, __m512h, 8)
+test_3 (_mm_maskz_sqrt_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_scalef_round_ph, __m512h, __mmask32, __m512h, __m512h, 8)
+test_3 (_mm_mask_reduce_ph, __m128h, __m128h, __mmask8, __m128h, 123)
+test_3 (_mm256_mask_reduce_ph, __m256h, __m256h, __mmask16, __m256h, 123)
+test_3 (_mm512_mask_reduce_ph, __m512h, __m512h, __mmask32, __m512h, 123)
+test_3 (_mm_maskz_reduce_sh, __m128h, __mmask8, __m128h, __m128h, 123)
+test_3 (_mm_mask_roundscale_ph, __m128h, __m128h, __mmask8, __m128h, 123)
+test_3 (_mm256_mask_roundscale_ph, __m256h, __m256h, __mmask16, __m256h, 123)
+test_3 (_mm512_mask_roundscale_ph, __m512h, __m512h, __mmask32, __m512h, 123)
+test_3 (_mm_maskz_roundscale_sh, __m128h, __mmask8, __m128h, __m128h, 123)
+test_3 (_mm_maskz_getexp_round_sh, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm512_mask_getexp_round_ph, __m512h, __m512h, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu16, __m512i, __m512i, __mmask32, __m512h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvt_roundph_epi64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundph_epu64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu32, __m512i, __m512i, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epi64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundph_pd, __m512d, __m512d, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvtx_roundph_ps, __m512, __m512, __mmask16, __m256h, 8)
+test_3 (_mm512_mask_cvtt_roundph_epu64, __m512i, __m512i, __mmask8, __m128h, 8)
+test_3 (_mm512_mask_cvt_roundepi16_ph, __m512h, __m512h, __mmask32, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu16_ph, __m512h, __m512h, __mmask32, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepi32_ph, __m256h, __m256h, __mmask16, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu32_ph, __m256h, __m256h, __mmask16, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepi64_ph, __m128h, __m128h, __mmask8, __m512i, 8)
+test_3 (_mm512_mask_cvt_roundepu64_ph, __m128h, __m128h, __mmask8, __m512i, 8)
+test_3 (_mm512_mask_cvtx_roundps_ph, __m256h, __m256h, __mmask16, __m512, 8)
+test_3 (_mm512_mask_cvt_roundpd_ph, __m128h, __m128h, __mmask8, __m512d, 8)
+test_3 (_mm_maskz_cvt_roundsh_ss, __m128, __mmask8, __m128, __m128h, 8)
+test_3 (_mm_maskz_cvt_roundsh_sd, __m128d, __mmask8, __m128d, __m128h, 8)
+test_3 (_mm_maskz_cvt_roundss_sh, __m128h, __mmask8, __m128h, __m128, 8)
+test_3 (_mm_maskz_cvt_roundsd_sh, __m128h, __mmask8, __m128h, __m128d, 8)
+test_3 (_mm512_fmaddsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmsubadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fnmadd_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fmsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm512_fnmsub_round_ph, __m512h, __m512h, __m512h, __m512h, 9)
+test_3 (_mm_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, 9)
+test_3 (_mm512_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, 8)
+test_3 (_mm512_maskz_fmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3 (_mm_maskz_fmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_maskz_fcmul_round_sch, __m128h, __mmask8, __m128h, __m128h, 8)
+test_3 (_mm_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, 8)
+test_3 (_mm512_maskz_fcmul_round_pch, __m512h, __mmask16, __m512h, __m512h, 8)
+test_3x (_mm512_mask_cmp_round_ph_mask, __mmask32, __mmask32, __m512h, __m512h, 1, 8)
+test_3x (_mm_mask_cmp_round_sh_mask, __mmask8, __mmask8, __m128h, __m128h, 1, 8)
+test_3x (_mm512_mask_reduce_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
+test_3x (_mm512_mask_roundscale_round_ph, __m512h, __m512h, __mmask32, __m512h, 123, 8)
+test_3x (_mm_maskz_reduce_round_sh, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_3x (_mm_maskz_roundscale_round_sh, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_3x (_mm512_mask_getmant_ph, __m512h, __m512h, __mmask32, __m512h, 1, 1)
+test_3x (_mm_maskz_getmant_sh, __m128h, __mmask8, __m128h, __m128h, 1, 1)
+test_3y (_mm_maskz_getmant_round_sh, __m128h, __mmask8, __m128h, __m128h, 1, 1, 8)
+test_3y (_mm512_mask_getmant_round_ph, __m512h, __m512h, __mmask32, __m512h, 1, 1, 8)
+test_4 (_mm512_mask_add_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_sub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_mul_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_div_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_add_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_sub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_mul_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_div_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm512_mask_max_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm512_mask_min_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_max_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_min_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_sqrt_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm512_mask_scalef_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 8)
+test_4 (_mm_mask_reduce_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123)
+test_4 (_mm_mask_roundscale_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123)
+test_4 (_mm_mask_getexp_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_cvt_roundsh_ss, __m128, __m128, __mmask8, __m128, __m128h, 8)
+test_4 (_mm_mask_cvt_roundsh_sd, __m128d, __m128d, __mmask8, __m128d, __m128h, 8)
+test_4 (_mm_mask_cvt_roundss_sh, __m128h, __m128h, __mmask8, __m128h, __m128, 8)
+test_4 (_mm_mask_cvt_roundsd_sh, __m128h, __m128h, __mmask8, __m128h, __m128d, 8)
+test_4 (_mm512_mask_fmaddsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmaddsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmaddsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmsubadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_mask_fmsubadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_maskz_fmsubadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fmadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fnmadd_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fnmadd_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fnmadd_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fmsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fmsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fmsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm512_mask_fnmsub_round_ph, __m512h, __m512h, __mmask32, __m512h, __m512h, 9)
+test_4 (_mm512_mask3_fnmsub_round_ph, __m512h, __m512h, __m512h, __m512h, __mmask32, 9)
+test_4 (_mm512_maskz_fnmsub_round_ph, __m512h, __mmask32, __m512h, __m512h, __m512h, 9)
+test_4 (_mm_mask_fmadd_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fmadd_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fmadd_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fnmadd_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fnmadd_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fnmadd_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm_mask_fnmsub_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 9)
+test_4 (_mm_mask3_fnmsub_round_sh, __m128h, __m128h, __m128h, __m128h, __mmask8, 9)
+test_4 (_mm_maskz_fnmsub_round_sh, __m128h, __mmask8, __m128h, __m128h, __m128h, 9)
+test_4 (_mm512_mask_fmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmadd_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask3_fmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_mask3_fcmadd_round_pch, __m512h, __m512h, __m512h, __m512h, __mmask16, 8)
+test_4 (_mm512_maskz_fmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm512_maskz_fcmadd_round_pch, __m512h, __mmask16, __m512h, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmadd_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask3_fmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_mask3_fcmadd_round_sch, __m128h, __m128h, __m128h, __m128h, __mmask8, 8)
+test_4 (_mm_maskz_fmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm_maskz_fcmadd_round_sch, __m128h, __mmask8, __m128h, __m128h, __m128h, 8)
+test_4 (_mm512_mask_fmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm512_mask_fcmul_round_pch, __m512h, __m512h, __mmask16, __m512h, __m512h, 8)
+test_4 (_mm_mask_fmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4 (_mm_mask_fcmul_round_sch, __m128h, __m128h, __mmask8, __m128h, __m128h, 8)
+test_4x (_mm_mask_reduce_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_4x (_mm_mask_roundscale_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 123, 8)
+test_4x (_mm_mask_getmant_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1)
+test_4y (_mm_mask_getmant_round_sh, __m128h, __m128h, __mmask8, __m128h, __m128h, 1, 1, 8)
+
+/* avx512fp16vlintrin.h */
+test_2 (_mm_cmp_ph_mask, __mmask8, __m128h, __m128h, 1)
+test_2 (_mm256_cmp_ph_mask, __mmask16, __m256h, __m256h, 1)
+test_3 (_mm_mask_cmp_ph_mask, __mmask8, __mmask8, __m128h, __m128h, 1)
+test_3 (_mm256_mask_cmp_ph_mask, __mmask16, __mmask16, __m256h, __m256h, 1)
+
/* shaintrin.h */
test_2 (_mm_sha1rnds4_epu32, __m128i, __m128i, __m128i, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index 7faa053..f71a7b2 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -703,11 +703,146 @@
#define __builtin_ia32_vpshld_v2di(A, B, C) __builtin_ia32_vpshld_v2di(A, B, 1)
#define __builtin_ia32_vpshld_v2di_mask(A, B, C, D, E) __builtin_ia32_vpshld_v2di_mask(A, B, 1, D, E)
+/* avx512fp16intrin.h */
+#define __builtin_ia32_addph512_mask_round(A, B, C, D, E) __builtin_ia32_addph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subph512_mask_round(A, B, C, D, E) __builtin_ia32_subph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulph512_mask_round(A, B, C, D, E) __builtin_ia32_mulph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divph512_mask_round(A, B, C, D, E) __builtin_ia32_divph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_addsh_mask_round(A, B, C, D, E) __builtin_ia32_addsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_subsh_mask_round(A, B, C, D, E) __builtin_ia32_subsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_mulsh_mask_round(A, B, C, D, E) __builtin_ia32_mulsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_divsh_mask_round(A, B, C, D, E) __builtin_ia32_divsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxph512_mask_round(A, B, C, D, E) __builtin_ia32_maxph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minph512_mask_round(A, B, C, D, E) __builtin_ia32_minph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_maxsh_mask_round(A, B, C, D, E) __builtin_ia32_maxsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_minsh_mask_round(A, B, C, D, E) __builtin_ia32_minsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_cmpph512_mask(A, B, C, D) __builtin_ia32_cmpph512_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph512_mask_round(A, B, C, D, E) __builtin_ia32_cmpph512_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_cmpsh_mask_round(A, B, C, D, E) __builtin_ia32_cmpsh_mask_round(A, B, 1, D, 8)
+#define __builtin_ia32_sqrtph512_mask_round(C, A, B, D) __builtin_ia32_sqrtph512_mask_round(C, A, B, 8)
+#define __builtin_ia32_sqrtsh_mask_round(D, C, A, B, E) __builtin_ia32_sqrtsh_mask_round(D, C, A, B, 8)
+#define __builtin_ia32_scalefph512_mask_round(A, B, C, D, E) __builtin_ia32_scalefph512_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_scalefsh_mask_round(A, B, C, D, E) __builtin_ia32_scalefsh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_reduceph512_mask_round(A, B, C, D, E) __builtin_ia32_reduceph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_reduceph128_mask(A, B, C, D) __builtin_ia32_reduceph128_mask(A, 123, C, D)
+#define __builtin_ia32_reduceph256_mask(A, B, C, D) __builtin_ia32_reduceph256_mask(A, 123, C, D)
+#define __builtin_ia32_reducesh_mask_round(A, B, C, D, E, F) __builtin_ia32_reducesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_rndscaleph512_mask_round(A, B, C, D, E) __builtin_ia32_rndscaleph512_mask_round(A, 123, C, D, 8)
+#define __builtin_ia32_rndscaleph128_mask(A, B, C, D) __builtin_ia32_rndscaleph128_mask(A, 123, C, D)
+#define __builtin_ia32_rndscaleph256_mask(A, B, C, D) __builtin_ia32_rndscaleph256_mask(A, 123, C, D)
+#define __builtin_ia32_rndscalesh_mask_round(A, B, C, D, E, F) __builtin_ia32_rndscalesh_mask_round(A, B, 123, D, E, 8)
+#define __builtin_ia32_fpclassph512_mask(A, D, C) __builtin_ia32_fpclassph512_mask(A, 1, C)
+#define __builtin_ia32_fpclasssh_mask(A, D, U) __builtin_ia32_fpclasssh_mask(A, 1, U)
+#define __builtin_ia32_getexpph512_mask(A, B, C, D) __builtin_ia32_getexpph512_mask(A, B, C, 8)
+#define __builtin_ia32_getexpsh_mask_round(A, B, C, D, E) __builtin_ia32_getexpsh_mask_round(A, B, C, D, 4)
+#define __builtin_ia32_getmantph512_mask(A, F, C, D, E) __builtin_ia32_getmantph512_mask(A, 1, C, D, 8)
+#define __builtin_ia32_getmantsh_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsh_mask_round(A, B, 1, W, U, 4)
+#define __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2dq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2udq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2qq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uqq512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2w512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2w512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, D) __builtin_ia32_vcvttph2uw512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuw2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtdq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtudq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtuqq2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2si32_round(A, B) __builtin_ia32_vcvtsh2si32_round(A, 8)
+#define __builtin_ia32_vcvtsh2si64_round(A, B) __builtin_ia32_vcvtsh2si64_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi32_round(A, B) __builtin_ia32_vcvtsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvtsh2usi64_round(A, B) __builtin_ia32_vcvtsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvttsh2si32_round(A, B) __builtin_ia32_vcvttsh2si32_round(A, 8)
+#define __builtin_ia32_vcvttsh2si64_round(A, B) __builtin_ia32_vcvttsh2si64_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi32_round(A, B) __builtin_ia32_vcvttsh2usi32_round(A, 8)
+#define __builtin_ia32_vcvttsh2usi64_round(A, B) __builtin_ia32_vcvttsh2usi64_round(A, 8)
+#define __builtin_ia32_vcvtsi2sh32_round(A, B, C) __builtin_ia32_vcvtsi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtsi2sh64_round(A, B, C) __builtin_ia32_vcvtsi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh32_round(A, B, C) __builtin_ia32_vcvtusi2sh32_round(A, B, 8)
+#define __builtin_ia32_vcvtusi2sh64_round(A, B, C) __builtin_ia32_vcvtusi2sh64_round(A, B, 8)
+#define __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2pd512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, D) __builtin_ia32_vcvtph2psx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, D) __builtin_ia32_vcvtpd2ph512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, D) __builtin_ia32_vcvtps2phx512_mask_round(A, B, C, 8)
+#define __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2ss_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsh2sd_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtss2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, E) __builtin_ia32_vcvtsd2sh_mask_round(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubph512_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubph512_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmaddsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_mask3(A, B, C, D, 8)
+#define __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, E) __builtin_ia32_vfnmsubsh3_maskz(A, B, C, D, 8)
+#define __builtin_ia32_vfcmaddcph512_round(A, B, C, D) __builtin_ia32_vfcmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmaddcph512_round(A, B, C, D) __builtin_ia32_vfmaddcph512_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcph512_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcph512_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcph512_round(A, B, C) __builtin_ia32_vfmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcph512_round(A, B, C) __builtin_ia32_vfcmulcph512_round(A, B, 8)
+#define __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcph512_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_round(A, B, C, D) __builtin_ia32_vfmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfcmaddcsh_round(A, B, C, D) __builtin_ia32_vfcmaddcsh_round(A, B, C, 8)
+#define __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, E) __builtin_ia32_vfcmaddcsh_mask3_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, E) __builtin_ia32_vfcmaddcsh_maskz_round(B, C, D, A, 8)
+#define __builtin_ia32_vfmulcsh_round(A, B, C) __builtin_ia32_vfmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfmulcsh_mask_round(A, C, D, B, 8)
+#define __builtin_ia32_vfcmulcsh_round(A, B, C) __builtin_ia32_vfcmulcsh_round(A, B, 8)
+#define __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, E) __builtin_ia32_vfcmulcsh_mask_round(A, C, D, B, 8)
+
+/* avx512fp16vlintrin.h */
+#define __builtin_ia32_cmpph128_mask(A, B, C, D) __builtin_ia32_cmpph128_mask(A, B, 1, D)
+#define __builtin_ia32_cmpph256_mask(A, B, C, D) __builtin_ia32_cmpph256_mask(A, B, 1, D)
+#define __builtin_ia32_fpclassph256_mask(A, D, C) __builtin_ia32_fpclassph256_mask(A, 1, C)
+#define __builtin_ia32_fpclassph128_mask(A, D, C) __builtin_ia32_fpclassph128_mask(A, 1, C)
+#define __builtin_ia32_getmantph256_mask(A, E, C, D) __builtin_ia32_getmantph256_mask(A, 1, C, D)
+#define __builtin_ia32_getmantph128_mask(A, E, C, D) __builtin_ia32_getmantph128_mask(A, 1, C, D)
+
/* vpclmulqdqintrin.h */
#define __builtin_ia32_vpclmulqdq_v4di(A, B, C) __builtin_ia32_vpclmulqdq_v4di(A, B, 1)
#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,kl,widekl,avxvnni")
+#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,avx512fp16")
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-covert-1.c
new file mode 100644
index 0000000..c30af69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse-covert-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency,^sse_partial_reg_converts_dependency" } */
+
+extern float f;
+extern double d;
+extern int i;
+
+void
+foo (void)
+{
+ d = f;
+ f = i;
+}
+
+/* { dg-final { scan-assembler "cvtss2sd" } } */
+/* { dg-final { scan-assembler "cvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "cvtps2pd" } } */
+/* { dg-final { scan-assembler-not "cvtdq2ps" } } */
+/* { dg-final { scan-assembler-not "pxor" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c
new file mode 100644
index 0000000..b6567e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency" } */
+
+extern float f;
+extern double d;
+
+void
+foo (void)
+{
+ d = f;
+}
+
+/* { dg-final { scan-assembler "cvtss2sd" } } */
+/* { dg-final { scan-assembler-not "cvtps2pd" } } */
+/* { dg-final { scan-assembler-not "pxor" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c
new file mode 100644
index 0000000..107f724
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_converts_dependency" } */
+
+extern float f;
+extern int i;
+
+void
+foo (void)
+{
+ f = i;
+}
+
+/* { dg-final { scan-assembler "cvtsi2ssl" } } */
+/* { dg-final { scan-assembler-not "pxor" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c
new file mode 100644
index 0000000..1b645eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16/* { dg-error "is not supported on this target" } */
+foo (_Float16 x) /* { dg-error "is not supported on this target" } */
+{
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-2.c b/gcc/testsuite/gcc.target/i386/sse2-float16-2.c
new file mode 100644
index 0000000..3da7683
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-float16-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx512f" } */
+
+union flt
+{
+ _Float16 flt;
+ short s;
+};
+
+_Float16
+foo (union flt x)
+{
+ return x.flt;
+}
+
+/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-3.c b/gcc/testsuite/gcc.target/i386/sse2-float16-3.c
new file mode 100644
index 0000000..60ff9d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-float16-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx512f" } */
+
+#include<complex.h>
+
+_Complex _Float16
+foo (_Complex _Float16 x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c
new file mode 100644
index 0000000..ad4726b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 1, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+char baz()
+{
+ v8qi tx = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddsb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-?128," 1 } } */
+/* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c
new file mode 100644
index 0000000..1d3bc8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 1, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddusb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_paddusb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$(?:255|-1)," 1 } } */
+/* { dg-final { scan-assembler-not "paddusb\[ \\t\]+%xmm\[0-9\]+" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c
new file mode 100644
index 0000000..68b57f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubsb-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 5, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+char baz()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { -100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubsb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-?128," 1 } } */
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */
+/* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c
new file mode 100644
index 0000000..5fc58ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef char v8qi __attribute__ ((vector_size (8)));
+
+char foo()
+{
+ v8qi tx = { 5, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 2, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubusb(tx, ty);
+ return t[0];
+}
+
+char bar()
+{
+ v8qi tx = { 100, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi ty = { 200, 0, 0, 0, 0, 0, 0, 0 };
+ v8qi t = __builtin_ia32_psubusb(tx, ty);
+ return t[0];
+}
+
+/* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "xorl\[ \\t\]+" 1 } } */
+/* { dg-final { scan-assembler-not "psubusb\[ \\t\]+%xmm\[0-9\]+" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c
new file mode 100644
index 0000000..4aa536b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-1.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target lp64 } } */
+/* This is a test exercising peeling for alignment for a negative step
+ vector loop. We're forcing atom tuning here because that has a higher
+ unaligned vs aligned cost unlike most other archs. */
+/* { dg-options "-O3 -march=x86-64 -mtune=atom -fdump-tree-vect-details -save-temps" } */
+
+float a[1024], b[1024];
+
+void __attribute__((noipa)) foo1 ()
+{
+ for (int i = 507; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo2 ()
+{
+ for (int i = 506; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo3 ()
+{
+ for (int i = 505; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo4 ()
+{
+ for (int i = 504; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo5 (int start)
+{
+ for (int i = start; i > 1; --i)
+ a[i] = b[i] * 2.;
+}
+
+int main()
+{
+ for (int i = 2; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo1 ();
+ for (int i = 2; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 507; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo2 ();
+ for (int i = 2; i < 507; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 506; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo3 ();
+ for (int i = 2; i < 506; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 505; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo4 ();
+ for (int i = 2; i < 505; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 2; i < 506; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo5 (505);
+ for (int i = 2; i < 506; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" } } */
+/* Verify all vector accesses are emitted as aligned. */
+/* { dg-final { scan-assembler-not "movup" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c
new file mode 100644
index 0000000..834bf0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-alignment-peeling-2.c
@@ -0,0 +1,90 @@
+/* { dg-do run { target lp64 } } */
+/* This is a test exercising peeling for alignment for a positive step
+ vector loop. We're forcing atom tuning here because that has a higher
+ unaligned vs aligned cost unlike most other archs. */
+/* { dg-options "-O3 -march=x86-64 -mtune=atom -fdump-tree-vect-details -save-temps" } */
+
+float a[1024], b[1024];
+
+void __attribute__((noipa)) foo1 ()
+{
+ for (int i = 2; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo2 ()
+{
+ for (int i = 3; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo3 ()
+{
+ for (int i = 4; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo4 ()
+{
+ for (int i = 5; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+void __attribute__((noipa)) foo5 (int start)
+{
+ for (int i = start; i < 508; ++i)
+ a[i] = b[i] * 2.;
+}
+
+int main()
+{
+ for (int i = 2; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo1 ();
+ for (int i = 2; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 3; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo2 ();
+ for (int i = 3; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 4; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo3 ();
+ for (int i = 4; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 5; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo4 ();
+ for (int i = 5; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+
+ for (int i = 3; i < 508; ++i)
+ {
+ __asm__ volatile ("" : : : "memory");
+ b[i] = i;
+ }
+ foo5 (3);
+ for (int i = 3; i < 508; ++i)
+ if (a[i] != 2*i)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" } } */
+/* Verify all vector accesses are emitted as aligned. */
+/* { dg-final { scan-assembler-not "movup" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-1.c b/gcc/testsuite/gcc.target/i386/vect-float16-1.c
new file mode 100644
index 0000000..0f82cf9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mno-avx512vl" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] + c[i];
+}
+
+/* { dg-final { scan-assembler-times "vaddph" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-10.c b/gcc/testsuite/gcc.target/i386/vect-float16-10.c
new file mode 100644
index 0000000..2176456
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-10.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mno-avx512vl" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] / c[i];
+}
+
+/* { dg-final { scan-assembler-times "vdivph" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-11.c b/gcc/testsuite/gcc.target/i386/vect-float16-11.c
new file mode 100644
index 0000000..e0409ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-11.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=128" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 128; i++)
+ a[i] = b[i] / c[i];
+}
+
+/* { dg-final { scan-assembler-times "vdivph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-12.c b/gcc/testsuite/gcc.target/i386/vect-float16-12.c
new file mode 100644
index 0000000..d92a25d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-12.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=256" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] / c[i];
+}
+
+/* { dg-final { scan-assembler-times "vdivph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-2.c b/gcc/testsuite/gcc.target/i386/vect-float16-2.c
new file mode 100644
index 0000000..974fca4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=128" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 128; i++)
+ a[i] = b[i] + c[i];
+}
+
+/* { dg-final { scan-assembler-times "vaddph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-3.c b/gcc/testsuite/gcc.target/i386/vect-float16-3.c
new file mode 100644
index 0000000..9bca914
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=256" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] + c[i];
+}
+
+/* { dg-final { scan-assembler-times "vaddph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-4.c b/gcc/testsuite/gcc.target/i386/vect-float16-4.c
new file mode 100644
index 0000000..e6f26f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mno-avx512vl" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] - c[i];
+}
+
+/* { dg-final { scan-assembler-times "vsubph" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-5.c b/gcc/testsuite/gcc.target/i386/vect-float16-5.c
new file mode 100644
index 0000000..38f287b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=128" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 128; i++)
+ a[i] = b[i] - c[i];
+}
+
+/* { dg-final { scan-assembler-times "vsubph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-6.c b/gcc/testsuite/gcc.target/i386/vect-float16-6.c
new file mode 100644
index 0000000..bc9f787
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=256" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] - c[i];
+}
+
+/* { dg-final { scan-assembler-times "vsubph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-7.c b/gcc/testsuite/gcc.target/i386/vect-float16-7.c
new file mode 100644
index 0000000..b4849cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-7.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mno-avx512vl" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] * c[i];
+}
+
+/* { dg-final { scan-assembler-times "vmulph" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-8.c b/gcc/testsuite/gcc.target/i386/vect-float16-8.c
new file mode 100644
index 0000000..71631b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-8.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=128" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 128; i++)
+ a[i] = b[i] * c[i];
+}
+
+/* { dg-final { scan-assembler-times "vmulph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-float16-9.c b/gcc/testsuite/gcc.target/i386/vect-float16-9.c
new file mode 100644
index 0000000..1be5c7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-float16-9.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512fp16 -mavx512vl -mprefer-vector-width=256" } */
+
+/* Check that we vectorize to a full 128-bit vector for _Float16 types. */
+
+void
+foo (_Float16 *__restrict__ a, _Float16 *__restrict__ b,
+ _Float16 *__restrict__ c)
+{
+ for (int i = 0; i < 256; i++)
+ a[i] = b[i] * c[i];
+}
+
+/* { dg-final { scan-assembler-times "vmulph" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-pr82426.c b/gcc/testsuite/gcc.target/i386/vect-pr82426.c
new file mode 100644
index 0000000..03b10ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-pr82426.c
@@ -0,0 +1,31 @@
+/* i?86 does not have V2SF, x32 does though. */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O3 -mavx -mfma" } */
+
+struct Matrix
+{
+ float m11;
+ float m12;
+ float m21;
+ float m22;
+ float dx;
+ float dy;
+};
+
+struct Matrix multiply(const struct Matrix *a, const struct Matrix *b)
+{
+ struct Matrix out;
+ out.m11 = a->m11*b->m11 + a->m12*b->m21;
+ out.m12 = a->m11*b->m12 + a->m12*b->m22;
+ out.m21 = a->m21*b->m11 + a->m22*b->m21;
+ out.m22 = a->m21*b->m12 + a->m22*b->m22;
+
+ out.dx = a->dx*b->m11 + a->dy*b->m21 + b->dx;
+ out.dy = a->dx*b->m12 + a->dy*b->m22 + b->dy;
+ return out;
+}
+
+/* The whole kernel should be vectorized with V4SF and V2SF operations. */
+/* { dg-final { scan-assembler-times "vadd" 1 } } */
+/* { dg-final { scan-assembler-times "vmul" 2 } } */
+/* { dg-final { scan-assembler-times "vfma" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-pr97352.c b/gcc/testsuite/gcc.target/i386/vect-pr97352.c
new file mode 100644
index 0000000..f6cbf36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-pr97352.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx -mno-avx2 -mno-avx512f" } */
+
+double x[2], a[4], b[4], c[5];
+
+void foo ()
+{
+ a[0] = c[0];
+ a[1] = c[1];
+ a[2] = c[0];
+ a[3] = c[1];
+ b[0] = c[2];
+ b[1] = c[3];
+ b[2] = c[2];
+ b[3] = c[3];
+ x[0] = c[4];
+ x[1] = c[4];
+}
+
+/* We should vectorize all three stores and the load from c apart
+ from c[4] which should be duped. */
+/* { dg-final { scan-assembler-times "vmov.pd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-rebuild.c b/gcc/testsuite/gcc.target/i386/vect-rebuild.c
index 570967f..8e85b98 100644
--- a/gcc/testsuite/gcc.target/i386/vect-rebuild.c
+++ b/gcc/testsuite/gcc.target/i386/vect-rebuild.c
@@ -30,4 +30,4 @@ v2df h (v4df x)
/* { dg-final { scan-assembler-not "unpck" } } */
/* { dg-final { scan-assembler-times "\tv?permilpd\[ \t\]" 1 } } */
-/* { dg-final { scan-assembler-times "\tv?extractf128\[ \t\]" 1 } } */
+/* { dg-final { scan-assembler-times "\tv?extract(?:f128|f64x2)\[ \t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/xorsign-avx.c b/gcc/testsuite/gcc.target/i386/xorsign-avx.c
new file mode 100644
index 0000000..f2e2054
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xorsign-avx.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target avx_runtime } } */
+/* { dg-options "-O2 -mavx -mfpmath=sse -ftree-vectorize" } */
+
+#include "xorsign.c"
diff --git a/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c b/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c
index 1936f5b..26a622a 100644
--- a/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c
+++ b/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mips16 -mcode-readable=yes" } */
+/* { dg-options "-mips16 -mcode-readable=yes -fno-tree-vrp" } */
/* { dg-skip-if "per-function expected output" { *-*-* } { "-flto" } { "" } } */
/* This testcase generates multiple constant pools within a function body. */
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 580e7c0..d4d4b90 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -333,6 +333,7 @@ foreach option {
schedule-insns2
split-wide-types
tree-vectorize
+ tree-vrp
unroll-all-loops
unroll-loops
ipa-ra
diff --git a/gcc/testsuite/gcc.target/mips/msa-insert-split.c b/gcc/testsuite/gcc.target/mips/msa-insert-split.c
index 50f3b8a..9ad5987 100644
--- a/gcc/testsuite/gcc.target/mips/msa-insert-split.c
+++ b/gcc/testsuite/gcc.target/mips/msa-insert-split.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mfp64 -mhard-float -mmsa" } */
+/* { dg-options "-fno-tree-vectorize -mfp64 -mhard-float -mmsa" } */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
typedef double v2f64 __attribute__ ((vector_size (16)));
diff --git a/gcc/testsuite/gcc.target/powerpc/dform-1.c b/gcc/testsuite/gcc.target/powerpc/dform-1.c
index fac3923..1a0b0cf 100644
--- a/gcc/testsuite/gcc.target/powerpc/dform-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/dform-1.c
@@ -1,6 +1,8 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mpower9-vector -O2" } */
+/* Now O2 enables vectorization by default, which makes expected scalar
+ loads gone, so simply disable it. */
+/* { dg-options "-mpower9-vector -O2 -fno-tree-vectorize" } */
#ifndef TYPE
#define TYPE double
diff --git a/gcc/testsuite/gcc.target/powerpc/dform-2.c b/gcc/testsuite/gcc.target/powerpc/dform-2.c
index 9947330..cc91f55 100644
--- a/gcc/testsuite/gcc.target/powerpc/dform-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/dform-2.c
@@ -1,6 +1,8 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mpower9-vector -O2" } */
+/* Now O2 enables vectorization by default, which generates unexpected float
+ conversion for vector construction, so simply disable it. */
+/* { dg-options "-mpower9-vector -O2 -fno-tree-vectorize" } */
#ifndef TYPE
#define TYPE float
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-call.c b/gcc/testsuite/gcc.target/powerpc/float128-call.c
index b64ffc6..cf7ec08 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-call.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-call.c
@@ -6,22 +6,35 @@
#error "-mfloat128 is not supported."
#endif
+/* Pick a constant to load that cannot be generated by the power10 lxvkq
+ instruction. */
#ifdef __LONG_DOUBLE_IEEE128__
#define TYPE long double
-#define ONE 1.0L
+#define TEN 10.0L
#else
#define TYPE __float128
-#define ONE 1.0Q
+#define TEN 10.0Q
#endif
/* Test to make sure vector registers are used for passing IEEE 128-bit
floating point values and returning them. Also make sure the 'q' suffix is
- handled. */
-TYPE one (void) { return ONE; }
+ handled for __float128. */
+TYPE one (void) { return TEN; }
void store (TYPE a, TYPE *p) { *p = a; }
-/* { dg-final { scan-assembler {\mlxvd2x 34\M} {target be} } } */
-/* { dg-final { scan-assembler {\mstxvd2x 34\M} {target be} } } */
-/* { dg-final { scan-assembler {\mlvx 2\M} {target le} } } */
-/* { dg-final { scan-assembler {\mstvx 2\M} {target le} } } */
+/* This regexp captures the different vector load/stores that can be generated:
+
+ lxvd2x -- big endian power7/power8, little endian power8
+ lvx -- Altivec
+ lxv -- D-form power9
+ lxvx -- X-form power9
+ plxv -- prefixed power10
+ stxvd2x -- big endian power7/power8, little endian power8
+ stvx -- Altivec
+ stxvx -- X-form vector store (power9/power10).
+ stv -- D-form vector store (power9 and above).
+ pstv -- prefixed vector store (power10 and above). */
+
+/* { dg-final { scan-assembler {\mlxvd2x 34\M|\mlvx 2\M|\mp?lxvx? 34\M} } } */
+/* { dg-final { scan-assembler {\mstxvd2x 34\M|\mstvx 2\M|\mp?stxvx? 34\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst.c b/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst.c
new file mode 100644
index 0000000..528a7e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+
+/* Verify store fusion is enabled */
+
+void fuse_stw (int *i, int a, int b, int c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+void fuse_std (long *i, long a, long b, long c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+void fuse_stfd (double *i, double a, double b, double c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+/* { dg-final { scan-assembler-times {stw 4,4\(3\)\n\tstw 6,8\(3\)} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {stw 4,4\(3\)\n\tstw 6,8\(3\)} 2 { target ilp32 } } } */
+/* { dg-final { scan-assembler-times {std 4,8\(3\)\n\tstd 6,16\(3\)} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {stfd 1,8\(3\)\n\tstfd 3,16\(3\)} 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst2.c b/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst2.c
new file mode 100644
index 0000000..62f1a92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fusion-p10-stst2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power10 -mno-power10-fusion -O2" } */
+
+/* Verify store fusion is disabled */
+
+void fuse_stw (int *i, int a, int b, int c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+void fuse_std (long *i, long a, long b, long c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+void fuse_stfd (double *i, double a, double b, double c)
+{
+ i[1] = a;
+ i[5] = b;
+ i[2] = c;
+}
+
+
+/* { dg-final { scan-assembler-not {stw 4,4\(3\)\n\tstw 6,8\(3\)} } } */
+/* { dg-final { scan-assembler-not {std 4,8\(3\)\n\tstd 6,16\(3\)} { target lp64 } } } */
+/* { dg-final { scan-assembler-not {stfd 1,8\(3\)\n\tstfd 3,16\(3\)} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c
index 0c65172..715b281 100644
--- a/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c
+++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c
@@ -5,14 +5,16 @@
void
foo (__vector_quad *dst)
{
- __vector_quad acc;
- __builtin_mma_xxsetaccz (&acc);
- *dst = acc;
+ __vector_quad acc0, acc1;
+ __builtin_mma_xxsetaccz (&acc0);
+ __builtin_mma_xxsetaccz (&acc1);
+ dst[0] = acc0;
+ dst[1] = acc1;
}
/* { dg-final { scan-assembler-not {\mlxv\M} } } */
/* { dg-final { scan-assembler-not {\mlxvp\M} } } */
/* { dg-final { scan-assembler-not {\mxxmtacc\M} } } */
-/* { dg-final { scan-assembler-times {\mxxsetaccz\M} 1 } } */
-/* { dg-final { scan-assembler-times {\mxxmfacc\M} 1 } } */
-/* { dg-final { scan-assembler-times {\mstxvp\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxsetaccz\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxmfacc\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstxvp\M} 4 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr101985-1.c b/gcc/testsuite/gcc.target/powerpc/pr101985-1.c
new file mode 100644
index 0000000..b4753ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr101985-1.c
@@ -0,0 +1,18 @@
+/* PR target/101985 */
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <altivec.h>
+
+int
+main (void)
+{
+ vector float a = { 1, 2, - 3, - 4};
+ vector float b = {-10, 20, -30, 40};
+ vector float c = { 10, 20, -30, -40};
+ a = vec_cpsgn (a, b);
+ if (! vec_all_eq (a, c))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr101985-2.c b/gcc/testsuite/gcc.target/powerpc/pr101985-2.c
new file mode 100644
index 0000000..435d3a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr101985-2.c
@@ -0,0 +1,18 @@
+/* PR target/101985 */
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <altivec.h>
+
+int
+main (void)
+{
+ vector double a = { 1, -4};
+ vector double b = { -10, 40};
+ vector double c = { 10, -40};
+ a = vec_cpsgn (a, b);
+ if (! vec_all_eq (a, c))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr78102.c b/gcc/testsuite/gcc.target/powerpc/pr78102.c
new file mode 100644
index 0000000..434e677
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr78102.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mvsx" } */
+/* { dg-require-effective-target vsx_hw } */
+
+#include <x86intrin.h>
+
+__m128i
+foo (const __m128i x, const __m128i y)
+{
+ return _mm_cmpeq_epi64 (x, y);
+}
+
+__v2di
+bar (const __v2di x, const __v2di y)
+{
+ return x == y;
+}
+
+__v2di
+baz (const __v2di x, const __v2di y)
+{
+ return x != y;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80510-2.c b/gcc/testsuite/gcc.target/powerpc/pr80510-2.c
index f85e005..d041d96 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80510-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80510-2.c
@@ -1,7 +1,9 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+/* Now O2 enables vectorization by default, which generates unexpected VSR
+ to GPR movement for vector construction, so simply disable it. */
+/* { dg-options "-mdejagnu-cpu=power8 -O2 -fno-tree-vectorize" } */
/* Make sure that STXSSPX is generated for float scalars in Altivec registers
on power7 instead of moving the value to a FPR register and doing a X-FORM
diff --git a/gcc/testsuite/gcc.target/powerpc/pr97142.c b/gcc/testsuite/gcc.target/powerpc/pr97142.c
new file mode 100644
index 0000000..0e5f1c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr97142.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast" } */
+
+#include <math.h>
+
+float test1 (float x, float y)
+{
+ return fmodf (x, y);
+}
+
+double test2 (double x, double y)
+{
+ return fmod (x, y);
+}
+
+float test3 (float x, float y)
+{
+ return remainderf (x, y);
+}
+
+double test4 (double x, double y)
+{
+ return remainder (x, y);
+}
+
+/* { dg-final { scan-assembler-not {(?n)\mb.*fmod} } } */
+/* { dg-final { scan-assembler-not {(?n)\mb.*fmodf} } } */
+/* { dg-final { scan-assembler-not {(?n)\mb.*remainder} } } */
+/* { dg-final { scan-assembler-not {(?n)\mb.*remainderf} } } */
+/* { dg-final { scan-assembler-times {\mfdiv\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfdivs\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfnmsub\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfnmsubs\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfriz\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfrin\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-packusdw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-packusdw.c
new file mode 100644
index 0000000..fe51003
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-packusdw.c
@@ -0,0 +1,73 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mvsx" } */
+/* { dg-require-effective-target vsx_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static unsigned short
+int_to_ushort (int iVal)
+{
+ unsigned short sVal;
+
+ if (iVal < 0)
+ sVal = 0;
+ else if (iVal > 0xffff)
+ sVal = 0xffff;
+ else sVal = iVal;
+
+ return sVal;
+}
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ } src1, src2;
+ union
+ {
+ __m128i x[NUM / 4];
+ unsigned short s[NUM * 2];
+ } dst;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_packus_epi32 (src1.x [i / 4], src2.x [i / 4]);
+
+ for (i = 0; i < NUM; i ++)
+ {
+ int dstIndex;
+ unsigned short sVal;
+
+ sVal = int_to_ushort (src1.i[i]);
+ dstIndex = (i % 4) + (i / 4) * 8;
+ if (sVal != dst.s[dstIndex])
+ abort ();
+
+ sVal = int_to_ushort (src2.i[i]);
+ dstIndex += 4;
+ if (sVal != dst.s[dstIndex])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pcmpeqq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pcmpeqq.c
new file mode 100644
index 0000000..39b9f01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pcmpeqq.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mpower8-vector" } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ } dst, src1, src2;
+ int i, sign=1;
+ long long is_eq;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.ll[i] = i * i * sign;
+ src2.ll[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cmpeq_epi64(src1.x [i / 2], src2.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ is_eq = src1.ll[i] == src2.ll[i] ? 0xffffffffffffffffLL : 0LL;
+ if (is_eq != dst.ll[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-phminposuw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-phminposuw.c
index 146df24..150a8a0 100644
--- a/gcc/testsuite/gcc.target/powerpc/sse4_1-phminposuw.c
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-phminposuw.c
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-options "-O2 -mvsx -Wno-psabi" } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-require-effective-target vsx_hw } */
#define NO_WARN_X86_INTRINSICS 1
#ifndef CHECK_H
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsb.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsb.c
new file mode 100644
index 0000000..2f5906d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsb.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 1024
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 16];
+ signed char i[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ signed char max;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 16)
+ dst.x[i / 16] = _mm_max_epi8 (src1.x[i / 16], src2.x[i / 16]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ max = src1.i[i] <= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (max != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsd.c
new file mode 100644
index 0000000..d196abe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxsd.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ int max;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_max_epi32 (src1.x[i / 4], src2.x[i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ max = src1.i[i] <= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (max != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxud.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxud.c
new file mode 100644
index 0000000..140a7f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxud.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ unsigned int i[NUM];
+ } dst, src1, src2;
+ int i;
+ unsigned int max;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i;
+ src2.i[i] = i + 20;
+ if ((i % 4))
+ src2.i[i] |= 0x80000000;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_max_epu32 (src1.x[i / 4], src2.x[i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ max = src1.i[i] <= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (max != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxuw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxuw.c
new file mode 100644
index 0000000..9f9b05f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmaxuw.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 8];
+ unsigned short i[NUM];
+ } dst, src1, src2;
+ int i;
+ unsigned short max;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i;
+ src2.i[i] = i + 20;
+ if ((i % 8))
+ src2.i[i] |= 0x8000;
+ }
+
+ for (i = 0; i < NUM; i += 8)
+ dst.x[i / 8] = _mm_max_epu16 (src1.x[i / 8], src2.x[i / 8]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ max = src1.i[i] <= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (max != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsb.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsb.c
new file mode 100644
index 0000000..533e2bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsb.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 1024
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 16];
+ signed char i[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ signed char min;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 16)
+ dst.x[i / 16] = _mm_min_epi8 (src1.x[i / 16], src2.x[i / 16]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ min = src1.i[i] >= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (min != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsd.c
new file mode 100644
index 0000000..585a2ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminsd.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ int min;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_min_epi32 (src1.x[i / 4], src2.x[i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ min = src1.i[i] >= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (min != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pminud.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminud.c
new file mode 100644
index 0000000..bd6b46f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminud.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ unsigned int i[NUM];
+ } dst, src1, src2;
+ int i;
+ unsigned int min;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i;
+ src2.i[i] = i + 20;
+ if ((i % 4))
+ src2.i[i] |= 0x80000000;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_min_epu32 (src1.x[i / 4], src2.x[i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ min = src1.i[i] >= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (min != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pminuw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminuw.c
new file mode 100644
index 0000000..b4ef717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pminuw.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 8];
+ unsigned short i[NUM];
+ } dst, src1, src2;
+ int i;
+ unsigned short min;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i;
+ src2.i[i] = i + 20;
+ if ((i % 8))
+ src2.i[i] |= 0x8000;
+ }
+
+ for (i = 0; i < NUM; i += 8)
+ dst.x[i / 8] = _mm_min_epu16 (src1.x[i / 8], src2.x[i / 8]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ min = src1.i[i] >= src2.i[i] ? src2.i[i] : src1.i[i];
+ if (min != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbd.c
new file mode 100644
index 0000000..f3021da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbd.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ signed char c[NUM * 4];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 4) + (i / 4) * 16] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x [i / 4] = _mm_cvtepi8_epi32 (src.x [i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 4) + (i / 4) * 16] != dst.i[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbq.c
new file mode 100644
index 0000000..9ec1ab7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbq.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-O2 -mpower8-vector" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ signed char c[NUM * 8];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 2) + (i / 2) * 16] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepi8_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 2) + (i / 2) * 16] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbw.c
new file mode 100644
index 0000000..dabd6bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxbw.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 8];
+ short s[NUM];
+ signed char c[NUM * 2];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 8) + (i / 8) * 16] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 8)
+ dst.x [i / 8] = _mm_cvtepi8_epi16 (src.x [i / 8]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 8) + (i / 8) * 16] != dst.s[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxdq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxdq.c
new file mode 100644
index 0000000..1c26378
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxdq.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-O2 -mpower8-vector" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ int i[NUM * 2];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.i[(i % 2) + (i / 2) * 4] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepi32_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.i[(i % 2) + (i / 2) * 4] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwd.c
new file mode 100644
index 0000000..e698f28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwd.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ short s[NUM * 2];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.s[(i % 4) + (i / 4) * 8] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x [i / 4] = _mm_cvtepi16_epi32 (src.x [i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.s[(i % 4) + (i / 4) * 8] != dst.i[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwq.c
new file mode 100644
index 0000000..6786469
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovsxwq.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-O2 -mpower8-vector" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ short s[NUM * 4];
+ } dst, src;
+ int i, sign = 1;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.s[(i % 2) + (i / 2) * 8] = i * i * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepi16_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.s[(i % 2) + (i / 2) * 8] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbd.c
new file mode 100644
index 0000000..f902ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbd.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ unsigned int i[NUM];
+ unsigned char c[NUM * 4];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 4) + (i / 4) * 16] = i * i;
+ if ((i % 4))
+ src.c[(i % 4) + (i / 4) * 16] |= 0x80;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x [i / 4] = _mm_cvtepu8_epi32 (src.x [i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 4) + (i / 4) * 16] != dst.i[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbq.c
new file mode 100644
index 0000000..1dbe126
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbq.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ unsigned long long ll[NUM];
+ unsigned char c[NUM * 8];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 2) + (i / 2) * 16] = i * i;
+ if ((i % 2))
+ src.c[(i % 2) + (i / 2) * 16] |= 0x80;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepu8_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 2) + (i / 2) * 16] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbw.c
new file mode 100644
index 0000000..8be531f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxbw.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 8];
+ unsigned short s[NUM];
+ unsigned char c[NUM * 2];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.c[(i % 8) + (i / 8) * 16] = i * i;
+ if ((i % 4))
+ src.c[(i % 8) + (i / 8) * 16] |= 0x80;
+ }
+
+ for (i = 0; i < NUM; i += 8)
+ dst.x [i / 8] = _mm_cvtepu8_epi16 (src.x [i / 8]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.c[(i % 8) + (i / 8) * 16] != dst.s[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxdq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxdq.c
new file mode 100644
index 0000000..8154407
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxdq.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ unsigned long long ll[NUM];
+ unsigned int i[NUM * 2];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.i[(i % 2) + (i / 2) * 4] = i * i;
+ if ((i % 2))
+ src.i[(i % 2) + (i / 2) * 4] |= 0x80000000;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepu32_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.i[(i % 2) + (i / 2) * 4] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwd.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwd.c
new file mode 100644
index 0000000..77c797b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwd.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ unsigned int i[NUM];
+ unsigned short s[NUM * 2];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.s[(i % 4) + (i / 4) * 8] = i * i;
+ if ((i % 4))
+ src.s[(i % 4) + (i / 4) * 8] |= 0x8000;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x [i / 4] = _mm_cvtepu16_epi32 (src.x [i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.s[(i % 4) + (i / 4) * 8] != dst.i[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwq.c
new file mode 100644
index 0000000..999542d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmovzxwq.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 128
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ unsigned long long ll[NUM];
+ unsigned short s[NUM * 4];
+ } dst, src;
+ int i;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src.s[(i % 2) + (i / 2) * 8] = i * i;
+ if ((i % 2))
+ src.s[(i % 2) + (i / 2) * 8] |= 0x8000;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x [i / 2] = _mm_cvtepu16_epi64 (src.x [i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ if (src.s[(i % 2) + (i / 2) * 8] != dst.ll[i])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmuldq.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmuldq.c
new file mode 100644
index 0000000..6a884f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmuldq.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mpower8-vector" } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ } dst;
+ union
+ {
+ __m128i x[NUM / 2];
+ int i[NUM * 2];
+ } src1, src2;
+ int i, sign = 1;
+ long long value;
+
+ for (i = 0; i < NUM * 2; i += 2)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x[i / 2] = _mm_mul_epi32 (src1.x[i / 2], src2.x[i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ value = (long long) src1.i[i * 2] * (long long) src2.i[i * 2];
+ if (value != dst.ll[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pmulld.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmulld.c
new file mode 100644
index 0000000..43eda16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pmulld.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mvsx" } */
+/* { dg-require-effective-target vsx_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <smmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 4];
+ int i[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ int value;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.i[i] = i * i * sign;
+ src2.i[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 4)
+ dst.x[i / 4] = _mm_mullo_epi32 (src1.x[i / 4], src2.x[i / 4]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ value = src1.i[i] * src2.i[i];
+ if (value != dst.i[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_2-check.h b/gcc/testsuite/gcc.target/powerpc/sse4_2-check.h
new file mode 100644
index 0000000..f6264e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_2-check.h
@@ -0,0 +1,18 @@
+#define NO_WARN_X86_INTRINSICS 1
+
+static void sse4_2_test (void);
+
+static void
+__attribute__ ((noinline))
+do_test (void)
+{
+ sse4_2_test ();
+}
+
+int
+main ()
+{
+ do_test ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c
new file mode 100644
index 0000000..e8ecd9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mvsx" } */
+/* { dg-require-effective-target vsx_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_2_test
+#endif
+
+#include CHECK_H
+
+#include <nmmintrin.h>
+
+#define NUM 64
+
+static void
+TEST (void)
+{
+ union
+ {
+ __m128i x[NUM / 2];
+ long long ll[NUM];
+ } dst, src1, src2;
+ int i, sign = 1;
+ long long is_eq;
+
+ for (i = 0; i < NUM; i++)
+ {
+ src1.ll[i] = i * i * sign;
+ src2.ll[i] = (i + 20) * sign;
+ sign = -sign;
+ }
+
+ for (i = 0; i < NUM; i += 2)
+ dst.x[i / 2] = _mm_cmpgt_epi64 (src1.x[i / 2], src2.x[i / 2]);
+
+ for (i = 0; i < NUM; i++)
+ {
+ is_eq = src1.ll[i] > src2.ll[i] ? 0xFFFFFFFFFFFFFFFFLL : 0LL;
+ if (is_eq != dst.ll[i])
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/unwind-backchain.c b/gcc/testsuite/gcc.target/powerpc/unwind-backchain.c
new file mode 100644
index 0000000..affa9b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/unwind-backchain.c
@@ -0,0 +1,24 @@
+/* -linux* targets have a fallback for the absence of unwind tables, thus are
+ the only ones we can guarantee backtrace returns all addresses. */
+/* { dg-do run { target { *-*-linux* } } } */
+/* { dg-options "-fno-asynchronous-unwind-tables" } */
+
+#include <execinfo.h>
+
+void
+test_backtrace()
+{
+ int addresses;
+ void *buffer[10];
+
+ addresses = backtrace(buffer, 10);
+ if(addresses != 4)
+ __builtin_abort();
+}
+
+int
+main()
+{
+ test_backtrace();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c b/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c
new file mode 100644
index 0000000..06d9473
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c
@@ -0,0 +1,11 @@
+/* Test __regio_symbol invalid attempt to get regio variable address. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+#include "regio.h"
+
+uint32_t test(void)
+{
+ return *(&__R30+1); /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-as-pointer.c b/gcc/testsuite/gcc.target/pru/regio-as-pointer.c
new file mode 100644
index 0000000..885464f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-as-pointer.c
@@ -0,0 +1,11 @@
+/* Test __regio_symbol invalid attempt to get regio variable address. */
+
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+#include "regio.h"
+
+uint32_t *test(void)
+{
+ return &__R31; /* { dg-error "return from pointer to non-enclosed address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-2.c b/gcc/testsuite/gcc.target/pru/regio-decl-2.c
new file mode 100644
index 0000000..9a9338e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-2.c
@@ -0,0 +1,13 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint32_t __R30[10]; /* { dg-error "aggregate types are prohibited in '__regio_symbol' address space" } */
+
+/* { dg-warning "'__R31' initialized and declared 'extern'" "" { target *-*-* } 0 } */
+extern volatile __regio_symbol
+uint32_t __R31 = 2; /* { dg-error "variables in '__regio_symbol' address space cannot have initial value" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-3.c b/gcc/testsuite/gcc.target/pru/regio-decl-3.c
new file mode 100644
index 0000000..36fcd8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-3.c
@@ -0,0 +1,19 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+uint32_t __regio_symbol *test1(void); /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+void test2(uint32_t __regio_symbol __R30); /* { dg-error "'__regio_symbol' specified for parameter '__R30'" } */
+
+void test3(uint32_t __regio_symbol *__R30); /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+typedef volatile uint32_t __regio_symbol * regio_type1_t; /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+
+struct A {
+ uint32_t __regio_symbol *__R30; /* { dg-error "pointers to '__regio_symbol' address space are prohibited" } */
+ uint32_t __regio_symbol __R31; /* { dg-error "__regio_symbol' specified for structure field '__R31'" } */
+};
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl-4.c b/gcc/testsuite/gcc.target/pru/regio-decl-4.c
new file mode 100644
index 0000000..48c45a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl-4.c
@@ -0,0 +1,17 @@
+/* Test __regio_symbol diagnostics for unsupported access. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile uint32_t __regio_symbol *__R30;
+uint32_t test_r(void)
+{
+ return *__R30; /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
+
+void test_w(uint32_t a)
+{
+ *__R30 = a; /* { dg-error "invalid access to '__regio_symbol' address space" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/regio-decl.c b/gcc/testsuite/gcc.target/pru/regio-decl.c
new file mode 100644
index 0000000..a4962aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-decl.c
@@ -0,0 +1,15 @@
+/* Test __regio_symbol diagnostics for unsupported declarations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+volatile __regio_symbol
+uint32_t __R30; /* { dg-error "variables in '__regio_symbol' address space must be declared 'extern'" } */
+
+extern __regio_symbol
+uint32_t __R31; /* { dg-error "variables in '__regio_symbol' address space must be declared 'volatile'" } */
+
+extern volatile
+__regio_symbol uint32_t __R32; /* { dg-error "register name '__R32' not recognized in '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-di.c b/gcc/testsuite/gcc.target/pru/regio-di.c
new file mode 100644
index 0000000..a422627
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-di.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for DImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile
+__regio_symbol uint64_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-hi.c b/gcc/testsuite/gcc.target/pru/regio-hi.c
new file mode 100644
index 0000000..5b89e8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-hi.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for HImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint16_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio-qi.c b/gcc/testsuite/gcc.target/pru/regio-qi.c
new file mode 100644
index 0000000..a3f6306
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio-qi.c
@@ -0,0 +1,9 @@
+/* Test __regio_symbol invalid access diagnostic for QImode. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include <stdint.h>
+
+extern volatile __regio_symbol
+uint8_t __R31; /* { dg-error "only 32-bit access is supported for '__regio_symbol' address space" } */
diff --git a/gcc/testsuite/gcc.target/pru/regio.c b/gcc/testsuite/gcc.target/pru/regio.c
new file mode 100644
index 0000000..2f01263
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio.c
@@ -0,0 +1,58 @@
+/* __regio_symbol operations. */
+
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+#include "regio.h"
+
+void
+test_r30_w_const (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr30, r\[012\]\[0-9\]?" } } */
+ __R30 = 1;
+}
+
+void
+test_r31_w_zext_qi (unsigned char val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14.b0" } } */
+ __R31 = val1;
+}
+
+void
+test_r31_w_zext_hi (unsigned short val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14.w0" } } */
+ __R31 = val1;
+}
+
+void
+test_r31_w (unsigned int val1)
+{
+ /* { dg-final { scan-assembler "mov\\tr31, r14" } } */
+ __R31 = val1;
+}
+
+uint32_t
+test_r30_r (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr14, r30" } } */
+ return __R30;
+}
+
+void
+test_r30_rw (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr\[012\]\[0-9\]?, r30" } } */
+ /* { dg-final { scan-assembler "mov\\tr30, r\[012\]\[0-9\]?" } } */
+ __R30 = __R30;
+}
+
+void
+test_r31_rw (void)
+{
+ /* { dg-final { scan-assembler "mov\\tr\[012\]\[0-9\]?, r31" } } */
+ /* { dg-final { scan-assembler "mov\\tr31, r\[012\]\[0-9\]?" } } */
+ __R31 |= 101;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/regio.h b/gcc/testsuite/gcc.target/pru/regio.h
new file mode 100644
index 0000000..3a120c1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/regio.h
@@ -0,0 +1,7 @@
+
+#include <stdint.h>
+
+/* Declare the I/O registers. */
+extern volatile __regio_symbol uint32_t __R30;
+extern volatile __regio_symbol uint32_t __R31;
+
diff --git a/gcc/testsuite/gcc.target/s390/pr102222.c b/gcc/testsuite/gcc.target/s390/pr102222.c
new file mode 100644
index 0000000..47d075e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr102222.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -m31 -mesa" } */
+
+struct squashfs_reg_inode_header_1 read_inode_inode;
+
+int read_inode_val;
+
+struct squashfs_reg_inode_header_1
+{
+ int file_size:32;
+} __attribute__((packed)) read_inode ();
+
+void foo (void)
+{
+ read_inode_inode.file_size = read_inode_val;
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr80725.c b/gcc/testsuite/gcc.target/s390/pr80725.c
index 4a402c4..d556e6b 100644
--- a/gcc/testsuite/gcc.target/s390/pr80725.c
+++ b/gcc/testsuite/gcc.target/s390/pr80725.c
@@ -18,7 +18,7 @@ foo (int x, int y)
while (a < x)
{
if (y)
- goto *d;
+ goto *(void *)d;
g = b | b + g;
bar (g);
c = (char) (long) foo;
diff --git a/gcc/testsuite/gcc.target/s390/rawmemchr-1.c b/gcc/testsuite/gcc.target/s390/rawmemchr-1.c
new file mode 100644
index 0000000..a512570
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/rawmemchr-1.c
@@ -0,0 +1,99 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details -mzarch -march=z13" } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrQI" 2 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrHI" 2 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated rawmemchrSI" 2 "ldist" } } */
+
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define rawmemchrT(T, pattern) \
+__attribute__((noinline,noclone)) \
+T* rawmemchr_##T (T *s) \
+{ \
+ while (*s != pattern) \
+ ++s; \
+ return s; \
+}
+
+rawmemchrT(int8_t, (int8_t)0xde)
+rawmemchrT(uint8_t, 0xde)
+rawmemchrT(int16_t, (int16_t)0xdead)
+rawmemchrT(uint16_t, 0xdead)
+rawmemchrT(int32_t, (int32_t)0xdeadbeef)
+rawmemchrT(uint32_t, 0xdeadbeef)
+
+#define runT(T, pattern) \
+void run_##T () \
+{ \
+ T *buf = malloc (4096 * 2 * sizeof(T)); \
+ assert (buf != NULL); \
+ memset (buf, 0xa, 4096 * 2 * sizeof(T)); \
+ /* ensure q is 4096-byte aligned */ \
+ T *q = (T*)((unsigned char *)buf \
+ + (4096 - ((uintptr_t)buf & 4095))); \
+ T *p; \
+ /* unaligned + block boundary + 1st load */ \
+ p = (T *) ((uintptr_t)q - 8); \
+ p[2] = pattern; \
+ assert ((rawmemchr_##T (&p[0]) == &p[2])); \
+ p[2] = (T) 0xaaaaaaaa; \
+ /* unaligned + block boundary + 2nd load */ \
+ p = (T *) ((uintptr_t)q - 8); \
+ p[6] = pattern; \
+ assert ((rawmemchr_##T (&p[0]) == &p[6])); \
+ p[6] = (T) 0xaaaaaaaa; \
+ /* unaligned + 1st load */ \
+ q[5] = pattern; \
+ assert ((rawmemchr_##T (&q[2]) == &q[5])); \
+ q[5] = (T) 0xaaaaaaaa; \
+ /* unaligned + 2nd load */ \
+ q[14] = pattern; \
+ assert ((rawmemchr_##T (&q[2]) == &q[14])); \
+ q[14] = (T) 0xaaaaaaaa; \
+ /* unaligned + 3rd load */ \
+ q[19] = pattern; \
+ assert ((rawmemchr_##T (&q[2]) == &q[19])); \
+ q[19] = (T) 0xaaaaaaaa; \
+ /* unaligned + 4th load */ \
+ q[25] = pattern; \
+ assert ((rawmemchr_##T (&q[2]) == &q[25])); \
+ q[25] = (T) 0xaaaaaaaa; \
+ /* aligned + 1st load */ \
+ q[5] = pattern; \
+ assert ((rawmemchr_##T (&q[0]) == &q[5])); \
+ q[5] = (T) 0xaaaaaaaa; \
+ /* aligned + 2nd load */ \
+ q[14] = pattern; \
+ assert ((rawmemchr_##T (&q[0]) == &q[14])); \
+ q[14] = (T) 0xaaaaaaaa; \
+ /* aligned + 3rd load */ \
+ q[19] = pattern; \
+ assert ((rawmemchr_##T (&q[0]) == &q[19])); \
+ q[19] = (T) 0xaaaaaaaa; \
+ /* aligned + 4th load */ \
+ q[25] = pattern; \
+ assert ((rawmemchr_##T (&q[0]) == &q[25])); \
+ q[25] = (T) 0xaaaaaaaa; \
+ free (buf); \
+}
+
+runT(int8_t, (int8_t)0xde)
+runT(uint8_t, 0xde)
+runT(int16_t, (int16_t)0xdead)
+runT(uint16_t, 0xdead)
+runT(int32_t, (int32_t)0xdeadbeef)
+runT(uint32_t, 0xdeadbeef)
+
+int main (void)
+{
+ run_uint8_t ();
+ run_int8_t ();
+ run_uint16_t ();
+ run_int16_t ();
+ run_uint32_t ();
+ run_int32_t ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/sparc/20210917-1.c b/gcc/testsuite/gcc.target/sparc/20210917-1.c
new file mode 100644
index 0000000..03e8bc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/20210917-1.c
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/102306 */
+/* Reported by Daniel Cederman <cederman@gaisler.com> */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O -mcpu=v8" } */
+
+extern void foo (void);
+
+void test (volatile unsigned char *a)
+{
+ char b = *a;
+ if (!b)
+ return;
+ if (b & 2)
+ foo ();
+}
+
+/* { dg-final { scan-assembler-times "ldub" 1 } } */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp
new file mode 100644
index 0000000..33d2476
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/abi-avx512fp16-xmm.exp
@@ -0,0 +1,48 @@
+# Copyright (C) 2019 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/>.
+
+# The x86-64 ABI testsuite needs one additional assembler file for most
+# testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+load_lib clearcap.exp
+load_lib file-format.exp
+
+if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
+ || [is-effective-target ia32]
+ || [gcc_target_object_format] != "elf"
+ || ![is-effective-target avx512fp16] } then {
+ return
+}
+
+
+torture-init
+clearcap-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-W -Wall -Wno-abi -mavx512fp16"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+clearcap-finish
+torture-finish
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h
new file mode 100644
index 0000000..425cc3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/args.h
@@ -0,0 +1,190 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+#include <string.h>
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 rdi
+#define I1 rsi
+#define I2 rdx
+#define I3 rcx
+#define I4 r8
+#define I5 r9
+#define F0 xmm0
+#define F1 xmm1
+#define F2 xmm2
+#define F3 xmm3
+#define F4 xmm4
+#define F5 xmm5
+#define F6 xmm6
+#define F7 xmm7
+
+typedef union {
+ _Float16 __Float16[8];
+ float _float[4];
+ double _double[2];
+ long long _longlong[2];
+ int _int[4];
+ ulonglong _ulonglong[2];
+#ifdef CHECK_M64_M128
+ __m64 _m64[2];
+ __m128 _m128[1];
+ __m128h _m128h[1];
+#endif
+} XMM_T;
+
+typedef union {
+ _Float16 __Float16;
+ float _float;
+ double _double;
+ ldouble _ldouble;
+ ulonglong _ulonglong[2];
+} X87_T;
+extern void (*callthis)(void);
+extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
+XMM_T xmm_regs[16];
+X87_T x87_regs[8];
+extern volatile unsigned long long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%rax, %%rax\n\t" \
+ "xor %%rbx, %%rbx\n\t" \
+ "xor %%rcx, %%rcx\n\t" \
+ "xor %%rdx, %%rdx\n\t" \
+ "xor %%rsi, %%rsi\n\t" \
+ "xor %%rdi, %%rdi\n\t" \
+ "xor %%r8, %%r8\n\t" \
+ "xor %%r9, %%r9\n\t" \
+ "xor %%r10, %%r10\n\t" \
+ "xor %%r11, %%r11\n\t" \
+ "xor %%r12, %%r12\n\t" \
+ "xor %%r13, %%r13\n\t" \
+ "xor %%r14, %%r14\n\t" \
+ "xor %%r15, %%r15\n\t" \
+ ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+};
+struct FloatRegisters
+{
+ double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
+ ldouble st0, st1, st2, st3, st4, st5, st6, st7;
+ XMM_T xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9,
+ xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs;
+extern struct FloatRegisters fregs;
+extern unsigned int num_iregs, num_fregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || iregs.I0 == I0); \
+ assert (num_iregs <= 1 || iregs.I1 == I1); \
+ assert (num_iregs <= 2 || iregs.I2 == I2); \
+ assert (num_iregs <= 3 || iregs.I3 == I3); \
+ assert (num_iregs <= 4 || iregs.I4 == I4); \
+ assert (num_iregs <= 5 || iregs.I5 == I5); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
+ = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
+ memset (&iregs, 0, sizeof (iregs)); \
+ memset (&fregs, 0, sizeof (fregs)); \
+ memset (xmm_regs, 0, sizeof (xmm_regs)); \
+ memset (x87_regs, 0, sizeof (x87_regs));
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* TODO: Do the checking. */
+#define check_f_arguments(T) do { \
+ assert (num_fregs <= 0 || fregs.xmm0._ ## T [0] == xmm_regs[0]._ ## T [0]); \
+ assert (num_fregs <= 1 || fregs.xmm1._ ## T [0] == xmm_regs[1]._ ## T [0]); \
+ assert (num_fregs <= 2 || fregs.xmm2._ ## T [0] == xmm_regs[2]._ ## T [0]); \
+ assert (num_fregs <= 3 || fregs.xmm3._ ## T [0] == xmm_regs[3]._ ## T [0]); \
+ assert (num_fregs <= 4 || fregs.xmm4._ ## T [0] == xmm_regs[4]._ ## T [0]); \
+ assert (num_fregs <= 5 || fregs.xmm5._ ## T [0] == xmm_regs[5]._ ## T [0]); \
+ assert (num_fregs <= 6 || fregs.xmm6._ ## T [0] == xmm_regs[6]._ ## T [0]); \
+ assert (num_fregs <= 7 || fregs.xmm7._ ## T [0] == xmm_regs[7]._ ## T [0]); \
+ } while (0)
+
+#define check_float16_arguments check_f_arguments(_Float16)
+#define check_float_arguments check_f_arguments(float)
+#define check_double_arguments check_f_arguments(double)
+
+#define check_vector_arguments(T,O) do { \
+ assert (num_fregs <= 0 \
+ || memcmp (((char *) &fregs.xmm0) + (O), \
+ &xmm_regs[0], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 1 \
+ || memcmp (((char *) &fregs.xmm1) + (O), \
+ &xmm_regs[1], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 2 \
+ || memcmp (((char *) &fregs.xmm2) + (O), \
+ &xmm_regs[2], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 3 \
+ || memcmp (((char *) &fregs.xmm3) + (O), \
+ &xmm_regs[3], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 4 \
+ || memcmp (((char *) &fregs.xmm4) + (O), \
+ &xmm_regs[4], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 5 \
+ || memcmp (((char *) &fregs.xmm5) + (O), \
+ &xmm_regs[5], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 6 \
+ || memcmp (((char *) &fregs.xmm6) + (O), \
+ &xmm_regs[6], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 7 \
+ || memcmp (((char *) &fregs.xmm7) + (O), \
+ &xmm_regs[7], \
+ sizeof (__ ## T) - (O)) == 0); \
+ } while (0)
+
+#define check_m64_arguments check_vector_arguments(m64, 0)
+#define check_m128_arguments check_vector_arguments(m128, 0)
+
+/* ldoubles are not passed in registers */
+#define check_ldouble_arguments
+
+/* TODO: Do the clearing. */
+#define clear_float_hardware_registers
+#define clear_x87_hardware_registers
+
+#define clear_float_registers \
+ clear_struct_registers \
+ clear_float_hardware_registers
+
+#define clear_x87_registers \
+ clear_struct_registers \
+ clear_x87_hardware_registers
+
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S
new file mode 100644
index 0000000..7849acd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/asm-support.S
@@ -0,0 +1,81 @@
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+.LFB3:
+ movq %rax, rax(%rip)
+ movq %rbx, rbx(%rip)
+ movq %rcx, rcx(%rip)
+ movq %rdx, rdx(%rip)
+ movq %rdi, rdi(%rip)
+ movq %rsi, rsi(%rip)
+ movq %rbp, rbp(%rip)
+ movq %rsp, rsp(%rip)
+ movq %r8, r8(%rip)
+ movq %r9, r9(%rip)
+ movq %r10, r10(%rip)
+ movq %r11, r11(%rip)
+ movq %r12, r12(%rip)
+ movq %r13, r13(%rip)
+ movq %r14, r14(%rip)
+ movq %r15, r15(%rip)
+ vmovdqu %xmm0, xmm_regs+0(%rip)
+ vmovdqu %xmm1, xmm_regs+16(%rip)
+ vmovdqu %xmm2, xmm_regs+32(%rip)
+ vmovdqu %xmm3, xmm_regs+48(%rip)
+ vmovdqu %xmm4, xmm_regs+64(%rip)
+ vmovdqu %xmm5, xmm_regs+80(%rip)
+ vmovdqu %xmm6, xmm_regs+96(%rip)
+ vmovdqu %xmm7, xmm_regs+112(%rip)
+ vmovdqu %xmm8, xmm_regs+128(%rip)
+ vmovdqu %xmm9, xmm_regs+144(%rip)
+ vmovdqu %xmm10, xmm_regs+160(%rip)
+ vmovdqu %xmm11, xmm_regs+176(%rip)
+ vmovdqu %xmm12, xmm_regs+192(%rip)
+ vmovdqu %xmm13, xmm_regs+208(%rip)
+ vmovdqu %xmm14, xmm_regs+224(%rip)
+ vmovdqu %xmm15, xmm_regs+240(%rip)
+ jmp *callthis(%rip)
+.LFE3:
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movq %rdi, rdi(%rip)
+ subq $8, %rsp
+ call *callthis(%rip)
+ addq $8, %rsp
+ movq %rax, rax(%rip)
+ movq %rdx, rdx(%rip)
+ vmovdqu %xmm0, xmm_regs+0(%rip)
+ vmovdqu %xmm1, xmm_regs+16(%rip)
+ fstpt x87_regs(%rip)
+ fstpt x87_regs+16(%rip)
+ fldt x87_regs+16(%rip)
+ fldt x87_regs(%rip)
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .comm callthis,8,8
+ .comm rax,8,8
+ .comm rbx,8,8
+ .comm rcx,8,8
+ .comm rdx,8,8
+ .comm rsi,8,8
+ .comm rdi,8,8
+ .comm rsp,8,8
+ .comm rbp,8,8
+ .comm r8,8,8
+ .comm r9,8,8
+ .comm r10,8,8
+ .comm r11,8,8
+ .comm r12,8,8
+ .comm r13,8,8
+ .comm r14,8,8
+ .comm r15,8,8
+ .comm xmm_regs,256,32
+ .comm x87_regs,128,32
+ .comm volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h
new file mode 100644
index 0000000..9fbec9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-check.h
@@ -0,0 +1,74 @@
+#include <stdlib.h>
+#include <cpuid.h>
+
+/* Check if the OS supports executing AVX512FP16 instructions. */
+
+#define XCR_XFEATURE_ENABLED_MASK 0x0
+
+#define XSTATE_FP 0x1
+#define XSTATE_SSE 0x2
+#define XSTATE_YMM 0x4
+#define XSTATE_OPMASK 0x20
+#define XSTATE_ZMM 0x40
+#define XSTATE_HI_ZMM 0x80
+
+static int
+check_osxsave (void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return 0;
+
+ return (ecx & bit_OSXSAVE) != 0;
+}
+
+static int
+avx512fp16_os_support (void)
+{
+ unsigned int eax, edx;
+ unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
+ unsigned int mask = XSTATE_MASK;
+
+ if (!check_osxsave ())
+ return 0;
+
+ __asm__ ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
+
+ return ((eax & mask) == mask);
+}
+
+static void do_test (void);
+
+int
+main ()
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!avx512fp16_os_support ())
+ return 0;
+
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+ /* Run AVX512FP16 test only if host has ISA support. */
+ if (((ebx & (bit_AVX512F | bit_AVX512BW))
+ == (bit_AVX512F | bit_AVX512BW))
+ && (edx & bit_AVX512FP16)
+ && AVX512VL (ebx))
+ {
+ do_test ();
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+ return 0;
+ }
+
+#ifdef DEBUG
+ printf ("SKIPPED\n");
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h
new file mode 100644
index 0000000..0abe09f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/avx512fp16-xmm-check.h
@@ -0,0 +1,3 @@
+#define AVX512VL(ebx) (ebx & bit_AVX512VL)
+#define XSTATE_MASK (XSTATE_SSE | XSTATE_OPMASK)
+#include "avx512fp16-check.h"
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h
new file mode 100644
index 0000000..892a66e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/defines.h
@@ -0,0 +1,166 @@
+#ifndef DEFINED_DEFINES_H
+#define DEFINED_DEFINES_H
+
+/* Get __m64 and __m128. */
+#include <immintrin.h>
+
+typedef unsigned long long ulonglong;
+typedef long double ldouble;
+
+/* These defines determines what part of the test should be run. When
+ GCC implements these parts, the defines should be uncommented to
+ enable testing. */
+
+/* Scalar type __int128. */
+/* #define CHECK_INT128 */
+
+/* Scalar type long double. */
+#define CHECK_LONG_DOUBLE
+
+/* Scalar type __float128. */
+/* #define CHECK_FLOAT128 */
+
+/* Scalar types __m64 and __m128. */
+#define CHECK_M64_M128
+
+/* Returning of complex type. */
+#define CHECK_COMPLEX
+
+/* Structs with size >= 16. */
+#define CHECK_LARGER_STRUCTS
+
+/* Checks for passing floats and doubles. */
+#define CHECK_FLOAT_DOUBLE_PASSING
+
+/* Union passing with not-extremely-simple unions. */
+#define CHECK_LARGER_UNION_PASSING
+
+/* Variable args. */
+#define CHECK_VARARGS
+
+/* Check argument passing and returning for scalar types with sizeof = 16. */
+/* TODO: Implement these tests. Don't activate them for now. */
+#define CHECK_LARGE_SCALAR_PASSING
+
+/* Defines for sizing and alignment. */
+
+#define TYPE_SIZE_CHAR 1
+#define TYPE_SIZE_SHORT 2
+#define TYPE_SIZE_INT 4
+#ifdef __ILP32__
+# define TYPE_SIZE_LONG 4
+#else
+# define TYPE_SIZE_LONG 8
+#endif
+#define TYPE_SIZE_LONG_LONG 8
+#define TYPE_SIZE_INT128 16
+#define TYPE_SIZE_FLOAT16 2
+#define TYPE_SIZE_FLOAT 4
+#define TYPE_SIZE_DOUBLE 8
+#define TYPE_SIZE_LONG_DOUBLE 16
+#define TYPE_SIZE_FLOAT128 16
+#define TYPE_SIZE_M64 8
+#define TYPE_SIZE_M128 16
+#define TYPE_SIZE_ENUM 4
+#ifdef __ILP32__
+# define TYPE_SIZE_POINTER 4
+#else
+# define TYPE_SIZE_POINTER 8
+#endif
+
+#define TYPE_ALIGN_CHAR 1
+#define TYPE_ALIGN_SHORT 2
+#define TYPE_ALIGN_INT 4
+#ifdef __ILP32__
+# define TYPE_ALIGN_LONG 4
+#else
+# define TYPE_ALIGN_LONG 8
+#endif
+#define TYPE_ALIGN_LONG_LONG 8
+#define TYPE_ALIGN_INT128 16
+#define TYPE_ALIGN_FLOAT16 2
+#define TYPE_ALIGN_FLOAT 4
+#define TYPE_ALIGN_DOUBLE 8
+#define TYPE_ALIGN_LONG_DOUBLE 16
+#define TYPE_ALIGN_FLOAT128 16
+#define TYPE_ALIGN_M64 8
+#define TYPE_ALIGN_M128 16
+#define TYPE_ALIGN_ENUM 4
+#ifdef __ILP32__
+# define TYPE_ALIGN_POINTER 4
+#else
+# define TYPE_ALIGN_POINTER 8
+#endif
+
+/* These defines control the building of the list of types to check. There
+ is a string identifying the type (with a comma after), a size of the type
+ (also with a comma and an integer for adding to the total amount of types)
+ and an alignment of the type (which is currently not really needed since
+ the abi specifies that alignof == sizeof for all scalar types). */
+#ifdef CHECK_INT128
+#define CI128_STR "__int128",
+#define CI128_SIZ TYPE_SIZE_INT128,
+#define CI128_ALI TYPE_ALIGN_INT128,
+#define CI128_RET "???",
+#else
+#define CI128_STR
+#define CI128_SIZ
+#define CI128_ALI
+#define CI128_RET
+#endif
+#ifdef CHECK_LONG_DOUBLE
+#define CLD_STR "long double",
+#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
+#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
+#define CLD_RET "x87_regs[0]._ldouble",
+#else
+#define CLD_STR
+#define CLD_SIZ
+#define CLD_ALI
+#define CLD_RET
+#endif
+#ifdef CHECK_FLOAT128
+#define CF128_STR "__float128",
+#define CF128_SIZ TYPE_SIZE_FLOAT128,
+#define CF128_ALI TYPE_ALIGN_FLOAT128,
+#define CF128_RET "???",
+#else
+#define CF128_STR
+#define CF128_SIZ
+#define CF128_ALI
+#define CF128_RET
+#endif
+#ifdef CHECK_M64_M128
+#define CMM_STR "__m64", "__m128",
+#define CMM_SIZ TYPE_SIZE_M64, TYPE_SIZE_M128,
+#define CMM_ALI TYPE_ALIGN_M64, TYPE_ALIGN_M128,
+#define CMM_RET "???", "???",
+#else
+#define CMM_STR
+#define CMM_SIZ
+#define CMM_ALI
+#define CMM_RET
+#endif
+
+/* Used in size and alignment tests. */
+enum dummytype { enumtype };
+
+extern void abort (void);
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define PACKED __attribute__((__packed__))
+#else
+#warning Some tests will fail due to missing __packed__ support
+#define PACKED
+#endif
+
+#endif /* DEFINED_DEFINES_H */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp
new file mode 100644
index 0000000..ecf673b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/abi-avx512fp16-ymm.exp
@@ -0,0 +1,45 @@
+# Copyright (C) 2019 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/>.
+
+# The x86-64 ABI testsuite needs one additional assembler file for most
+# testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+load_lib file-format.exp
+
+if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
+ || [is-effective-target ia32]
+ || [gcc_target_object_format] != "elf"
+ || ![is-effective-target avx512fp16] } then {
+ return
+}
+
+
+torture-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-W -Wall -Wno-abi -mavx512fp16"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h
new file mode 100644
index 0000000..add1095
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/args.h
@@ -0,0 +1,182 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+#include <immintrin.h>
+#include <string.h>
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 rdi
+#define I1 rsi
+#define I2 rdx
+#define I3 rcx
+#define I4 r8
+#define I5 r9
+#define F0 ymm0
+#define F1 ymm1
+#define F2 ymm2
+#define F3 ymm3
+#define F4 ymm4
+#define F5 ymm5
+#define F6 ymm6
+#define F7 ymm7
+
+typedef union {
+ _Float16 __Float16[16];
+ float _float[8];
+ double _double[4];
+ long long _longlong[4];
+ int _int[8];
+ unsigned long long _ulonglong[4];
+ __m64 _m64[4];
+ __m128 _m128[2];
+ __m256 _m256[1];
+ __m256h _m256h[1];
+} YMM_T;
+
+typedef union {
+ float _float;
+ double _double;
+ long double _ldouble;
+ unsigned long long _ulonglong[2];
+} X87_T;
+extern void (*callthis)(void);
+extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
+YMM_T ymm_regs[16];
+X87_T x87_regs[8];
+extern volatile unsigned long long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%rax, %%rax\n\t" \
+ "xor %%rbx, %%rbx\n\t" \
+ "xor %%rcx, %%rcx\n\t" \
+ "xor %%rdx, %%rdx\n\t" \
+ "xor %%rsi, %%rsi\n\t" \
+ "xor %%rdi, %%rdi\n\t" \
+ "xor %%r8, %%r8\n\t" \
+ "xor %%r9, %%r9\n\t" \
+ "xor %%r10, %%r10\n\t" \
+ "xor %%r11, %%r11\n\t" \
+ "xor %%r12, %%r12\n\t" \
+ "xor %%r13, %%r13\n\t" \
+ "xor %%r14, %%r14\n\t" \
+ "xor %%r15, %%r15\n\t" \
+ ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+};
+struct FloatRegisters
+{
+ double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
+ long double st0, st1, st2, st3, st4, st5, st6, st7;
+ YMM_T ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9,
+ ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs;
+extern struct FloatRegisters fregs;
+extern unsigned int num_iregs, num_fregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || iregs.I0 == I0); \
+ assert (num_iregs <= 1 || iregs.I1 == I1); \
+ assert (num_iregs <= 2 || iregs.I2 == I2); \
+ assert (num_iregs <= 3 || iregs.I3 == I3); \
+ assert (num_iregs <= 4 || iregs.I4 == I4); \
+ assert (num_iregs <= 5 || iregs.I5 == I5); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
+ = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
+ memset (&iregs, 0, sizeof (iregs)); \
+ memset (&fregs, 0, sizeof (fregs)); \
+ memset (ymm_regs, 0, sizeof (ymm_regs)); \
+ memset (x87_regs, 0, sizeof (x87_regs));
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* TODO: Do the checking. */
+#define check_f_arguments(T) do { \
+ assert (num_fregs <= 0 || fregs.ymm0._ ## T [0] == ymm_regs[0]._ ## T [0]); \
+ assert (num_fregs <= 1 || fregs.ymm1._ ## T [0] == ymm_regs[1]._ ## T [0]); \
+ assert (num_fregs <= 2 || fregs.ymm2._ ## T [0] == ymm_regs[2]._ ## T [0]); \
+ assert (num_fregs <= 3 || fregs.ymm3._ ## T [0] == ymm_regs[3]._ ## T [0]); \
+ assert (num_fregs <= 4 || fregs.ymm4._ ## T [0] == ymm_regs[4]._ ## T [0]); \
+ assert (num_fregs <= 5 || fregs.ymm5._ ## T [0] == ymm_regs[5]._ ## T [0]); \
+ assert (num_fregs <= 6 || fregs.ymm6._ ## T [0] == ymm_regs[6]._ ## T [0]); \
+ assert (num_fregs <= 7 || fregs.ymm7._ ## T [0] == ymm_regs[7]._ ## T [0]); \
+ } while (0)
+
+#define check_float_arguments check_f_arguments(float)
+#define check_double_arguments check_f_arguments(double)
+
+#define check_vector_arguments(T,O) do { \
+ assert (num_fregs <= 0 \
+ || memcmp (((char *) &fregs.ymm0) + (O), \
+ &ymm_regs[0], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 1 \
+ || memcmp (((char *) &fregs.ymm1) + (O), \
+ &ymm_regs[1], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 2 \
+ || memcmp (((char *) &fregs.ymm2) + (O), \
+ &ymm_regs[2], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 3 \
+ || memcmp (((char *) &fregs.ymm3) + (O), \
+ &ymm_regs[3], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 4 \
+ || memcmp (((char *) &fregs.ymm4) + (O), \
+ &ymm_regs[4], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 5 \
+ || memcmp (((char *) &fregs.ymm5) + (O), \
+ &ymm_regs[5], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 6 \
+ || memcmp (((char *) &fregs.ymm6) + (O), \
+ &ymm_regs[6], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 7 \
+ || memcmp (((char *) &fregs.ymm7) + (O), \
+ &ymm_regs[7], \
+ sizeof (__ ## T) - (O)) == 0); \
+ } while (0)
+
+#define check_m64_arguments check_vector_arguments(m64, 0)
+#define check_m128_arguments check_vector_arguments(m128, 0)
+#define check_m256_arguments check_vector_arguments(m256, 0)
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S
new file mode 100644
index 0000000..73a5919
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/asm-support.S
@@ -0,0 +1,81 @@
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+.LFB3:
+ movq %rax, rax(%rip)
+ movq %rbx, rbx(%rip)
+ movq %rcx, rcx(%rip)
+ movq %rdx, rdx(%rip)
+ movq %rdi, rdi(%rip)
+ movq %rsi, rsi(%rip)
+ movq %rbp, rbp(%rip)
+ movq %rsp, rsp(%rip)
+ movq %r8, r8(%rip)
+ movq %r9, r9(%rip)
+ movq %r10, r10(%rip)
+ movq %r11, r11(%rip)
+ movq %r12, r12(%rip)
+ movq %r13, r13(%rip)
+ movq %r14, r14(%rip)
+ movq %r15, r15(%rip)
+ vmovdqu %ymm0, ymm_regs+0(%rip)
+ vmovdqu %ymm1, ymm_regs+32(%rip)
+ vmovdqu %ymm2, ymm_regs+64(%rip)
+ vmovdqu %ymm3, ymm_regs+96(%rip)
+ vmovdqu %ymm4, ymm_regs+128(%rip)
+ vmovdqu %ymm5, ymm_regs+160(%rip)
+ vmovdqu %ymm6, ymm_regs+192(%rip)
+ vmovdqu %ymm7, ymm_regs+224(%rip)
+ vmovdqu %ymm8, ymm_regs+256(%rip)
+ vmovdqu %ymm9, ymm_regs+288(%rip)
+ vmovdqu %ymm10, ymm_regs+320(%rip)
+ vmovdqu %ymm11, ymm_regs+352(%rip)
+ vmovdqu %ymm12, ymm_regs+384(%rip)
+ vmovdqu %ymm13, ymm_regs+416(%rip)
+ vmovdqu %ymm14, ymm_regs+448(%rip)
+ vmovdqu %ymm15, ymm_regs+480(%rip)
+ jmp *callthis(%rip)
+.LFE3:
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movq %rdi, rdi(%rip)
+ subq $8, %rsp
+ call *callthis(%rip)
+ addq $8, %rsp
+ movq %rax, rax(%rip)
+ movq %rdx, rdx(%rip)
+ vmovdqu %ymm0, ymm_regs+0(%rip)
+ vmovdqu %ymm1, ymm_regs+32(%rip)
+ fstpt x87_regs(%rip)
+ fstpt x87_regs+16(%rip)
+ fldt x87_regs+16(%rip)
+ fldt x87_regs(%rip)
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .comm callthis,8,8
+ .comm rax,8,8
+ .comm rbx,8,8
+ .comm rcx,8,8
+ .comm rdx,8,8
+ .comm rsi,8,8
+ .comm rdi,8,8
+ .comm rsp,8,8
+ .comm rbp,8,8
+ .comm r8,8,8
+ .comm r9,8,8
+ .comm r10,8,8
+ .comm r11,8,8
+ .comm r12,8,8
+ .comm r13,8,8
+ .comm r14,8,8
+ .comm r15,8,8
+ .comm ymm_regs,512,32
+ .comm x87_regs,128,32
+ .comm volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h
new file mode 100644
index 0000000..6a55030
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/avx512fp16-ymm-check.h
@@ -0,0 +1,3 @@
+#define AVX512VL(ebx) (ebx & bit_AVX512VL)
+#define XSTATE_MASK (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK)
+#include "../avx512fp16-check.h"
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c
new file mode 100644
index 0000000..48e0139
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_m256_returning.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+__m256
+fun_test_returning___m256 (void)
+{
+ volatile_var++;
+ return (__m256){73,0,0,0,0,0,0,0};
+}
+
+__m256h
+fun_test_returning___m256h (void)
+{
+ volatile_var++;
+ return (__m256h){1.1f16,2.1f16,3.1f16,4.1f16,
+ 5.1f16,6.1f16,7.1f16,8.1f16,
+ 9.1f16,10.1f16,11.1f16,12.1f16,
+ 13.1f16,14.1f16,15.1f16,16.1f16};
+}
+
+__m256 test_256;
+__m256h test_256h;
+
+static void
+do_test (void)
+{
+ unsigned failed = 0;
+ YMM_T ymmt1, ymmt2;
+
+ clear_struct_registers;
+ test_256 = (__m256){73,0,0,0,0,0,0,0};
+ ymmt1._m256[0] = test_256;
+ ymmt2._m256[0] = WRAP_RET (fun_test_returning___m256)();
+ if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
+ printf ("fail m256\n"), failed++;
+
+ clear_struct_registers;
+ test_256h = (__m256h){1.1f16,2.1f16,3.1f16,4.1f16,
+ 5.1f16,6.1f16,7.1f16,8.1f16,
+ 9.1f16,10.1f16,11.1f16,12.1f16,
+ 13.1f16,14.1f16,15.1f16,16.1f16};
+ ymmt1._m256h[0] = test_256h;
+ ymmt2._m256h[0] = WRAP_RET (fun_test_returning___m256h)();
+ if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
+ printf ("fail m256h\n"), failed++;
+
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c
new file mode 100644
index 0000000..bfa80d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_m256.c
@@ -0,0 +1,370 @@
+#include <stdio.h>
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
+ i16, i17, i18, i19, i20, i21, i22, i23;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+fun_check_passing_m256_8_values (__m256 i0 ATTRIBUTE_UNUSED,
+ __m256 i1 ATTRIBUTE_UNUSED,
+ __m256 i2 ATTRIBUTE_UNUSED,
+ __m256 i3 ATTRIBUTE_UNUSED,
+ __m256 i4 ATTRIBUTE_UNUSED,
+ __m256 i5 ATTRIBUTE_UNUSED,
+ __m256 i6 ATTRIBUTE_UNUSED,
+ __m256 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m256);
+ compare (values.i1, i1, __m256);
+ compare (values.i2, i2, __m256);
+ compare (values.i3, i3, __m256);
+ compare (values.i4, i4, __m256);
+ compare (values.i5, i5, __m256);
+ compare (values.i6, i6, __m256);
+ compare (values.i7, i7, __m256);
+}
+
+fun_check_passing_m256h_8_values (__m256h i0 ATTRIBUTE_UNUSED,
+ __m256h i1 ATTRIBUTE_UNUSED,
+ __m256h i2 ATTRIBUTE_UNUSED,
+ __m256h i3 ATTRIBUTE_UNUSED,
+ __m256h i4 ATTRIBUTE_UNUSED,
+ __m256h i5 ATTRIBUTE_UNUSED,
+ __m256h i6 ATTRIBUTE_UNUSED,
+ __m256h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m256h);
+ compare (values.i1, i1, __m256h);
+ compare (values.i2, i2, __m256h);
+ compare (values.i3, i3, __m256h);
+ compare (values.i4, i4, __m256h);
+ compare (values.i5, i5, __m256h);
+ compare (values.i6, i6, __m256h);
+ compare (values.i7, i7, __m256h);
+}
+
+void
+fun_check_passing_m256_8_regs (__m256 i0 ATTRIBUTE_UNUSED,
+ __m256 i1 ATTRIBUTE_UNUSED,
+ __m256 i2 ATTRIBUTE_UNUSED,
+ __m256 i3 ATTRIBUTE_UNUSED,
+ __m256 i4 ATTRIBUTE_UNUSED,
+ __m256 i5 ATTRIBUTE_UNUSED,
+ __m256 i6 ATTRIBUTE_UNUSED,
+ __m256 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m256_arguments;
+}
+
+void
+fun_check_passing_m256h_8_regs (__m256h i0 ATTRIBUTE_UNUSED,
+ __m256h i1 ATTRIBUTE_UNUSED,
+ __m256h i2 ATTRIBUTE_UNUSED,
+ __m256h i3 ATTRIBUTE_UNUSED,
+ __m256h i4 ATTRIBUTE_UNUSED,
+ __m256h i5 ATTRIBUTE_UNUSED,
+ __m256h i6 ATTRIBUTE_UNUSED,
+ __m256h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m256_arguments;
+}
+
+void
+fun_check_passing_m256_20_values (__m256 i0 ATTRIBUTE_UNUSED,
+ __m256 i1 ATTRIBUTE_UNUSED,
+ __m256 i2 ATTRIBUTE_UNUSED,
+ __m256 i3 ATTRIBUTE_UNUSED,
+ __m256 i4 ATTRIBUTE_UNUSED,
+ __m256 i5 ATTRIBUTE_UNUSED,
+ __m256 i6 ATTRIBUTE_UNUSED,
+ __m256 i7 ATTRIBUTE_UNUSED,
+ __m256 i8 ATTRIBUTE_UNUSED,
+ __m256 i9 ATTRIBUTE_UNUSED,
+ __m256 i10 ATTRIBUTE_UNUSED,
+ __m256 i11 ATTRIBUTE_UNUSED,
+ __m256 i12 ATTRIBUTE_UNUSED,
+ __m256 i13 ATTRIBUTE_UNUSED,
+ __m256 i14 ATTRIBUTE_UNUSED,
+ __m256 i15 ATTRIBUTE_UNUSED,
+ __m256 i16 ATTRIBUTE_UNUSED,
+ __m256 i17 ATTRIBUTE_UNUSED,
+ __m256 i18 ATTRIBUTE_UNUSED,
+ __m256 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m256);
+ compare (values.i1, i1, __m256);
+ compare (values.i2, i2, __m256);
+ compare (values.i3, i3, __m256);
+ compare (values.i4, i4, __m256);
+ compare (values.i5, i5, __m256);
+ compare (values.i6, i6, __m256);
+ compare (values.i7, i7, __m256);
+ compare (values.i8, i8, __m256);
+ compare (values.i9, i9, __m256);
+ compare (values.i10, i10, __m256);
+ compare (values.i11, i11, __m256);
+ compare (values.i12, i12, __m256);
+ compare (values.i13, i13, __m256);
+ compare (values.i14, i14, __m256);
+ compare (values.i15, i15, __m256);
+ compare (values.i16, i16, __m256);
+ compare (values.i17, i17, __m256);
+ compare (values.i18, i18, __m256);
+ compare (values.i19, i19, __m256);
+}
+
+void
+fun_check_passing_m256h_20_values (__m256h i0 ATTRIBUTE_UNUSED,
+ __m256h i1 ATTRIBUTE_UNUSED,
+ __m256h i2 ATTRIBUTE_UNUSED,
+ __m256h i3 ATTRIBUTE_UNUSED,
+ __m256h i4 ATTRIBUTE_UNUSED,
+ __m256h i5 ATTRIBUTE_UNUSED,
+ __m256h i6 ATTRIBUTE_UNUSED,
+ __m256h i7 ATTRIBUTE_UNUSED,
+ __m256h i8 ATTRIBUTE_UNUSED,
+ __m256h i9 ATTRIBUTE_UNUSED,
+ __m256h i10 ATTRIBUTE_UNUSED,
+ __m256h i11 ATTRIBUTE_UNUSED,
+ __m256h i12 ATTRIBUTE_UNUSED,
+ __m256h i13 ATTRIBUTE_UNUSED,
+ __m256h i14 ATTRIBUTE_UNUSED,
+ __m256h i15 ATTRIBUTE_UNUSED,
+ __m256h i16 ATTRIBUTE_UNUSED,
+ __m256h i17 ATTRIBUTE_UNUSED,
+ __m256h i18 ATTRIBUTE_UNUSED,
+ __m256h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m256h);
+ compare (values.i1, i1, __m256h);
+ compare (values.i2, i2, __m256h);
+ compare (values.i3, i3, __m256h);
+ compare (values.i4, i4, __m256h);
+ compare (values.i5, i5, __m256h);
+ compare (values.i6, i6, __m256h);
+ compare (values.i7, i7, __m256h);
+ compare (values.i8, i8, __m256h);
+ compare (values.i9, i9, __m256h);
+ compare (values.i10, i10, __m256h);
+ compare (values.i11, i11, __m256h);
+ compare (values.i12, i12, __m256h);
+ compare (values.i13, i13, __m256h);
+ compare (values.i14, i14, __m256h);
+ compare (values.i15, i15, __m256h);
+ compare (values.i16, i16, __m256h);
+ compare (values.i17, i17, __m256h);
+ compare (values.i18, i18, __m256h);
+ compare (values.i19, i19, __m256h);
+}
+
+void
+fun_check_passing_m256_20_regs (__m256 i0 ATTRIBUTE_UNUSED,
+ __m256 i1 ATTRIBUTE_UNUSED,
+ __m256 i2 ATTRIBUTE_UNUSED,
+ __m256 i3 ATTRIBUTE_UNUSED,
+ __m256 i4 ATTRIBUTE_UNUSED,
+ __m256 i5 ATTRIBUTE_UNUSED,
+ __m256 i6 ATTRIBUTE_UNUSED,
+ __m256 i7 ATTRIBUTE_UNUSED,
+ __m256 i8 ATTRIBUTE_UNUSED,
+ __m256 i9 ATTRIBUTE_UNUSED,
+ __m256 i10 ATTRIBUTE_UNUSED,
+ __m256 i11 ATTRIBUTE_UNUSED,
+ __m256 i12 ATTRIBUTE_UNUSED,
+ __m256 i13 ATTRIBUTE_UNUSED,
+ __m256 i14 ATTRIBUTE_UNUSED,
+ __m256 i15 ATTRIBUTE_UNUSED,
+ __m256 i16 ATTRIBUTE_UNUSED,
+ __m256 i17 ATTRIBUTE_UNUSED,
+ __m256 i18 ATTRIBUTE_UNUSED,
+ __m256 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m256_arguments;
+}
+
+void
+fun_check_passing_m256h_20_regs (__m256h i0 ATTRIBUTE_UNUSED,
+ __m256h i1 ATTRIBUTE_UNUSED,
+ __m256h i2 ATTRIBUTE_UNUSED,
+ __m256h i3 ATTRIBUTE_UNUSED,
+ __m256h i4 ATTRIBUTE_UNUSED,
+ __m256h i5 ATTRIBUTE_UNUSED,
+ __m256h i6 ATTRIBUTE_UNUSED,
+ __m256h i7 ATTRIBUTE_UNUSED,
+ __m256h i8 ATTRIBUTE_UNUSED,
+ __m256h i9 ATTRIBUTE_UNUSED,
+ __m256h i10 ATTRIBUTE_UNUSED,
+ __m256h i11 ATTRIBUTE_UNUSED,
+ __m256h i12 ATTRIBUTE_UNUSED,
+ __m256h i13 ATTRIBUTE_UNUSED,
+ __m256h i14 ATTRIBUTE_UNUSED,
+ __m256h i15 ATTRIBUTE_UNUSED,
+ __m256h i16 ATTRIBUTE_UNUSED,
+ __m256h i17 ATTRIBUTE_UNUSED,
+ __m256h i18 ATTRIBUTE_UNUSED,
+ __m256h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m256_arguments;
+}
+
+#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
+
+#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11, _i12, _i13, _i14, \
+ _i15, _i16, _i17, _i18, _i19, _func1, \
+ _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ values.i10.TYPE[0] = _i10; \
+ values.i11.TYPE[0] = _i11; \
+ values.i12.TYPE[0] = _i12; \
+ values.i13.TYPE[0] = _i13; \
+ values.i14.TYPE[0] = _i14; \
+ values.i15.TYPE[0] = _i15; \
+ values.i16.TYPE[0] = _i16; \
+ values.i17.TYPE[0] = _i17; \
+ values.i18.TYPE[0] = _i18; \
+ values.i19.TYPE[0] = _i19; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11, _i12, _i13, _i14, _i15, \
+ _i16, _i17, _i18, _i19); \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11, _i12, _i13, _i14, _i15, \
+ _i16, _i17, _i18, _i19);
+
+void
+test_m256_on_stack ()
+{
+ __m256 x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m256){32 + i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m256-8";
+ def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m256_8_values,
+ fun_check_passing_m256_8_regs, _m256);
+}
+
+void
+test_m256h_on_stack ()
+{
+ __m256h x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m256h){1.1f16 + i, 2.1f16 + i, 3.1f16 + i, 4.1f16 + i,
+ 5.1f16 + i, 6.1f16 + i, 7.1f16 + i, 8.1f16 + i,
+ 9.1f16 + i, 10.1f16 + i, 11.1f16 + i, 12.1f16 + i,
+ 13.1f16 + i, 14.1f16 + i, 15.1f16 + i, 16.1f16 + i};
+ pass = "m256h-8";
+ def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m256h_8_values,
+ fun_check_passing_m256h_8_regs, _m256h);
+}
+
+void
+test_too_many_m256 ()
+{
+ __m256 x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m256){32 + i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m256-20";
+ def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
+ x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
+ x[17], x[18], x[19], fun_check_passing_m256_20_values,
+ fun_check_passing_m256_20_regs, _m256);
+}
+
+void
+test_too_many_m256h ()
+{
+ __m256h x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m256h){1.1f16 + i, 2.1f16 + i, 3.1f16 + i, 4.1f16 + i,
+ 5.1f16 + i, 6.1f16 + i, 7.1f16 + i, 8.1f16 + i,
+ 9.1f16 + i, 10.1f16 + i, 11.1f16 + i, 12.1f16 + i,
+ 13.1f16 + i, 14.1f16 + i, 15.1f16 + i, 16.1f16 + i};
+ pass = "m256h-20";
+ def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
+ x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
+ x[17], x[18], x[19], fun_check_passing_m256h_20_values,
+ fun_check_passing_m256h_20_regs, _m256h);
+}
+
+static void
+do_test (void)
+{
+ test_m256_on_stack ();
+ test_too_many_m256 ();
+ test_m256h_on_stack ();
+ test_too_many_m256h ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c
new file mode 100644
index 0000000..eff10ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_structs.c
@@ -0,0 +1,113 @@
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct m256_struct
+{
+ __m256 x;
+};
+
+struct m256_2_struct
+{
+ __m256 x1, x2;
+};
+
+struct m256h_struct
+{
+ __m256h x;
+};
+
+struct m256h_2_struct
+{
+ __m256h x1, x2;
+};
+
+/* Check that the struct is passed as the individual members in fregs. */
+void
+check_struct_passing1 (struct m256_struct ms1 ATTRIBUTE_UNUSED,
+ struct m256_struct ms2 ATTRIBUTE_UNUSED,
+ struct m256_struct ms3 ATTRIBUTE_UNUSED,
+ struct m256_struct ms4 ATTRIBUTE_UNUSED,
+ struct m256_struct ms5 ATTRIBUTE_UNUSED,
+ struct m256_struct ms6 ATTRIBUTE_UNUSED,
+ struct m256_struct ms7 ATTRIBUTE_UNUSED,
+ struct m256_struct ms8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_struct_passing2 (struct m256_2_struct ms ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ms.x1 == rsp+8);
+ assert ((unsigned long)&ms.x2 == rsp+40);
+}
+
+void
+check_struct_passing1h (struct m256h_struct ms1 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms2 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms3 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms4 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms5 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms6 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms7 ATTRIBUTE_UNUSED,
+ struct m256h_struct ms8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_struct_passing2h (struct m256h_2_struct ms ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ms.x1 == rsp+8);
+ assert ((unsigned long)&ms.x2 == rsp+40);
+}
+
+static void
+do_test (void)
+{
+ struct m256_struct m256s [8];
+ struct m256h_struct m256hs [8];
+ struct m256_2_struct m256_2s = {
+ { 48.394, 39.3, -397.9, 3484.9, -8.394, -93.3, 7.9, 84.94 },
+ { -8.394, -3.3, -39.9, 34.9, 7.9, 84.94, -48.394, 39.3 }
+ };
+ struct m256h_2_struct m256h_2s = {
+ { 47.364f16, 36.3f16, -367.6f16, 3474.6f16, -7.364f16, -63.3f16, 7.6f16, 74.64f16,
+ 57.865f16, 86.8f16, -867.6f16, 8575.6f16, -7.865f16, -68.8f16, 7.6f16, 75.65f16 },
+ { -7.364f16, -3.3f16, -36.6f16, 34.6f16, 7.6f16, 74.64f16, -47.364f16, 36.3f16,
+ -8.364f16, -3.3f16, -36.6f16, 34.6f16, 8.6f16, 84.64f16, -48.364f16, 36.3f16 }
+ };
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ m256s[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+
+ m256hs[i].x = (__m256h){33+i, 0, i, 0, -i, 0, i - 11, i + 9,
+ 31+i, 2, i, 3, -i, 4, i - 10, i + 7};
+ }
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.ymm0)[i]._m256[0] = m256s[i].x;
+ num_fregs = 8;
+ WRAP_CALL (check_struct_passing1)(m256s[0], m256s[1], m256s[2], m256s[3],
+ m256s[4], m256s[5], m256s[6], m256s[7]);
+ WRAP_CALL (check_struct_passing2)(m256_2s);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.ymm0)[i]._m256h[0] = m256hs[i].x;
+ num_fregs = 8;
+ WRAP_CALL (check_struct_passing1h)(m256hs[0], m256hs[1], m256hs[2], m256hs[3],
+ m256hs[4], m256hs[5], m256hs[6], m256hs[7]);
+ WRAP_CALL (check_struct_passing2h)(m256h_2s);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c
new file mode 100644
index 0000000..76f300c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_passing_unions.c
@@ -0,0 +1,337 @@
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+union un1
+{
+ __m256 x;
+ float f;
+};
+
+union un2
+{
+ __m256 x;
+ double d;
+};
+
+union un3
+{
+ __m256 x;
+ __m128 v;
+};
+
+union un4
+{
+ __m256 x;
+ long double ld;
+};
+
+union un5
+{
+ __m256 x;
+ int i;
+};
+
+union un1a
+{
+ __m256 x;
+ _Float16 f;
+};
+
+union un1h
+{
+ __m256h x;
+ float f;
+};
+
+union un1hh
+{
+ __m256h x;
+ _Float16 f;
+};
+
+union un2h
+{
+ __m256h x;
+ double d;
+};
+
+union un3h
+{
+ __m256h x;
+ __m128 v;
+};
+
+union un4h
+{
+ __m256h x;
+ long double ld;
+};
+
+union un5h
+{
+ __m256h x;
+ int i;
+};
+
+void
+check_union_passing1(union un1 u1 ATTRIBUTE_UNUSED,
+ union un1 u2 ATTRIBUTE_UNUSED,
+ union un1 u3 ATTRIBUTE_UNUSED,
+ union un1 u4 ATTRIBUTE_UNUSED,
+ union un1 u5 ATTRIBUTE_UNUSED,
+ union un1 u6 ATTRIBUTE_UNUSED,
+ union un1 u7 ATTRIBUTE_UNUSED,
+ union un1 u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing1a(union un1a u1 ATTRIBUTE_UNUSED,
+ union un1a u2 ATTRIBUTE_UNUSED,
+ union un1a u3 ATTRIBUTE_UNUSED,
+ union un1a u4 ATTRIBUTE_UNUSED,
+ union un1a u5 ATTRIBUTE_UNUSED,
+ union un1a u6 ATTRIBUTE_UNUSED,
+ union un1a u7 ATTRIBUTE_UNUSED,
+ union un1a u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing1h(union un1h u1 ATTRIBUTE_UNUSED,
+ union un1h u2 ATTRIBUTE_UNUSED,
+ union un1h u3 ATTRIBUTE_UNUSED,
+ union un1h u4 ATTRIBUTE_UNUSED,
+ union un1h u5 ATTRIBUTE_UNUSED,
+ union un1h u6 ATTRIBUTE_UNUSED,
+ union un1h u7 ATTRIBUTE_UNUSED,
+ union un1h u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing1hh(union un1hh u1 ATTRIBUTE_UNUSED,
+ union un1hh u2 ATTRIBUTE_UNUSED,
+ union un1hh u3 ATTRIBUTE_UNUSED,
+ union un1hh u4 ATTRIBUTE_UNUSED,
+ union un1hh u5 ATTRIBUTE_UNUSED,
+ union un1hh u6 ATTRIBUTE_UNUSED,
+ union un1hh u7 ATTRIBUTE_UNUSED,
+ union un1hh u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED,
+ union un2 u2 ATTRIBUTE_UNUSED,
+ union un2 u3 ATTRIBUTE_UNUSED,
+ union un2 u4 ATTRIBUTE_UNUSED,
+ union un2 u5 ATTRIBUTE_UNUSED,
+ union un2 u6 ATTRIBUTE_UNUSED,
+ union un2 u7 ATTRIBUTE_UNUSED,
+ union un2 u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing2h(union un2h u1 ATTRIBUTE_UNUSED,
+ union un2h u2 ATTRIBUTE_UNUSED,
+ union un2h u3 ATTRIBUTE_UNUSED,
+ union un2h u4 ATTRIBUTE_UNUSED,
+ union un2h u5 ATTRIBUTE_UNUSED,
+ union un2h u6 ATTRIBUTE_UNUSED,
+ union un2h u7 ATTRIBUTE_UNUSED,
+ union un2h u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing3(union un3 u1 ATTRIBUTE_UNUSED,
+ union un3 u2 ATTRIBUTE_UNUSED,
+ union un3 u3 ATTRIBUTE_UNUSED,
+ union un3 u4 ATTRIBUTE_UNUSED,
+ union un3 u5 ATTRIBUTE_UNUSED,
+ union un3 u6 ATTRIBUTE_UNUSED,
+ union un3 u7 ATTRIBUTE_UNUSED,
+ union un3 u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing3h(union un3h u1 ATTRIBUTE_UNUSED,
+ union un3h u2 ATTRIBUTE_UNUSED,
+ union un3h u3 ATTRIBUTE_UNUSED,
+ union un3h u4 ATTRIBUTE_UNUSED,
+ union un3h u5 ATTRIBUTE_UNUSED,
+ union un3h u6 ATTRIBUTE_UNUSED,
+ union un3h u7 ATTRIBUTE_UNUSED,
+ union un3h u8 ATTRIBUTE_UNUSED)
+{
+ check_m256_arguments;
+}
+
+void
+check_union_passing4(union un4 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.ld == rsp+8);
+}
+
+void
+check_union_passing4h(union un4h u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.ld == rsp+8);
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.i == rsp+8);
+}
+
+void
+check_union_passing5h(union un5h u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.i == rsp+8);
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+
+#define check_union_passing1h WRAP_CALL(check_union_passing1h)
+#define check_union_passing1a WRAP_CALL(check_union_passing1a)
+#define check_union_passing1hh WRAP_CALL(check_union_passing1hh)
+#define check_union_passing2h WRAP_CALL(check_union_passing2h)
+#define check_union_passing3h WRAP_CALL(check_union_passing3h)
+#define check_union_passing4h WRAP_CALL(check_union_passing4h)
+#define check_union_passing5h WRAP_CALL(check_union_passing5h)
+
+static void
+do_test (void)
+{
+ union un1 u1[8];
+ union un2 u2[8];
+ union un3 u3[8];
+ union un4 u4;
+ union un5 u5;
+ union un1a u1a[8];
+ union un1h u1h[8];
+ union un1hh u1hh[8];
+ union un2h u2h[8];
+ union un3h u3h[8];
+ union un4h u4h;
+ union un5h u5h;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ u1[i].x = (__m256){32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+ u1h[i].x = (__m256h){32+i, 0, i, 0, -i, 0, i - 12, i + 8,
+ 33+i, 1, i, 2, -i, 4, i - 11, i + 9};
+ }
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.ymm0)[i]._m256[0] = u1[i].x;
+ num_fregs = 8;
+ check_union_passing1(u1[0], u1[1], u1[2], u1[3],
+ u1[4], u1[5], u1[6], u1[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u1a[i].x = u1[i].x;
+ (&fregs.ymm0)[i]._m256[0] = u1a[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing1a(u1a[0], u1a[1], u1a[2], u1a[3],
+ u1a[4], u1a[5], u1a[6], u1a[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.ymm0)[i]._m256h[0] = u1h[i].x;
+ num_fregs = 8;
+ check_union_passing1h(u1h[0], u1h[1], u1h[2], u1h[3],
+ u1h[4], u1h[5], u1h[6], u1h[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u1hh[i].x = u1h[i].x;
+ (&fregs.ymm0)[i]._m256h[0] = u1hh[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing1hh(u1hh[0], u1hh[1], u1hh[2], u1hh[3],
+ u1hh[4], u1hh[5], u1hh[6], u1hh[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u2[i].x = u1[i].x;
+ (&fregs.ymm0)[i]._m256[0] = u2[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing2(u2[0], u2[1], u2[2], u2[3],
+ u2[4], u2[5], u2[6], u2[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u2h[i].x = u1h[i].x;
+ (&fregs.ymm0)[i]._m256h[0] = u2h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing2h(u2h[0], u2h[1], u2h[2], u2h[3],
+ u2h[4], u2h[5], u2h[6], u2h[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u3[i].x = u1[i].x;
+ (&fregs.ymm0)[i]._m256[0] = u3[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing3(u3[0], u3[1], u3[2], u3[3],
+ u3[4], u3[5], u3[6], u3[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u3h[i].x = u1h[i].x;
+ (&fregs.ymm0)[i]._m256h[0] = u3h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing3h(u3h[0], u3h[1], u3h[2], u3h[3],
+ u3h[4], u3h[5], u3h[6], u3h[7]);
+
+ check_union_passing4(u4);
+ check_union_passing5(u5);
+
+ check_union_passing4h(u4h);
+ check_union_passing5h(u5h);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c
new file mode 100644
index 0000000..f15adb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m256h/test_varargs-m256.c
@@ -0,0 +1,160 @@
+/* Test variable number of 256-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "avx512fp16-ymm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m256_varargs (__m256 i0, __m256 i1, __m256 i2,
+ __m256 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m256 *argp;
+
+ compare (values.i0, i0, __m256);
+ compare (values.i1, i1, __m256);
+ compare (values.i2, i2, __m256);
+ compare (values.i3, i3, __m256);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m256 *)(((char *) fp) + 8);
+
+ /* Check __m256 arguments passed on stack. */
+ compare (values.i4, argp[0], __m256);
+ compare (values.i5, argp[1], __m256);
+ compare (values.i6, argp[2], __m256);
+ compare (values.i7, argp[3], __m256);
+ compare (values.i8, argp[4], __m256);
+ compare (values.i9, argp[5], __m256);
+
+ /* Check register contents. */
+ compare (fregs.ymm0, ymm_regs[0], __m256);
+ compare (fregs.ymm1, ymm_regs[1], __m256);
+ compare (fregs.ymm2, ymm_regs[2], __m256);
+ compare (fregs.ymm3, ymm_regs[3], __m256);
+}
+
+void
+fun_check_passing_m256h_varargs (__m256h i0, __m256h i1, __m256h i2,
+ __m256h i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m256h *argp;
+
+ compare (values.i0, i0, __m256h);
+ compare (values.i1, i1, __m256h);
+ compare (values.i2, i2, __m256h);
+ compare (values.i3, i3, __m256h);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m256h *)(((char *) fp) + 8);
+
+ /* Check __m256h arguments passed on stack. */
+ compare (values.i4, argp[0], __m256h);
+ compare (values.i5, argp[1], __m256h);
+ compare (values.i6, argp[2], __m256h);
+ compare (values.i7, argp[3], __m256h);
+ compare (values.i8, argp[4], __m256h);
+ compare (values.i9, argp[5], __m256h);
+
+ /* Check register contents. */
+ compare (fregs.ymm0, ymm_regs[0], __m256h);
+ compare (fregs.ymm1, ymm_regs[1], __m256h);
+ compare (fregs.ymm2, ymm_regs[2], __m256h);
+ compare (fregs.ymm3, ymm_regs[3], __m256h);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m256_varargs (void)
+{
+ __m256 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m256-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m256_varargs,
+ _m256);
+}
+
+void
+test_m256h_varargs (void)
+{
+ __m256h x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m256h) {
+ 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+ 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i,
+ 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i,
+ 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i
+ };
+ pass = "m256h-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m256h_varargs,
+ _m256h);
+}
+
+void
+do_test (void)
+{
+ test_m256_varargs ();
+ test_m256h_varargs ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp
new file mode 100644
index 0000000..33d2476
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/abi-avx512fp16-zmm.exp
@@ -0,0 +1,48 @@
+# Copyright (C) 2019 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/>.
+
+# The x86-64 ABI testsuite needs one additional assembler file for most
+# testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+load_lib clearcap.exp
+load_lib file-format.exp
+
+if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
+ || [is-effective-target ia32]
+ || [gcc_target_object_format] != "elf"
+ || ![is-effective-target avx512fp16] } then {
+ return
+}
+
+
+torture-init
+clearcap-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-W -Wall -Wno-abi -mavx512fp16"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+clearcap-finish
+torture-finish
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h
new file mode 100644
index 0000000..d59c337
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/args.h
@@ -0,0 +1,186 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+#include <immintrin.h>
+#include <string.h>
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 rdi
+#define I1 rsi
+#define I2 rdx
+#define I3 rcx
+#define I4 r8
+#define I5 r9
+#define F0 zmm0
+#define F1 zmm1
+#define F2 zmm2
+#define F3 zmm3
+#define F4 zmm4
+#define F5 zmm5
+#define F6 zmm6
+#define F7 zmm7
+
+typedef union {
+ _Float16 __Float16[32];
+ float _float[16];
+ double _double[8];
+ long long _longlong[8];
+ int _int[16];
+ unsigned long long _ulonglong[8];
+ __m64 _m64[8];
+ __m128 _m128[4];
+ __m256 _m256[2];
+ __m512 _m512[1];
+ __m512h _m512h[1];
+} ZMM_T;
+
+typedef union {
+ float _float;
+ double _double;
+ long double _ldouble;
+ unsigned long long _ulonglong[2];
+} X87_T;
+extern void (*callthis)(void);
+extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
+ZMM_T zmm_regs[32];
+X87_T x87_regs[8];
+extern volatile unsigned long long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%rax, %%rax\n\t" \
+ "xor %%rbx, %%rbx\n\t" \
+ "xor %%rcx, %%rcx\n\t" \
+ "xor %%rdx, %%rdx\n\t" \
+ "xor %%rsi, %%rsi\n\t" \
+ "xor %%rdi, %%rdi\n\t" \
+ "xor %%r8, %%r8\n\t" \
+ "xor %%r9, %%r9\n\t" \
+ "xor %%r10, %%r10\n\t" \
+ "xor %%r11, %%r11\n\t" \
+ "xor %%r12, %%r12\n\t" \
+ "xor %%r13, %%r13\n\t" \
+ "xor %%r14, %%r14\n\t" \
+ "xor %%r15, %%r15\n\t" \
+ ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+};
+struct FloatRegisters
+{
+ double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
+ long double st0, st1, st2, st3, st4, st5, st6, st7;
+ ZMM_T zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7, zmm8, zmm9,
+ zmm10, zmm11, zmm12, zmm13, zmm14, zmm15, zmm16, zmm17, zmm18,
+ zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27,
+ zmm28, zmm29, zmm30, zmm31;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs;
+extern struct FloatRegisters fregs;
+extern unsigned int num_iregs, num_fregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || iregs.I0 == I0); \
+ assert (num_iregs <= 1 || iregs.I1 == I1); \
+ assert (num_iregs <= 2 || iregs.I2 == I2); \
+ assert (num_iregs <= 3 || iregs.I3 == I3); \
+ assert (num_iregs <= 4 || iregs.I4 == I4); \
+ assert (num_iregs <= 5 || iregs.I5 == I5); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
+ = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
+ memset (&iregs, 0, sizeof (iregs)); \
+ memset (&fregs, 0, sizeof (fregs)); \
+ memset (zmm_regs, 0, sizeof (zmm_regs)); \
+ memset (x87_regs, 0, sizeof (x87_regs));
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* TODO: Do the checking. */
+#define check_f_arguments(T) do { \
+ assert (num_fregs <= 0 || fregs.zmm0._ ## T [0] == zmm_regs[0]._ ## T [0]); \
+ assert (num_fregs <= 1 || fregs.zmm1._ ## T [0] == zmm_regs[1]._ ## T [0]); \
+ assert (num_fregs <= 2 || fregs.zmm2._ ## T [0] == zmm_regs[2]._ ## T [0]); \
+ assert (num_fregs <= 3 || fregs.zmm3._ ## T [0] == zmm_regs[3]._ ## T [0]); \
+ assert (num_fregs <= 4 || fregs.zmm4._ ## T [0] == zmm_regs[4]._ ## T [0]); \
+ assert (num_fregs <= 5 || fregs.zmm5._ ## T [0] == zmm_regs[5]._ ## T [0]); \
+ assert (num_fregs <= 6 || fregs.zmm6._ ## T [0] == zmm_regs[6]._ ## T [0]); \
+ assert (num_fregs <= 7 || fregs.zmm7._ ## T [0] == zmm_regs[7]._ ## T [0]); \
+ } while (0)
+
+#define check_float_arguments check_f_arguments(float)
+#define check_double_arguments check_f_arguments(double)
+
+#define check_vector_arguments(T,O) do { \
+ assert (num_fregs <= 0 \
+ || memcmp (((char *) &fregs.zmm0) + (O), \
+ &zmm_regs[0], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 1 \
+ || memcmp (((char *) &fregs.zmm1) + (O), \
+ &zmm_regs[1], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 2 \
+ || memcmp (((char *) &fregs.zmm2) + (O), \
+ &zmm_regs[2], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 3 \
+ || memcmp (((char *) &fregs.zmm3) + (O), \
+ &zmm_regs[3], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 4 \
+ || memcmp (((char *) &fregs.zmm4) + (O), \
+ &zmm_regs[4], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 5 \
+ || memcmp (((char *) &fregs.zmm5) + (O), \
+ &zmm_regs[5], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 6 \
+ || memcmp (((char *) &fregs.zmm6) + (O), \
+ &zmm_regs[6], \
+ sizeof (__ ## T) - (O)) == 0); \
+ assert (num_fregs <= 7 \
+ || memcmp (((char *) &fregs.zmm7) + (O), \
+ &zmm_regs[7], \
+ sizeof (__ ## T) - (O)) == 0); \
+ } while (0)
+
+#define check_m64_arguments check_vector_arguments(m64, 0)
+#define check_m128_arguments check_vector_arguments(m128, 0)
+#define check_m256_arguments check_vector_arguments(m256, 0)
+#define check_m512_arguments check_vector_arguments(m512, 0)
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S
new file mode 100644
index 0000000..0ef8287
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/asm-support.S
@@ -0,0 +1,97 @@
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+.LFB3:
+ movq %rax, rax(%rip)
+ movq %rbx, rbx(%rip)
+ movq %rcx, rcx(%rip)
+ movq %rdx, rdx(%rip)
+ movq %rdi, rdi(%rip)
+ movq %rsi, rsi(%rip)
+ movq %rbp, rbp(%rip)
+ movq %rsp, rsp(%rip)
+ movq %r8, r8(%rip)
+ movq %r9, r9(%rip)
+ movq %r10, r10(%rip)
+ movq %r11, r11(%rip)
+ movq %r12, r12(%rip)
+ movq %r13, r13(%rip)
+ movq %r14, r14(%rip)
+ movq %r15, r15(%rip)
+ vmovdqu32 %zmm0, zmm_regs+0(%rip)
+ vmovdqu32 %zmm1, zmm_regs+64(%rip)
+ vmovdqu32 %zmm2, zmm_regs+128(%rip)
+ vmovdqu32 %zmm3, zmm_regs+192(%rip)
+ vmovdqu32 %zmm4, zmm_regs+256(%rip)
+ vmovdqu32 %zmm5, zmm_regs+320(%rip)
+ vmovdqu32 %zmm6, zmm_regs+384(%rip)
+ vmovdqu32 %zmm7, zmm_regs+448(%rip)
+ vmovdqu32 %zmm8, zmm_regs+512(%rip)
+ vmovdqu32 %zmm9, zmm_regs+576(%rip)
+ vmovdqu32 %zmm10, zmm_regs+640(%rip)
+ vmovdqu32 %zmm11, zmm_regs+704(%rip)
+ vmovdqu32 %zmm12, zmm_regs+768(%rip)
+ vmovdqu32 %zmm13, zmm_regs+832(%rip)
+ vmovdqu32 %zmm14, zmm_regs+896(%rip)
+ vmovdqu32 %zmm15, zmm_regs+960(%rip)
+ vmovdqu32 %zmm16, zmm_regs+1024(%rip)
+ vmovdqu32 %zmm17, zmm_regs+1088(%rip)
+ vmovdqu32 %zmm18, zmm_regs+1152(%rip)
+ vmovdqu32 %zmm19, zmm_regs+1216(%rip)
+ vmovdqu32 %zmm20, zmm_regs+1280(%rip)
+ vmovdqu32 %zmm21, zmm_regs+1344(%rip)
+ vmovdqu32 %zmm22, zmm_regs+1408(%rip)
+ vmovdqu32 %zmm23, zmm_regs+1472(%rip)
+ vmovdqu32 %zmm24, zmm_regs+1536(%rip)
+ vmovdqu32 %zmm25, zmm_regs+1600(%rip)
+ vmovdqu32 %zmm26, zmm_regs+1664(%rip)
+ vmovdqu32 %zmm27, zmm_regs+1728(%rip)
+ vmovdqu32 %zmm28, zmm_regs+1792(%rip)
+ vmovdqu32 %zmm29, zmm_regs+1856(%rip)
+ vmovdqu32 %zmm30, zmm_regs+1920(%rip)
+ vmovdqu32 %zmm31, zmm_regs+1984(%rip)
+ jmp *callthis(%rip)
+.LFE3:
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movq %rdi, rdi(%rip)
+ subq $8, %rsp
+ call *callthis(%rip)
+ addq $8, %rsp
+ movq %rax, rax(%rip)
+ movq %rdx, rdx(%rip)
+ vmovdqu32 %zmm0, zmm_regs+0(%rip)
+ vmovdqu32 %zmm1, zmm_regs+64(%rip)
+ fstpt x87_regs(%rip)
+ fstpt x87_regs+16(%rip)
+ fldt x87_regs+16(%rip)
+ fldt x87_regs(%rip)
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .comm callthis,8,8
+ .comm rax,8,8
+ .comm rbx,8,8
+ .comm rcx,8,8
+ .comm rdx,8,8
+ .comm rsi,8,8
+ .comm rdi,8,8
+ .comm rsp,8,8
+ .comm rbp,8,8
+ .comm r8,8,8
+ .comm r9,8,8
+ .comm r10,8,8
+ .comm r11,8,8
+ .comm r12,8,8
+ .comm r13,8,8
+ .comm r14,8,8
+ .comm r15,8,8
+ .comm zmm_regs,2048,64
+ .comm x87_regs,128,32
+ .comm volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h
new file mode 100644
index 0000000..4b882cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/avx512fp16-zmm-check.h
@@ -0,0 +1,4 @@
+#define AVX512VL(ebx) 1
+#define XSTATE_MASK (XSTATE_SSE | XSTATE_YMM | XSTATE_ZMM \
+ | XSTATE_HI_ZMM | XSTATE_OPMASK)
+#include "../avx512fp16-check.h"
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c
new file mode 100644
index 0000000..5cb5943
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_m512_returning.c
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include "avx512fp16-zmm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+__m512
+fun_test_returning___m512 (void)
+{
+ volatile_var++;
+ return (__m512){73,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+}
+
+__m512h
+fun_test_returning___m512h (void)
+{
+ volatile_var++;
+ return (__m512h){ 1.1f16, 2.2f16, 3.3f16, 4.4f16,
+ 5.5f16, 6.6f16, 7.7f16, 8.8f16,
+ 9.9f16, 10.10f16, 11.11f16, 12.12f16,
+ 13.13f16, 14.14f16, 15.15f16, 16.16f16,
+ 17.17f16, 18.18f16, 19.19f16, 20.20f16,
+ 21.21f16, 22.22f16, 23.23f16, 24.24f16,
+ 25.25f16, 26.26f16, 27.27f16, 28.28f16,
+ 29.29f16, 30.30f16, 31.31f16, 32.32f16};
+}
+
+__m512 test_512;
+__m512h test_512h;
+
+static void
+do_test (void)
+{
+ unsigned failed = 0;
+ ZMM_T zmmt1, zmmt2;
+
+ clear_struct_registers;
+ test_512 = (__m512){73,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ zmmt1._m512[0] = test_512;
+ zmmt2._m512[0] = WRAP_RET (fun_test_returning___m512)();
+ if (memcmp (&zmmt1, &zmmt2, sizeof (zmmt2)) != 0)
+ printf ("fail m512\n"), failed++;
+
+ clear_struct_registers;
+ test_512h = (__m512h){ 1.1f16, 2.2f16, 3.3f16, 4.4f16,
+ 5.5f16, 6.6f16, 7.7f16, 8.8f16,
+ 9.9f16, 10.10f16, 11.11f16, 12.12f16,
+ 13.13f16, 14.14f16, 15.15f16, 16.16f16,
+ 17.17f16, 18.18f16, 19.19f16, 20.20f16,
+ 21.21f16, 22.22f16, 23.23f16, 24.24f16,
+ 25.25f16, 26.26f16, 27.27f16, 28.28f16,
+ 29.29f16, 30.30f16, 31.31f16, 32.32f16};
+ zmmt1._m512h[0] = test_512h;
+ zmmt2._m512h[0] = WRAP_RET (fun_test_returning___m512h)();
+ if (memcmp (&zmmt1, &zmmt2, sizeof (zmmt2)) != 0)
+ printf ("fail m512h\n"), failed++;
+
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c
new file mode 100644
index 0000000..ad5ba2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_m512.c
@@ -0,0 +1,380 @@
+#include <stdio.h>
+#include "avx512fp16-zmm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
+ i16, i17, i18, i19, i20, i21, i22, i23;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+fun_check_passing_m512_8_values (__m512 i0 ATTRIBUTE_UNUSED,
+ __m512 i1 ATTRIBUTE_UNUSED,
+ __m512 i2 ATTRIBUTE_UNUSED,
+ __m512 i3 ATTRIBUTE_UNUSED,
+ __m512 i4 ATTRIBUTE_UNUSED,
+ __m512 i5 ATTRIBUTE_UNUSED,
+ __m512 i6 ATTRIBUTE_UNUSED,
+ __m512 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m512);
+ compare (values.i1, i1, __m512);
+ compare (values.i2, i2, __m512);
+ compare (values.i3, i3, __m512);
+ compare (values.i4, i4, __m512);
+ compare (values.i5, i5, __m512);
+ compare (values.i6, i6, __m512);
+ compare (values.i7, i7, __m512);
+}
+
+fun_check_passing_m512h_8_values (__m512h i0 ATTRIBUTE_UNUSED,
+ __m512h i1 ATTRIBUTE_UNUSED,
+ __m512h i2 ATTRIBUTE_UNUSED,
+ __m512h i3 ATTRIBUTE_UNUSED,
+ __m512h i4 ATTRIBUTE_UNUSED,
+ __m512h i5 ATTRIBUTE_UNUSED,
+ __m512h i6 ATTRIBUTE_UNUSED,
+ __m512h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m512h);
+ compare (values.i1, i1, __m512h);
+ compare (values.i2, i2, __m512h);
+ compare (values.i3, i3, __m512h);
+ compare (values.i4, i4, __m512h);
+ compare (values.i5, i5, __m512h);
+ compare (values.i6, i6, __m512h);
+ compare (values.i7, i7, __m512h);
+}
+
+void
+fun_check_passing_m512_8_regs (__m512 i0 ATTRIBUTE_UNUSED,
+ __m512 i1 ATTRIBUTE_UNUSED,
+ __m512 i2 ATTRIBUTE_UNUSED,
+ __m512 i3 ATTRIBUTE_UNUSED,
+ __m512 i4 ATTRIBUTE_UNUSED,
+ __m512 i5 ATTRIBUTE_UNUSED,
+ __m512 i6 ATTRIBUTE_UNUSED,
+ __m512 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+fun_check_passing_m512h_8_regs (__m512h i0 ATTRIBUTE_UNUSED,
+ __m512h i1 ATTRIBUTE_UNUSED,
+ __m512h i2 ATTRIBUTE_UNUSED,
+ __m512h i3 ATTRIBUTE_UNUSED,
+ __m512h i4 ATTRIBUTE_UNUSED,
+ __m512h i5 ATTRIBUTE_UNUSED,
+ __m512h i6 ATTRIBUTE_UNUSED,
+ __m512h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+fun_check_passing_m512_20_values (__m512 i0 ATTRIBUTE_UNUSED,
+ __m512 i1 ATTRIBUTE_UNUSED,
+ __m512 i2 ATTRIBUTE_UNUSED,
+ __m512 i3 ATTRIBUTE_UNUSED,
+ __m512 i4 ATTRIBUTE_UNUSED,
+ __m512 i5 ATTRIBUTE_UNUSED,
+ __m512 i6 ATTRIBUTE_UNUSED,
+ __m512 i7 ATTRIBUTE_UNUSED,
+ __m512 i8 ATTRIBUTE_UNUSED,
+ __m512 i9 ATTRIBUTE_UNUSED,
+ __m512 i10 ATTRIBUTE_UNUSED,
+ __m512 i11 ATTRIBUTE_UNUSED,
+ __m512 i12 ATTRIBUTE_UNUSED,
+ __m512 i13 ATTRIBUTE_UNUSED,
+ __m512 i14 ATTRIBUTE_UNUSED,
+ __m512 i15 ATTRIBUTE_UNUSED,
+ __m512 i16 ATTRIBUTE_UNUSED,
+ __m512 i17 ATTRIBUTE_UNUSED,
+ __m512 i18 ATTRIBUTE_UNUSED,
+ __m512 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m512);
+ compare (values.i1, i1, __m512);
+ compare (values.i2, i2, __m512);
+ compare (values.i3, i3, __m512);
+ compare (values.i4, i4, __m512);
+ compare (values.i5, i5, __m512);
+ compare (values.i6, i6, __m512);
+ compare (values.i7, i7, __m512);
+ compare (values.i8, i8, __m512);
+ compare (values.i9, i9, __m512);
+ compare (values.i10, i10, __m512);
+ compare (values.i11, i11, __m512);
+ compare (values.i12, i12, __m512);
+ compare (values.i13, i13, __m512);
+ compare (values.i14, i14, __m512);
+ compare (values.i15, i15, __m512);
+ compare (values.i16, i16, __m512);
+ compare (values.i17, i17, __m512);
+ compare (values.i18, i18, __m512);
+ compare (values.i19, i19, __m512);
+}
+
+void
+fun_check_passing_m512h_20_values (__m512h i0 ATTRIBUTE_UNUSED,
+ __m512h i1 ATTRIBUTE_UNUSED,
+ __m512h i2 ATTRIBUTE_UNUSED,
+ __m512h i3 ATTRIBUTE_UNUSED,
+ __m512h i4 ATTRIBUTE_UNUSED,
+ __m512h i5 ATTRIBUTE_UNUSED,
+ __m512h i6 ATTRIBUTE_UNUSED,
+ __m512h i7 ATTRIBUTE_UNUSED,
+ __m512h i8 ATTRIBUTE_UNUSED,
+ __m512h i9 ATTRIBUTE_UNUSED,
+ __m512h i10 ATTRIBUTE_UNUSED,
+ __m512h i11 ATTRIBUTE_UNUSED,
+ __m512h i12 ATTRIBUTE_UNUSED,
+ __m512h i13 ATTRIBUTE_UNUSED,
+ __m512h i14 ATTRIBUTE_UNUSED,
+ __m512h i15 ATTRIBUTE_UNUSED,
+ __m512h i16 ATTRIBUTE_UNUSED,
+ __m512h i17 ATTRIBUTE_UNUSED,
+ __m512h i18 ATTRIBUTE_UNUSED,
+ __m512h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m512h);
+ compare (values.i1, i1, __m512h);
+ compare (values.i2, i2, __m512h);
+ compare (values.i3, i3, __m512h);
+ compare (values.i4, i4, __m512h);
+ compare (values.i5, i5, __m512h);
+ compare (values.i6, i6, __m512h);
+ compare (values.i7, i7, __m512h);
+ compare (values.i8, i8, __m512h);
+ compare (values.i9, i9, __m512h);
+ compare (values.i10, i10, __m512h);
+ compare (values.i11, i11, __m512h);
+ compare (values.i12, i12, __m512h);
+ compare (values.i13, i13, __m512h);
+ compare (values.i14, i14, __m512h);
+ compare (values.i15, i15, __m512h);
+ compare (values.i16, i16, __m512h);
+ compare (values.i17, i17, __m512h);
+ compare (values.i18, i18, __m512h);
+ compare (values.i19, i19, __m512h);
+}
+
+void
+fun_check_passing_m512_20_regs (__m512 i0 ATTRIBUTE_UNUSED,
+ __m512 i1 ATTRIBUTE_UNUSED,
+ __m512 i2 ATTRIBUTE_UNUSED,
+ __m512 i3 ATTRIBUTE_UNUSED,
+ __m512 i4 ATTRIBUTE_UNUSED,
+ __m512 i5 ATTRIBUTE_UNUSED,
+ __m512 i6 ATTRIBUTE_UNUSED,
+ __m512 i7 ATTRIBUTE_UNUSED,
+ __m512 i8 ATTRIBUTE_UNUSED,
+ __m512 i9 ATTRIBUTE_UNUSED,
+ __m512 i10 ATTRIBUTE_UNUSED,
+ __m512 i11 ATTRIBUTE_UNUSED,
+ __m512 i12 ATTRIBUTE_UNUSED,
+ __m512 i13 ATTRIBUTE_UNUSED,
+ __m512 i14 ATTRIBUTE_UNUSED,
+ __m512 i15 ATTRIBUTE_UNUSED,
+ __m512 i16 ATTRIBUTE_UNUSED,
+ __m512 i17 ATTRIBUTE_UNUSED,
+ __m512 i18 ATTRIBUTE_UNUSED,
+ __m512 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+fun_check_passing_m512h_20_regs (__m512h i0 ATTRIBUTE_UNUSED,
+ __m512h i1 ATTRIBUTE_UNUSED,
+ __m512h i2 ATTRIBUTE_UNUSED,
+ __m512h i3 ATTRIBUTE_UNUSED,
+ __m512h i4 ATTRIBUTE_UNUSED,
+ __m512h i5 ATTRIBUTE_UNUSED,
+ __m512h i6 ATTRIBUTE_UNUSED,
+ __m512h i7 ATTRIBUTE_UNUSED,
+ __m512h i8 ATTRIBUTE_UNUSED,
+ __m512h i9 ATTRIBUTE_UNUSED,
+ __m512h i10 ATTRIBUTE_UNUSED,
+ __m512h i11 ATTRIBUTE_UNUSED,
+ __m512h i12 ATTRIBUTE_UNUSED,
+ __m512h i13 ATTRIBUTE_UNUSED,
+ __m512h i14 ATTRIBUTE_UNUSED,
+ __m512h i15 ATTRIBUTE_UNUSED,
+ __m512h i16 ATTRIBUTE_UNUSED,
+ __m512h i17 ATTRIBUTE_UNUSED,
+ __m512h i18 ATTRIBUTE_UNUSED,
+ __m512h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
+ \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
+
+#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
+ _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
+ _i18, _i19, _func1, _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ values.i10.TYPE[0] = _i10; \
+ values.i11.TYPE[0] = _i11; \
+ values.i12.TYPE[0] = _i12; \
+ values.i13.TYPE[0] = _i13; \
+ values.i14.TYPE[0] = _i14; \
+ values.i15.TYPE[0] = _i15; \
+ values.i16.TYPE[0] = _i16; \
+ values.i17.TYPE[0] = _i17; \
+ values.i18.TYPE[0] = _i18; \
+ values.i19.TYPE[0] = _i19; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
+ _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
+ _i18, _i19); \
+ \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
+ _i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
+ _i18, _i19);
+
+void
+test_m512_on_stack ()
+{
+ __m512 x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m512){32 + i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m512-8";
+ def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m512_8_values,
+ fun_check_passing_m512_8_regs, _m512);
+}
+
+void
+test_m512h_on_stack ()
+{
+ __m512h x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m512h){1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+ 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i,
+ 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i,
+ 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i,
+ 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i,
+ 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i,
+ 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i,
+ 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i};
+
+ pass = "m512h-8";
+ def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m512h_8_values,
+ fun_check_passing_m512h_8_regs, _m512h);
+}
+
+void
+test_too_many_m512 ()
+{
+ __m512 x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m512){32 + i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m512-20";
+ def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
+ x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
+ x[17], x[18], x[19], fun_check_passing_m512_20_values,
+ fun_check_passing_m512_20_regs, _m512);
+}
+
+void
+test_too_many_m512h ()
+{
+ __m512h x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m512h){ 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+ 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i,
+ 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i,
+ 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i,
+ 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i,
+ 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i,
+ 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i,
+ 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i};
+ pass = "m512h-20";
+ def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
+ x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
+ x[17], x[18], x[19], fun_check_passing_m512h_20_values,
+ fun_check_passing_m512h_20_regs, _m512h);
+}
+
+static void
+do_test (void)
+{
+ test_m512_on_stack ();
+ test_too_many_m512 ();
+ test_m512h_on_stack ();
+ test_too_many_m512h ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c
new file mode 100644
index 0000000..734e0f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_structs.c
@@ -0,0 +1,123 @@
+#include "avx512fp16-zmm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct m512_struct
+{
+ __m512 x;
+};
+
+struct m512h_struct
+{
+ __m512h x;
+};
+
+struct m512_2_struct
+{
+ __m512 x1, x2;
+};
+
+struct m512h_2_struct
+{
+ __m512h x1, x2;
+};
+
+/* Check that the struct is passed as the individual members in fregs. */
+void
+check_struct_passing1 (struct m512_struct ms1 ATTRIBUTE_UNUSED,
+ struct m512_struct ms2 ATTRIBUTE_UNUSED,
+ struct m512_struct ms3 ATTRIBUTE_UNUSED,
+ struct m512_struct ms4 ATTRIBUTE_UNUSED,
+ struct m512_struct ms5 ATTRIBUTE_UNUSED,
+ struct m512_struct ms6 ATTRIBUTE_UNUSED,
+ struct m512_struct ms7 ATTRIBUTE_UNUSED,
+ struct m512_struct ms8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_struct_passing1h (struct m512h_struct ms1 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms2 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms3 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms4 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms5 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms6 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms7 ATTRIBUTE_UNUSED,
+ struct m512h_struct ms8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_struct_passing2 (struct m512_2_struct ms ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ms.x1 == rsp+8);
+ assert ((unsigned long)&ms.x2 == rsp+72);
+}
+
+void
+check_struct_passing2h (struct m512h_2_struct ms ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ms.x1 == rsp+8);
+ assert ((unsigned long)&ms.x2 == rsp+72);
+}
+
+static void
+do_test (void)
+{
+ struct m512_struct m512s [8];
+ struct m512h_struct m512hs [8];
+ struct m512_2_struct m512_2s = {
+ { 48.394, 39.3, -397.9, 3484.9, -8.394, -93.3, 7.9, 84.94,
+ 48.3941, 39.31, -397.91, 3484.91, -8.3941, -93.31, 7.91, 84.941 },
+ { -8.394, -3.3, -39.9, 34.9, 7.9, 84.94, -48.394, 39.3,
+ -8.3942, -3.32, -39.92, 34.92, 7.92, 84.942, -48.3942, 39.32 }
+ };
+ struct m512h_2_struct m512h_2s = {
+ { 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16,
+ 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16,
+ 58.395f16, 39.3f16, -397.9f16, 3585.9f16, -8.395f16, -93.3f16, 7.9f16, 85.95f16,
+ 58.3951f16, 39.31f16, -397.91f16, 3585.91f16, -8.3951f16, -93.31f16, 7.91f16, 85.951f16},
+ { 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16,
+ 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16,
+ 67.396f16, 39.3f16, -397.9f16, 3676.9f16, -7.396f16, -93.3f16, 7.9f16, 76.96f16,
+ 67.3961f16, 39.31f16, -397.91f16, 3676.91f16, -7.3961f16, -93.31f16, 7.91f16, 76.961f16},
+ };
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ m512s[i].x = (__m512){32+i, 0, i, 0, -i, 0, i - 12, i + 8,
+ 32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+ m512hs[i].x = (__m512h){33+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 34+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 35+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 36+i, 1, i, 2, -i, 0, i - 15, i + 9};
+ }
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.zmm0)[i]._m512[0] = m512s[i].x;
+ num_fregs = 8;
+ WRAP_CALL (check_struct_passing1)(m512s[0], m512s[1], m512s[2], m512s[3],
+ m512s[4], m512s[5], m512s[6], m512s[7]);
+ WRAP_CALL (check_struct_passing2)(m512_2s);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.zmm0)[i]._m512h[0] = m512hs[i].x;
+ num_fregs = 8;
+ WRAP_CALL (check_struct_passing1h)(m512hs[0], m512hs[1], m512hs[2], m512hs[3],
+ m512hs[4], m512hs[5], m512hs[6], m512hs[7]);
+ WRAP_CALL (check_struct_passing2h)(m512h_2s);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c
new file mode 100644
index 0000000..fa801fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_passing_unions.c
@@ -0,0 +1,415 @@
+#include "avx512fp16-zmm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+union un1
+{
+ __m512 x;
+ float f;
+};
+
+union un2
+{
+ __m512 x;
+ double d;
+};
+
+union un3
+{
+ __m512 x;
+ __m128 v;
+};
+
+union un4
+{
+ __m512 x;
+ long double ld;
+};
+
+union un5
+{
+ __m512 x;
+ int i;
+};
+
+union un6
+{
+ __m512 x;
+ __m256 v;
+};
+
+union un1h
+{
+ __m512 x;
+ _Float16 f;
+};
+
+union un1hf
+{
+ __m512h x;
+ float f;
+};
+
+union un1hh
+{
+ __m512h x;
+ _Float16 f;
+};
+
+union un2h
+{
+ __m512h x;
+ double d;
+};
+
+union un3h
+{
+ __m512h x;
+ __m128 v;
+};
+
+union un4h
+{
+ __m512h x;
+ long double ld;
+};
+
+union un5h
+{
+ __m512h x;
+ int i;
+};
+
+union un6h
+{
+ __m512h x;
+ __m256 v;
+};
+
+void
+check_union_passing1(union un1 u1 ATTRIBUTE_UNUSED,
+ union un1 u2 ATTRIBUTE_UNUSED,
+ union un1 u3 ATTRIBUTE_UNUSED,
+ union un1 u4 ATTRIBUTE_UNUSED,
+ union un1 u5 ATTRIBUTE_UNUSED,
+ union un1 u6 ATTRIBUTE_UNUSED,
+ union un1 u7 ATTRIBUTE_UNUSED,
+ union un1 u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing1h(union un1h u1 ATTRIBUTE_UNUSED,
+ union un1h u2 ATTRIBUTE_UNUSED,
+ union un1h u3 ATTRIBUTE_UNUSED,
+ union un1h u4 ATTRIBUTE_UNUSED,
+ union un1h u5 ATTRIBUTE_UNUSED,
+ union un1h u6 ATTRIBUTE_UNUSED,
+ union un1h u7 ATTRIBUTE_UNUSED,
+ union un1h u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing1hf(union un1hf u1 ATTRIBUTE_UNUSED,
+ union un1hf u2 ATTRIBUTE_UNUSED,
+ union un1hf u3 ATTRIBUTE_UNUSED,
+ union un1hf u4 ATTRIBUTE_UNUSED,
+ union un1hf u5 ATTRIBUTE_UNUSED,
+ union un1hf u6 ATTRIBUTE_UNUSED,
+ union un1hf u7 ATTRIBUTE_UNUSED,
+ union un1hf u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing1hh(union un1hh u1 ATTRIBUTE_UNUSED,
+ union un1hh u2 ATTRIBUTE_UNUSED,
+ union un1hh u3 ATTRIBUTE_UNUSED,
+ union un1hh u4 ATTRIBUTE_UNUSED,
+ union un1hh u5 ATTRIBUTE_UNUSED,
+ union un1hh u6 ATTRIBUTE_UNUSED,
+ union un1hh u7 ATTRIBUTE_UNUSED,
+ union un1hh u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED,
+ union un2 u2 ATTRIBUTE_UNUSED,
+ union un2 u3 ATTRIBUTE_UNUSED,
+ union un2 u4 ATTRIBUTE_UNUSED,
+ union un2 u5 ATTRIBUTE_UNUSED,
+ union un2 u6 ATTRIBUTE_UNUSED,
+ union un2 u7 ATTRIBUTE_UNUSED,
+ union un2 u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing2h(union un2h u1 ATTRIBUTE_UNUSED,
+ union un2h u2 ATTRIBUTE_UNUSED,
+ union un2h u3 ATTRIBUTE_UNUSED,
+ union un2h u4 ATTRIBUTE_UNUSED,
+ union un2h u5 ATTRIBUTE_UNUSED,
+ union un2h u6 ATTRIBUTE_UNUSED,
+ union un2h u7 ATTRIBUTE_UNUSED,
+ union un2h u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing3(union un3 u1 ATTRIBUTE_UNUSED,
+ union un3 u2 ATTRIBUTE_UNUSED,
+ union un3 u3 ATTRIBUTE_UNUSED,
+ union un3 u4 ATTRIBUTE_UNUSED,
+ union un3 u5 ATTRIBUTE_UNUSED,
+ union un3 u6 ATTRIBUTE_UNUSED,
+ union un3 u7 ATTRIBUTE_UNUSED,
+ union un3 u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing3h(union un3h u1 ATTRIBUTE_UNUSED,
+ union un3h u2 ATTRIBUTE_UNUSED,
+ union un3h u3 ATTRIBUTE_UNUSED,
+ union un3h u4 ATTRIBUTE_UNUSED,
+ union un3h u5 ATTRIBUTE_UNUSED,
+ union un3h u6 ATTRIBUTE_UNUSED,
+ union un3h u7 ATTRIBUTE_UNUSED,
+ union un3h u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing4(union un4 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.ld == rsp+8);
+}
+
+void
+check_union_passing4h(union un4h u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.ld == rsp+8);
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.i == rsp+8);
+}
+
+void
+check_union_passing5h(union un5h u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.x == rsp+8);
+ assert ((unsigned long)&u.i == rsp+8);
+}
+
+void
+check_union_passing6(union un6 u1 ATTRIBUTE_UNUSED,
+ union un6 u2 ATTRIBUTE_UNUSED,
+ union un6 u3 ATTRIBUTE_UNUSED,
+ union un6 u4 ATTRIBUTE_UNUSED,
+ union un6 u5 ATTRIBUTE_UNUSED,
+ union un6 u6 ATTRIBUTE_UNUSED,
+ union un6 u7 ATTRIBUTE_UNUSED,
+ union un6 u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+void
+check_union_passing6h(union un6h u1 ATTRIBUTE_UNUSED,
+ union un6h u2 ATTRIBUTE_UNUSED,
+ union un6h u3 ATTRIBUTE_UNUSED,
+ union un6h u4 ATTRIBUTE_UNUSED,
+ union un6h u5 ATTRIBUTE_UNUSED,
+ union un6h u6 ATTRIBUTE_UNUSED,
+ union un6h u7 ATTRIBUTE_UNUSED,
+ union un6h u8 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m512_arguments;
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+#define check_union_passing1h WRAP_CALL(check_union_passing1h)
+#define check_union_passing1hf WRAP_CALL(check_union_passing1hf)
+#define check_union_passing1hh WRAP_CALL(check_union_passing1hh)
+#define check_union_passing2h WRAP_CALL(check_union_passing2h)
+#define check_union_passing3h WRAP_CALL(check_union_passing3h)
+#define check_union_passing4h WRAP_CALL(check_union_passing4h)
+#define check_union_passing5h WRAP_CALL(check_union_passing5h)
+#define check_union_passing6h WRAP_CALL(check_union_passing6h)
+
+
+static void
+do_test (void)
+{
+ union un1 u1[8];
+ union un2 u2[8];
+ union un3 u3[8];
+ union un4 u4;
+ union un5 u5;
+ union un6 u6[8];
+ union un1h u1h[8];
+ union un1hf u1hf[8];
+ union un1hh u1hh[8];
+ union un2h u2h[8];
+ union un3h u3h[8];
+ union un4h u4h;
+ union un5h u5h;
+ union un6h u6h[8];
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ u1[i].x = (__m512){32+i, 0, i, 0, -i, 0, i - 12, i + 8,
+ 32+i, 0, i, 0, -i, 0, i - 12, i + 8};
+
+ u1hf[i].x = (__m512h){ 33+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 34+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 35+i, 1, i, 2, -i, 0, i - 15, i + 9,
+ 36+i, 1, i, 2, -i, 0, i - 15, i + 9};
+ }
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.zmm0)[i]._m512[0] = u1[i].x;
+ num_fregs = 8;
+ check_union_passing1(u1[0], u1[1], u1[2], u1[3],
+ u1[4], u1[5], u1[6], u1[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u1h[i].x = u1[i].x;
+ (&fregs.zmm0)[i]._m512[0] = u1h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing1h(u1h[0], u1h[1], u1h[2], u1h[3],
+ u1h[4], u1h[5], u1h[6], u1h[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ (&fregs.zmm0)[i]._m512h[0] = u1hf[i].x;
+ num_fregs = 8;
+ check_union_passing1hf(u1hf[0], u1hf[1], u1hf[2], u1hf[3],
+ u1hf[4], u1hf[5], u1hf[6], u1hf[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u1hh[i].x = u1hf[i].x;
+ (&fregs.zmm0)[i]._m512h[0] = u1hh[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing1hh(u1hh[0], u1hh[1], u1hh[2], u1hh[3],
+ u1hh[4], u1hh[5], u1hh[6], u1hh[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u2[i].x = u1[i].x;
+ (&fregs.zmm0)[i]._m512[0] = u2[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing2(u2[0], u2[1], u2[2], u2[3],
+ u2[4], u2[5], u2[6], u2[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u2h[i].x = u1hf[i].x;
+ (&fregs.zmm0)[i]._m512h[0] = u2h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing2h(u2h[0], u2h[1], u2h[2], u2h[3],
+ u2h[4], u2h[5], u2h[6], u2h[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u3[i].x = u1[i].x;
+ (&fregs.zmm0)[i]._m512[0] = u3[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing3(u3[0], u3[1], u3[2], u3[3],
+ u3[4], u3[5], u3[6], u3[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u3h[i].x = u1hf[i].x;
+ (&fregs.zmm0)[i]._m512h[0] = u3h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing3h(u3h[0], u3h[1], u3h[2], u3h[3],
+ u3h[4], u3h[5], u3h[6], u3h[7]);
+
+ check_union_passing4(u4);
+ check_union_passing5(u5);
+
+ check_union_passing4h(u4h);
+ check_union_passing5h(u5h);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u6[i].x = u1[i].x;
+ (&fregs.zmm0)[i]._m512[0] = u6[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing6(u6[0], u6[1], u6[2], u6[3],
+ u6[4], u6[5], u6[6], u6[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u6h[i].x = u1hf[i].x;
+ (&fregs.zmm0)[i]._m512h[0] = u6h[i].x;
+ }
+ num_fregs = 8;
+ check_union_passing6h(u6h[0], u6h[1], u6h[2], u6h[3],
+ u6h[4], u6h[5], u6h[6], u6h[7]);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c
new file mode 100644
index 0000000..e6d165a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/m512h/test_varargs-m512.c
@@ -0,0 +1,164 @@
+/* Test variable number of 512-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "avx512fp16-zmm-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m512_varargs (__m512 i0, __m512 i1, __m512 i2,
+ __m512 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m512 *argp;
+
+ compare (values.i0, i0, __m512);
+ compare (values.i1, i1, __m512);
+ compare (values.i2, i2, __m512);
+ compare (values.i3, i3, __m512);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m512 *)(((char *) fp) + 8);
+
+ /* Check __m512 arguments passed on stack. */
+ compare (values.i4, argp[0], __m512);
+ compare (values.i5, argp[1], __m512);
+ compare (values.i6, argp[2], __m512);
+ compare (values.i7, argp[3], __m512);
+ compare (values.i8, argp[4], __m512);
+ compare (values.i9, argp[5], __m512);
+
+ /* Check register contents. */
+ compare (fregs.zmm0, zmm_regs[0], __m512);
+ compare (fregs.zmm1, zmm_regs[1], __m512);
+ compare (fregs.zmm2, zmm_regs[2], __m512);
+ compare (fregs.zmm3, zmm_regs[3], __m512);
+}
+
+void
+fun_check_passing_m512h_varargs (__m512h i0, __m512h i1, __m512h i2,
+ __m512h i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m512h *argp;
+
+ compare (values.i0, i0, __m512h);
+ compare (values.i1, i1, __m512h);
+ compare (values.i2, i2, __m512h);
+ compare (values.i3, i3, __m512h);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m512h *)(((char *) fp) + 8);
+
+ /* Check __m512h arguments passed on stack. */
+ compare (values.i4, argp[0], __m512h);
+ compare (values.i5, argp[1], __m512h);
+ compare (values.i6, argp[2], __m512h);
+ compare (values.i7, argp[3], __m512h);
+ compare (values.i8, argp[4], __m512h);
+ compare (values.i9, argp[5], __m512h);
+
+ /* Check register contents. */
+ compare (fregs.zmm0, zmm_regs[0], __m512h);
+ compare (fregs.zmm1, zmm_regs[1], __m512h);
+ compare (fregs.zmm2, zmm_regs[2], __m512h);
+ compare (fregs.zmm3, zmm_regs[3], __m512h);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m512_varargs (void)
+{
+ __m512 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m512){32+i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m512-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m512_varargs,
+ _m512);
+}
+
+void
+test_m512h_varargs (void)
+{
+ __m512h x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m512h) {
+ 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+ 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i,
+ 9.9f16 + i, 10.10f16 + i, 11.11f16 + i, 12.12f16 + i,
+ 13.13f16 + i, 14.14f16 + i, 15.15f16 + i, 16.16f16 + i,
+ 17.17f16 + i, 18.18f16 + i, 19.19f16 + i, 20.20f16 + i,
+ 21.21f16 + i, 22.22f16 + i, 23.23f16 + i, 24.24f16 + i,
+ 25.25f16 + i, 26.26f16 + i, 27.27f16 + i, 28.28f16 + i,
+ 29.29f16 + i, 30.30f16 + i, 31.31f16 + i, 32.32f16 + i
+ };
+ pass = "m512h-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m512h_varargs,
+ _m512h);
+}
+
+void
+do_test (void)
+{
+ test_m512_varargs ();
+ test_m512h_varargs ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h
new file mode 100644
index 0000000..98fbc66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/macros.h
@@ -0,0 +1,53 @@
+#ifndef MACROS_H
+
+#define check_size(_t, _size) assert(sizeof(_t) == (_size))
+
+#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
+
+#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
+ && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
+
+#define check_basic_struct_size_and_align(_type, _size, _align) { \
+ struct _str { _type dummy; } _t; \
+ check_size(_t, _size); \
+ check_align_lv(_t, _align); \
+}
+
+#define check_array_size_and_align(_type, _size, _align) { \
+ _type _a[1]; _type _b[2]; _type _c[16]; \
+ struct _str { _type _a[1]; } _s; \
+ check_align_lv(_a[0], _align); \
+ check_size(_a, _size); \
+ check_size(_b, (_size*2)); \
+ check_size(_c, (_size*16)); \
+ check_size(_s, _size); \
+ check_align_lv(_s._a[0], _align); \
+}
+
+#define check_basic_union_size_and_align(_type, _size, _align) { \
+ union _union { _type dummy; } _u; \
+ check_size(_u, _size); \
+ check_align_lv(_u, _align); \
+}
+
+#define run_signed_tests2(_function, _arg1, _arg2) \
+ _function(_arg1, _arg2); \
+ _function(signed _arg1, _arg2); \
+ _function(unsigned _arg1, _arg2);
+
+#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
+ _function(_arg1, _arg2, _arg3); \
+ _function(signed _arg1, _arg2, _arg3); \
+ _function(unsigned _arg1, _arg2, _arg3);
+
+/* Check size of a struct and a union of three types. */
+
+#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
+{ \
+ struct _str { type1 t1; type2 t2; type3 t3; } _t; \
+ union _uni { type1 t1; type2 t2; type3 t3; } _u; \
+ check_size(_t, struct_size); \
+ check_size(_u, align_size); \
+}
+
+#endif // MACROS_H
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
new file mode 100644
index 0000000..869eec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_3_element_struct_and_unions.c
@@ -0,0 +1,794 @@
+/* This is an autogenerated file. Do not edit. */
+
+#include "defines.h"
+#include "macros.h"
+
+/* Check structs and unions of all permutations of 3 basic types. */
+int
+main (void)
+{
+ check_struct_and_union3(char, char, char, 3, 1);
+ check_struct_and_union3(char, char, short, 4, 2);
+ check_struct_and_union3(char, char, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, char, long, 16, 8);
+#endif
+ check_struct_and_union3(char, char, long long, 16, 8);
+ check_struct_and_union3(char, char, float, 8, 4);
+ check_struct_and_union3(char, char, double, 16, 8);
+ check_struct_and_union3(char, char, long double, 32, 16);
+ check_struct_and_union3(char, short, char, 6, 2);
+ check_struct_and_union3(char, short, short, 6, 2);
+ check_struct_and_union3(char, short, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, short, long, 16, 8);
+#endif
+ check_struct_and_union3(char, short, long long, 16, 8);
+ check_struct_and_union3(char, short, float, 8, 4);
+ check_struct_and_union3(char, short, double, 16, 8);
+ check_struct_and_union3(char, short, long double, 32, 16);
+ check_struct_and_union3(char, int, char, 12, 4);
+ check_struct_and_union3(char, int, short, 12, 4);
+ check_struct_and_union3(char, int, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, int, long, 16, 8);
+#endif
+ check_struct_and_union3(char, int, long long, 16, 8);
+ check_struct_and_union3(char, int, float, 12, 4);
+ check_struct_and_union3(char, int, double, 16, 8);
+ check_struct_and_union3(char, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(char, long, char, 24, 8);
+ check_struct_and_union3(char, long, short, 24, 8);
+ check_struct_and_union3(char, long, int, 24, 8);
+ check_struct_and_union3(char, long, long, 24, 8);
+ check_struct_and_union3(char, long, long long, 24, 8);
+ check_struct_and_union3(char, long, float, 24, 8);
+ check_struct_and_union3(char, long, double, 24, 8);
+ check_struct_and_union3(char, long, long double, 32, 16);
+#endif
+ check_struct_and_union3(char, long long, char, 24, 8);
+ check_struct_and_union3(char, long long, short, 24, 8);
+ check_struct_and_union3(char, long long, int, 24, 8);
+ check_struct_and_union3(char, long long, long, 24, 8);
+ check_struct_and_union3(char, long long, long long, 24, 8);
+ check_struct_and_union3(char, long long, float, 24, 8);
+ check_struct_and_union3(char, long long, double, 24, 8);
+ check_struct_and_union3(char, long long, long double, 32, 16);
+ check_struct_and_union3(char, float, char, 12, 4);
+ check_struct_and_union3(char, float, short, 12, 4);
+ check_struct_and_union3(char, float, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, float, long, 16, 8);
+#endif
+ check_struct_and_union3(char, float, long long, 16, 8);
+ check_struct_and_union3(char, float, float, 12, 4);
+ check_struct_and_union3(char, float, double, 16, 8);
+ check_struct_and_union3(char, float, long double, 32, 16);
+ check_struct_and_union3(char, double, char, 24, 8);
+ check_struct_and_union3(char, double, short, 24, 8);
+ check_struct_and_union3(char, double, int, 24, 8);
+ check_struct_and_union3(char, double, long, 24, 8);
+ check_struct_and_union3(char, double, long long, 24, 8);
+ check_struct_and_union3(char, double, float, 24, 8);
+ check_struct_and_union3(char, double, double, 24, 8);
+ check_struct_and_union3(char, double, long double, 32, 16);
+ check_struct_and_union3(char, long double, char, 48, 16);
+ check_struct_and_union3(char, long double, short, 48, 16);
+ check_struct_and_union3(char, long double, int, 48, 16);
+ check_struct_and_union3(char, long double, long, 48, 16);
+ check_struct_and_union3(char, long double, long long, 48, 16);
+ check_struct_and_union3(char, long double, float, 48, 16);
+ check_struct_and_union3(char, long double, double, 48, 16);
+ check_struct_and_union3(char, long double, long double, 48, 16);
+ check_struct_and_union3(short, char, char, 4, 2);
+ check_struct_and_union3(short, char, short, 6, 2);
+ check_struct_and_union3(short, char, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(short, char, long, 16, 8);
+#endif
+ check_struct_and_union3(short, char, long long, 16, 8);
+ check_struct_and_union3(short, char, float, 8, 4);
+ check_struct_and_union3(short, char, double, 16, 8);
+ check_struct_and_union3(short, char, long double, 32, 16);
+ check_struct_and_union3(short, short, char, 6, 2);
+ check_struct_and_union3(short, short, short, 6, 2);
+ check_struct_and_union3(short, short, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(short, short, long, 16, 8);
+#endif
+ check_struct_and_union3(short, short, long long, 16, 8);
+ check_struct_and_union3(short, short, float, 8, 4);
+ check_struct_and_union3(short, short, double, 16, 8);
+ check_struct_and_union3(short, short, long double, 32, 16);
+ check_struct_and_union3(short, int, char, 12, 4);
+ check_struct_and_union3(short, int, short, 12, 4);
+ check_struct_and_union3(short, int, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(short, int, long, 16, 8);
+#endif
+ check_struct_and_union3(short, int, long long, 16, 8);
+ check_struct_and_union3(short, int, float, 12, 4);
+ check_struct_and_union3(short, int, double, 16, 8);
+ check_struct_and_union3(short, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(short, long, char, 24, 8);
+ check_struct_and_union3(short, long, short, 24, 8);
+ check_struct_and_union3(short, long, int, 24, 8);
+ check_struct_and_union3(short, long, long, 24, 8);
+ check_struct_and_union3(short, long, long long, 24, 8);
+ check_struct_and_union3(short, long, float, 24, 8);
+ check_struct_and_union3(short, long, double, 24, 8);
+ check_struct_and_union3(short, long, long double, 32, 16);
+#endif
+ check_struct_and_union3(short, long long, char, 24, 8);
+ check_struct_and_union3(short, long long, short, 24, 8);
+ check_struct_and_union3(short, long long, int, 24, 8);
+ check_struct_and_union3(short, long long, long, 24, 8);
+ check_struct_and_union3(short, long long, long long, 24, 8);
+ check_struct_and_union3(short, long long, float, 24, 8);
+ check_struct_and_union3(short, long long, double, 24, 8);
+ check_struct_and_union3(short, long long, long double, 32, 16);
+ check_struct_and_union3(short, float, char, 12, 4);
+ check_struct_and_union3(short, float, short, 12, 4);
+ check_struct_and_union3(short, float, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(short, float, long, 16, 8);
+#endif
+ check_struct_and_union3(short, float, long long, 16, 8);
+ check_struct_and_union3(short, float, float, 12, 4);
+ check_struct_and_union3(short, float, double, 16, 8);
+ check_struct_and_union3(short, float, long double, 32, 16);
+ check_struct_and_union3(short, double, char, 24, 8);
+ check_struct_and_union3(short, double, short, 24, 8);
+ check_struct_and_union3(short, double, int, 24, 8);
+ check_struct_and_union3(short, double, long, 24, 8);
+ check_struct_and_union3(short, double, long long, 24, 8);
+ check_struct_and_union3(short, double, float, 24, 8);
+ check_struct_and_union3(short, double, double, 24, 8);
+ check_struct_and_union3(short, double, long double, 32, 16);
+ check_struct_and_union3(short, long double, char, 48, 16);
+ check_struct_and_union3(short, long double, short, 48, 16);
+ check_struct_and_union3(short, long double, int, 48, 16);
+ check_struct_and_union3(short, long double, long, 48, 16);
+ check_struct_and_union3(short, long double, long long, 48, 16);
+ check_struct_and_union3(short, long double, float, 48, 16);
+ check_struct_and_union3(short, long double, double, 48, 16);
+ check_struct_and_union3(short, long double, long double, 48, 16);
+ check_struct_and_union3(int, char, char, 8, 4);
+ check_struct_and_union3(int, char, short, 8, 4);
+ check_struct_and_union3(int, char, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, char, long, 16, 8);
+#endif
+ check_struct_and_union3(int, char, long long, 16, 8);
+ check_struct_and_union3(int, char, float, 12, 4);
+ check_struct_and_union3(int, char, double, 16, 8);
+ check_struct_and_union3(int, char, long double, 32, 16);
+ check_struct_and_union3(int, short, char, 8, 4);
+ check_struct_and_union3(int, short, short, 8, 4);
+ check_struct_and_union3(int, short, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, short, long, 16, 8);
+#endif
+ check_struct_and_union3(int, short, long long, 16, 8);
+ check_struct_and_union3(int, short, float, 12, 4);
+ check_struct_and_union3(int, short, double, 16, 8);
+ check_struct_and_union3(int, short, long double, 32, 16);
+ check_struct_and_union3(int, int, char, 12, 4);
+ check_struct_and_union3(int, int, short, 12, 4);
+ check_struct_and_union3(int, int, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, int, long, 16, 8);
+#endif
+ check_struct_and_union3(int, int, long long, 16, 8);
+ check_struct_and_union3(int, int, float, 12, 4);
+ check_struct_and_union3(int, int, double, 16, 8);
+ check_struct_and_union3(int, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(int, long, char, 24, 8);
+ check_struct_and_union3(int, long, short, 24, 8);
+ check_struct_and_union3(int, long, int, 24, 8);
+ check_struct_and_union3(int, long, long, 24, 8);
+ check_struct_and_union3(int, long, long long, 24, 8);
+ check_struct_and_union3(int, long, float, 24, 8);
+ check_struct_and_union3(int, long, double, 24, 8);
+#endif
+ check_struct_and_union3(int, long, long double, 32, 16);
+ check_struct_and_union3(int, long long, char, 24, 8);
+ check_struct_and_union3(int, long long, short, 24, 8);
+ check_struct_and_union3(int, long long, int, 24, 8);
+ check_struct_and_union3(int, long long, long, 24, 8);
+ check_struct_and_union3(int, long long, long long, 24, 8);
+ check_struct_and_union3(int, long long, float, 24, 8);
+ check_struct_and_union3(int, long long, double, 24, 8);
+ check_struct_and_union3(int, long long, long double, 32, 16);
+ check_struct_and_union3(int, float, char, 12, 4);
+ check_struct_and_union3(int, float, short, 12, 4);
+ check_struct_and_union3(int, float, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, float, long, 16, 8);
+#endif
+ check_struct_and_union3(int, float, long long, 16, 8);
+ check_struct_and_union3(int, float, float, 12, 4);
+ check_struct_and_union3(int, float, double, 16, 8);
+ check_struct_and_union3(int, float, long double, 32, 16);
+ check_struct_and_union3(int, double, char, 24, 8);
+ check_struct_and_union3(int, double, short, 24, 8);
+ check_struct_and_union3(int, double, int, 24, 8);
+ check_struct_and_union3(int, double, long, 24, 8);
+ check_struct_and_union3(int, double, long long, 24, 8);
+ check_struct_and_union3(int, double, float, 24, 8);
+ check_struct_and_union3(int, double, double, 24, 8);
+ check_struct_and_union3(int, double, long double, 32, 16);
+ check_struct_and_union3(int, long double, char, 48, 16);
+ check_struct_and_union3(int, long double, short, 48, 16);
+ check_struct_and_union3(int, long double, int, 48, 16);
+ check_struct_and_union3(int, long double, long, 48, 16);
+ check_struct_and_union3(int, long double, long long, 48, 16);
+ check_struct_and_union3(int, long double, float, 48, 16);
+ check_struct_and_union3(int, long double, double, 48, 16);
+ check_struct_and_union3(int, long double, long double, 48, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(long, char, char, 16, 8);
+ check_struct_and_union3(long, char, short, 16, 8);
+ check_struct_and_union3(long, char, int, 16, 8);
+ check_struct_and_union3(long, char, long, 24, 8);
+ check_struct_and_union3(long, char, long long, 24, 8);
+ check_struct_and_union3(long, char, float, 16, 8);
+ check_struct_and_union3(long, char, double, 24, 8);
+ check_struct_and_union3(long, char, long double, 32, 16);
+ check_struct_and_union3(long, short, char, 16, 8);
+ check_struct_and_union3(long, short, short, 16, 8);
+ check_struct_and_union3(long, short, int, 16, 8);
+ check_struct_and_union3(long, short, long, 24, 8);
+ check_struct_and_union3(long, short, long long, 24, 8);
+ check_struct_and_union3(long, short, float, 16, 8);
+ check_struct_and_union3(long, short, double, 24, 8);
+ check_struct_and_union3(long, short, long double, 32, 16);
+ check_struct_and_union3(long, int, char, 16, 8);
+ check_struct_and_union3(long, int, short, 16, 8);
+ check_struct_and_union3(long, int, int, 16, 8);
+ check_struct_and_union3(long, int, long, 24, 8);
+ check_struct_and_union3(long, int, long long, 24, 8);
+ check_struct_and_union3(long, int, float, 16, 8);
+ check_struct_and_union3(long, int, double, 24, 8);
+#endif
+ check_struct_and_union3(long, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(long, long, char, 24, 8);
+ check_struct_and_union3(long, long, short, 24, 8);
+ check_struct_and_union3(long, long, int, 24, 8);
+ check_struct_and_union3(long, long, long, 24, 8);
+ check_struct_and_union3(long, long, long long, 24, 8);
+ check_struct_and_union3(long, long, float, 24, 8);
+ check_struct_and_union3(long, long, double, 24, 8);
+ check_struct_and_union3(long, long, long double, 32, 16);
+ check_struct_and_union3(long, long long, char, 24, 8);
+ check_struct_and_union3(long, long long, short, 24, 8);
+ check_struct_and_union3(long, long long, int, 24, 8);
+ check_struct_and_union3(long, long long, long, 24, 8);
+ check_struct_and_union3(long, long long, long long, 24, 8);
+ check_struct_and_union3(long, long long, float, 24, 8);
+ check_struct_and_union3(long, long long, double, 24, 8);
+ check_struct_and_union3(long, long long, long double, 32, 16);
+ check_struct_and_union3(long, float, char, 16, 8);
+ check_struct_and_union3(long, float, short, 16, 8);
+ check_struct_and_union3(long, float, int, 16, 8);
+ check_struct_and_union3(long, float, long, 24, 8);
+ check_struct_and_union3(long, float, long long, 24, 8);
+ check_struct_and_union3(long, float, float, 16, 8);
+ check_struct_and_union3(long, float, double, 24, 8);
+ check_struct_and_union3(long, float, long double, 32, 16);
+ check_struct_and_union3(long, double, char, 24, 8);
+ check_struct_and_union3(long, double, short, 24, 8);
+ check_struct_and_union3(long, double, int, 24, 8);
+ check_struct_and_union3(long, double, long, 24, 8);
+ check_struct_and_union3(long, double, long long, 24, 8);
+ check_struct_and_union3(long, double, float, 24, 8);
+ check_struct_and_union3(long, double, double, 24, 8);
+ check_struct_and_union3(long, double, long double, 32, 16);
+ check_struct_and_union3(long, long double, char, 48, 16);
+ check_struct_and_union3(long, long double, short, 48, 16);
+ check_struct_and_union3(long, long double, int, 48, 16);
+ check_struct_and_union3(long, long double, long, 48, 16);
+ check_struct_and_union3(long, long double, long long, 48, 16);
+ check_struct_and_union3(long, long double, float, 48, 16);
+ check_struct_and_union3(long, long double, double, 48, 16);
+ check_struct_and_union3(long, long double, long double, 48, 16);
+#endif
+ check_struct_and_union3(long long, char, char, 16, 8);
+ check_struct_and_union3(long long, char, short, 16, 8);
+ check_struct_and_union3(long long, char, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, char, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, char, long long, 24, 8);
+ check_struct_and_union3(long long, char, float, 16, 8);
+ check_struct_and_union3(long long, char, double, 24, 8);
+ check_struct_and_union3(long long, char, long double, 32, 16);
+ check_struct_and_union3(long long, short, char, 16, 8);
+ check_struct_and_union3(long long, short, short, 16, 8);
+ check_struct_and_union3(long long, short, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, short, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, short, long long, 24, 8);
+ check_struct_and_union3(long long, short, float, 16, 8);
+ check_struct_and_union3(long long, short, double, 24, 8);
+ check_struct_and_union3(long long, short, long double, 32, 16);
+ check_struct_and_union3(long long, int, char, 16, 8);
+ check_struct_and_union3(long long, int, short, 16, 8);
+ check_struct_and_union3(long long, int, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, int, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, int, long long, 24, 8);
+ check_struct_and_union3(long long, int, float, 16, 8);
+ check_struct_and_union3(long long, int, double, 24, 8);
+ check_struct_and_union3(long long, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, long, char, 24, 8);
+ check_struct_and_union3(long long, long, short, 24, 8);
+ check_struct_and_union3(long long, long, int, 24, 8);
+ check_struct_and_union3(long long, long, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, long, long long, 24, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, long, float, 24, 8);
+ check_struct_and_union3(long long, long, double, 24, 8);
+#endif
+ check_struct_and_union3(long long, long, long double, 32, 16);
+ check_struct_and_union3(long long, long long, char, 24, 8);
+ check_struct_and_union3(long long, long long, short, 24, 8);
+ check_struct_and_union3(long long, long long, int, 24, 8);
+ check_struct_and_union3(long long, long long, long, 24, 8);
+ check_struct_and_union3(long long, long long, long long, 24, 8);
+ check_struct_and_union3(long long, long long, float, 24, 8);
+ check_struct_and_union3(long long, long long, double, 24, 8);
+ check_struct_and_union3(long long, long long, long double, 32, 16);
+ check_struct_and_union3(long long, float, char, 16, 8);
+ check_struct_and_union3(long long, float, short, 16, 8);
+ check_struct_and_union3(long long, float, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, float, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, float, long long, 24, 8);
+ check_struct_and_union3(long long, float, float, 16, 8);
+ check_struct_and_union3(long long, float, double, 24, 8);
+ check_struct_and_union3(long long, float, long double, 32, 16);
+ check_struct_and_union3(long long, double, char, 24, 8);
+ check_struct_and_union3(long long, double, short, 24, 8);
+ check_struct_and_union3(long long, double, int, 24, 8);
+ check_struct_and_union3(long long, double, long, 24, 8);
+ check_struct_and_union3(long long, double, long long, 24, 8);
+ check_struct_and_union3(long long, double, float, 24, 8);
+ check_struct_and_union3(long long, double, double, 24, 8);
+ check_struct_and_union3(long long, double, long double, 32, 16);
+ check_struct_and_union3(long long, long double, char, 48, 16);
+ check_struct_and_union3(long long, long double, short, 48, 16);
+ check_struct_and_union3(long long, long double, int, 48, 16);
+ check_struct_and_union3(long long, long double, long, 48, 16);
+ check_struct_and_union3(long long, long double, long long, 48, 16);
+ check_struct_and_union3(long long, long double, float, 48, 16);
+ check_struct_and_union3(long long, long double, double, 48, 16);
+ check_struct_and_union3(long long, long double, long double, 48, 16);
+ check_struct_and_union3(float, char, char, 8, 4);
+ check_struct_and_union3(float, char, short, 8, 4);
+ check_struct_and_union3(float, char, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, char, long, 16, 8);
+#endif
+ check_struct_and_union3(float, char, long long, 16, 8);
+ check_struct_and_union3(float, char, float, 12, 4);
+ check_struct_and_union3(float, char, double, 16, 8);
+ check_struct_and_union3(float, char, long double, 32, 16);
+ check_struct_and_union3(float, short, char, 8, 4);
+ check_struct_and_union3(float, short, short, 8, 4);
+ check_struct_and_union3(float, short, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, short, long, 16, 8);
+#endif
+ check_struct_and_union3(float, short, long long, 16, 8);
+ check_struct_and_union3(float, short, float, 12, 4);
+ check_struct_and_union3(float, short, double, 16, 8);
+ check_struct_and_union3(float, short, long double, 32, 16);
+ check_struct_and_union3(float, int, char, 12, 4);
+ check_struct_and_union3(float, int, short, 12, 4);
+ check_struct_and_union3(float, int, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, int, long, 16, 8);
+#endif
+ check_struct_and_union3(float, int, long long, 16, 8);
+ check_struct_and_union3(float, int, float, 12, 4);
+ check_struct_and_union3(float, int, double, 16, 8);
+ check_struct_and_union3(float, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(float, long, char, 24, 8);
+ check_struct_and_union3(float, long, short, 24, 8);
+ check_struct_and_union3(float, long, int, 24, 8);
+ check_struct_and_union3(float, long, long, 24, 8);
+ check_struct_and_union3(float, long, long long, 24, 8);
+ check_struct_and_union3(float, long, float, 24, 8);
+ check_struct_and_union3(float, long, double, 24, 8);
+#endif
+ check_struct_and_union3(float, long, long double, 32, 16);
+ check_struct_and_union3(float, long long, char, 24, 8);
+ check_struct_and_union3(float, long long, short, 24, 8);
+ check_struct_and_union3(float, long long, int, 24, 8);
+ check_struct_and_union3(float, long long, long, 24, 8);
+ check_struct_and_union3(float, long long, long long, 24, 8);
+ check_struct_and_union3(float, long long, float, 24, 8);
+ check_struct_and_union3(float, long long, double, 24, 8);
+ check_struct_and_union3(float, long long, long double, 32, 16);
+ check_struct_and_union3(float, float, char, 12, 4);
+ check_struct_and_union3(float, float, short, 12, 4);
+ check_struct_and_union3(float, float, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, float, long, 16, 8);
+#endif
+ check_struct_and_union3(float, float, long long, 16, 8);
+ check_struct_and_union3(float, float, float, 12, 4);
+ check_struct_and_union3(float, float, double, 16, 8);
+ check_struct_and_union3(float, float, long double, 32, 16);
+ check_struct_and_union3(float, double, char, 24, 8);
+ check_struct_and_union3(float, double, short, 24, 8);
+ check_struct_and_union3(float, double, int, 24, 8);
+ check_struct_and_union3(float, double, long, 24, 8);
+ check_struct_and_union3(float, double, long long, 24, 8);
+ check_struct_and_union3(float, double, float, 24, 8);
+ check_struct_and_union3(float, double, double, 24, 8);
+ check_struct_and_union3(float, double, long double, 32, 16);
+ check_struct_and_union3(float, long double, char, 48, 16);
+ check_struct_and_union3(float, long double, short, 48, 16);
+ check_struct_and_union3(float, long double, int, 48, 16);
+ check_struct_and_union3(float, long double, long, 48, 16);
+ check_struct_and_union3(float, long double, long long, 48, 16);
+ check_struct_and_union3(float, long double, float, 48, 16);
+ check_struct_and_union3(float, long double, double, 48, 16);
+ check_struct_and_union3(float, long double, long double, 48, 16);
+ check_struct_and_union3(double, char, char, 16, 8);
+ check_struct_and_union3(double, char, short, 16, 8);
+ check_struct_and_union3(double, char, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, char, long, 24, 8);
+#endif
+ check_struct_and_union3(double, char, long long, 24, 8);
+ check_struct_and_union3(double, char, float, 16, 8);
+ check_struct_and_union3(double, char, double, 24, 8);
+ check_struct_and_union3(double, char, long double, 32, 16);
+ check_struct_and_union3(double, short, char, 16, 8);
+ check_struct_and_union3(double, short, short, 16, 8);
+ check_struct_and_union3(double, short, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, short, long, 24, 8);
+#endif
+ check_struct_and_union3(double, short, long long, 24, 8);
+ check_struct_and_union3(double, short, float, 16, 8);
+ check_struct_and_union3(double, short, double, 24, 8);
+ check_struct_and_union3(double, short, long double, 32, 16);
+ check_struct_and_union3(double, int, char, 16, 8);
+ check_struct_and_union3(double, int, short, 16, 8);
+ check_struct_and_union3(double, int, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, int, long, 24, 8);
+#endif
+ check_struct_and_union3(double, int, long long, 24, 8);
+ check_struct_and_union3(double, int, float, 16, 8);
+ check_struct_and_union3(double, int, double, 24, 8);
+ check_struct_and_union3(double, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(double, long, char, 24, 8);
+ check_struct_and_union3(double, long, short, 24, 8);
+ check_struct_and_union3(double, long, int, 24, 8);
+ check_struct_and_union3(double, long, long, 24, 8);
+#endif
+ check_struct_and_union3(double, long, long long, 24, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, long, float, 24, 8);
+#endif
+ check_struct_and_union3(double, long, double, 24, 8);
+ check_struct_and_union3(double, long, long double, 32, 16);
+ check_struct_and_union3(double, long long, char, 24, 8);
+ check_struct_and_union3(double, long long, short, 24, 8);
+ check_struct_and_union3(double, long long, int, 24, 8);
+ check_struct_and_union3(double, long long, long, 24, 8);
+ check_struct_and_union3(double, long long, long long, 24, 8);
+ check_struct_and_union3(double, long long, float, 24, 8);
+ check_struct_and_union3(double, long long, double, 24, 8);
+ check_struct_and_union3(double, long long, long double, 32, 16);
+ check_struct_and_union3(double, float, char, 16, 8);
+ check_struct_and_union3(double, float, short, 16, 8);
+ check_struct_and_union3(double, float, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, float, long, 24, 8);
+#endif
+ check_struct_and_union3(double, float, long long, 24, 8);
+ check_struct_and_union3(double, float, float, 16, 8);
+ check_struct_and_union3(double, float, double, 24, 8);
+ check_struct_and_union3(double, float, long double, 32, 16);
+ check_struct_and_union3(double, double, char, 24, 8);
+ check_struct_and_union3(double, double, short, 24, 8);
+ check_struct_and_union3(double, double, int, 24, 8);
+ check_struct_and_union3(double, double, long, 24, 8);
+ check_struct_and_union3(double, double, long long, 24, 8);
+ check_struct_and_union3(double, double, float, 24, 8);
+ check_struct_and_union3(double, double, double, 24, 8);
+ check_struct_and_union3(double, double, long double, 32, 16);
+ check_struct_and_union3(double, long double, char, 48, 16);
+ check_struct_and_union3(double, long double, short, 48, 16);
+ check_struct_and_union3(double, long double, int, 48, 16);
+ check_struct_and_union3(double, long double, long, 48, 16);
+ check_struct_and_union3(double, long double, long long, 48, 16);
+ check_struct_and_union3(double, long double, float, 48, 16);
+ check_struct_and_union3(double, long double, double, 48, 16);
+ check_struct_and_union3(double, long double, long double, 48, 16);
+ check_struct_and_union3(long double, char, char, 32, 16);
+ check_struct_and_union3(long double, char, short, 32, 16);
+ check_struct_and_union3(long double, char, int, 32, 16);
+ check_struct_and_union3(long double, char, long, 32, 16);
+ check_struct_and_union3(long double, char, long long, 32, 16);
+ check_struct_and_union3(long double, char, float, 32, 16);
+ check_struct_and_union3(long double, char, double, 32, 16);
+ check_struct_and_union3(long double, char, long double, 48, 16);
+ check_struct_and_union3(long double, short, char, 32, 16);
+ check_struct_and_union3(long double, short, short, 32, 16);
+ check_struct_and_union3(long double, short, int, 32, 16);
+ check_struct_and_union3(long double, short, long, 32, 16);
+ check_struct_and_union3(long double, short, long long, 32, 16);
+ check_struct_and_union3(long double, short, float, 32, 16);
+ check_struct_and_union3(long double, short, double, 32, 16);
+ check_struct_and_union3(long double, short, long double, 48, 16);
+ check_struct_and_union3(long double, int, char, 32, 16);
+ check_struct_and_union3(long double, int, short, 32, 16);
+ check_struct_and_union3(long double, int, int, 32, 16);
+ check_struct_and_union3(long double, int, long, 32, 16);
+ check_struct_and_union3(long double, int, long long, 32, 16);
+ check_struct_and_union3(long double, int, float, 32, 16);
+ check_struct_and_union3(long double, int, double, 32, 16);
+ check_struct_and_union3(long double, int, long double, 48, 16);
+ check_struct_and_union3(long double, long, char, 32, 16);
+ check_struct_and_union3(long double, long, short, 32, 16);
+ check_struct_and_union3(long double, long, int, 32, 16);
+ check_struct_and_union3(long double, long, long, 32, 16);
+ check_struct_and_union3(long double, long, long long, 32, 16);
+ check_struct_and_union3(long double, long, float, 32, 16);
+ check_struct_and_union3(long double, long, double, 32, 16);
+ check_struct_and_union3(long double, long, long double, 48, 16);
+ check_struct_and_union3(long double, long long, char, 32, 16);
+ check_struct_and_union3(long double, long long, short, 32, 16);
+ check_struct_and_union3(long double, long long, int, 32, 16);
+ check_struct_and_union3(long double, long long, long, 32, 16);
+ check_struct_and_union3(long double, long long, long long, 32, 16);
+ check_struct_and_union3(long double, long long, float, 32, 16);
+ check_struct_and_union3(long double, long long, double, 32, 16);
+ check_struct_and_union3(long double, long long, long double, 48, 16);
+ check_struct_and_union3(long double, float, char, 32, 16);
+ check_struct_and_union3(long double, float, short, 32, 16);
+ check_struct_and_union3(long double, float, int, 32, 16);
+ check_struct_and_union3(long double, float, long, 32, 16);
+ check_struct_and_union3(long double, float, long long, 32, 16);
+ check_struct_and_union3(long double, float, float, 32, 16);
+ check_struct_and_union3(long double, float, double, 32, 16);
+ check_struct_and_union3(long double, float, long double, 48, 16);
+ check_struct_and_union3(long double, double, char, 32, 16);
+ check_struct_and_union3(long double, double, short, 32, 16);
+ check_struct_and_union3(long double, double, int, 32, 16);
+ check_struct_and_union3(long double, double, long, 32, 16);
+ check_struct_and_union3(long double, double, long long, 32, 16);
+ check_struct_and_union3(long double, double, float, 32, 16);
+ check_struct_and_union3(long double, double, double, 32, 16);
+ check_struct_and_union3(long double, double, long double, 48, 16);
+ check_struct_and_union3(long double, long double, char, 48, 16);
+ check_struct_and_union3(long double, long double, short, 48, 16);
+ check_struct_and_union3(long double, long double, int, 48, 16);
+ check_struct_and_union3(long double, long double, long, 48, 16);
+ check_struct_and_union3(long double, long double, long long, 48, 16);
+ check_struct_and_union3(long double, long double, float, 48, 16);
+ check_struct_and_union3(long double, long double, double, 48, 16);
+ check_struct_and_union3(long double, long double, long double, 48, 16);
+ check_struct_and_union3(char, char, _Float16, 4, 2);
+ check_struct_and_union3(char, _Float16, char, 6, 2);
+ check_struct_and_union3(char, _Float16, _Float16, 6, 2);
+ check_struct_and_union3(char, _Float16, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, _Float16, long, 16, 8);
+#endif
+ check_struct_and_union3(char, _Float16, long long, 16, 8);
+ check_struct_and_union3(char, _Float16, float, 8, 4);
+ check_struct_and_union3(char, _Float16, double, 16, 8);
+ check_struct_and_union3(char, _Float16, long double, 32, 16);
+ check_struct_and_union3(char, int, _Float16, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(char, long, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(char, long long, _Float16, 24, 8);
+ check_struct_and_union3(char, float, _Float16, 12, 4);
+ check_struct_and_union3(char, double, _Float16, 24, 8);
+ check_struct_and_union3(char, long double, _Float16, 48, 16);
+ check_struct_and_union3(_Float16, char, char, 4, 2);
+ check_struct_and_union3(_Float16, char, _Float16, 6, 2);
+ check_struct_and_union3(_Float16, char, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(_Float16, char, long, 16, 8);
+#endif
+ check_struct_and_union3(_Float16, char, long long, 16, 8);
+ check_struct_and_union3(_Float16, char, float, 8, 4);
+ check_struct_and_union3(_Float16, char, double, 16, 8);
+ check_struct_and_union3(_Float16, char, long double, 32, 16);
+ check_struct_and_union3(_Float16, _Float16, char, 6, 2);
+ check_struct_and_union3(_Float16, _Float16, _Float16, 6, 2);
+ check_struct_and_union3(_Float16, _Float16, int, 8, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(_Float16, _Float16, long, 16, 8);
+#endif
+ check_struct_and_union3(_Float16, _Float16, long long, 16, 8);
+ check_struct_and_union3(_Float16, _Float16, float, 8, 4);
+ check_struct_and_union3(_Float16, _Float16, double, 16, 8);
+ check_struct_and_union3(_Float16, _Float16, long double, 32, 16);
+ check_struct_and_union3(_Float16, int, char, 12, 4);
+ check_struct_and_union3(_Float16, int, _Float16, 12, 4);
+ check_struct_and_union3(_Float16, int, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(_Float16, int, long, 16, 8);
+#endif
+ check_struct_and_union3(_Float16, int, long long, 16, 8);
+ check_struct_and_union3(_Float16, int, float, 12, 4);
+ check_struct_and_union3(_Float16, int, double, 16, 8);
+ check_struct_and_union3(_Float16, int, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(_Float16, long, char, 24, 8);
+ check_struct_and_union3(_Float16, long, _Float16, 24, 8);
+ check_struct_and_union3(_Float16, long, int, 24, 8);
+ check_struct_and_union3(_Float16, long, long, 24, 8);
+ check_struct_and_union3(_Float16, long, long long, 24, 8);
+ check_struct_and_union3(_Float16, long, float, 24, 8);
+ check_struct_and_union3(_Float16, long, double, 24, 8);
+#endif
+ check_struct_and_union3(_Float16, long, long double, 32, 16);
+ check_struct_and_union3(_Float16, long long, char, 24, 8);
+ check_struct_and_union3(_Float16, long long, _Float16, 24, 8);
+ check_struct_and_union3(_Float16, long long, int, 24, 8);
+ check_struct_and_union3(_Float16, long long, long, 24, 8);
+ check_struct_and_union3(_Float16, long long, long long, 24, 8);
+ check_struct_and_union3(_Float16, long long, float, 24, 8);
+ check_struct_and_union3(_Float16, long long, double, 24, 8);
+ check_struct_and_union3(_Float16, long long, long double, 32, 16);
+ check_struct_and_union3(_Float16, float, char, 12, 4);
+ check_struct_and_union3(_Float16, float, _Float16, 12, 4);
+ check_struct_and_union3(_Float16, float, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(_Float16, float, long, 16, 8);
+#endif
+ check_struct_and_union3(_Float16, float, long long, 16, 8);
+ check_struct_and_union3(_Float16, float, float, 12, 4);
+ check_struct_and_union3(_Float16, float, double, 16, 8);
+ check_struct_and_union3(_Float16, float, long double, 32, 16);
+ check_struct_and_union3(_Float16, double, char, 24, 8);
+ check_struct_and_union3(_Float16, double, _Float16, 24, 8);
+ check_struct_and_union3(_Float16, double, int, 24, 8);
+ check_struct_and_union3(_Float16, double, long, 24, 8);
+ check_struct_and_union3(_Float16, double, long long, 24, 8);
+ check_struct_and_union3(_Float16, double, float, 24, 8);
+ check_struct_and_union3(_Float16, double, double, 24, 8);
+ check_struct_and_union3(_Float16, double, long double, 32, 16);
+ check_struct_and_union3(_Float16, long double, char, 48, 16);
+ check_struct_and_union3(_Float16, long double, _Float16, 48, 16);
+ check_struct_and_union3(_Float16, long double, int, 48, 16);
+ check_struct_and_union3(_Float16, long double, long, 48, 16);
+ check_struct_and_union3(_Float16, long double, long long, 48, 16);
+ check_struct_and_union3(_Float16, long double, float, 48, 16);
+ check_struct_and_union3(_Float16, long double, double, 48, 16);
+ check_struct_and_union3(_Float16, long double, long double, 48, 16);
+ check_struct_and_union3(int, char, _Float16, 8, 4);
+ check_struct_and_union3(int, _Float16, char, 8, 4);
+ check_struct_and_union3(int, _Float16, _Float16, 8, 4);
+ check_struct_and_union3(int, _Float16, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, _Float16, long, 16, 8);
+#endif
+ check_struct_and_union3(int, _Float16, long long, 16, 8);
+ check_struct_and_union3(int, _Float16, float, 12, 4);
+ check_struct_and_union3(int, _Float16, double, 16, 8);
+ check_struct_and_union3(int, _Float16, long double, 32, 16);
+ check_struct_and_union3(int, int, _Float16, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(int, long, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(int, long long, _Float16, 24, 8);
+ check_struct_and_union3(int, float, _Float16, 12, 4);
+ check_struct_and_union3(int, double, _Float16, 24, 8);
+ check_struct_and_union3(int, long double, _Float16, 48, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(long, char, _Float16, 16, 8);
+ check_struct_and_union3(long, _Float16, char, 16, 8);
+ check_struct_and_union3(long, _Float16, _Float16, 16, 8);
+ check_struct_and_union3(long, _Float16, int, 16, 8);
+ check_struct_and_union3(long, _Float16, long, 24, 8);
+ check_struct_and_union3(long, _Float16, long long, 24, 8);
+ check_struct_and_union3(long, _Float16, float, 16, 8);
+ check_struct_and_union3(long, _Float16, double, 24, 8);
+#endif
+ check_struct_and_union3(long, _Float16, long double, 32, 16);
+#ifndef __ILP32__
+ check_struct_and_union3(long, int, _Float16, 16, 8);
+ check_struct_and_union3(long, long, _Float16, 24, 8);
+ check_struct_and_union3(long, long long, _Float16, 24, 8);
+ check_struct_and_union3(long, float, _Float16, 16, 8);
+ check_struct_and_union3(long, double, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(long, long double, _Float16, 48, 16);
+ check_struct_and_union3(long long, char, _Float16, 16, 8);
+ check_struct_and_union3(long long, _Float16, char, 16, 8);
+ check_struct_and_union3(long long, _Float16, _Float16, 16, 8);
+ check_struct_and_union3(long long, _Float16, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, _Float16, long, 24, 8);
+#endif
+ check_struct_and_union3(long long, _Float16, long long, 24, 8);
+ check_struct_and_union3(long long, _Float16, float, 16, 8);
+ check_struct_and_union3(long long, _Float16, double, 24, 8);
+ check_struct_and_union3(long long, _Float16, long double, 32, 16);
+ check_struct_and_union3(long long, int, _Float16, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(long long, long, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(long long, long long, _Float16, 24, 8);
+ check_struct_and_union3(long long, float, _Float16, 16, 8);
+ check_struct_and_union3(long long, double, _Float16, 24, 8);
+ check_struct_and_union3(long long, long double, _Float16, 48, 16);
+ check_struct_and_union3(float, char, _Float16, 8, 4);
+ check_struct_and_union3(float, _Float16, char, 8, 4);
+ check_struct_and_union3(float, _Float16, _Float16, 8, 4);
+ check_struct_and_union3(float, _Float16, int, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, _Float16, long, 16, 8);
+#endif
+ check_struct_and_union3(float, _Float16, long long, 16, 8);
+ check_struct_and_union3(float, _Float16, float, 12, 4);
+ check_struct_and_union3(float, _Float16, double, 16, 8);
+ check_struct_and_union3(float, _Float16, long double, 32, 16);
+ check_struct_and_union3(float, int, _Float16, 12, 4);
+#ifndef __ILP32__
+ check_struct_and_union3(float, long, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(float, long long, _Float16, 24, 8);
+ check_struct_and_union3(float, float, _Float16, 12, 4);
+ check_struct_and_union3(float, double, _Float16, 24, 8);
+ check_struct_and_union3(float, long double, _Float16, 48, 16);
+ check_struct_and_union3(double, char, _Float16, 16, 8);
+ check_struct_and_union3(double, _Float16, char, 16, 8);
+ check_struct_and_union3(double, _Float16, _Float16, 16, 8);
+ check_struct_and_union3(double, _Float16, int, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, _Float16, long, 24, 8);
+#endif
+ check_struct_and_union3(double, _Float16, long long, 24, 8);
+ check_struct_and_union3(double, _Float16, float, 16, 8);
+ check_struct_and_union3(double, _Float16, double, 24, 8);
+ check_struct_and_union3(double, _Float16, long double, 32, 16);
+ check_struct_and_union3(double, int, _Float16, 16, 8);
+#ifndef __ILP32__
+ check_struct_and_union3(double, long, _Float16, 24, 8);
+#endif
+ check_struct_and_union3(double, long long, _Float16, 24, 8);
+ check_struct_and_union3(double, float, _Float16, 16, 8);
+ check_struct_and_union3(double, double, _Float16, 24, 8);
+ check_struct_and_union3(double, long double, _Float16, 48, 16);
+ check_struct_and_union3(long double, char, _Float16, 32, 16);
+ check_struct_and_union3(long double, _Float16, char, 32, 16);
+ check_struct_and_union3(long double, _Float16, _Float16, 32, 16);
+ check_struct_and_union3(long double, _Float16, int, 32, 16);
+ check_struct_and_union3(long double, _Float16, long, 32, 16);
+ check_struct_and_union3(long double, _Float16, long long, 32, 16);
+ check_struct_and_union3(long double, _Float16, float, 32, 16);
+ check_struct_and_union3(long double, _Float16, double, 32, 16);
+ check_struct_and_union3(long double, _Float16, long double, 48, 16);
+ check_struct_and_union3(long double, int, _Float16, 32, 16);
+ check_struct_and_union3(long double, long, _Float16, 32, 16);
+ check_struct_and_union3(long double, long long, _Float16, 32, 16);
+ check_struct_and_union3(long double, float, _Float16, 32, 16);
+ check_struct_and_union3(long double, double, _Float16, 32, 16);
+ check_struct_and_union3(long double, long double, _Float16, 48, 16);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c
new file mode 100644
index 0000000..2a72b5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_alignment.c
@@ -0,0 +1,45 @@
+/* This checks alignment of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
+ run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
+ run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
+ run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
+ run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests2(check_align, __int128, TYPE_ALIGN_INT128);
+#endif
+ check_align(enumtype, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_align(float, TYPE_ALIGN_FLOAT);
+ check_align(double, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_align(__float128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Packed types - MMX, 3DNow!, SSE and SSE2. */
+#ifdef CHECK_M64_M128
+ check_align(__m64, TYPE_ALIGN_M64);
+ check_align(__m128, TYPE_ALIGN_M128);
+#endif
+
+ /* _Float16 point types. */
+ check_align(_Float16, TYPE_ALIGN_FLOAT16);
+
+ /* Pointer types. */
+ check_align(void *, TYPE_ALIGN_POINTER);
+ check_align(void (*)(), TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c
new file mode 100644
index 0000000..d58b9d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_array_size_and_align.c
@@ -0,0 +1,43 @@
+/* This checks . */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests3(check_array_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+ check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Packed types - MMX, 3DNow!, SSE and SSE2. */
+#ifdef CHECK_M64_M128
+ check_array_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+ check_array_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ check_array_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c
new file mode 100644
index 0000000..36fb24e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_returning.c
@@ -0,0 +1,87 @@
+/* This is an autogenerated file. Do not edit. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+char
+fun_test_returning_char (void)
+{
+ volatile_var++;
+ return 64;
+}
+
+short
+fun_test_returning_short (void)
+{
+ volatile_var++;
+ return 65;
+}
+
+int
+fun_test_returning_int (void)
+{
+ volatile_var++;
+ return 66;
+}
+
+long
+fun_test_returning_long (void)
+{
+ volatile_var++;
+ return 67;
+}
+
+long long
+fun_test_returning_long_long (void)
+{
+ volatile_var++;
+ return 68;
+}
+
+float
+fun_test_returning_float (void)
+{
+ volatile_var++;
+ return 69;
+}
+
+double
+fun_test_returning_double (void)
+{
+ volatile_var++;
+ return 70;
+}
+
+long double
+fun_test_returning_long_double (void)
+{
+ volatile_var++;
+ return 71;
+}
+
+_Float16
+fun_test_returning_float16 (void)
+{
+ volatile_var++;
+ return 72;
+}
+
+#define def_test_returning_type_xmm(fun, type, ret, reg) \
+ { type var = WRAP_RET (fun) (); \
+ assert (ret == (type) reg && ret == var); }
+
+static void
+do_test (void)
+{
+ def_test_returning_type_xmm(fun_test_returning_char, char, 64, rax);
+ def_test_returning_type_xmm(fun_test_returning_short, short, 65, rax);
+ def_test_returning_type_xmm(fun_test_returning_int, int, 66, rax);
+ def_test_returning_type_xmm(fun_test_returning_long, long, 67, rax);
+ def_test_returning_type_xmm(fun_test_returning_long_long, long long, 68, rax);
+ def_test_returning_type_xmm(fun_test_returning_float, float, 69, xmm_regs[0]._float[0]);
+ def_test_returning_type_xmm(fun_test_returning_double, double, 70, xmm_regs[0]._double[0]);
+ def_test_returning_type_xmm(fun_test_returning_long_double, long double, 71, x87_regs[0]._ldouble);
+ def_test_returning_type_xmm(fun_test_returning_float16, _Float16, 72, xmm_regs[0].__Float16[0]);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c
new file mode 100644
index 0000000..47f3a5e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_sizes.c
@@ -0,0 +1,43 @@
+/* This checks sizes of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
+ run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
+ run_signed_tests2(check_size, int, TYPE_SIZE_INT);
+ run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
+ run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
+#endif
+ check_size(enumtype, TYPE_SIZE_ENUM);
+
+ /* Floating point types. */
+ check_size(_Float16, TYPE_SIZE_FLOAT16);
+ check_size(float, TYPE_SIZE_FLOAT);
+ check_size(double, TYPE_SIZE_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_size(long double, TYPE_SIZE_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_size(__float128, TYPE_SIZE_FLOAT128);
+#endif
+
+ /* Packed types - MMX, 3DNow!, SSE and SSE2. */
+#ifdef CHECK_M64_M128
+ check_size(__m64, TYPE_SIZE_M64);
+ check_size(__m128, TYPE_SIZE_M128);
+#endif
+
+ /* Pointer types. */
+ check_size(void *, TYPE_SIZE_POINTER);
+ check_size(void (*)(), TYPE_SIZE_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c
new file mode 100644
index 0000000..3d1add4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_struct_size_and_align.c
@@ -0,0 +1,42 @@
+/* This checks size and alignment of structs with a single basic type
+ element. All basic types are checked. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+
+
+static void
+do_test (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests3(check_basic_struct_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+ check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_struct_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+ check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Packed types - MMX, 3DNow!, SSE and SSE2. */
+#ifdef CHECK_M64_M128
+ check_basic_struct_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+ check_basic_struct_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c
new file mode 100644
index 0000000..632feeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_basic_union_size_and_align.c
@@ -0,0 +1,40 @@
+/* Test of simple unions, size and alignment. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+
+static void
+do_test (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests3(check_basic_union_size_and_align, __int128, TYPE_SIZE_INT128, TYPE_ALIGN_INT128);
+#endif
+ check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_union_size_and_align(_Float16, TYPE_SIZE_FLOAT16, TYPE_ALIGN_FLOAT16);
+ check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Packed types - MMX, 3DNow!, SSE and SSE2. */
+#ifdef CHECK_M64_M128
+ check_basic_union_size_and_align(__m64, TYPE_SIZE_M64, TYPE_ALIGN_M64);
+ check_basic_union_size_and_align(__m128, TYPE_SIZE_M128, TYPE_ALIGN_M128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c
new file mode 100644
index 0000000..829d86e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_complex_returning.c
@@ -0,0 +1,104 @@
+/* This is a small test case for returning a complex number. Written by
+ Andreas Jaeger. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+
+#define BUILD_F16_COMPLEX(real, imag) \
+ ({ __complex__ _Float16 __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+__complex__ _Float16
+aj_f16_times2 (__complex__ _Float16 x)
+{
+ __complex__ _Float16 res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+#define BUILD_F_COMPLEX(real, imag) \
+ ({ __complex__ float __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_D_COMPLEX(real, imag) \
+ ({ __complex__ double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_LD_COMPLEX(real, imag) \
+ ({ __complex__ long double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+__complex__ float
+aj_f_times2 (__complex__ float x)
+{
+ __complex__ float res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ double
+aj_d_times2 (__complex__ double x)
+{
+ __complex__ double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ long double
+aj_ld_times2 (__complex__ long double x)
+{
+ __complex__ long double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+static void
+do_test (void)
+{
+#ifdef CHECK_COMPLEX
+ _Complex _Float16 f16c, f16d;
+ _Complex float fc, fd;
+ _Complex double dc, dd;
+ _Complex long double ldc, ldd;
+
+ f16c = BUILD_F16_COMPLEX (2.0, 3.0);
+ f16d = aj_f16_times2 (f16c);
+
+ assert (__real__ f16d == 4.0f16 && __imag__ f16d == 6.0f16);
+
+ fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
+ fd = aj_f_times2 (fc);
+
+ assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
+
+ dc = BUILD_LD_COMPLEX (2.0, 3.0);
+ dd = aj_ld_times2 (dc);
+
+ assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
+
+ ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
+ ldd = aj_ld_times2 (ldc);
+
+ assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
+#endif
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
new file mode 100644
index 0000000..363dfa9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_m64m128_returning.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+__m64
+fun_test_returning___m64 (void)
+{
+ volatile_var++;
+ return (__m64){72,0};
+}
+
+__m128
+fun_test_returning___m128 (void)
+{
+ volatile_var++;
+ return (__m128){73,0,0,0};
+}
+
+__m128h
+fun_test_returning___m128h (void)
+{
+ volatile_var++;
+ return (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+ 6.6f16, 7.7f16, 8.8f16};
+}
+
+__m64 test_64;
+__m128 test_128;
+__m128h test_128h;
+
+static void
+do_test (void)
+{
+ unsigned failed = 0;
+ XMM_T xmmt1, xmmt2;
+
+ /* We jump through hoops to compare the results as gcc 3.3 does throw
+ an ICE when trying to generate a compare for a == b, when a and b
+ are of __m64 or __m128 type :-( */
+ clear_struct_registers;
+ test_64 = (__m64){72,0};
+ xmmt1._m64[0] = test_64;
+ xmmt2._m64[0] = WRAP_RET (fun_test_returning___m64)();
+ if (xmmt1._longlong[0] != xmmt2._longlong[0]
+ || xmmt1._longlong[0] != xmm_regs[0]._longlong[0])
+ printf ("fail m64\n"), failed++;
+
+ clear_struct_registers;
+ test_128 = (__m128){73,0};
+ xmmt1._m128[0] = test_128;
+ xmmt2._m128[0] = WRAP_RET (fun_test_returning___m128)();
+ if (xmmt1._longlong[0] != xmmt2._longlong[0]
+ || xmmt1._longlong[0] != xmm_regs[0]._longlong[0])
+ printf ("fail m128\n"), failed++;
+
+ clear_struct_registers;
+ test_128h = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+ 6.6f16, 7.7f16, 8.8f16};
+ xmmt1._m128h[0] = test_128h;
+ xmmt2._m128h[0] = WRAP_RET (fun_test_returning___m128h)();
+ if (xmmt1._longlong[0] != xmmt2._longlong[0]
+ || xmmt1._longlong[0] != xmm_regs[0]._longlong[0])
+ printf ("fail m128h\n"), failed++;
+
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c
new file mode 100644
index 0000000..678b25c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_floats.c
@@ -0,0 +1,1066 @@
+/* This is an autogenerated file. Do not edit. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ _Float16 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+ f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values__Float16;
+
+struct
+{
+ float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23;
+} values_float;
+
+struct
+{
+ double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+ f16, f17, f18, f19, f20, f21, f22, f23;
+} values_double;
+
+struct
+{
+ ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+ f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_ldouble;
+
+void
+fun_check_float16_passing_8_values (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values__Float16.f0 == f0);
+ assert (values__Float16.f1 == f1);
+ assert (values__Float16.f2 == f2);
+ assert (values__Float16.f3 == f3);
+ assert (values__Float16.f4 == f4);
+ assert (values__Float16.f5 == f5);
+ assert (values__Float16.f6 == f6);
+ assert (values__Float16.f7 == f7);
+}
+
+void
+fun_check_float16_passing_8_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float16_arguments;
+}
+
+void
+fun_check_float16_passing_16_values (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED,
+ _Float16 f8 ATTRIBUTE_UNUSED,
+ _Float16 f9 ATTRIBUTE_UNUSED,
+ _Float16 f10 ATTRIBUTE_UNUSED,
+ _Float16 f11 ATTRIBUTE_UNUSED,
+ _Float16 f12 ATTRIBUTE_UNUSED,
+ _Float16 f13 ATTRIBUTE_UNUSED,
+ _Float16 f14 ATTRIBUTE_UNUSED,
+ _Float16 f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values__Float16.f0 == f0);
+ assert (values__Float16.f1 == f1);
+ assert (values__Float16.f2 == f2);
+ assert (values__Float16.f3 == f3);
+ assert (values__Float16.f4 == f4);
+ assert (values__Float16.f5 == f5);
+ assert (values__Float16.f6 == f6);
+ assert (values__Float16.f7 == f7);
+ assert (values__Float16.f8 == f8);
+ assert (values__Float16.f9 == f9);
+ assert (values__Float16.f10 == f10);
+ assert (values__Float16.f11 == f11);
+ assert (values__Float16.f12 == f12);
+ assert (values__Float16.f13 == f13);
+ assert (values__Float16.f14 == f14);
+ assert (values__Float16.f15 == f15);
+}
+
+void
+fun_check_float16_passing_16_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED,
+ _Float16 f8 ATTRIBUTE_UNUSED,
+ _Float16 f9 ATTRIBUTE_UNUSED,
+ _Float16 f10 ATTRIBUTE_UNUSED,
+ _Float16 f11 ATTRIBUTE_UNUSED,
+ _Float16 f12 ATTRIBUTE_UNUSED,
+ _Float16 f13 ATTRIBUTE_UNUSED,
+ _Float16 f14 ATTRIBUTE_UNUSED,
+ _Float16 f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float16_arguments;
+}
+
+void
+fun_check_float16_passing_20_values (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED,
+ _Float16 f8 ATTRIBUTE_UNUSED,
+ _Float16 f9 ATTRIBUTE_UNUSED,
+ _Float16 f10 ATTRIBUTE_UNUSED,
+ _Float16 f11 ATTRIBUTE_UNUSED,
+ _Float16 f12 ATTRIBUTE_UNUSED,
+ _Float16 f13 ATTRIBUTE_UNUSED,
+ _Float16 f14 ATTRIBUTE_UNUSED,
+ _Float16 f15 ATTRIBUTE_UNUSED,
+ _Float16 f16 ATTRIBUTE_UNUSED,
+ _Float16 f17 ATTRIBUTE_UNUSED,
+ _Float16 f18 ATTRIBUTE_UNUSED,
+ _Float16 f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values__Float16.f0 == f0);
+ assert (values__Float16.f1 == f1);
+ assert (values__Float16.f2 == f2);
+ assert (values__Float16.f3 == f3);
+ assert (values__Float16.f4 == f4);
+ assert (values__Float16.f5 == f5);
+ assert (values__Float16.f6 == f6);
+ assert (values__Float16.f7 == f7);
+ assert (values__Float16.f8 == f8);
+ assert (values__Float16.f9 == f9);
+ assert (values__Float16.f10 == f10);
+ assert (values__Float16.f11 == f11);
+ assert (values__Float16.f12 == f12);
+ assert (values__Float16.f13 == f13);
+ assert (values__Float16.f14 == f14);
+ assert (values__Float16.f15 == f15);
+ assert (values__Float16.f16 == f16);
+ assert (values__Float16.f17 == f17);
+ assert (values__Float16.f18 == f18);
+ assert (values__Float16.f19 == f19);
+}
+
+void
+fun_check_float16_passing_20_regs (_Float16 f0 ATTRIBUTE_UNUSED,
+ _Float16 f1 ATTRIBUTE_UNUSED,
+ _Float16 f2 ATTRIBUTE_UNUSED,
+ _Float16 f3 ATTRIBUTE_UNUSED,
+ _Float16 f4 ATTRIBUTE_UNUSED,
+ _Float16 f5 ATTRIBUTE_UNUSED,
+ _Float16 f6 ATTRIBUTE_UNUSED,
+ _Float16 f7 ATTRIBUTE_UNUSED,
+ _Float16 f8 ATTRIBUTE_UNUSED,
+ _Float16 f9 ATTRIBUTE_UNUSED,
+ _Float16 f10 ATTRIBUTE_UNUSED,
+ _Float16 f11 ATTRIBUTE_UNUSED,
+ _Float16 f12 ATTRIBUTE_UNUSED,
+ _Float16 f13 ATTRIBUTE_UNUSED,
+ _Float16 f14 ATTRIBUTE_UNUSED,
+ _Float16 f15 ATTRIBUTE_UNUSED,
+ _Float16 f16 ATTRIBUTE_UNUSED,
+ _Float16 f17 ATTRIBUTE_UNUSED,
+ _Float16 f18 ATTRIBUTE_UNUSED,
+ _Float16 f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float16_arguments;
+}
+
+void
+fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED,
+ float f8 ATTRIBUTE_UNUSED,
+ float f9 ATTRIBUTE_UNUSED,
+ float f10 ATTRIBUTE_UNUSED,
+ float f11 ATTRIBUTE_UNUSED,
+ float f12 ATTRIBUTE_UNUSED,
+ float f13 ATTRIBUTE_UNUSED,
+ float f14 ATTRIBUTE_UNUSED,
+ float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED,
+ float f8 ATTRIBUTE_UNUSED,
+ float f9 ATTRIBUTE_UNUSED,
+ float f10 ATTRIBUTE_UNUSED,
+ float f11 ATTRIBUTE_UNUSED,
+ float f12 ATTRIBUTE_UNUSED,
+ float f13 ATTRIBUTE_UNUSED,
+ float f14 ATTRIBUTE_UNUSED,
+ float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED,
+ float f8 ATTRIBUTE_UNUSED,
+ float f9 ATTRIBUTE_UNUSED,
+ float f10 ATTRIBUTE_UNUSED,
+ float f11 ATTRIBUTE_UNUSED,
+ float f12 ATTRIBUTE_UNUSED,
+ float f13 ATTRIBUTE_UNUSED,
+ float f14 ATTRIBUTE_UNUSED,
+ float f15 ATTRIBUTE_UNUSED,
+ float f16 ATTRIBUTE_UNUSED,
+ float f17 ATTRIBUTE_UNUSED,
+ float f18 ATTRIBUTE_UNUSED,
+ float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+ assert (values_float.f16 == f16);
+ assert (values_float.f17 == f17);
+ assert (values_float.f18 == f18);
+ assert (values_float.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED,
+ float f1 ATTRIBUTE_UNUSED,
+ float f2 ATTRIBUTE_UNUSED,
+ float f3 ATTRIBUTE_UNUSED,
+ float f4 ATTRIBUTE_UNUSED,
+ float f5 ATTRIBUTE_UNUSED,
+ float f6 ATTRIBUTE_UNUSED,
+ float f7 ATTRIBUTE_UNUSED,
+ float f8 ATTRIBUTE_UNUSED,
+ float f9 ATTRIBUTE_UNUSED,
+ float f10 ATTRIBUTE_UNUSED,
+ float f11 ATTRIBUTE_UNUSED,
+ float f12 ATTRIBUTE_UNUSED,
+ float f13 ATTRIBUTE_UNUSED,
+ float f14 ATTRIBUTE_UNUSED,
+ float f15 ATTRIBUTE_UNUSED,
+ float f16 ATTRIBUTE_UNUSED,
+ float f17 ATTRIBUTE_UNUSED,
+ float f18 ATTRIBUTE_UNUSED,
+ float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED,
+ double f8 ATTRIBUTE_UNUSED,
+ double f9 ATTRIBUTE_UNUSED,
+ double f10 ATTRIBUTE_UNUSED,
+ double f11 ATTRIBUTE_UNUSED,
+ double f12 ATTRIBUTE_UNUSED,
+ double f13 ATTRIBUTE_UNUSED,
+ double f14 ATTRIBUTE_UNUSED,
+ double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED,
+ double f8 ATTRIBUTE_UNUSED,
+ double f9 ATTRIBUTE_UNUSED,
+ double f10 ATTRIBUTE_UNUSED,
+ double f11 ATTRIBUTE_UNUSED,
+ double f12 ATTRIBUTE_UNUSED,
+ double f13 ATTRIBUTE_UNUSED,
+ double f14 ATTRIBUTE_UNUSED,
+ double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED,
+ double f8 ATTRIBUTE_UNUSED,
+ double f9 ATTRIBUTE_UNUSED,
+ double f10 ATTRIBUTE_UNUSED,
+ double f11 ATTRIBUTE_UNUSED,
+ double f12 ATTRIBUTE_UNUSED,
+ double f13 ATTRIBUTE_UNUSED,
+ double f14 ATTRIBUTE_UNUSED,
+ double f15 ATTRIBUTE_UNUSED,
+ double f16 ATTRIBUTE_UNUSED,
+ double f17 ATTRIBUTE_UNUSED,
+ double f18 ATTRIBUTE_UNUSED,
+ double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+ assert (values_double.f16 == f16);
+ assert (values_double.f17 == f17);
+ assert (values_double.f18 == f18);
+ assert (values_double.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED,
+ double f1 ATTRIBUTE_UNUSED,
+ double f2 ATTRIBUTE_UNUSED,
+ double f3 ATTRIBUTE_UNUSED,
+ double f4 ATTRIBUTE_UNUSED,
+ double f5 ATTRIBUTE_UNUSED,
+ double f6 ATTRIBUTE_UNUSED,
+ double f7 ATTRIBUTE_UNUSED,
+ double f8 ATTRIBUTE_UNUSED,
+ double f9 ATTRIBUTE_UNUSED,
+ double f10 ATTRIBUTE_UNUSED,
+ double f11 ATTRIBUTE_UNUSED,
+ double f12 ATTRIBUTE_UNUSED,
+ double f13 ATTRIBUTE_UNUSED,
+ double f14 ATTRIBUTE_UNUSED,
+ double f15 ATTRIBUTE_UNUSED,
+ double f16 ATTRIBUTE_UNUSED,
+ double f17 ATTRIBUTE_UNUSED,
+ double f18 ATTRIBUTE_UNUSED,
+ double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+
+}
+
+void
+fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED,
+ ldouble f8 ATTRIBUTE_UNUSED,
+ ldouble f9 ATTRIBUTE_UNUSED,
+ ldouble f10 ATTRIBUTE_UNUSED,
+ ldouble f11 ATTRIBUTE_UNUSED,
+ ldouble f12 ATTRIBUTE_UNUSED,
+ ldouble f13 ATTRIBUTE_UNUSED,
+ ldouble f14 ATTRIBUTE_UNUSED,
+ ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+
+}
+
+void
+fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED,
+ ldouble f8 ATTRIBUTE_UNUSED,
+ ldouble f9 ATTRIBUTE_UNUSED,
+ ldouble f10 ATTRIBUTE_UNUSED,
+ ldouble f11 ATTRIBUTE_UNUSED,
+ ldouble f12 ATTRIBUTE_UNUSED,
+ ldouble f13 ATTRIBUTE_UNUSED,
+ ldouble f14 ATTRIBUTE_UNUSED,
+ ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED,
+ ldouble f8 ATTRIBUTE_UNUSED,
+ ldouble f9 ATTRIBUTE_UNUSED,
+ ldouble f10 ATTRIBUTE_UNUSED,
+ ldouble f11 ATTRIBUTE_UNUSED,
+ ldouble f12 ATTRIBUTE_UNUSED,
+ ldouble f13 ATTRIBUTE_UNUSED,
+ ldouble f14 ATTRIBUTE_UNUSED,
+ ldouble f15 ATTRIBUTE_UNUSED,
+ ldouble f16 ATTRIBUTE_UNUSED,
+ ldouble f17 ATTRIBUTE_UNUSED,
+ ldouble f18 ATTRIBUTE_UNUSED,
+ ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+ assert (values_ldouble.f16 == f16);
+ assert (values_ldouble.f17 == f17);
+ assert (values_ldouble.f18 == f18);
+ assert (values_ldouble.f19 == f19);
+
+}
+
+void
+fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED,
+ ldouble f1 ATTRIBUTE_UNUSED,
+ ldouble f2 ATTRIBUTE_UNUSED,
+ ldouble f3 ATTRIBUTE_UNUSED,
+ ldouble f4 ATTRIBUTE_UNUSED,
+ ldouble f5 ATTRIBUTE_UNUSED,
+ ldouble f6 ATTRIBUTE_UNUSED,
+ ldouble f7 ATTRIBUTE_UNUSED,
+ ldouble f8 ATTRIBUTE_UNUSED,
+ ldouble f9 ATTRIBUTE_UNUSED,
+ ldouble f10 ATTRIBUTE_UNUSED,
+ ldouble f11 ATTRIBUTE_UNUSED,
+ ldouble f12 ATTRIBUTE_UNUSED,
+ ldouble f13 ATTRIBUTE_UNUSED,
+ ldouble f14 ATTRIBUTE_UNUSED,
+ ldouble f15 ATTRIBUTE_UNUSED,
+ ldouble f16 ATTRIBUTE_UNUSED,
+ ldouble f17 ATTRIBUTE_UNUSED,
+ ldouble f18 ATTRIBUTE_UNUSED,
+ ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+#define def_check_float16_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6,\
+ _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float16_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
+ _f7, _f8, _f9, _f10, _f11, _f12, _f13, \
+ _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+ _f10, _f11, _f12, _f13, _f14, _f15); \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+ _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float16_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
+ _f7, _f8, _f9, _f10, _f11, _f12, \
+ _f13, _f14, _f15, _f16, _f17, \
+ _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, \
+ _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, \
+ _f17, _f18, _f19); \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
+ _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, \
+ _f18, _f19);
+
+
+#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_float_registers; \
+ fregs.F0._ ## TYPE [0] = _f0; \
+ fregs.F1._ ## TYPE [0] = _f1; \
+ fregs.F2._ ## TYPE [0] = _f2; \
+ fregs.F3._ ## TYPE [0] = _f3; \
+ fregs.F4._ ## TYPE [0] = _f4; \
+ fregs.F5._ ## TYPE [0] = _f5; \
+ fregs.F6._ ## TYPE [0] = _f6; \
+ fregs.F7._ ## TYPE [0] = _f7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_x87_registers; \
+ num_fregs = 0; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_x87_registers; \
+ num_fregs = 0; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_x87_registers; \
+ num_fregs = 0; \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+void
+test_float16_on_stack ()
+{
+ def_check_float16_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+ fun_check_float16_passing_8_values,
+ fun_check_float16_passing_8_regs, _Float16);
+
+ def_check_float16_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47,
+ fun_check_float16_passing_16_values,
+ fun_check_float16_passing_16_regs, _Float16);
+}
+
+void
+test_too_many_float16 ()
+{
+ def_check_float16_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ fun_check_float16_passing_20_values,
+ fun_check_float16_passing_20_regs, _Float16);
+}
+
+void
+test_floats_on_stack ()
+{
+ def_check_float_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+ fun_check_float_passing_float8_values,
+ fun_check_float_passing_float8_regs, float);
+
+ def_check_float_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47,
+ fun_check_float_passing_float16_values,
+ fun_check_float_passing_float16_regs, float);
+}
+
+void
+test_too_many_floats ()
+{
+ def_check_float_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ fun_check_float_passing_float20_values,
+ fun_check_float_passing_float20_regs, float);
+}
+
+void
+test_doubles_on_stack ()
+{
+ def_check_float_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+ fun_check_float_passing_double8_values,
+ fun_check_float_passing_double8_regs, double);
+
+ def_check_float_passing16 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47,
+ fun_check_float_passing_double16_values,
+ fun_check_float_passing_double16_regs, double);
+}
+
+void
+test_too_many_doubles ()
+{
+ def_check_float_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ fun_check_float_passing_double20_values,
+ fun_check_float_passing_double20_regs, double);
+}
+
+void
+test_long_doubles_on_stack ()
+{
+ def_check_x87_passing8 (32, 33, 34, 35, 36, 37, 38, 39,
+ fun_check_x87_passing_ldouble8_values,
+ fun_check_x87_passing_ldouble8_regs, ldouble);
+}
+
+void
+test_too_many_long_doubles ()
+{
+ def_check_x87_passing20 (32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51,
+ fun_check_x87_passing_ldouble20_values,
+ fun_check_x87_passing_ldouble20_regs, ldouble);
+}
+
+void
+test_float128s_on_stack ()
+{
+}
+
+void
+test_too_many_float128s ()
+{
+}
+
+
+static void
+do_test (void)
+{
+ test_float16_on_stack ();
+ test_too_many_float16 ();
+ test_floats_on_stack ();
+ test_too_many_floats ();
+ test_doubles_on_stack ();
+ test_too_many_doubles ();
+ test_long_doubles_on_stack ();
+ test_too_many_long_doubles ();
+ test_float128s_on_stack ();
+ test_too_many_float128s ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c
new file mode 100644
index 0000000..66c27ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_m64m128.c
@@ -0,0 +1,510 @@
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
+ i16, i17, i18, i19, i20, i21, i22, i23;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m64_8_values (__m64 i0 ATTRIBUTE_UNUSED,
+ __m64 i1 ATTRIBUTE_UNUSED,
+ __m64 i2 ATTRIBUTE_UNUSED,
+ __m64 i3 ATTRIBUTE_UNUSED,
+ __m64 i4 ATTRIBUTE_UNUSED,
+ __m64 i5 ATTRIBUTE_UNUSED,
+ __m64 i6 ATTRIBUTE_UNUSED,
+ __m64 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m64);
+ compare (values.i1, i1, __m64);
+ compare (values.i2, i2, __m64);
+ compare (values.i3, i3, __m64);
+ compare (values.i4, i4, __m64);
+ compare (values.i5, i5, __m64);
+ compare (values.i6, i6, __m64);
+ compare (values.i7, i7, __m64);
+}
+
+void
+fun_check_passing_m64_8_regs (__m64 i0 ATTRIBUTE_UNUSED,
+ __m64 i1 ATTRIBUTE_UNUSED,
+ __m64 i2 ATTRIBUTE_UNUSED,
+ __m64 i3 ATTRIBUTE_UNUSED,
+ __m64 i4 ATTRIBUTE_UNUSED,
+ __m64 i5 ATTRIBUTE_UNUSED,
+ __m64 i6 ATTRIBUTE_UNUSED,
+ __m64 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m64_arguments;
+}
+
+void
+fun_check_passing_m64_20_values (__m64 i0 ATTRIBUTE_UNUSED,
+ __m64 i1 ATTRIBUTE_UNUSED,
+ __m64 i2 ATTRIBUTE_UNUSED,
+ __m64 i3 ATTRIBUTE_UNUSED,
+ __m64 i4 ATTRIBUTE_UNUSED,
+ __m64 i5 ATTRIBUTE_UNUSED,
+ __m64 i6 ATTRIBUTE_UNUSED,
+ __m64 i7 ATTRIBUTE_UNUSED,
+ __m64 i8 ATTRIBUTE_UNUSED,
+ __m64 i9 ATTRIBUTE_UNUSED,
+ __m64 i10 ATTRIBUTE_UNUSED,
+ __m64 i11 ATTRIBUTE_UNUSED,
+ __m64 i12 ATTRIBUTE_UNUSED,
+ __m64 i13 ATTRIBUTE_UNUSED,
+ __m64 i14 ATTRIBUTE_UNUSED,
+ __m64 i15 ATTRIBUTE_UNUSED,
+ __m64 i16 ATTRIBUTE_UNUSED,
+ __m64 i17 ATTRIBUTE_UNUSED,
+ __m64 i18 ATTRIBUTE_UNUSED,
+ __m64 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m64);
+ compare (values.i1, i1, __m64);
+ compare (values.i2, i2, __m64);
+ compare (values.i3, i3, __m64);
+ compare (values.i4, i4, __m64);
+ compare (values.i5, i5, __m64);
+ compare (values.i6, i6, __m64);
+ compare (values.i7, i7, __m64);
+ compare (values.i8, i8, __m64);
+ compare (values.i9, i9, __m64);
+ compare (values.i10, i10, __m64);
+ compare (values.i11, i11, __m64);
+ compare (values.i12, i12, __m64);
+ compare (values.i13, i13, __m64);
+ compare (values.i14, i14, __m64);
+ compare (values.i15, i15, __m64);
+ compare (values.i16, i16, __m64);
+ compare (values.i17, i17, __m64);
+ compare (values.i18, i18, __m64);
+ compare (values.i19, i19, __m64);
+}
+
+void
+fun_check_passing_m64_20_regs (__m64 i0 ATTRIBUTE_UNUSED,
+ __m64 i1 ATTRIBUTE_UNUSED,
+ __m64 i2 ATTRIBUTE_UNUSED,
+ __m64 i3 ATTRIBUTE_UNUSED,
+ __m64 i4 ATTRIBUTE_UNUSED,
+ __m64 i5 ATTRIBUTE_UNUSED,
+ __m64 i6 ATTRIBUTE_UNUSED,
+ __m64 i7 ATTRIBUTE_UNUSED,
+ __m64 i8 ATTRIBUTE_UNUSED,
+ __m64 i9 ATTRIBUTE_UNUSED,
+ __m64 i10 ATTRIBUTE_UNUSED,
+ __m64 i11 ATTRIBUTE_UNUSED,
+ __m64 i12 ATTRIBUTE_UNUSED,
+ __m64 i13 ATTRIBUTE_UNUSED,
+ __m64 i14 ATTRIBUTE_UNUSED,
+ __m64 i15 ATTRIBUTE_UNUSED,
+ __m64 i16 ATTRIBUTE_UNUSED,
+ __m64 i17 ATTRIBUTE_UNUSED,
+ __m64 i18 ATTRIBUTE_UNUSED,
+ __m64 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m64_arguments;
+}
+
+void
+fun_check_passing_m128_8_values (__m128 i0 ATTRIBUTE_UNUSED,
+ __m128 i1 ATTRIBUTE_UNUSED,
+ __m128 i2 ATTRIBUTE_UNUSED,
+ __m128 i3 ATTRIBUTE_UNUSED,
+ __m128 i4 ATTRIBUTE_UNUSED,
+ __m128 i5 ATTRIBUTE_UNUSED,
+ __m128 i6 ATTRIBUTE_UNUSED,
+ __m128 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m128);
+ compare (values.i1, i1, __m128);
+ compare (values.i2, i2, __m128);
+ compare (values.i3, i3, __m128);
+ compare (values.i4, i4, __m128);
+ compare (values.i5, i5, __m128);
+ compare (values.i6, i6, __m128);
+ compare (values.i7, i7, __m128);
+}
+
+void
+fun_check_passing_m128h_8_values (__m128h i0 ATTRIBUTE_UNUSED,
+ __m128h i1 ATTRIBUTE_UNUSED,
+ __m128h i2 ATTRIBUTE_UNUSED,
+ __m128h i3 ATTRIBUTE_UNUSED,
+ __m128h i4 ATTRIBUTE_UNUSED,
+ __m128h i5 ATTRIBUTE_UNUSED,
+ __m128h i6 ATTRIBUTE_UNUSED,
+ __m128h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m128h);
+ compare (values.i1, i1, __m128h);
+ compare (values.i2, i2, __m128h);
+ compare (values.i3, i3, __m128h);
+ compare (values.i4, i4, __m128h);
+ compare (values.i5, i5, __m128h);
+ compare (values.i6, i6, __m128h);
+ compare (values.i7, i7, __m128h);
+}
+
+void
+fun_check_passing_m128_8_regs (__m128 i0 ATTRIBUTE_UNUSED,
+ __m128 i1 ATTRIBUTE_UNUSED,
+ __m128 i2 ATTRIBUTE_UNUSED,
+ __m128 i3 ATTRIBUTE_UNUSED,
+ __m128 i4 ATTRIBUTE_UNUSED,
+ __m128 i5 ATTRIBUTE_UNUSED,
+ __m128 i6 ATTRIBUTE_UNUSED,
+ __m128 i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m128_arguments;
+}
+
+void
+fun_check_passing_m128h_8_regs (__m128h i0 ATTRIBUTE_UNUSED,
+ __m128h i1 ATTRIBUTE_UNUSED,
+ __m128h i2 ATTRIBUTE_UNUSED,
+ __m128h i3 ATTRIBUTE_UNUSED,
+ __m128h i4 ATTRIBUTE_UNUSED,
+ __m128h i5 ATTRIBUTE_UNUSED,
+ __m128h i6 ATTRIBUTE_UNUSED,
+ __m128h i7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m128_arguments;
+}
+
+void
+fun_check_passing_m128_20_values (__m128 i0 ATTRIBUTE_UNUSED,
+ __m128 i1 ATTRIBUTE_UNUSED,
+ __m128 i2 ATTRIBUTE_UNUSED,
+ __m128 i3 ATTRIBUTE_UNUSED,
+ __m128 i4 ATTRIBUTE_UNUSED,
+ __m128 i5 ATTRIBUTE_UNUSED,
+ __m128 i6 ATTRIBUTE_UNUSED,
+ __m128 i7 ATTRIBUTE_UNUSED,
+ __m128 i8 ATTRIBUTE_UNUSED,
+ __m128 i9 ATTRIBUTE_UNUSED,
+ __m128 i10 ATTRIBUTE_UNUSED,
+ __m128 i11 ATTRIBUTE_UNUSED,
+ __m128 i12 ATTRIBUTE_UNUSED,
+ __m128 i13 ATTRIBUTE_UNUSED,
+ __m128 i14 ATTRIBUTE_UNUSED,
+ __m128 i15 ATTRIBUTE_UNUSED,
+ __m128 i16 ATTRIBUTE_UNUSED,
+ __m128 i17 ATTRIBUTE_UNUSED,
+ __m128 i18 ATTRIBUTE_UNUSED,
+ __m128 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m128);
+ compare (values.i1, i1, __m128);
+ compare (values.i2, i2, __m128);
+ compare (values.i3, i3, __m128);
+ compare (values.i4, i4, __m128);
+ compare (values.i5, i5, __m128);
+ compare (values.i6, i6, __m128);
+ compare (values.i7, i7, __m128);
+ compare (values.i8, i8, __m128);
+ compare (values.i9, i9, __m128);
+ compare (values.i10, i10, __m128);
+ compare (values.i11, i11, __m128);
+ compare (values.i12, i12, __m128);
+ compare (values.i13, i13, __m128);
+ compare (values.i14, i14, __m128);
+ compare (values.i15, i15, __m128);
+ compare (values.i16, i16, __m128);
+ compare (values.i17, i17, __m128);
+ compare (values.i18, i18, __m128);
+ compare (values.i19, i19, __m128);
+}
+
+void
+fun_check_passing_m128h_20_values (__m128h i0 ATTRIBUTE_UNUSED,
+ __m128h i1 ATTRIBUTE_UNUSED,
+ __m128h i2 ATTRIBUTE_UNUSED,
+ __m128h i3 ATTRIBUTE_UNUSED,
+ __m128h i4 ATTRIBUTE_UNUSED,
+ __m128h i5 ATTRIBUTE_UNUSED,
+ __m128h i6 ATTRIBUTE_UNUSED,
+ __m128h i7 ATTRIBUTE_UNUSED,
+ __m128h i8 ATTRIBUTE_UNUSED,
+ __m128h i9 ATTRIBUTE_UNUSED,
+ __m128h i10 ATTRIBUTE_UNUSED,
+ __m128h i11 ATTRIBUTE_UNUSED,
+ __m128h i12 ATTRIBUTE_UNUSED,
+ __m128h i13 ATTRIBUTE_UNUSED,
+ __m128h i14 ATTRIBUTE_UNUSED,
+ __m128h i15 ATTRIBUTE_UNUSED,
+ __m128h i16 ATTRIBUTE_UNUSED,
+ __m128h i17 ATTRIBUTE_UNUSED,
+ __m128h i18 ATTRIBUTE_UNUSED,
+ __m128h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ compare (values.i0, i0, __m128h);
+ compare (values.i1, i1, __m128h);
+ compare (values.i2, i2, __m128h);
+ compare (values.i3, i3, __m128h);
+ compare (values.i4, i4, __m128h);
+ compare (values.i5, i5, __m128h);
+ compare (values.i6, i6, __m128h);
+ compare (values.i7, i7, __m128h);
+ compare (values.i8, i8, __m128h);
+ compare (values.i9, i9, __m128h);
+ compare (values.i10, i10, __m128h);
+ compare (values.i11, i11, __m128h);
+ compare (values.i12, i12, __m128h);
+ compare (values.i13, i13, __m128h);
+ compare (values.i14, i14, __m128h);
+ compare (values.i15, i15, __m128h);
+ compare (values.i16, i16, __m128h);
+ compare (values.i17, i17, __m128h);
+ compare (values.i18, i18, __m128h);
+ compare (values.i19, i19, __m128h);
+}
+
+void
+fun_check_passing_m128_20_regs (__m128 i0 ATTRIBUTE_UNUSED,
+ __m128 i1 ATTRIBUTE_UNUSED,
+ __m128 i2 ATTRIBUTE_UNUSED,
+ __m128 i3 ATTRIBUTE_UNUSED,
+ __m128 i4 ATTRIBUTE_UNUSED,
+ __m128 i5 ATTRIBUTE_UNUSED,
+ __m128 i6 ATTRIBUTE_UNUSED,
+ __m128 i7 ATTRIBUTE_UNUSED,
+ __m128 i8 ATTRIBUTE_UNUSED,
+ __m128 i9 ATTRIBUTE_UNUSED,
+ __m128 i10 ATTRIBUTE_UNUSED,
+ __m128 i11 ATTRIBUTE_UNUSED,
+ __m128 i12 ATTRIBUTE_UNUSED,
+ __m128 i13 ATTRIBUTE_UNUSED,
+ __m128 i14 ATTRIBUTE_UNUSED,
+ __m128 i15 ATTRIBUTE_UNUSED,
+ __m128 i16 ATTRIBUTE_UNUSED,
+ __m128 i17 ATTRIBUTE_UNUSED,
+ __m128 i18 ATTRIBUTE_UNUSED,
+ __m128 i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m128_arguments;
+}
+
+void
+fun_check_passing_m128h_20_regs (__m128h i0 ATTRIBUTE_UNUSED,
+ __m128h i1 ATTRIBUTE_UNUSED,
+ __m128h i2 ATTRIBUTE_UNUSED,
+ __m128h i3 ATTRIBUTE_UNUSED,
+ __m128h i4 ATTRIBUTE_UNUSED,
+ __m128h i5 ATTRIBUTE_UNUSED,
+ __m128h i6 ATTRIBUTE_UNUSED,
+ __m128h i7 ATTRIBUTE_UNUSED,
+ __m128h i8 ATTRIBUTE_UNUSED,
+ __m128h i9 ATTRIBUTE_UNUSED,
+ __m128h i10 ATTRIBUTE_UNUSED,
+ __m128h i11 ATTRIBUTE_UNUSED,
+ __m128h i12 ATTRIBUTE_UNUSED,
+ __m128h i13 ATTRIBUTE_UNUSED,
+ __m128h i14 ATTRIBUTE_UNUSED,
+ __m128h i15 ATTRIBUTE_UNUSED,
+ __m128h i16 ATTRIBUTE_UNUSED,
+ __m128h i17 ATTRIBUTE_UNUSED,
+ __m128h i18 ATTRIBUTE_UNUSED,
+ __m128h i19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_m128_arguments;
+}
+
+#define def_check_int_passing8(_i0, _i1, _i2, _i3, \
+ _i4, _i5, _i6, _i7, \
+ _func1, _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
+ clear_float_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
+
+#define def_check_int_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11, _i12, _i13, \
+ _i14, _i15, _i16, _i17, _i18, _i19, \
+ _func1, _func2, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ values.i10.TYPE[0] = _i10; \
+ values.i11.TYPE[0] = _i11; \
+ values.i12.TYPE[0] = _i12; \
+ values.i13.TYPE[0] = _i13; \
+ values.i14.TYPE[0] = _i14; \
+ values.i15.TYPE[0] = _i15; \
+ values.i16.TYPE[0] = _i16; \
+ values.i17.TYPE[0] = _i17; \
+ values.i18.TYPE[0] = _i18; \
+ values.i19.TYPE[0] = _i19; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, \
+ _i17, _i18, _i19); \
+ clear_float_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ num_fregs = 8; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, \
+ _i17, _i18, _i19);
+
+void
+test_m64_on_stack ()
+{
+ __m64 x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m64){32 + i, 0};
+ pass = "m64-8";
+ def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m64_8_values,
+ fun_check_passing_m64_8_regs, _m64);
+}
+
+void
+test_too_many_m64 ()
+{
+ __m64 x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m64){32 + i, 0};
+ pass = "m64-20";
+ def_check_int_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14],
+ x[15], x[16], x[17], x[18], x[19],
+ fun_check_passing_m64_20_values,
+ fun_check_passing_m64_20_regs, _m64);
+}
+
+void
+test_m128_on_stack ()
+{
+ __m128 x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m128){32 + i, 0, 0, 0};
+ pass = "m128-8";
+ def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m128_8_values,
+ fun_check_passing_m128_8_regs, _m128);
+}
+
+void
+test_m128h_on_stack ()
+{
+ __m128h x[8];
+ int i;
+ for (i = 0; i < 8; i++)
+ x[i] = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+ 6.6f16, 7.7f16, 8.8f16};
+ pass = "m128h-8";
+ def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ fun_check_passing_m128h_8_values,
+ fun_check_passing_m128h_8_regs, _m128h);
+}
+
+void
+test_too_many_m128 ()
+{
+ __m128 x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m128){32 + i, 0, 0, 0};
+ pass = "m128-20";
+ def_check_int_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14],
+ x[15], x[16], x[17], x[18], x[19],
+ fun_check_passing_m128_20_values,
+ fun_check_passing_m128_20_regs, _m128);
+}
+
+void
+test_too_many_m128h ()
+{
+ __m128h x[20];
+ int i;
+ for (i = 0; i < 20; i++)
+ x[i] = (__m128h){1.1f16, 2.2f16, 3.3f16, 4.4f16, 5.5f16,
+ 6.6f16, 7.7f16, 8.8f16};
+ pass = "m128h-20";
+ def_check_int_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14],
+ x[15], x[16], x[17], x[18], x[19],
+ fun_check_passing_m128h_20_values,
+ fun_check_passing_m128h_20_regs, _m128h);
+}
+
+static void
+do_test (void)
+{
+ test_m64_on_stack ();
+ test_too_many_m64 ();
+ test_m128_on_stack ();
+ test_too_many_m128 ();
+ test_m128h_on_stack ();
+ test_too_many_m128h ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c
new file mode 100644
index 0000000..4d1956a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_structs.c
@@ -0,0 +1,332 @@
+/* This tests passing of structs. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "args.h"
+#include <complex.h>
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long long l;
+};
+
+struct long2_struct
+{
+ long long l1, l2;
+};
+
+struct long3_struct
+{
+ long long l1, l2, l3;
+};
+
+
+/* Check that the struct is passed as the individual members in iregs. */
+void
+check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing3 (struct long2_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing4 (struct long3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == rsp+8);
+ assert ((unsigned long)&ls.l2 == rsp+16);
+ assert ((unsigned long)&ls.l3 == rsp+24);
+}
+
+#ifdef CHECK_M64_M128
+struct m128_struct
+{
+ __m128 x;
+};
+
+struct m128_2_struct
+{
+ __m128 x1, x2;
+};
+
+/* Check that the struct is passed as the individual members in fregs. */
+void
+check_struct_passing5 (struct m128_struct ms1 ATTRIBUTE_UNUSED,
+ struct m128_struct ms2 ATTRIBUTE_UNUSED,
+ struct m128_struct ms3 ATTRIBUTE_UNUSED,
+ struct m128_struct ms4 ATTRIBUTE_UNUSED,
+ struct m128_struct ms5 ATTRIBUTE_UNUSED,
+ struct m128_struct ms6 ATTRIBUTE_UNUSED,
+ struct m128_struct ms7 ATTRIBUTE_UNUSED,
+ struct m128_struct ms8 ATTRIBUTE_UNUSED)
+{
+ check_m128_arguments;
+}
+
+void
+check_struct_passing6 (struct m128_2_struct ms ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ms.x1 == rsp+8);
+ assert ((unsigned long)&ms.x2 == rsp+24);
+}
+#endif
+
+struct flex1_struct
+{
+ long long i;
+ long long flex[];
+};
+
+struct flex2_struct
+{
+ long long i;
+ long long flex[0];
+};
+
+void
+check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct complex1_struct
+{
+ int c;
+ __complex__ float x;
+};
+
+struct complex1a_struct
+{
+ long long l;
+ float f;
+};
+
+struct complex2_struct
+{
+ int c;
+ __complex__ float x;
+ float y;
+};
+
+struct complex2a_struct
+{
+ long long l;
+ double d;
+};
+
+struct complex3_struct
+{
+ int c;
+ __complex__ _Float16 x;
+};
+
+struct complex3a_struct
+{
+ long long l;
+ _Float16 f;
+};
+
+struct complex4_struct
+{
+ int c;
+ __complex__ _Float16 x;
+ _Float16 y;
+};
+
+struct complex4a_struct
+{
+ long long l;
+ _Float16 f;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+ check_float_arguments;
+}
+
+void
+check_struct_passing10 (struct complex2_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+ check_double_arguments;
+}
+
+void
+check_struct_passing11 (struct complex3_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+ check_float16_arguments;
+}
+
+void
+check_struct_passing12 (struct complex4_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+ check_float16_arguments;
+}
+
+static struct flex1_struct f1s = { 60, { } };
+static struct flex2_struct f2s = { 61, { } };
+
+static void
+do_test (void)
+{
+ struct int_struct is = { 48 };
+ struct long_struct ls = { 49 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct long2_struct l2s = { 50, 51 };
+ struct long3_struct l3s = { 52, 53, 54 };
+#endif
+#ifdef CHECK_M64_M128
+ struct m128_struct m128s[8];
+ struct m128_2_struct m128_2s = {
+ { 48.394, 39.3, -397.9, 3484.9 },
+ { -8.394, -93.3, 7.9, 84.94 }
+ };
+ int i;
+#endif
+ struct complex1_struct c1s = { 4, ( -13.4 + 3.5*I ) };
+ union
+ {
+ struct complex1_struct c;
+ struct complex1a_struct u;
+ } c1u;
+ struct complex2_struct c2s = { 4, ( -13.4 + 3.5*I ), -34.5 };
+ union
+ {
+ struct complex2_struct c;
+ struct complex2a_struct u;
+ } c2u;
+
+ struct complex3_struct c3s = { 4, ( -13.4 + 3.5*I ) };
+ union
+ {
+ struct complex3_struct c;
+ struct complex3a_struct u;
+ } c3u;
+
+ struct complex4_struct c4s = { 4, ( -13.4 + 3.5*I ), -34.5 };
+ union
+ {
+ struct complex4_struct c;
+ struct complex4a_struct u;
+ } c4u;
+
+ clear_struct_registers;
+ iregs.I0 = is.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing1)(is);
+
+ clear_struct_registers;
+ iregs.I0 = ls.l;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing2)(ls);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ iregs.I0 = l2s.l1;
+ iregs.I1 = l2s.l2;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing3)(l2s);
+ WRAP_CALL (check_struct_passing4)(l3s);
+#endif
+
+#ifdef CHECK_M64_M128
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ m128s[i].x = (__m128){32+i, 0, i, 0};
+ (&fregs.xmm0)[i]._m128[0] = m128s[i].x;
+ }
+ num_fregs = 8;
+ clear_float_hardware_registers;
+ WRAP_CALL (check_struct_passing5)(m128s[0], m128s[1], m128s[2], m128s[3],
+ m128s[4], m128s[5], m128s[6], m128s[7]);
+ WRAP_CALL (check_struct_passing6)(m128_2s);
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = f1s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing7)(f1s);
+
+ clear_struct_registers;
+ iregs.I0 = f2s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing8)(f2s);
+
+ clear_struct_registers;
+ c1u.c = c1s;
+ iregs.I0 = c1u.u.l;
+ num_iregs = 1;
+ fregs.xmm0._float [0] = c1u.u.f;
+ num_fregs = 1;
+ clear_int_hardware_registers;
+ clear_float_hardware_registers;
+ WRAP_CALL (check_struct_passing9)(c1s);
+
+ clear_struct_registers;
+ c2u.c = c2s;
+ iregs.I0 = c2u.u.l;
+ num_iregs = 1;
+ fregs.xmm0._double[0] = c2u.u.d;
+ num_fregs = 1;
+ clear_int_hardware_registers;
+ clear_float_hardware_registers;
+ WRAP_CALL (check_struct_passing10)(c2s);
+
+ clear_struct_registers;
+ c3u.c = c3s;
+ iregs.I0 = c3u.u.l;
+ num_iregs = 1;
+ num_fregs = 0;
+ clear_int_hardware_registers;
+ clear_float_hardware_registers;
+ WRAP_CALL (check_struct_passing11)(c3s);
+
+ clear_struct_registers;
+ c4u.c = c4s;
+ iregs.I0 = c4u.u.l;
+ num_iregs = 1;
+ fregs.xmm0.__Float16 [0] = c4u.u.f;
+ num_fregs = 1;
+ clear_int_hardware_registers;
+ clear_float_hardware_registers;
+ WRAP_CALL (check_struct_passing12)(c4s);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c
new file mode 100644
index 0000000..640b305
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_passing_unions.c
@@ -0,0 +1,335 @@
+/* This tests passing of structs. */
+
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct long_struct ls;
+ union un1 un;
+};
+
+
+void
+check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+
+#ifdef CHECK_M64_M128
+union un4
+{
+ __m128 x;
+ float f;
+};
+
+union un5
+{
+ __m128 x;
+ long i;
+};
+
+void
+check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
+ union un4 u2 ATTRIBUTE_UNUSED,
+ union un4 u3 ATTRIBUTE_UNUSED,
+ union un4 u4 ATTRIBUTE_UNUSED,
+ union un4 u5 ATTRIBUTE_UNUSED,
+ union un4 u6 ATTRIBUTE_UNUSED,
+ union un4 u7 ATTRIBUTE_UNUSED,
+ union un4 u8 ATTRIBUTE_UNUSED)
+{
+ check_m128_arguments;
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+ check_vector_arguments(m128, 8);
+}
+
+union un4a
+{
+ __m128 x;
+ _Float16 f;
+};
+
+void
+check_union_passing4a(union un4a u1 ATTRIBUTE_UNUSED,
+ union un4a u2 ATTRIBUTE_UNUSED,
+ union un4a u3 ATTRIBUTE_UNUSED,
+ union un4a u4 ATTRIBUTE_UNUSED,
+ union un4a u5 ATTRIBUTE_UNUSED,
+ union un4a u6 ATTRIBUTE_UNUSED,
+ union un4a u7 ATTRIBUTE_UNUSED,
+ union un4a u8 ATTRIBUTE_UNUSED)
+{
+ check_m128_arguments;
+}
+
+union un4b
+{
+ __m128h x;
+ _Float16 f;
+};
+
+void
+check_union_passing4b(union un4b u1 ATTRIBUTE_UNUSED,
+ union un4b u2 ATTRIBUTE_UNUSED,
+ union un4b u3 ATTRIBUTE_UNUSED,
+ union un4b u4 ATTRIBUTE_UNUSED,
+ union un4b u5 ATTRIBUTE_UNUSED,
+ union un4b u6 ATTRIBUTE_UNUSED,
+ union un4b u7 ATTRIBUTE_UNUSED,
+ union un4b u8 ATTRIBUTE_UNUSED)
+{
+ check_m128_arguments;
+}
+
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing4a WRAP_CALL(check_union_passing4a)
+#define check_union_passing4b WRAP_CALL(check_union_passing4b)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+#endif
+
+union un6
+{
+ long double ld;
+ int i;
+};
+
+
+void
+check_union_passing6(union un6 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.ld == rsp+8);
+ assert ((unsigned long)&u.i == rsp+8);
+}
+
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+union un7
+{
+ long double ld;
+ _Float16 f;
+};
+
+void
+check_union_passing7(union un7 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.ld == rsp+8);
+ assert ((unsigned long)&u.f == rsp+8);
+}
+
+#define check_union_passing7 WRAP_CALL(check_union_passing7)
+
+union un8
+{
+ _Float16 f;
+ int i;
+};
+
+void
+check_union_passing8(union un8 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing8 WRAP_CALL(check_union_passing8)
+
+static void
+do_test (void)
+{
+ union un1 u1;
+#ifdef CHECK_LARGER_UNION_PASSING
+ union un2 u2;
+ union un3 u3;
+ struct int_struct is;
+ struct long_struct ls;
+#endif /* CHECK_LARGER_UNION_PASSING */
+#ifdef CHECK_M64_M128
+ union un4 u4[8];
+ union un4a u4a[8];
+ union un4b u4b[8];
+ union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
+ int i;
+#endif
+ union un6 u6;
+ union un7 u7;
+ union un8 u8;
+
+ /* Check a union with char, int. */
+ clear_struct_registers;
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.c = 32;
+ iregs.I0 = 32;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.i = 33;
+ iregs.I0 = 33;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+
+ /* Check a union with char, long, char. */
+#ifdef CHECK_LARGER_UNION_PASSING
+ clear_struct_registers;
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c1 = 34;
+ iregs.I0 = 34;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.l = 35;
+ iregs.I0 = 35;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c2 = 36;
+ iregs.I0 = 36;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+
+ /* check a union containing two structs and a union. */
+ clear_struct_registers;
+ is.i = 37;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.is = is;
+ iregs.I0 = 37;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ ls.l = 38;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.ls = ls;
+ iregs.I0 = 38;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.c = 39;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 39;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.i = 40;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 40;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+#endif /* CHECK_LARGER_UNION_PASSING */
+
+#ifdef CHECK_M64_M128
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u4[i].x = (__m128){32+i, 0, i, 0};
+ (&fregs.xmm0)[i]._m128[0] = u4[i].x;
+ }
+ num_fregs = 8;
+ clear_float_hardware_registers;
+ check_union_passing4(u4[0], u4[1], u4[2], u4[3],
+ u4[4], u4[5], u4[6], u4[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u4a[i].x = (__m128){32+i, 0, i, 0};
+ (&fregs.xmm0)[i]._m128[0] = u4[i].x;
+ }
+ num_fregs = 8;
+ clear_float_hardware_registers;
+ check_union_passing4a(u4a[0], u4a[1], u4a[2], u4a[3],
+ u4a[4], u4a[5], u4a[6], u4a[7]);
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ {
+ u4b[i].x = (__m128h){33+i, 0, i, 0, -i, 1, 2 * i, i + 8};
+ (&fregs.xmm0)[i]._m128h[0] = u4b[i].x;
+ }
+ num_fregs = 8;
+ clear_float_hardware_registers;
+ check_union_passing4b(u4b[0], u4b[1], u4b[2], u4b[3],
+ u4b[4], u4b[5], u4b[6], u4b[7]);
+
+ clear_struct_registers;
+ fregs.xmm0._m128[0] = u5.x;
+ num_fregs = 1;
+ num_iregs = 1;
+ iregs.I0 = u5.i;
+ clear_float_hardware_registers;
+ check_union_passing5(u5);
+#endif
+
+ u6.i = 2;
+ check_union_passing6(u6);
+
+ u7.f = 2.0f16;
+ check_union_passing7(u7);
+
+ clear_struct_registers;
+ u8.i = 8;
+ num_iregs = 1;
+ iregs.I0 = u8.i;
+ clear_int_hardware_registers;
+ check_union_passing8(u8);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c
new file mode 100644
index 0000000..5de18ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_struct_returning.c
@@ -0,0 +1,274 @@
+/* This tests returning of structures. */
+
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+unsigned int num_iregs, num_fregs;
+
+int current_test;
+int num_failed = 0;
+
+#undef assert
+#define assert(test) do { if (!(test)) {fprintf (stderr, "failed in test %d\n", current_test); num_failed++; } } while (0)
+
+#define xmm0h xmm_regs[0].__Float16
+#define xmm1h xmm_regs[1].__Float16
+#define xmm0f xmm_regs[0]._float
+#define xmm0d xmm_regs[0]._double
+#define xmm1f xmm_regs[1]._float
+#define xmm1d xmm_regs[1]._double
+
+typedef enum {
+ INT = 0,
+ SSE_H,
+ SSE_F,
+ SSE_D,
+ X87,
+ MEM,
+ INT_SSE,
+ SSE_INT,
+ SSE_F_V,
+ SSE_F_H,
+ SSE_F_H8
+} Type;
+
+/* Structures which should be returned in INTEGER. */
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
+
+D(1,char m1, s.m1=42)
+D(2,short m1, s.m1=42)
+D(3,int m1, s.m1=42)
+D(4,long m1, s.m1=42)
+D(5,long long m1, s.m1=42)
+D(6,char m1;short s, s.m1=42)
+D(7,char m1;int i, s.m1=42)
+D(8,char m1; long l, s.m1=42)
+D(9,char m1; long long l, s.m1=42)
+D(10,char m1[16], s.m1[0]=42)
+D(11,short m1[8], s.m1[0]=42)
+D(12,int m1[4], s.m1[0]=42)
+D(13,long m1[2], s.m1[0]=42)
+D(14,long long m1[2], s.m1[0]=42)
+
+#undef D
+
+/* Structures which should be returned in SSE. */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
+
+D(100,float f,SSE_F, s.f=42)
+D(101,double d,SSE_D, s.d=42)
+D(102,float f;float f2,SSE_F, s.f=42)
+D(103,float f;double d,SSE_F, s.f=42)
+D(104,double d; float f,SSE_D, s.d=42)
+D(105,double d; double d2,SSE_D, s.d=42)
+D(106,float f[2],SSE_F, s.f[0]=42)
+D(107,float f[3],SSE_F, s.f[0]=42)
+D(108,float f[4],SSE_F, s.f[0]=42)
+D(109,double d[2],SSE_D, s.d[0]=42)
+D(110,float f[2]; double d,SSE_F, s.f[0]=42)
+D(111,double d;float f[2],SSE_D, s.d=42)
+
+D(120,_Float16 f,SSE_H, s.f=42)
+D(121,_Float16 f;_Float16 f2,SSE_H, s.f=42)
+D(122,_Float16 f;float d,SSE_H, s.f=42)
+D(123,_Float16 f;double d,SSE_H, s.f=42)
+D(124,double d; _Float16 f,SSE_D, s.d=42)
+D(125,_Float16 f[2],SSE_H, s.f[0]=42)
+D(126,_Float16 f[3],SSE_H, s.f[0]=42)
+D(127,_Float16 f[4],SSE_H, s.f[0]=42)
+D(128,_Float16 f[2]; double d,SSE_H, s.f[0]=42)
+D(129,double d;_Float16 f[2],SSE_D, s.d=42)
+
+#undef D
+
+/* Structures which should be returned on x87 stack. */
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = X87; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42 }; return s; }
+
+/* The only struct containing a long double, which is returned in
+ registers at all, is the singleton struct. All others are too large.
+ This includes a struct containing complex long double, which is passed
+ in memory, although a complex long double type itself is returned in
+ two registers. */
+D(200,long double ld)
+
+#undef D
+
+/* Structures which should be returned in INT (low) and SSE (high). */
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT_SSE; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42,43 }; return s; }
+
+D(300,char m1; float m2)
+D(301,char m1; double m2)
+D(302,short m1; float m2)
+D(303,short m1; double m2)
+D(304,int m1; float m2)
+D(305,int m1; double m2)
+D(306,long long m1; float m2)
+D(307,long long m1; double m2)
+
+D(310,char m1; _Float16 m2)
+D(311,short m1; _Float16 m2)
+D(312,int m1; _Float16 m2)
+D(313,long long m1; _Float16 m2)
+
+#undef D
+
+void check_300 (void)
+{
+ XMM_T x;
+ x._ulonglong[0] = rax;
+ switch (current_test) {
+ case 300: assert ((rax & 0xff) == 42 && x._float[1] == 43); break;
+ case 301: assert ((rax & 0xff) == 42 && xmm0d[0] == 43); break;
+ case 302: assert ((rax & 0xffff) == 42 && x._float[1] == 43); break;
+ case 303: assert ((rax & 0xffff) == 42 && xmm0d[0] == 43); break;
+ case 304: assert ((rax & 0xffffffff) == 42 && x._float[1] == 43); break;
+ case 305: assert ((rax & 0xffffffff) == 42 && xmm0d[0] == 43); break;
+ case 306: assert (rax == 42 && xmm0f[0] == 43); break;
+ case 307: assert (rax == 42 && xmm0d[0] == 43); break;
+ case 310: assert ((rax & 0xff) == 42 && x.__Float16[1] == 43); break;
+ case 311: assert ((rax & 0xffff) == 42 && x.__Float16[1] == 43); break;
+ case 312: assert ((rax & 0xffffffff) == 42 && x.__Float16[2] == 43); break;
+ case 313: assert (rax == 42 && xmm0h[0] == 43); break;
+
+ default: assert (0); break;
+ }
+}
+
+/* Structures which should be returned in SSE (low) and INT (high). */
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = SSE_INT; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
+
+D(400,float f[2];char c, s.f[0]=42; s.c=43)
+D(401,double d;char c, s.d=42; s.c=43)
+
+D(402,_Float16 f[4];char c, s.f[0]=42; s.c=43)
+
+#undef D
+
+void check_400 (void)
+{
+ switch (current_test) {
+ case 400: assert (xmm0f[0] == 42 && (rax & 0xff) == 43); break;
+ case 401: assert (xmm0d[0] == 42 && (rax & 0xff) == 43); break;
+ case 402: assert (xmm0h[0] == 42 && (rax & 0xff) == 43); break;
+
+ default: assert (0); break;
+ }
+}
+
+/* Structures which should be returned in MEM. */
+void *struct_addr;
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
+
+/* Too large. */
+D(500,char m1[17])
+D(501,short m1[9])
+D(502,int m1[5])
+D(503,long m1[3])
+D(504,short m1[8];char c)
+D(505,char m1[1];int i[4])
+D(506,float m1[5])
+D(507,double m1[3])
+D(508,char m1[1];float f[4])
+D(509,char m1[1];double d[2])
+D(510,__complex long double m1[1])
+
+/* Too large due to padding. */
+D(520,char m1[1];int i;char c2; int i2; char c3)
+
+/* Unnaturally aligned members. */
+D(530,short m1[1];int i PACKED)
+
+D(540,_Float16 m1[10])
+D(541,char m1[1];_Float16 f[8])
+
+#undef D
+
+
+/* Special tests. */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
+D(600,float f[4], SSE_F_V, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+D(601,_Float16 f[4], SSE_F_H, s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+D(602,_Float16 f[8], SSE_F_H8,
+ s.f[0] = s.f[1] = s.f[2] = s.f[3] = s.f[4] = s.f[5] = s.f[6] = s.f[7] = 42)
+#undef D
+
+void clear_all (void)
+{
+ clear_int_registers;
+ clear_float_registers;
+ clear_x87_registers;
+}
+
+void check_all (Type class, unsigned long size)
+{
+ switch (class) {
+ case INT: if (size < 8) rax &= ~0UL >> (64-8*size); assert (rax == 42); break;
+ case SSE_H: assert (xmm0h[0] == 42); break;
+ case SSE_F: assert (xmm0f[0] == 42); break;
+ case SSE_D: assert (xmm0d[0] == 42); break;
+ case SSE_F_V: assert (xmm0f[0] == 42 && xmm0f[1]==42 && xmm1f[0] == 42 && xmm1f[1] == 42); break;
+ case SSE_F_H: assert (xmm0h[0] == 42 && xmm0h[1]==42 && xmm0h[2] == 42 && xmm0h[3] == 42); break;
+ case SSE_F_H8: assert (xmm0h[0] == 42 && xmm0h[1]==42 && xmm0h[2] == 42 && xmm0h[3] == 42
+ && xmm1h[0] == 42 && xmm1h[1]==42 && xmm1h[2] == 42 && xmm1h[3] == 42); break;
+ case X87: assert (x87_regs[0]._ldouble == 42); break;
+ case INT_SSE: check_300(); break;
+ case SSE_INT: check_400(); break;
+ /* Ideally we would like to check that rax == struct_addr.
+ Unfortunately the address of the target struct escapes (for setting
+ struct_addr), so the return struct is a temporary one whose address
+ is given to the f_* functions, otherwise a conforming program
+ could notice the struct changing already before the function returns.
+ This temporary struct could be anywhere. For GCC it will be on
+ stack, but no one is forbidding that it could be a static variable
+ if there's no threading or proper locking. Nobody in his right mind
+ will not use the stack for that. */
+ case MEM: assert (*(unsigned char*)struct_addr == 42 && rdi == rax); break;
+ }
+}
+
+#define D(I) { struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
+ clear_all(); \
+ s = WRAP_RET(f_ ## I) (); \
+ check_all(class_ ## I, sizeof(s)); \
+}
+
+static void
+do_test (void)
+{
+ D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) D(9) D(10) D(11) D(12) D(13) D(14)
+
+ D(100) D(101) D(102) D(103) D(104) D(105) D(106) D(107) D(108) D(109) D(110)
+ D(111)
+
+ D(120) D(121) D(122) D(123) D(124) D(125) D(126) D(127) D(128) D(129)
+
+ D(200)
+
+ D(300) D(301) D(302) D(303) D(304) D(305) D(306) D(307)
+ D(310) D(311) D(312) D(313)
+
+ D(400) D(401) D(402)
+
+ D(500) D(501) D(502) D(503) D(504) D(505) D(506) D(507) D(508) D(509)
+ D(520)
+ D(530)
+
+ D(540) D(541)
+
+ D(600) D(601) D(602)
+ if (num_failed)
+ abort ();
+}
+#undef D
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c
new file mode 100644
index 0000000..5bdc44d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512fp16/test_varargs-m128.c
@@ -0,0 +1,164 @@
+/* Test variable number of 128-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "avx512fp16-xmm-check.h"
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m128_varargs (__m128 i0, __m128 i1, __m128 i2,
+ __m128 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m128 *argp;
+
+ compare (values.i0, i0, __m128);
+ compare (values.i1, i1, __m128);
+ compare (values.i2, i2, __m128);
+ compare (values.i3, i3, __m128);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m128 *) (((char *) fp) + 8);
+
+ /* Check __m128 arguments passed on stack. */
+ compare (values.i8, argp[0], __m128);
+ compare (values.i9, argp[1], __m128);
+
+ /* Check register contents. */
+ compare (fregs.xmm0, xmm_regs[0], __m128);
+ compare (fregs.xmm1, xmm_regs[1], __m128);
+ compare (fregs.xmm2, xmm_regs[2], __m128);
+ compare (fregs.xmm3, xmm_regs[3], __m128);
+ compare (fregs.xmm4, xmm_regs[4], __m128);
+ compare (fregs.xmm5, xmm_regs[5], __m128);
+ compare (fregs.xmm6, xmm_regs[6], __m128);
+ compare (fregs.xmm7, xmm_regs[7], __m128);
+}
+
+void
+fun_check_passing_m128h_varargs (__m128h i0, __m128h i1, __m128h i2,
+ __m128h i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m128h *argp;
+
+ compare (values.i0, i0, __m128h);
+ compare (values.i1, i1, __m128h);
+ compare (values.i2, i2, __m128h);
+ compare (values.i3, i3, __m128h);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m128h *) (((char *) fp) + 8);
+
+ /* Check __m128h arguments passed on stack. */
+ compare (values.i8, argp[0], __m128h);
+ compare (values.i9, argp[1], __m128h);
+
+ /* Check register contents. */
+ compare (fregs.xmm0, xmm_regs[0], __m128h);
+ compare (fregs.xmm1, xmm_regs[1], __m128h);
+ compare (fregs.xmm2, xmm_regs[2], __m128h);
+ compare (fregs.xmm3, xmm_regs[3], __m128h);
+ compare (fregs.xmm4, xmm_regs[4], __m128h);
+ compare (fregs.xmm5, xmm_regs[5], __m128h);
+ compare (fregs.xmm6, xmm_regs[6], __m128h);
+ compare (fregs.xmm7, xmm_regs[7], __m128h);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_float_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m128_varargs (void)
+{
+ __m128 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m128){32+i, 0, 0, 0};
+ pass = "m128-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m128_varargs,
+ _m128);
+}
+
+void
+test_m128h_varargs (void)
+{
+ __m128h x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m128h) {
+ 1.1f16 + i, 2.2f16 + i, 3.3f16 + i, 4.4f16 + i,
+ 5.5f16 + i, 6.6f16 + i, 7.7f16 + i, 8.8f16 + i
+ };
+ pass = "m128h-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m128h_varargs,
+ _m128h);
+}
+
+static void
+do_test (void)
+{
+ test_m128_varargs ();
+ test_m128h_varargs ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gdc.dg/lto/pr102094_0.d b/gcc/testsuite/gdc.dg/lto/pr102094_0.d
new file mode 100644
index 0000000..f83631a
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/lto/pr102094_0.d
@@ -0,0 +1,18 @@
+// { dg-lto-do link }
+module pr102094_0;
+
+extern(C) int printf(char* s, ...);
+
+struct S102094
+{
+ int a;
+}
+
+void main()
+{
+ S102094 x;
+ void nested()
+ {
+ printf(cast(char*)0, x);
+ }
+}
diff --git a/gcc/testsuite/gdc.dg/pr102185.d b/gcc/testsuite/gdc.dg/pr102185.d
new file mode 100644
index 0000000..39823a3
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr102185.d
@@ -0,0 +1,7 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102185
+// { dg-do compile }
+
+static assert(__traits(getTargetInfo, "floatAbi").length == 0 ||
+ __traits(getTargetInfo, "floatAbi") == "hard" ||
+ __traits(getTargetInfo, "floatAbi") == "soft" ||
+ __traits(getTargetInfo, "floatAbi") == "softfp");
diff --git a/gcc/testsuite/gdc.dg/pr102476.d b/gcc/testsuite/gdc.dg/pr102476.d
new file mode 100644
index 0000000..543716e
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr102476.d
@@ -0,0 +1,3 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102476
+// { dg-do link }
+// { dg-options "-fmain -fno-druntime" }
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f90
new file mode 100644
index 0000000..8cc1601
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_19.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! This testcase failed before with optimization as
+! allocatef's CFI descriptor argument 'x' failed with -fstrict-alias due to
+! internally alising with the GFC descriptor
+!
+
+program testit
+ use iso_c_binding
+ implicit none (external, type)
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+ type(m), allocatable :: a(:)
+
+ call testf (a)
+
+contains
+ subroutine allocatef (x) bind (c)
+ type(m), allocatable :: x(:)
+ allocate (x(5:15))
+ end subroutine
+
+ subroutine testf (y)
+ type(m), allocatable, target :: y(:)
+ call allocatef (y)
+ if (.not. allocated (y)) stop 1
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
index 7731d1a..c596e47 100644
--- a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
@@ -19,23 +19,37 @@ contains
subroutine substr(str) BIND(C)
character(*) :: str(:)
- if (str(2) .ne. "ghi") stop 2
+ if (str(1) .ne. "bcd") stop 2
+ if (str(2) .ne. "ghi") stop 3
str = ['uvw','xyz']
end subroutine
+ subroutine substr4(str4) BIND(C)
+ character(*, kind=4) :: str4(:)
+ print *, str4(1)
+ print *, str4(2)
+ if (str4(1) .ne. 4_"bcd") stop 4
+ if (str4(2) .ne. 4_"ghi") stop 5
+ str4 = [4_'uvw', 4_'xyz']
+ end subroutine
+
end module
program p
use mod_ctg
implicit none
real :: x(6)
- character(5) :: str(2) = ['abcde','fghij']
+ character(5) :: str(2) = ['abcde', 'fghij']
+ character(5, kind=4) :: str4(2) = [4_'abcde', 4_'fghij']
integer :: i
x = [ (real(i), i=1, size(x)) ]
call ctg(x(2::2))
if (any (abs (x - [1.,20.,3.,40.,5.,60.]) > 1.e-6)) stop 3
- call substr(str(:)(2:4))
- if (any (str .ne. ['auvwe','fxyzj'])) stop 4
+ !call substr(str(:)(2:4))
+ !if (any (str .ne. ['auvwe','fxyzj'])) stop 4
+
+ call substr4(str4(:)(2:4))
+ if (any (str4 .ne. [4_'auvwe', 4_'fxyzj'])) stop 4
end program
diff --git a/gcc/testsuite/gfortran.dg/PR100911.c b/gcc/testsuite/gfortran.dg/PR100911.c
new file mode 100644
index 0000000..f3345ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100911.c
@@ -0,0 +1,82 @@
+/* Test the fix for PR100911 */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+
+#define _CFI_type_mask 0xFF
+#define _CFI_type_kind_shift 8
+
+#define _CFI_decode_type(NAME) (signed char)((NAME) & CFI_type_mask)
+#define _CFI_decode_kind(NAME) (signed char)(((NAME) >> CFI_type_kind_shift) & CFI_type_mask)
+
+#define _CFI_encode_type(TYPE, KIND) (int16_t)\
+((((KIND) & CFI_type_mask) << CFI_type_kind_shift)\
+ | ((TYPE) & CFI_type_mask))
+
+#define N 11
+#define M 7
+
+#define CFI_type_Cptr CFI_type_cptr
+
+typedef int* c_ptr;
+
+bool c_vrfy_cptr (const CFI_cdesc_t *restrict);
+
+void check_tk (const CFI_cdesc_t*restrict, const CFI_type_t, const signed char, const size_t, const size_t);
+
+bool
+c_vrfy_cptr (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_ptr *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_ptr);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_ptr*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((**ip) != (int)(i+1))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_ptr*)CFI_address(auxp, &i);
+ if ((**ip) != (int)(i-lb+1))
+ return false;
+ }
+ return true;
+}
+
+void
+check_tk (const CFI_cdesc_t *restrict auxp, const CFI_type_t type, const signed char kind, const size_t elem_len, const size_t nelem)
+{
+ signed char ityp, iknd;
+
+ assert (auxp);
+ assert (auxp->elem_len==elem_len*nelem);
+ assert (auxp->rank==1);
+ assert (auxp->dim[0].sm>0);
+ assert ((size_t)auxp->dim[0].sm==elem_len*nelem);
+ /* */
+ assert (auxp->type==type);
+ ityp = _CFI_decode_type(auxp->type);
+ assert (ityp == CFI_type_cptr);
+ iknd = _CFI_decode_kind(auxp->type);
+ assert (_CFI_decode_type(type)==ityp);
+ assert (kind==iknd);
+ assert (c_vrfy_cptr (auxp));
+ return;
+}
+
+// Local Variables:
+// mode: C
+// End:
diff --git a/gcc/testsuite/gfortran.dg/PR100911.f90 b/gcc/testsuite/gfortran.dg/PR100911.f90
new file mode 100644
index 0000000..69f485b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100911.f90
@@ -0,0 +1,282 @@
+! { dg-do run }
+! { dg-additional-sources PR100911.c }
+!
+! Test the fix for PR100911
+!
+
+module isof_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t
+
+ implicit none
+
+ private
+
+ public :: &
+ CFI_type_cptr
+
+ public :: &
+ check_tk_as, &
+ check_tk_ar
+
+ public :: &
+ cfi_encode_type
+
+ integer, parameter :: CFI_type_t = c_int16_t
+
+ integer(kind=c_int16_t), parameter :: CFI_type_mask = int(z"FF", kind=c_int16_t)
+ integer(kind=c_int16_t), parameter :: CFI_type_kind_shift = 8_c_int16_t
+
+ ! Intrinsic types. Their kind number defines their storage size. */
+ integer(kind=c_signed_char), parameter :: CFI_type_cptr = 7
+
+ interface
+ subroutine check_tk_as(a, t, k, e, n) &
+ bind(c, name="check_tk")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(:)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_tk_as
+ subroutine check_tk_ar(a, t, k, e, n) &
+ bind(c, name="check_tk")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(..)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_tk_ar
+ end interface
+
+contains
+
+ elemental function cfi_encode_type(type, kind) result(itype)
+ integer(kind=c_signed_char), intent(in) :: type
+ integer(kind=c_signed_char), intent(in) :: kind
+
+ integer(kind=c_int16_t) :: itype, ikind
+
+ itype = int(type, kind=c_int16_t)
+ itype = iand(itype, CFI_type_mask)
+ ikind = int(kind, kind=c_int16_t)
+ ikind = iand(ikind, CFI_type_mask)
+ ikind = shiftl(ikind, CFI_type_kind_shift)
+ itype = ior(ikind, itype)
+ return
+ end function cfi_encode_type
+
+end module isof_m
+
+module iso_check_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t, c_size_t
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_int, c_ptr, c_loc, c_associated
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_ptr
+
+ use :: isof_m, only: &
+ CFI_type_cptr
+
+ use :: isof_m, only: &
+ check_tk_as, &
+ check_tk_ar
+
+ use :: isof_m, only: &
+ cfi_encode_type
+
+ implicit none
+
+ integer :: i
+ integer(kind=c_size_t), parameter :: b = 8
+ integer, parameter :: n = 11
+
+ type, bind(c) :: c_foo_t
+ integer(kind=c_int) :: a
+ end type c_foo_t
+
+ type(c_foo_t), parameter :: ref_c_foo_t(*) = [(c_foo_t(a=i), i=1,n)]
+
+ type(c_foo_t), protected, target :: target_c_foo_t(n)
+
+
+contains
+
+ subroutine check_c_ptr()
+ type(c_ptr) :: p(n)
+ integer :: i
+ !
+ target_c_foo_t = ref_c_foo_t
+ p = [(c_loc(target_c_foo_t(i)), i=1,n)]
+ call f_check_c_ptr_as(p)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 1
+ do i = 1, n
+ if(.not.c_associated(p(i), c_loc(target_c_foo_t(i)))) stop 2
+ end do
+ target_c_foo_t = ref_c_foo_t
+ p = [(c_loc(target_c_foo_t(i)), i=1,n)]
+ call c_check_c_ptr_as(p)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 3
+ do i = 1, n
+ if(.not.c_associated(p(i), c_loc(target_c_foo_t(i)))) stop 4
+ end do
+ target_c_foo_t = ref_c_foo_t
+ p = [(c_loc(target_c_foo_t(i)), i=1,n)]
+ call f_check_c_ptr_ar(p)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 5
+ do i = 1, n
+ if(.not.c_associated(p(i), c_loc(target_c_foo_t(i)))) stop 6
+ end do
+ target_c_foo_t = ref_c_foo_t
+ p = [(c_loc(target_c_foo_t(i)), i=1,n)]
+ call c_check_c_ptr_ar(p)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 7
+ do i = 1, n
+ if(.not.c_associated(p(i), c_loc(target_c_foo_t(i)))) stop 8
+ end do
+ return
+ end subroutine check_c_ptr
+
+ subroutine f_check_c_ptr_as(a)
+ type(c_ptr), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 9
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 10
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 11
+ end do
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 12
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 13
+ end do
+ return
+ end subroutine f_check_c_ptr_as
+
+ subroutine c_check_c_ptr_as(a) bind(c)
+ type(c_ptr), intent(in) :: a(:)
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 14
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 15
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 16
+ end do
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 17
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 18
+ end do
+ return
+ end subroutine c_check_c_ptr_as
+
+ subroutine f_check_c_ptr_ar(a)
+ type(c_ptr), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 19
+ select rank(a)
+ rank(1)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 20
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 21
+ end do
+ rank default
+ stop 22
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 23
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 24
+ end do
+ rank default
+ stop 25
+ end select
+ return
+ end subroutine f_check_c_ptr_ar
+
+ subroutine c_check_c_ptr_ar(a) bind(c)
+ type(c_ptr), intent(in) :: a(..)
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 26
+ select rank(a)
+ rank(1)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 27
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 28
+ end do
+ rank default
+ stop 29
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(target_c_foo_t(:)%a/=ref_c_foo_t(:)%a)) stop 30
+ do i = 1, n
+ if(.not.c_associated(a(i), c_loc(target_c_foo_t(i)))) stop 31
+ end do
+ rank default
+ stop 32
+ end select
+ return
+ end subroutine c_check_c_ptr_ar
+
+end module iso_check_m
+
+program main_p
+
+ use :: iso_check_m, only: &
+ check_c_ptr
+
+ implicit none
+
+ call check_c_ptr()
+ stop
+
+end program main_p
+
+!! Local Variables:
+!! mode: f90
+!! End:
+
diff --git a/gcc/testsuite/gfortran.dg/PR100914.c b/gcc/testsuite/gfortran.dg/PR100914.c
new file mode 100644
index 0000000..ea339e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100914.c
@@ -0,0 +1,225 @@
+/* Test the fix for PR100914 */
+
+#include <assert.h>
+#include <complex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <ISO_Fortran_binding.h>
+
+#define _CFI_type_mask 0xFF
+#define _CFI_type_kind_shift 8
+
+#define _CFI_decode_type(NAME) (signed char)((NAME) & CFI_type_mask)
+#define _CFI_decode_kind(NAME) (signed char)(((NAME) >> CFI_type_kind_shift) & CFI_type_mask)
+
+#define _CFI_encode_type(TYPE, KIND) (int16_t)\
+((((KIND) & CFI_type_mask) << CFI_type_kind_shift)\
+ | ((TYPE) & CFI_type_mask))
+
+#undef CMPLXF
+#define CMPLXF(x, y) ((float complex)((float)(x) + I * (float)(y)))
+
+#undef CMPLX
+#define CMPLX(x, y) ((double complex)((double)(x) + (double complex)I * (double)(y)))
+
+#undef CMPLXL
+#define CMPLXL(x, y) ((long double complex)((long double)(x) + (long double complex)I * (long double)(y)))
+
+#undef CMPLX
+#define CMPLX(x, y) ((_Float128 _Complex )((double)(x) + (double complex)I * (double)(y)))
+
+#define N 11
+#define M 7
+
+typedef float _Complex c_float_complex;
+typedef double _Complex c_double_complex;
+typedef long double _Complex c_long_double_complex;
+typedef _Float128 _Complex c_float128_complex;
+
+bool c_vrfy_c_float_complex (const CFI_cdesc_t *restrict);
+
+bool c_vrfy_c_double_complex (const CFI_cdesc_t *restrict);
+
+bool c_vrfy_c_long_double_complex (const CFI_cdesc_t *restrict);
+
+bool c_vrfy_c_float128_complex (const CFI_cdesc_t *restrict);
+
+bool c_vrfy_complex (const CFI_cdesc_t *restrict);
+
+bool c_vrfy_desc (const CFI_cdesc_t*restrict, const CFI_type_t, const signed char, const size_t, const size_t);
+
+void check_tk (const CFI_cdesc_t*restrict, const CFI_type_t, const signed char, const size_t, const size_t);
+
+
+
+bool
+c_vrfy_c_float_complex (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_float_complex *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_float_complex);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_float_complex*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((cabsf (*ip-(c_float_complex)(CMPLXF((i+1), (2*(i+1)))))>(float)0.0))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_float_complex*)CFI_address(auxp, &i);
+ if ((cabsf (*ip-(c_float_complex)(CMPLXF((i-lb+1), (2*(i-lb+1)))))>(float)0.0))
+ return false;
+ }
+ return true;
+}
+
+bool
+c_vrfy_c_double_complex (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_double_complex *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_double_complex);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_double_complex*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((cabs (*ip-(c_double_complex)(CMPLX((i+1), (2*(i+1)))))>(double)0.0))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_double_complex*)CFI_address(auxp, &i);
+ if ((cabs (*ip-(c_double_complex)(CMPLX((i-lb+1), (2*(i-lb+1)))))>(double)0.0))
+ return false;
+ }
+ return true;
+}
+
+bool
+c_vrfy_c_long_double_complex (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_long_double_complex *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_long_double_complex);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_long_double_complex*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((cabsl (*ip-(c_long_double_complex)(CMPLXL((i+1), (2*(i+1)))))>(long double)0.0))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_long_double_complex*)CFI_address(auxp, &i);
+ if ((cabsl (*ip-(c_long_double_complex)(CMPLXL((i-lb+1), (2*(i-lb+1)))))>(long double)0.0))
+ return false;
+ }
+ return true;
+}
+
+bool
+c_vrfy_c_float128_complex (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_float128_complex *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_float128_complex);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_float128_complex*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((cabs ((double complex)(*ip-(c_float128_complex)(CMPLX((i+1), (2*(i+1))))))>(double)0.0))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_float128_complex*)CFI_address(auxp, &i);
+ if ((cabs ((double complex)(*ip-(c_float128_complex)(CMPLX((i-lb+1), (2*(i-lb+1))))))>(double)0.0))
+ return false;
+ }
+ return true;
+}
+
+bool
+c_vrfy_complex (const CFI_cdesc_t *restrict auxp)
+{
+ signed char type, kind;
+
+ assert (auxp);
+ type = _CFI_decode_type(auxp->type);
+ kind = _CFI_decode_kind(auxp->type);
+ assert (type == CFI_type_Complex);
+ switch (kind)
+ {
+ case 4:
+ return c_vrfy_c_float_complex (auxp);
+ break;
+ case 8:
+ return c_vrfy_c_double_complex (auxp);
+ break;
+ case 10:
+ return c_vrfy_c_long_double_complex (auxp);
+ break;
+ case 16:
+ return c_vrfy_c_float128_complex (auxp);
+ break;
+ default:
+ assert (false);
+ }
+ return true;
+}
+
+void
+check_tk (const CFI_cdesc_t *restrict auxp, const CFI_type_t type, const signed char kind, const size_t elem_len, const size_t nelem)
+{
+ signed char ityp, iknd;
+
+ assert (auxp);
+ assert (auxp->elem_len==elem_len*nelem);
+ assert (auxp->rank==1);
+ assert (auxp->dim[0].sm>0);
+ assert ((size_t)auxp->dim[0].sm==elem_len*nelem);
+ /* */
+ assert (auxp->type==type);
+ ityp = _CFI_decode_type(auxp->type);
+ assert (ityp == CFI_type_Complex);
+ iknd = _CFI_decode_kind(auxp->type);
+ assert (_CFI_decode_type(type)==ityp);
+ assert (kind==iknd);
+ assert (c_vrfy_complex (auxp));
+ return;
+}
+
+// Local Variables:
+// mode: C
+// End:
diff --git a/gcc/testsuite/gfortran.dg/PR100914.f90 b/gcc/testsuite/gfortran.dg/PR100914.f90
new file mode 100644
index 0000000..8588157
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100914.f90
@@ -0,0 +1,652 @@
+! Fails on x86 targets where sizeof(long double) == 16.
+! { dg-do run }
+! { dg-additional-sources PR100914.c }
+! { dg-require-effective-target fortran_real_c_float128 }
+! { dg-additional-options "-Wno-pedantic" }
+!
+! Test the fix for PR100914
+!
+
+module isof_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t
+
+ implicit none
+
+ private
+
+ public :: &
+ CFI_type_Complex, &
+ CFI_type_float_Complex, &
+ CFI_type_double_Complex, &
+ CFI_type_long_double_Complex, &
+ CFI_type_float128_Complex
+
+ public :: &
+ check_tk_as, &
+ check_tk_ar
+
+
+ public :: &
+ cfi_encode_type
+
+ integer, parameter :: CFI_type_t = c_int16_t
+
+ integer(kind=c_int16_t), parameter :: CFI_type_mask = int(z"FF", kind=c_int16_t)
+ integer(kind=c_int16_t), parameter :: CFI_type_kind_shift = 8_c_int16_t
+
+ ! Intrinsic types. Their kind number defines their storage size. */
+ integer(kind=c_signed_char), parameter :: CFI_type_Complex = 4
+
+ ! C-Fortran Interoperability types.
+ integer(kind=cfi_type_t), parameter :: CFI_type_float_Complex = &
+ ior(int(CFI_type_Complex, kind=c_int16_t), shiftl(4_c_int16_t, CFI_type_kind_shift))
+ integer(kind=cfi_type_t), parameter :: CFI_type_double_Complex = &
+ ior(int(CFI_type_Complex, kind=c_int16_t), shiftl(8_c_int16_t, CFI_type_kind_shift))
+ integer(kind=cfi_type_t), parameter :: CFI_type_long_double_Complex = &
+ ior(int(CFI_type_Complex, kind=c_int16_t), shiftl(10_c_int16_t, CFI_type_kind_shift))
+ integer(kind=cfi_type_t), parameter :: CFI_type_float128_Complex = &
+ ior(int(CFI_type_Complex, kind=c_int16_t), shiftl(16_c_int16_t, CFI_type_kind_shift))
+
+ interface
+ subroutine check_tk_as(a, t, k, e, n) &
+ bind(c, name="check_tk")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(:)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_tk_as
+ subroutine check_tk_ar(a, t, k, e, n) &
+ bind(c, name="check_tk")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(..)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_tk_ar
+ end interface
+
+contains
+
+ elemental function cfi_encode_type(type, kind) result(itype)
+ integer(kind=c_signed_char), intent(in) :: type
+ integer(kind=c_signed_char), intent(in) :: kind
+
+ integer(kind=c_int16_t) :: itype, ikind
+
+ itype = int(type, kind=c_int16_t)
+ itype = iand(itype, CFI_type_mask)
+ ikind = int(kind, kind=c_int16_t)
+ ikind = iand(ikind, CFI_type_mask)
+ ikind = shiftl(ikind, CFI_type_kind_shift)
+ itype = ior(ikind, itype)
+ return
+ end function cfi_encode_type
+
+end module isof_m
+
+module iso_check_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t, c_size_t
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_float_complex, &
+ c_double_complex, &
+ c_long_double_complex, &
+ c_float128_complex
+
+ use :: isof_m, only: &
+ CFI_type_Complex
+
+ use :: isof_m, only: &
+ CFI_type_float_Complex, &
+ CFI_type_double_Complex, &
+ CFI_type_long_double_Complex, &
+ CFI_type_float128_Complex
+
+ use :: isof_m, only: &
+ check_tk_as, &
+ check_tk_ar
+
+ use :: isof_m, only: &
+ cfi_encode_type
+
+ implicit none
+
+ private
+
+ public :: &
+ check_c_float_complex, &
+ check_c_double_complex, &
+ check_c_long_double_complex, &
+ check_c_float128_complex
+
+ integer :: i
+ integer(kind=c_size_t), parameter :: b = 8
+ integer, parameter :: n = 11
+
+ complex(kind=c_float_complex), parameter :: ref_c_float_complex(*) = &
+ [(cmplx(i, 2*i, kind=c_float_complex), i=1,n)]
+ complex(kind=c_double_complex), parameter :: ref_c_double_complex(*) = &
+ [(cmplx(i, 2*i, kind=c_double_complex), i=1,n)]
+ complex(kind=c_long_double_complex), parameter :: ref_c_long_double_complex(*) = &
+ [(cmplx(i, 2*i, kind=c_long_double_complex), i=1,n)]
+ complex(kind=c_float128_complex), parameter :: ref_c_float128_complex(*) = &
+ [(cmplx(i, 2*i, kind=c_float128_complex), i=1,n)]
+
+contains
+
+ ! CFI_type_float_complex
+ subroutine check_c_float_complex()
+ complex(kind=c_float_complex) :: a(n)
+ !
+ if (c_float_complex/=4) stop 1
+ a = ref_c_float_complex
+ call f_check_c_float_complex_as(a)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 2
+ a = ref_c_float_complex
+ call c_check_c_float_complex_as(a)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 3
+ a = ref_c_float_complex
+ call f_check_c_float_complex_ar(a)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 4
+ a = ref_c_float_complex
+ call c_check_c_float_complex_ar(a)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 5
+ return
+ end subroutine check_c_float_complex
+
+ subroutine f_check_c_float_complex_as(a)
+ complex(kind=c_float_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 6
+ if(k/=4_c_signed_char) stop 7
+ if(int(k, kind=c_size_t)/=(e/2)) stop 8
+ if(t/=CFI_type_float_complex) stop 9
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 10
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 11
+ return
+ end subroutine f_check_c_float_complex_as
+
+ subroutine c_check_c_float_complex_as(a) bind(c)
+ complex(kind=c_float_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 12
+ if(k/=4_c_signed_char) stop 13
+ if(int(k, kind=c_size_t)/=(e/2)) stop 14
+ if(t/=CFI_type_float_complex) stop 15
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 16
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 17
+ return
+ end subroutine c_check_c_float_complex_as
+
+ subroutine f_check_c_float_complex_ar(a)
+ complex(kind=c_float_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 18
+ if(k/=4_c_signed_char) stop 19
+ if(int(k, kind=c_size_t)/=(e/2)) stop 20
+ if(t/=CFI_type_float_complex) stop 21
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 22
+ rank default
+ stop 23
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 24
+ rank default
+ stop 25
+ end select
+ return
+ end subroutine f_check_c_float_complex_ar
+
+ subroutine c_check_c_float_complex_ar(a) bind(c)
+ complex(kind=c_float_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 26
+ if(k/=4_c_signed_char) stop 27
+ if(int(k, kind=c_size_t)/=(e/2)) stop 28
+ if(t/=CFI_type_float_complex) stop 29
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 30
+ rank default
+ stop 31
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float_complex)>0.0_c_float_complex)) stop 32
+ rank default
+ stop 33
+ end select
+ return
+ end subroutine c_check_c_float_complex_ar
+
+ ! CFI_type_double_complex
+ subroutine check_c_double_complex()
+ complex(kind=c_double_complex) :: a(n)
+ !
+ if (c_double_complex/=8) stop 34
+ a = ref_c_double_complex
+ call f_check_c_double_complex_as(a)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 35
+ a = ref_c_double_complex
+ call c_check_c_double_complex_as(a)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 36
+ a = ref_c_double_complex
+ call f_check_c_double_complex_ar(a)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 37
+ a = ref_c_double_complex
+ call c_check_c_double_complex_ar(a)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 38
+ return
+ end subroutine check_c_double_complex
+
+ subroutine f_check_c_double_complex_as(a)
+ complex(kind=c_double_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 39
+ if(k/=8_c_signed_char) stop 40
+ if(int(k, kind=c_size_t)/=(e/2)) stop 41
+ if(t/=CFI_type_double_complex) stop 42
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 43
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 44
+ return
+ end subroutine f_check_c_double_complex_as
+
+ subroutine c_check_c_double_complex_as(a) bind(c)
+ complex(kind=c_double_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 45
+ if(k/=8_c_signed_char) stop 46
+ if(int(k, kind=c_size_t)/=(e/2)) stop 47
+ if(t/=CFI_type_double_complex) stop 48
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 49
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 50
+ return
+ end subroutine c_check_c_double_complex_as
+
+ subroutine f_check_c_double_complex_ar(a)
+ complex(kind=c_double_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 51
+ if(k/=8_c_signed_char) stop 52
+ if(int(k, kind=c_size_t)/=(e/2)) stop 53
+ if(t/=CFI_type_double_complex) stop 54
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 55
+ rank default
+ stop 56
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 57
+ rank default
+ stop 58
+ end select
+ return
+ end subroutine f_check_c_double_complex_ar
+
+ subroutine c_check_c_double_complex_ar(a) bind(c)
+ complex(kind=c_double_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 59
+ if(k/=8_c_signed_char) stop 60
+ if(int(k, kind=c_size_t)/=(e/2)) stop 61
+ if(t/=CFI_type_double_complex) stop 62
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 63
+ rank default
+ stop 64
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_double_complex)>0.0_c_double_complex)) stop 65
+ rank default
+ stop 66
+ end select
+ return
+ end subroutine c_check_c_double_complex_ar
+
+ ! CFI_type_long_double_complex
+ subroutine check_c_long_double_complex()
+ complex(kind=c_long_double_complex) :: a(n)
+ !
+ if (c_long_double_complex/=10) stop 67
+ a = ref_c_long_double_complex
+ call f_check_c_long_double_complex_as(a)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 68
+ a = ref_c_long_double_complex
+ call c_check_c_long_double_complex_as(a)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 69
+ a = ref_c_long_double_complex
+ call f_check_c_long_double_complex_ar(a)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 70
+ a = ref_c_long_double_complex
+ call c_check_c_long_double_complex_ar(a)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 71
+ return
+ end subroutine check_c_long_double_complex
+
+ subroutine f_check_c_long_double_complex_as(a)
+ complex(kind=c_long_double_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 72
+ if(k/=10_c_signed_char) stop 73
+ if(e/=32) stop 74
+ if(t/=CFI_type_long_double_complex) stop 75
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 76
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 77
+ return
+ end subroutine f_check_c_long_double_complex_as
+
+ subroutine c_check_c_long_double_complex_as(a) bind(c)
+ complex(kind=c_long_double_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 78
+ if(k/=10_c_signed_char) stop 79
+ if(e/=32) stop 80
+ if(t/=CFI_type_long_double_complex) stop 81
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 82
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 83
+ return
+ end subroutine c_check_c_long_double_complex_as
+
+ subroutine f_check_c_long_double_complex_ar(a)
+ complex(kind=c_long_double_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 84
+ if(k/=10_c_signed_char) stop 85
+ if(e/=32) stop 86
+ if(t/=CFI_type_long_double_complex) stop 87
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 88
+ rank default
+ stop 89
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 90
+ rank default
+ stop 91
+ end select
+ return
+ end subroutine f_check_c_long_double_complex_ar
+
+ subroutine c_check_c_long_double_complex_ar(a) bind(c)
+ complex(kind=c_long_double_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 92
+ if(k/=10_c_signed_char) stop 93
+ if(e/=32) stop 94
+ if(t/=CFI_type_long_double_complex) stop 95
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 96
+ rank default
+ stop 97
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_long_double_complex)>0.0_c_long_double_complex)) stop 98
+ rank default
+ stop 99
+ end select
+ return
+ end subroutine c_check_c_long_double_complex_ar
+
+ ! CFI_type_float128_complex
+ subroutine check_c_float128_complex()
+ complex(kind=c_float128_complex) :: a(n)
+ !
+ if (c_float128_complex/=16) stop 100
+ a = ref_c_float128_complex
+ call f_check_c_float128_complex_as(a)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 101
+ a = ref_c_float128_complex
+ call c_check_c_float128_complex_as(a)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 102
+ a = ref_c_float128_complex
+ call f_check_c_float128_complex_ar(a)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 103
+ a = ref_c_float128_complex
+ call c_check_c_float128_complex_ar(a)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 104
+ return
+ end subroutine check_c_float128_complex
+
+ subroutine f_check_c_float128_complex_as(a)
+ complex(kind=c_float128_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 105
+ if(k/=16_c_signed_char) stop 106
+ if(int(k, kind=c_size_t)/=(e/2)) stop 107
+ if(t/=CFI_type_float128_complex) stop 108
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 109
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 110
+ return
+ end subroutine f_check_c_float128_complex_as
+
+ subroutine c_check_c_float128_complex_as(a) bind(c)
+ complex(kind=c_float128_complex), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 111
+ if(k/=16_c_signed_char) stop 112
+ if(int(k, kind=c_size_t)/=(e/2)) stop 113
+ if(t/=CFI_type_float128_complex) stop 114
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 115
+ call check_tk_as(a, t, k, e, 1_c_size_t)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 116
+ return
+ end subroutine c_check_c_float128_complex_as
+
+ subroutine f_check_c_float128_complex_ar(a)
+ complex(kind=c_float128_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 117
+ if(k/=16_c_signed_char) stop 118
+ if(int(k, kind=c_size_t)/=(e/2)) stop 119
+ if(t/=CFI_type_float128_complex) stop 120
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 121
+ rank default
+ stop 122
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 123
+ rank default
+ stop 124
+ end select
+ return
+ end subroutine f_check_c_float128_complex_ar
+
+ subroutine c_check_c_float128_complex_ar(a) bind(c)
+ complex(kind=c_float128_complex), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = kind(a)
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_complex, k)
+ if(k<=0_c_signed_char) stop 125
+ if(k/=16_c_signed_char) stop 126
+ if(int(k, kind=c_size_t)/=(e/2)) stop 127
+ if(t/=CFI_type_float128_complex) stop 128
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 129
+ rank default
+ stop 130
+ end select
+ call check_tk_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ if(any(abs(a-ref_c_float128_complex)>0.0_c_float128_complex)) stop 131
+ rank default
+ stop 132
+ end select
+ return
+ end subroutine c_check_c_float128_complex_ar
+
+end module iso_check_m
+
+program main_p
+
+ use :: iso_check_m, only: &
+ check_c_float_complex, &
+ check_c_double_complex, &
+ check_c_long_double_complex, &
+ check_c_float128_complex
+
+ implicit none
+
+ call check_c_float_complex()
+ call check_c_double_complex()
+ ! see PR100910
+ ! call check_c_long_double_complex()
+ call check_c_float128_complex()
+ stop
+
+end program main_p
+
+!! Local Variables:
+!! mode: f90
+!! End:
+
diff --git a/gcc/testsuite/gfortran.dg/PR100915.c b/gcc/testsuite/gfortran.dg/PR100915.c
new file mode 100644
index 0000000..4eaf82a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100915.c
@@ -0,0 +1,80 @@
+/* Test the fix for PR100915 */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+
+#define _CFI_type_mask 0xFF
+#define _CFI_type_kind_shift 8
+
+#define _CFI_decode_type(NAME) (signed char)((NAME) & CFI_type_mask)
+#define _CFI_decode_kind(NAME) (signed char)(((NAME) >> CFI_type_kind_shift) & CFI_type_mask)
+
+#define _CFI_encode_type(TYPE, KIND) (int16_t)\
+((((KIND) & CFI_type_mask) << CFI_type_kind_shift)\
+ | ((TYPE) & CFI_type_mask))
+
+#define N 11
+#define M 7
+
+typedef int(*c_funptr)(int);
+
+bool c_vrfy_c_funptr (const CFI_cdesc_t *restrict);
+
+void check_fn (const CFI_cdesc_t*restrict, const CFI_type_t, const signed char, const size_t, const size_t);
+
+bool
+c_vrfy_c_funptr (const CFI_cdesc_t *restrict auxp)
+{
+ CFI_index_t i, lb, ub, ex;
+ size_t sz;
+ c_funptr *ip = NULL;
+
+ assert (auxp);
+ assert (auxp->base_addr);
+ assert (auxp->elem_len>0);
+ lb = auxp->dim[0].lower_bound;
+ ex = auxp->dim[0].extent;
+ assert (ex==11);
+ sz = (size_t)auxp->elem_len / sizeof (c_funptr);
+ assert (sz==1);
+ ub = ex + lb - 1;
+ ip = (c_funptr*)auxp->base_addr;
+ for (i=0; i<ex; i++, ip+=sz)
+ if ((**ip)((int)(i)) != 2*(int)(i))
+ return false;
+ for (i=lb; i<ub+1; i++)
+ {
+ ip = (c_funptr*)CFI_address(auxp, &i);
+ if ((**ip)((int)(i-lb)) != 2*(int)(i-lb))
+ return false;
+ }
+ return true;
+}
+
+void
+check_fn (const CFI_cdesc_t *restrict auxp, const CFI_type_t type, const signed char kind, const size_t elem_len, const size_t nelem)
+{
+ signed char ityp, iknd;
+
+ assert (auxp);
+ assert (auxp->elem_len==elem_len*nelem);
+ assert (auxp->rank==1);
+ assert (auxp->dim[0].sm>0);
+ assert ((size_t)auxp->dim[0].sm==elem_len*nelem);
+ /* */
+ assert (auxp->type==type);
+ ityp = _CFI_decode_type(auxp->type);
+ assert (ityp == CFI_type_cfunptr);
+ iknd = _CFI_decode_kind(auxp->type);
+ assert (_CFI_decode_type(type)==ityp);
+ assert (kind==iknd);
+ assert (c_vrfy_c_funptr (auxp));
+ return;
+}
+
+// Local Variables:
+// mode: C
+// End:
diff --git a/gcc/testsuite/gfortran.dg/PR100915.f90 b/gcc/testsuite/gfortran.dg/PR100915.f90
new file mode 100644
index 0000000..64a2a88
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/PR100915.f90
@@ -0,0 +1,273 @@
+! { dg-do run }
+! { dg-additional-sources PR100915.c }
+!
+! Test the fix for PR100915
+!
+
+module isof_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t
+
+ implicit none
+
+ private
+
+ public :: &
+ CFI_type_cptr, CFI_type_cfunptr
+
+ public :: &
+ check_fn_as, &
+ check_fn_ar
+
+ public :: &
+ mult2
+
+ public :: &
+ cfi_encode_type
+
+ integer, parameter :: CFI_type_t = c_int16_t
+
+ integer(kind=c_int16_t), parameter :: CFI_type_mask = int(z"FF", kind=c_int16_t)
+ integer(kind=c_int16_t), parameter :: CFI_type_kind_shift = 8_c_int16_t
+
+ ! Intrinsic types. Their kind number defines their storage size. */
+ integer(kind=c_signed_char), parameter :: CFI_type_cptr = 7
+ integer(kind=c_signed_char), parameter :: CFI_type_cfunptr = 8
+
+ interface
+ subroutine check_fn_as(a, t, k, e, n) &
+ bind(c, name="check_fn")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(:)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_fn_as
+ subroutine check_fn_ar(a, t, k, e, n) &
+ bind(c, name="check_fn")
+ use, intrinsic :: iso_c_binding, only: &
+ c_int16_t, c_signed_char, c_size_t
+ implicit none
+ type(*), intent(in) :: a(..)
+ integer(c_int16_t), value, intent(in) :: t
+ integer(c_signed_char), value, intent(in) :: k
+ integer(c_size_t), value, intent(in) :: e
+ integer(c_size_t), value, intent(in) :: n
+ end subroutine check_fn_ar
+ end interface
+
+contains
+
+ function mult2(a) result(b) bind(c)
+ use, intrinsic :: iso_c_binding, only: &
+ c_int
+
+ integer(kind=c_int), value, intent(in) :: a
+
+ integer(kind=c_int) :: b
+
+ b = 2_c_int * a
+ return
+ end function mult2
+
+ elemental function cfi_encode_type(type, kind) result(itype)
+ integer(kind=c_signed_char), intent(in) :: type
+ integer(kind=c_signed_char), intent(in) :: kind
+
+ integer(kind=c_int16_t) :: itype, ikind
+
+ itype = int(type, kind=c_int16_t)
+ itype = iand(itype, CFI_type_mask)
+ ikind = int(kind, kind=c_int16_t)
+ ikind = iand(ikind, CFI_type_mask)
+ ikind = shiftl(ikind, CFI_type_kind_shift)
+ itype = ior(ikind, itype)
+ return
+ end function cfi_encode_type
+
+end module isof_m
+
+module iso_check_m
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_signed_char, c_int16_t, c_size_t
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_funptr, c_funloc, c_associated
+
+ use :: isof_m, only: &
+ CFI_type_cptr, CFI_type_cfunptr
+
+ use :: isof_m, only: &
+ check_fn_as, &
+ check_fn_ar
+
+ use :: isof_m, only: &
+ mult2
+
+ use :: isof_m, only: &
+ cfi_encode_type
+
+ implicit none
+
+ integer :: i
+ integer(kind=c_size_t), parameter :: b = 8
+ integer, parameter :: n = 11
+
+contains
+
+ subroutine check_c_funptr()
+ type(c_funptr) :: p(n)
+ integer :: i
+ !
+ p = [(c_funloc(mult2), i=1,n)]
+ call f_check_c_funptr_as(p)
+ do i = 1, n
+ if(.not.c_associated(p(i), c_funloc(mult2))) stop 1
+ end do
+ p = [(c_funloc(mult2), i=1,n)]
+ call c_check_c_funptr_as(p)
+ do i = 1, n
+ if(.not.c_associated(p(i), c_funloc(mult2))) stop 2
+ end do
+ p = [(c_funloc(mult2), i=1,n)]
+ call f_check_c_funptr_ar(p)
+ do i = 1, n
+ if(.not.c_associated(p(i), c_funloc(mult2))) stop 3
+ end do
+ p = [(c_funloc(mult2), i=1,n)]
+ call c_check_c_funptr_ar(p)
+ do i = 1, n
+ if(.not.c_associated(p(i), c_funloc(mult2))) stop 4
+ end do
+ return
+ end subroutine check_c_funptr
+
+ subroutine f_check_c_funptr_as(a)
+ type(c_funptr), intent(in) :: a(:)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cfunptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 5
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 6
+ end do
+ call check_fn_as(a, t, k, e, 1_c_size_t)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 7
+ end do
+ return
+ end subroutine f_check_c_funptr_as
+
+ subroutine c_check_c_funptr_as(a) bind(c)
+ type(c_funptr), intent(in) :: a(:)
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cfunptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 8
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 9
+ end do
+ call check_fn_as(a, t, k, e, 1_c_size_t)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 10
+ end do
+ return
+ end subroutine c_check_c_funptr_as
+
+ subroutine f_check_c_funptr_ar(a)
+ type(c_funptr), intent(in) :: a(..)
+ !
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cfunptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 11
+ select rank(a)
+ rank(1)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 12
+ end do
+ rank default
+ stop 13
+ end select
+ call check_fn_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 14
+ end do
+ rank default
+ stop 15
+ end select
+ return
+ end subroutine f_check_c_funptr_ar
+
+ subroutine c_check_c_funptr_ar(a) bind(c)
+ type(c_funptr), intent(in) :: a(..)
+ integer(kind=c_int16_t) :: t
+ integer(kind=c_signed_char) :: k
+ integer(kind=c_size_t) :: e
+ !
+ k = 0
+ e = storage_size(a)/b
+ t = cfi_encode_type(CFI_type_cfunptr, k)
+ ! Assumes 64-bit target.
+ ! if(e/=8) stop 16
+ select rank(a)
+ rank(1)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 17
+ end do
+ rank default
+ stop 18
+ end select
+ call check_fn_ar(a, t, k, e, 1_c_size_t)
+ select rank(a)
+ rank(1)
+ do i = 1, n
+ if(.not.c_associated(a(i), c_funloc(mult2))) stop 19
+ end do
+ rank default
+ stop 20
+ end select
+ return
+ end subroutine c_check_c_funptr_ar
+
+end module iso_check_m
+
+program main_p
+
+ use :: iso_check_m, only: &
+ check_c_funptr
+
+ implicit none
+
+ call check_c_funptr()
+ stop
+
+end program main_p
+
+!! Local Variables:
+!! mode: f90
+!! End:
+
diff --git a/gcc/testsuite/gfortran.dg/PR93963.f90 b/gcc/testsuite/gfortran.dg/PR93963.f90
index 4e1b06f..66c9379 100644
--- a/gcc/testsuite/gfortran.dg/PR93963.f90
+++ b/gcc/testsuite/gfortran.dg/PR93963.f90
@@ -3,6 +3,8 @@
! Test the fix for PR93963
!
+module m
+contains
function rank_p(this) result(rnk) bind(c)
use, intrinsic :: iso_c_binding, only: c_int
@@ -97,27 +99,60 @@ function rank_a(this) result(rnk) bind(c)
return
end function rank_a
-program selr_p
-
+function rank_o(this) result(rnk) bind(c)
use, intrinsic :: iso_c_binding, only: c_int
implicit none
+
+ integer(kind=c_int), intent(in) :: this(..)
+ integer(kind=c_int) :: rnk
- interface
- function rank_p(this) result(rnk) bind(c)
- use, intrinsic :: iso_c_binding, only: c_int
- integer(kind=c_int), pointer, intent(in) :: this(..)
- integer(kind=c_int) :: rnk
- end function rank_p
- end interface
-
- interface
- function rank_a(this) result(rnk) bind(c)
- use, intrinsic :: iso_c_binding, only: c_int
- integer(kind=c_int), allocatable, intent(in) :: this(..)
- integer(kind=c_int) :: rnk
- end function rank_a
- end interface
+ select rank(this)
+ rank(0)
+ rnk = 0
+ rank(1)
+ rnk = 1
+ rank(2)
+ rnk = 2
+ rank(3)
+ rnk = 3
+ rank(4)
+ rnk = 4
+ rank(5)
+ rnk = 5
+ rank(6)
+ rnk = 6
+ rank(7)
+ rnk = 7
+ rank(8)
+ rnk = 8
+ rank(9)
+ rnk = 9
+ rank(10)
+ rnk = 10
+ rank(11)
+ rnk = 11
+ rank(12)
+ rnk = 12
+ rank(13)
+ rnk = 13
+ rank(14)
+ rnk = 14
+ rank(15)
+ rnk = 15
+ rank default
+ rnk = -1000
+ end select
+ return
+end function rank_o
+
+end module m
+
+program selr_p
+ use m
+ use, intrinsic :: iso_c_binding, only: c_int
+
+ implicit none
integer(kind=c_int), parameter :: siz = 7
integer(kind=c_int), parameter :: rnk = 1
@@ -139,12 +174,19 @@ program selr_p
irnk = rank_p(intp)
if (irnk /= rnk) stop 5
if (irnk /= rank(intp)) stop 6
+ irnk = rank_o(intp)
+ if (irnk /= rnk) stop 7
+ if (irnk /= rank(intp)) stop 8
deallocate(intp)
nullify(intp)
!
allocate(inta(siz))
- if (irnk /= rnk) stop 7
- if (irnk /= rank(inta)) stop 8
+ irnk = rank_a(inta)
+ if (irnk /= rnk) stop 9
+ if (irnk /= rank(inta)) stop 10
+ irnk = rank_o(inta)
+ if (irnk /= rnk) stop 11
+ if (irnk /= rank(inta)) stop 12
deallocate(inta)
end program selr_p
diff --git a/gcc/testsuite/gfortran.dg/PR94110.f90 b/gcc/testsuite/gfortran.dg/PR94110.f90
index 9ec70ec..4e43332 100644
--- a/gcc/testsuite/gfortran.dg/PR94110.f90
+++ b/gcc/testsuite/gfortran.dg/PR94110.f90
@@ -9,6 +9,16 @@ program asa_p
integer, parameter :: n = 7
+ type t
+ end type t
+
+ interface
+ subroutine fc2 (x)
+ import :: t
+ class(t), pointer, intent(in) :: x(..)
+ end subroutine
+ end interface
+
integer :: p(n)
integer :: s
@@ -84,5 +94,10 @@ contains
return
end function sum_p_ar
+ subroutine sub1(y)
+ type(t), target :: y(*)
+ call fc2 (y) ! { dg-error "Actual argument for .x. cannot be an assumed-size array" }
+ end subroutine sub1
+
end program asa_p
diff --git a/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90 b/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90
new file mode 100644
index 0000000..8bb7ea1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associated_assumed_rank.f90
@@ -0,0 +1,126 @@
+! { dg-do run }
+
+! PR fortran/101334
+
+implicit none (type, external)
+real, target :: AT(10,10), BT
+real, contiguous, pointer :: A(:,:)
+real, pointer :: B
+real, pointer :: AP(:,:), BP
+real, pointer :: CP(:), DP(:,:), D, EP(:)
+
+call test_char()
+
+A => AT
+B => BT
+
+AP => A
+BP => B
+call foo(AP,B, A, 1) ! OK - associated
+call foo(BP,B, A, 2) ! OK - associated
+
+! Those are all not associated:
+
+AP => null()
+BP => null()
+call foo(AP, B, A, 3) ! LHS not associated
+call foo(BP, B, A, 4) ! LHS not associated
+
+DP => null()
+D => null()
+call foo(AP, B, DP, 5) ! LHS+RHS not associated
+call foo(BP, D, A, 6) ! LHS+RHS not associated
+
+AP => A
+BP => B
+call foo(AP, B, DP, 7) ! RHS not associated
+call foo(BP, D, A, 8) ! RHS not associated
+
+CP(1:size(A)) => A
+call foo(CP, B, A, 9) ! Shape (rank) differs
+
+AP => A(2:,:)
+call foo(AP, B, A, 10) ! Shape differs
+
+AP => A(:,2:)
+call foo(AP, B, A, 11) ! Shape differs
+
+AP(10:,10:) => A
+call foo(AP, B, A, 12) ! OK - bounds different, shape same
+
+CP => AT(1:-1, 5)
+EP => AT(1:-1, 5) ! Case(i) + case(iv)
+call foo2(CP, EP) ! CP associated - but CP not associated with EP
+contains
+subroutine foo2(p, lpd)
+ implicit none (type, external)
+ real, pointer :: p(..) ! "pointer"
+ real, pointer :: lpd(:) ! array "target"
+ if (.not.associated(p)) stop 18 ! OK - associated
+ if (associated(p, lpd)) stop 19 ! .. but for zero-sized array
+end
+
+subroutine foo(p, lp, lpd, cnt)
+ implicit none (type, external)
+ real, pointer :: p(..) ! "pointer"
+ real, pointer :: lp ! scalar "target"
+ real, pointer :: lpd(:,:) ! array "target"
+ integer, value :: cnt
+
+ if (cnt == 1) then
+ if (.not. associated(p, lpd)) stop 1 ! OK
+ elseif (cnt == 2) then
+ if (.not. associated(p, lp)) stop 2 ! OK
+ elseif (cnt == 3) then
+ if (associated(p, lpd)) stop 3 ! LHS NULL ptr
+ if (associated(p)) stop 4 ! LHS NULL ptr
+ elseif (cnt == 4) then
+ if (associated(p, lp)) stop 5 ! LHS NULL ptr
+ if (associated(p)) stop 6 ! LHS NULL ptr
+ elseif (cnt == 5) then
+ if (associated(p, lpd)) stop 7 ! LHS+RHS NULL ptr
+ if (associated(p)) stop 8 ! LHS+RHS NULL ptr
+ elseif (cnt == 6) then
+ if (associated(p, lp)) stop 9 ! LHS+RHS NULL ptr
+ if (associated(p)) stop 10 ! LHS+RHS NULL ptr
+ elseif (cnt == 7) then
+ if (associated(p, lpd)) stop 11 ! RHS NULL ptr
+ elseif (cnt == 8) then
+ if (associated(p, lp)) stop 12 ! RHS NULL ptr
+ elseif (cnt == 9) then
+ if (associated(p, lpd)) stop 13 ! rank differs
+ if (associated(p, lp)) stop 14 ! rank differs
+ elseif (cnt == 10) then
+ if (associated(p, lpd)) stop 15 ! shape differs
+ elseif (cnt == 11) then
+ if (associated(p, lpd)) stop 16 ! shape differs
+ elseif (cnt == 12) then
+ if (.not.associated(p, lpd)) stop 17 ! OK - shape same, lbound different
+ else
+ stop 99
+ endif
+end
+subroutine test_char()
+ character(len=0), target :: str0
+ character(len=2), target :: str2
+ character(len=:), pointer :: ptr
+ ptr => str0
+ call test_char2(ptr, str0)
+ ptr => str2
+ call test_char2(ptr, str2)
+end
+subroutine test_char2(x,y)
+ character(len=:), pointer :: x
+ character(len=*), target :: y
+ if (len(y) == 0) then
+ if (len(x) /= 0) stop 20
+ if (.not. associated(x)) stop 21
+ if (associated(x, y)) stop 22
+ else
+ if (len(y) /= 2) stop 23
+ if (len(x) /= 2) stop 24
+ if (.not. associated(x)) stop 25
+ if (.not. associated(x, y)) stop 26
+ end if
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_18.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
index a8fa3ff..0bc419a 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_18.f90
@@ -7,7 +7,10 @@ program p
contains
subroutine g(x)
real :: x(..)
- call h(x)
+ select rank (x)
+ rank (1)
+ call h(x)
+ end select
end
subroutine h(x)
real :: x(*)
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_22.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_22.f90
new file mode 100644
index 0000000..8be0c10
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_22.f90
@@ -0,0 +1,169 @@
+! { dg-do run }
+! { dg-additional-sources assumed_rank_22_aux.c }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! FIXME: wrong extend in array descriptor, see C file.
+! { dg-output "c_assumed - 40 - OK" { xfail *-*-* } }
+! { dg-output "c_assumed - 100 - OK" { xfail *-*-* } }
+!
+! PR fortran/94070
+!
+! Contributed by Tobias Burnus
+! and José Rui Faustino de Sousa
+!
+program main
+ implicit none
+ integer :: A(5,4,2)
+ integer, allocatable :: B(:,:,:)
+ integer :: C(5,4,-2:-1)
+
+ interface
+ subroutine c_assumed (x, num) bind(C)
+ integer :: x(..)
+ integer, value :: num
+ end subroutine
+ subroutine c_allocated (x) bind(C)
+ integer, allocatable :: x(..)
+ end subroutine
+ end interface
+
+ allocate (B(-1:3,4,-1:-1))
+
+ call caller (a) ! num=0: assumed-size
+ call test (b, num=20) ! full array
+ call test (b(:,:,0:-1), num=40) ! zero-sized array
+ call test (c, num=60)
+ call test (c(:,:,:-1), num=80) ! full-size slice
+ call test (c(:,:,1:-1), num=100) !zero-size array
+
+ call test_alloc(b)
+
+ call c_assumed (b, num=20)
+ call c_assumed (b(:,:,0:-1), num=40)
+ call c_assumed (c, num=60)
+ call c_assumed (c(:,:,:-1), num=80)
+ call c_assumed (c(:,:,1:-1), num=100)
+
+ call c_allocated (b)
+contains
+ subroutine caller(y)
+ integer :: y(-1:3,4,*)
+ call test(y, num=0)
+ call c_assumed (y, num=0)
+ end
+ subroutine test (x, num)
+ integer :: x(..), num
+
+ ! SIZE (x)
+ if (num == 0) then
+ if (size (x) /= -20) stop 1
+ elseif (num == 20) then
+ if (size (x) /= 20) stop 21
+ elseif (num == 40) then
+ if (size (x) /= 0) stop 41
+ elseif (num == 60) then
+ if (size (x) /= 40) stop 61
+ elseif (num == 80) then
+ if (size (x) /= 40) stop 81
+ elseif (num == 100) then
+ if (size (x) /= 0) stop 101
+ else
+ stop 99 ! Invalid num
+ endif
+
+ ! SIZE (x, dim=...)
+ if (size (x, dim=1) /= 5) stop num + 2
+ if (size (x, dim=2) /= 4) stop num + 3
+
+ if (num == 0) then
+ if (size (x, dim=3) /= -1) stop 4
+ elseif (num == 20) then
+ if (size (x, dim=3) /= 1) stop 24
+ elseif (num == 40) then
+ if (size (x, dim=3) /= 0) stop 44
+ elseif (num == 60) then
+ if (size (x, dim=3) /= 2) stop 64
+ elseif (num == 80) then
+ if (size (x, dim=3) /= 2) stop 84
+ elseif (num == 100) then
+ if (size (x, dim=3) /= 0) stop 104
+ endif
+
+ ! SHAPE (x)
+ if (num == 0) then
+ if (any (shape (x) /= [5, 4, -1])) stop 5
+ elseif (num == 20) then
+ if (any (shape (x) /= [5, 4, 1])) stop 25
+ elseif (num == 40) then
+ if (any (shape (x) /= [5, 4, 0])) stop 45
+ elseif (num == 60) then
+ if (any (shape (x) /= [5, 4, 2])) stop 65
+ elseif (num == 80) then
+ if (any (shape (x) /= [5, 4, 2])) stop 85
+ elseif (num == 100) then
+ if (any (shape (x) /= [5, 4, 0])) stop 105
+ endif
+
+ ! LBOUND (X)
+ if (any (lbound (x) /= [1, 1, 1])) stop num + 6
+
+ ! LBOUND (X, dim=...)
+ if (lbound (x, dim=1) /= 1) stop num + 7
+ if (lbound (x, dim=2) /= 1) stop num + 8
+ if (lbound (x, dim=3) /= 1) stop num + 9
+
+ ! UBOUND (X)
+ if (num == 0) then
+ if (any (ubound (x) /= [5, 4, -1])) stop 11
+ elseif (num == 20) then
+ if (any (ubound (x) /= [5, 4, 1])) stop 31
+ elseif (num == 40) then
+ if (any (ubound (x) /= [5, 4, 0])) stop 51
+ elseif (num == 60) then
+ if (any (ubound (x) /= [5, 4, 2])) stop 71
+ elseif (num == 80) then
+ if (any (ubound (x) /= [5, 4, 2])) stop 91
+ elseif (num == 100) then
+ if (any (ubound (x) /= [5, 4, 0])) stop 111
+ endif
+
+ ! UBOUND (X, dim=...)
+ if (ubound (x, dim=1) /= 5) stop num + 12
+ if (ubound (x, dim=2) /= 4) stop num + 13
+ if (num == 0) then
+ if (ubound (x, dim=3) /= -1) stop 14
+ elseif (num == 20) then
+ if (ubound (x, dim=3) /= 1) stop 34
+ elseif (num == 40) then
+ if (ubound (x, dim=3) /= 0) stop 54
+ elseif (num == 60) then
+ if (ubound (x, dim=3) /= 2) stop 74
+ elseif (num == 80) then
+ if (ubound (x, dim=3) /= 2) stop 94
+ elseif (num == 100) then
+ if (ubound (x, dim=3) /= 0) stop 114
+ endif
+ end
+
+ subroutine test_alloc (x)
+ integer, allocatable :: x(..)
+
+ if (size (x) /= 20) stop 61
+ if (size (x, dim=1) /= 5) stop 62
+ if (size (x, dim=2) /= 4) stop 63
+ if (size (x, dim=3) /= 1) stop 64
+
+ if (any (shape (x) /= [5, 4, 1])) stop 65
+
+ if (any (lbound (x) /= [-1, 1, -1])) stop 66
+ if (lbound (x, dim=1) /= -1) stop 77
+ if (lbound (x, dim=2) /= 1) stop 78
+ if (lbound (x, dim=3) /= -1) stop 79
+
+ if (any (ubound (x) /= [3, 4, -1])) stop 80
+ if (ubound (x, dim=1) /= 3) stop 92
+ if (ubound (x, dim=2) /= 4) stop 93
+ if (ubound (x, dim=3) /= -1) stop 94
+ end
+end
+! { dg-final { scan-tree-dump-not "_gfortran_size" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c b/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c
new file mode 100644
index 0000000..e5fe021
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_22_aux.c
@@ -0,0 +1,68 @@
+/* Called by assumed_rank_22.f90. */
+
+#include <ISO_Fortran_binding.h>
+#include <assert.h>
+
+void
+c_assumed (CFI_cdesc_t *x, int num)
+{
+ assert (num == 0 || num == 20 || num == 40 || num == 60 || num == 80
+ || num == 100);
+ assert (x->elem_len == sizeof (int));
+ assert (x->rank == 3);
+ assert (x->type == CFI_type_int32_t);
+
+ assert (x->attribute == CFI_attribute_other);
+ assert (x->dim[0].lower_bound == 0);
+ assert (x->dim[1].lower_bound == 0);
+ assert (x->dim[2].lower_bound == 0);
+ assert (x->dim[0].extent == 5);
+ assert (x->dim[1].extent == 4);
+ if (num == 0)
+ assert (x->dim[2].extent == -1);
+ else if (num == 20)
+ assert (x->dim[2].extent == 1);
+ else if (num == 40)
+ {
+ /* FIXME: - dg-output = 'c_assumed ... OK' checked in .f90 file. */
+ /* assert (x->dim[2].extent == 0); */
+ if (x->dim[2].extent == 0)
+ __builtin_printf ("c_assumed - 40 - OK\n");
+ else
+ __builtin_printf ("error: c_assumed num=%d: "
+ "x->dim[2].extent = %d != 0\n",
+ num, x->dim[2].extent);
+ }
+ else if (num == 60)
+ assert (x->dim[2].extent == 2);
+ else if (num == 80)
+ assert (x->dim[2].extent == 2);
+ else if (num == 100)
+ {
+ /* FIXME: - dg-output = 'c_assumed ... OK' checked in .f90 file. */
+ /* assert (x->dim[2].extent == 0); */
+ if (x->dim[2].extent == 0)
+ __builtin_printf ("c_assumed - 100 - OK\n");
+ else
+ __builtin_printf ("error: c_assumed num=%d: "
+ "x->dim[2].extent = %d != 0\n",
+ num, x->dim[2].extent);
+ }
+ else
+ assert (0);
+}
+
+void
+c_allocated (CFI_cdesc_t *x)
+{
+ assert (x->elem_len == sizeof (int));
+ assert (x->rank == 3);
+ assert (x->type == CFI_type_int32_t);
+ assert (x->attribute == CFI_attribute_allocatable);
+ assert (x->dim[0].lower_bound == -1);
+ assert (x->dim[1].lower_bound == 1);
+ assert (x->dim[2].lower_bound == -1);
+ assert (x->dim[0].extent == 5);
+ assert (x->dim[1].extent == 4);
+ assert (x->dim[2].extent == 1);
+}
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_23.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_23.f90
new file mode 100644
index 0000000..c83aa7d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_23.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+!
+! PR fortran/54753
+! TS29113:C535c
+! F2018:C839
+!
+module m
+
+ interface
+ subroutine s1 (x, y)
+ class(*) :: x(..)
+ class(*), intent (out) :: y(..)
+ end subroutine
+ end interface
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_24.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_24.f90
new file mode 100644
index 0000000..d91b5ec
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_24.f90
@@ -0,0 +1,137 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=all" }
+module m
+ implicit none (external, type)
+contains
+ subroutine cl(x)
+ class(*) :: x(..)
+ if (rank(x) /= 1) stop 1
+ if (ubound(x, dim=1) /= -1) stop 2
+ select rank (x)
+ rank (1)
+ select type (x)
+ type is (integer)
+ ! ok
+ class default
+ stop 3
+ end select
+ end select
+ end subroutine
+ subroutine tp(x)
+ type(*) :: x(..)
+ if (rank(x) /= 1) stop 4
+ if (ubound(x, dim=1) /= -1) stop 5
+ end subroutine
+
+ subroutine foo (ccc, ddd, sss, ttt)
+ integer :: sss(*), ttt(*)
+ class(*) :: ccc(*), ddd(*)
+ call cl(sss)
+ call tp(ttt)
+ call cl(ccc)
+ call tp(ddd)
+ end
+
+ subroutine foo2 (ccc, ddd, sss, ttt, ispresent)
+ integer :: sss(*), ttt(*)
+ class(*) :: ccc(*), ddd(*)
+ optional :: ccc, ddd, sss, ttt
+ logical, value :: ispresent
+ if (present(ccc) .neqv. ispresent) stop 6
+ if (present(ccc)) then
+ call cl(sss)
+ call tp(ttt)
+ call cl(ccc)
+ call tp(ddd)
+ end if
+ end
+end
+
+module m2
+ implicit none (external, type)
+contains
+ subroutine cl2(x)
+ class(*), allocatable :: x(..)
+ if (rank(x) /= 1) stop 7
+ if (.not. allocated (x)) &
+ return
+ if (lbound(x, dim=1) /= -2) stop 8
+ if (ubound(x, dim=1) /= -1) stop 9
+ if (size (x, dim=1) /= 2) stop 10
+ select rank (x)
+ rank (1)
+ select type (x)
+ type is (integer)
+ ! ok
+ class default
+ stop 11
+ end select
+ end select
+ end subroutine
+
+ subroutine tp2(x)
+ class(*), pointer :: x(..)
+ if (rank(x) /= 1) stop 12
+ if (.not. associated (x)) &
+ return
+ if (lbound(x, dim=1) /= -2) stop 13
+ if (ubound(x, dim=1) /= -1) stop 14
+ if (size (x, dim=1) /= 2) stop 15
+ select rank (x)
+ rank (1)
+ select type (x)
+ type is (integer)
+ ! ok
+ class default
+ stop 16
+ end select
+ end select
+ end subroutine
+
+ subroutine foo3 (ccc, ddd, sss, ttt)
+ class(*), allocatable :: sss(:)
+ class(*), pointer :: ttt(:)
+ class(*), allocatable :: ccc(:)
+ class(*), pointer :: ddd(:)
+ call cl2(sss)
+ call tp2(ttt)
+ call cl2(ccc)
+ call tp2(ddd)
+ end
+
+ subroutine foo4 (ccc, ddd, sss, ttt, ispresent)
+ class(*), allocatable, optional :: sss(:)
+ class(*), pointer, optional :: ttt(:)
+ class(*), allocatable, optional :: ccc(:)
+ class(*), pointer, optional :: ddd(:)
+ logical, value :: ispresent
+ if (present(ccc) .neqv. ispresent) stop 17
+ if (present(ccc)) then
+ call cl2(sss)
+ call tp2(ttt)
+ call cl2(ccc)
+ call tp2(ddd)
+ end if
+ end
+end
+
+use m
+use m2
+implicit none (external, type)
+integer :: a(1),b(1),c(1),d(1)
+class(*),allocatable :: aa(:),cc(:)
+class(*),pointer :: bb(:),dd(:)
+call foo (a,b,c,d)
+call foo2 (a,b,c,d, .true.)
+call foo2 (ispresent=.false.)
+
+nullify(bb,dd)
+call foo3 (aa,bb,cc,dd)
+call foo4 (aa,bb,cc,dd, .true.)
+call foo4 (ispresent=.false.)
+allocate(integer :: aa(-2:-1), bb(-2:-1), cc(-2:-1), dd(-2:-1))
+call foo3 (aa,bb,cc,dd)
+call foo4 (aa,bb,cc,dd, .true.)
+call foo4 (ispresent=.false.)
+deallocate(aa,bb,cc,dd)
+end
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_10.f90 b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
index bf0c873..a8bbf2d 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_10.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
@@ -31,7 +31,10 @@ contains
subroutine test_array (a)
use iso_c_binding, only: c_size_t
class(*), dimension(..), target :: a
- call test_lib (a, int (sizeof (a), kind=c_size_t))
+ select rank (a)
+ rank (1)
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end select
end subroutine
end module
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_11.f90 b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
index df6572d..391fa0d 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_11.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
@@ -31,7 +31,10 @@ contains
subroutine test_array (a)
use iso_c_binding, only: c_size_t
class(*), dimension(..), target :: a
- call test_lib (a, int (sizeof (a), kind=c_size_t))
+ select rank (a)
+ rank (1)
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end select
end subroutine
end module
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_12.f90 b/gcc/testsuite/gfortran.dg/assumed_type_12.f90
new file mode 100644
index 0000000..ce6d0bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_12.f90
@@ -0,0 +1,34 @@
+! PR fortran/102086
+
+implicit none (type, external)
+contains
+subroutine as(a)
+ type(*) :: a(:,:)
+end
+subroutine ar(b)
+ type(*) :: b(..)
+end
+subroutine bar(x,y)
+ type(*) :: x
+ type(*) :: y(3,*)
+ call as(x) ! { dg-error "Rank mismatch in argument 'a' at .1. \\(rank-2 and scalar\\)" }
+ call ar(x) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'b' must be assumed-shape or assumed-rank" }
+ call ar(y) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'b' must be assumed-shape or assumed-rank" }
+ call as(y(1,3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
+ call ar(y(1,3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
+ call as(y(1:1,3:3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
+ call ar(y(1:1,3:3)) ! { dg-error "Assumed-type variable y at .1. shall not have a subobject reference" }
+end
+
+subroutine okayish(x,y,z)
+ type(*) :: x(:)
+ type(*) :: y(:,:)
+ type(*) :: z(..)
+ call as(x) ! { dg-error "Rank mismatch in argument 'a' at .1. \\(rank-2 and rank-1\\)" }
+ call as(y)
+ call as(z) ! { dg-error "The assumed-rank array at .1. requires that the dummy argument 'a' has assumed-rank" }
+ call ar(x)
+ call ar(y)
+ call ar(z)
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_13.c b/gcc/testsuite/gfortran.dg/assumed_type_13.c
new file mode 100644
index 0000000..d602d35
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_13.c
@@ -0,0 +1,26 @@
+#include <ISO_Fortran_binding.h>
+
+void
+test_c (CFI_cdesc_t *x, size_t n, int num)
+{
+ if (!x->base_addr)
+ __builtin_abort ();
+ if (x->version != CFI_VERSION)
+ __builtin_abort ();
+ if (x->rank != 1)
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ if (x->dim[0].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[0].extent != 3)
+ __builtin_abort ();
+
+ if (x->elem_len != n || x->dim[0].sm != n)
+ __builtin_abort ();
+
+ if (num == 1 && x->type != CFI_type_int16_t)
+ __builtin_abort ();
+ if (num == 2 && x->type != CFI_type_double_Complex)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_13.f90 b/gcc/testsuite/gfortran.dg/assumed_type_13.f90
new file mode 100644
index 0000000..da167ae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_13.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-additional-sources assumed_type_13.c }
+
+use iso_c_binding, only: c_size_t, c_int
+implicit none (type, external)
+
+interface
+ subroutine test_c (x, n, num) bind (C)
+ import :: c_size_t, c_int
+ integer(c_size_t), value :: n
+ integer(c_int), value :: num
+ type(*) :: x(:)
+ end subroutine test_c
+end interface
+
+complex(8) :: b(3)
+
+call test_c ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
+call test_c (b, sizeof(b(1)), num=2)
+call outer_bc ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
+call outer_bc (b, sizeof(b(1)), num=2)
+call outer_f ([1_2, 2_2, 3_2], sizeof(1_2), num=1)
+call outer_f (b, sizeof(b(1)), num=2)
+
+contains
+
+subroutine outer_bc (x, n, num) bind(C)
+ integer(c_size_t), value :: n
+ integer(c_int), value :: num
+ type(*) :: x(:)
+ ! print *,sizeof(x)/size(x), n
+ if (sizeof(x)/size(x) /= n) error stop 1
+ call inner_bc (x, n, num)
+ call inner_f (x, n, num)
+ call test_c (x, n, num)
+end
+
+subroutine outer_f (x, n, num)
+ integer(c_size_t), value :: n
+ integer(c_int), value :: num
+ type(*) :: x(:)
+ ! print *,sizeof(x)/size(x), n
+ if (sizeof(x)/size(x) /= n) error stop 1
+ call inner_f (x, n, num)
+ call inner_bc (x, n, num)
+ call test_c (x, n, num)
+end
+
+subroutine inner_bc(x, n, num) bind(C)
+ integer(c_size_t), value :: n
+ integer(c_int), value :: num
+ type(*) :: x(:)
+ ! print *,sizeof(x)/size(x), n
+ if (sizeof(x)/size(x) /= n) error stop 2
+ call test_c (x, n, num)
+end
+
+subroutine inner_f(x, n, num)
+ integer(c_size_t), value :: n
+ integer(c_int), value :: num
+ type(*) :: x(:)
+ ! print *,sizeof(x)/size(x), n
+ if (sizeof(x)/size(x) /= n) error stop 3
+ call test_c (x, n, num)
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90 b/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90
new file mode 100644
index 0000000..97a365a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_deprecated-2.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-additional-options "-Wall" }
+!
+! Ensure that only those parameters are warned for which are actually used
+!
+module m
+ implicit none
+ integer, parameter :: parm = 4 ! unused
+ integer, parameter :: parm2 = 4 ! used in the main program
+ integer, parameter :: parm3 = 4 ! used in "f()" - { dg-warning "Using parameter 'parm3' declared at .1. is deprecated" }
+ integer, save :: var, var2
+!GCC$ ATTRIBUTES DEPRECATED :: parm, parm2, parm3, var, var2
+contains
+ subroutine f()
+ print *, parm3 ! warning shown above
+ end
+end module m
+
+use m ! { dg-warning "Using parameter 'parm2' declared at .1. is deprecated" }
+implicit none
+print *, var2, parm2 ! { dg-warning "Using variable 'var2' at .1. is deprecated" }
+end
diff --git a/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90
new file mode 100644
index 0000000..3b01ad3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90
@@ -0,0 +1,104 @@
+! PR fortran/92482
+!
+! Contributed by José Rui Faustino de Sousa
+!
+! Note the xfail issue below for 'strg_print_2("abc")
+
+program strp_p
+
+ use, intrinsic :: iso_c_binding, only: &
+ c_char
+
+ implicit none
+
+ integer, parameter :: l = 3
+
+ character(len=l, kind=c_char), target :: str
+ character(len=:, kind=c_char), pointer :: strp_1
+ character(len=l, kind=c_char), pointer :: strp_2
+
+ str = "abc"
+ nullify(strp_1, strp_2)
+ strp_1 => str
+ strp_2 => str
+ if (len(str) /= 3 .or. str /= "abc") stop 1
+ if (len(strp_1) /= 3 .or. strp_1 /= "abc") stop 2
+ if (len(strp_2) /= 3 .or. strp_2 /= "abc") stop 3
+ call strg_print_0("abc") ! Error (10.0.0) or segmentation fault (9.1.0)
+ call strg_print_0(str) ! Error (10.0.0) or segmentation fault (9.1.0)
+ call strg_print_0(strp_1) ! Error (10.0.0) or segmentation fault (9.1.0)
+ call strg_print_0(strp_2) ! Error (10.0.0) or segmentation fault (9.1.0)
+ call strg_print_1(strp_1) ! Not yet supported
+
+ call strg_print_2("abc", xfail=.true.)
+ call strg_print_2(str)
+ call strg_print_2(strp_1)
+ call strg_print_2(strp_2)
+
+ call strg_print_2_c("abc")
+ call strg_print_2_c(str)
+ call strg_print_2_c(strp_1)
+ call strg_print_2_c(strp_2)
+
+contains
+
+ subroutine strg_print_0(this) bind(c) ! Error (10.0.0 20191106) or warning (9.1.0) issued with bind(c)
+ character(len=*, kind=c_char), target, intent(in) :: this
+
+ if (len (this) /= 3) stop 10
+ if (this /= "abc") stop 11
+ end subroutine strg_print_0
+
+ subroutine strg_print_1(this) bind(c) ! Not yet supported with bind(c)
+ character(len=:, kind=c_char), pointer, intent(in) :: this
+ character(len=:), pointer :: strn
+
+ if (.not. associated (this)) stop 20
+ if (len (this) /= 3) stop 21
+ if (this /= "abc") stop 22
+ strn => this
+ if (.not. associated (strn)) stop 23
+ if(associated(strn))then
+ if (len (this) /= 3) stop 24
+ if (this /= "abc") stop 25
+ end if
+ end subroutine strg_print_1
+
+ subroutine strg_print_2(this, xfail)
+ use, intrinsic :: iso_c_binding, only: &
+ c_loc, c_f_pointer
+
+ type(*), target, intent(in) :: this(..)
+ logical, optional, value :: xfail
+ character(len=l), pointer :: strn
+
+ call c_f_pointer(c_loc(this), strn)
+ if (.not. associated (strn)) stop 30
+ if(associated(strn))then
+ if (len (strn) /= 3) stop 31
+ if (strn /= "abc") then
+ if (present (xfail)) then
+ print *, 'INVALID STRING - EXPECTED "abc" / PR47225'
+ else
+ stop 32
+ end if
+ end if
+ end if
+ end subroutine strg_print_2
+
+ subroutine strg_print_2_c(this) bind(c)
+ use, intrinsic :: iso_c_binding, only: &
+ c_loc, c_f_pointer
+
+ type(*), target, intent(in) :: this(..)
+ character(len=l), pointer :: strn
+
+ call c_f_pointer(c_loc(this), strn)
+ if (.not. associated (strn)) stop 40
+ if(associated(strn))then
+ if (len (strn) /= 3) stop 41
+ if (strn /= "abc") stop 42
+ end if
+ end subroutine strg_print_2_c
+
+end program strp_p
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c
new file mode 100644
index 0000000..06bbd6f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.c
@@ -0,0 +1,345 @@
+#include <ISO_Fortran_binding.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct loc_t {
+ intptr_t x, y, z;
+};
+
+typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+
+static void
+basic_check(CFI_cdesc_t *x, bool is_cont)
+{
+ if (!x->base_addr)
+ __builtin_abort ();
+ if (x->elem_len != 3*sizeof(char))
+ __builtin_abort ();
+ if (x->version != CFI_VERSION)
+ __builtin_abort ();
+ if (x->rank != 1)
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ if (x->type != CFI_type_char)
+ __builtin_abort ();
+ if (x->dim[0].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[0].extent != 3)
+ __builtin_abort ();
+ if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
+ __builtin_abort ();
+ if (is_cont != CFI_is_contiguous (x))
+ __builtin_abort ();
+}
+
+static void
+print_str (void *p, size_t len)
+{
+ __builtin_printf ("DEBUG: >");
+ for (size_t i = 0; i < len; ++i)
+ __builtin_printf ("%c", ((const char*) p)[i]);
+ __builtin_printf ("<\n");
+}
+
+static void
+check_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
+{
+ /* Avoid checking for '\0'. */
+ if (strncmp ((const char*) CFI_address (x, subscripts), str, strlen(str)) != 0)
+ __builtin_abort ();
+}
+
+static void
+set_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
+{
+ char *p = CFI_address (x, subscripts);
+ size_t len = strlen (str);
+ if (x->elem_len != len)
+ __builtin_abort ();
+ for (size_t i = 0; i < len; ++i)
+ p[i] = str[i];
+}
+
+static struct loc_t
+do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+ struct loc_t addr1, addr2;
+ if (k != 3)
+ __builtin_abort ();
+ basic_check (x, is_cont || num == 2);
+ basic_check (y, is_cont || num == 2);
+ basic_check (z, is_cont || num == 2);
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "abc", zero);
+ check_str (x, "ghi", one);
+ check_str (x, "nop", two);
+ check_str (y, "abc", zero);
+ check_str (y, "ghi", one);
+ check_str (y, "nop", two);
+ check_str (z, "abc", zero);
+ check_str (z, "ghi", one);
+ check_str (z, "nop", two);
+ }
+ else if (num == 1)
+ {
+ if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (num == 2)
+ {
+ if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+ addr1.x = (intptr_t) x->base_addr;
+ addr1.y = (intptr_t) y->base_addr;
+ addr1.z = (intptr_t) z->base_addr;
+ addr2 = fn (x, y, z, 3, num);
+ if (!CFI_is_contiguous (x) && fort_cont)
+ {
+ /* Check for callee copy in/copy out. */
+ if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ // intent_in
+ if (intent_in && !is_cont && num == 1)
+ {
+ check_str (x, "abc", zero);
+ check_str (x, "ghi", one);
+ check_str (x, "nop", two);
+ check_str (y, "abc", zero);
+ check_str (y, "ghi", one);
+ check_str (y, "nop", two);
+ check_str (z, "abc", zero);
+ check_str (z, "ghi", one);
+ check_str (z, "nop", two);
+ }
+ else if (intent_in && num == 1)
+ {
+ if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in && num == 2)
+ {
+ if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in)
+ __builtin_abort ();
+ if (intent_in)
+ {
+ if (is_cont && num == 1)
+ {
+ /* Copy in - set the value to check that no copy out is done. */
+ memcpy ((char*) x->base_addr, "123456789", 9);
+ memcpy ((char*) y->base_addr, "123456789", 9);
+ memcpy ((char*) z->base_addr, "123456789", 9);
+ }
+ return addr1;
+ }
+ // !intent_in
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "ABC", zero);
+ check_str (x, "DEF", one);
+ check_str (x, "GHI", two);
+ check_str (y, "ABC", zero);
+ check_str (y, "DEF", one);
+ check_str (y, "GHI", two);
+ check_str (z, "ABC", zero);
+ check_str (z, "DEF", one);
+ check_str (z, "GHI", two);
+ }
+ else
+ {
+ if (strncmp ((const char*) x->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ }
+ return addr1;
+}
+
+struct loc_t
+char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
+}
+
+struct loc_t
+char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
+}
+
+struct loc_t
+char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
+}
+
+struct loc_t
+char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
+}
+
+static void
+reset_var (CFI_cdesc_t *x, int num)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+
+ if (num == 1)
+ {
+ set_str (x, "abc", zero);
+ set_str (x, "ghi", one);
+ set_str (x, "nop", two);
+ }
+ else if (num == 2)
+ {
+ set_str (x, "def", zero);
+ set_str (x, "ghi", one);
+ set_str (x, "jlm", two);
+ }
+ else
+ __builtin_abort ();
+}
+
+static void
+reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
+{
+ reset_var (x, num);
+ reset_var (y, num);
+ reset_var (z, num);
+}
+
+struct loc_t
+char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ /* Make use of having a noncontiguous argument to check that the callee
+ handles noncontiguous variables. */
+ do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
+ /* Actual func call. */
+ reset_vars (x, y, z, num);
+ return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
+}
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f90 b/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f90
new file mode 100644
index 0000000..77dd3a2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-1.f90
@@ -0,0 +1,1574 @@
+! { dg-do run }
+! { dg-additional-sources bind-c-contiguous-1.c }
+! { dg-additional-options "-fcheck=all" }
+! { dg-prune-output "command-line option '-fcheck=.*' is valid for Fortran but not for C" }
+
+! Fortran demands that with bind(C), the callee ensure that for
+! * 'contiguous'
+! * len=* with explicit/assumed-size arrays
+! noncontiguous actual arguments are handled.
+! (in without bind(C) in gfortran, caller handles the copy in/out
+
+! Additionally, for a bind(C) callee, a Fortran-written caller
+! has to ensure the same (for contiguous + len=* to explicit-/assumed-size arrays)
+
+module m
+ use iso_c_binding, only: c_intptr_t, c_bool, c_loc, c_int
+ implicit none (type, external)
+
+ type, bind(C) :: loc_t
+ integer(c_intptr_t) :: x, y, z
+ end type loc_t
+
+interface
+ type(loc_t) function char_assumed_size_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_assumed_size_in_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), intent(in) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_expl_size_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*) :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_expl_size_in_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), intent(in) :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_assumed_rank_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*) :: xx(..)
+ character(len=3) :: yy(..)
+ character(len=k) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), intent(in) :: xx(..)
+ character(len=3), intent(in) :: yy(..)
+ character(len=k), intent(in) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous :: xx(..)
+ character(len=3), contiguous :: yy(..)
+ character(len=k), contiguous :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, intent(in) :: xx(..)
+ character(len=3), contiguous, intent(in) :: yy(..)
+ character(len=k), contiguous, intent(in) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_shape_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*) :: xx(:)
+ character(len=3) :: yy(5:)
+ character(len=k) :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), intent(in) :: xx(:)
+ character(len=3), intent(in) :: yy(5:)
+ character(len=k), intent(in) :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous :: xx(:)
+ character(len=3), contiguous :: yy(5:)
+ character(len=k), contiguous :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, intent(in) :: xx(:)
+ character(len=3), contiguous, intent(in) :: yy(5:)
+ character(len=k), contiguous, intent(in) :: zz(-k:)
+ end function
+end interface
+
+contains
+
+type(loc_t) function char_assumed_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(3) = "ABC"
+ yy(4) = "DEF"
+ yy(5) = "GHI"
+ zz(6,n,3) = "ABC"
+ zz(6,n,4) = "DEF"
+ zz(6,n,5) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" } if (num == 1) then
+end
+
+type(loc_t) function char_expl_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*) :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(3) = "ABC"
+ yy(4) = "DEF"
+ yy(5) = "GHI"
+ zz(6,n,3) = "ABC"
+ zz(6,n,4) = "DEF"
+ zz(6,n,5) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_expl_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*) :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+
+type(loc_t) function char_assumed_rank_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(..)
+ character(len=3) :: yy(..)
+ character(len=k) :: zz(..)
+ if (3 /= len(xx)) error stop 40
+ if (3 /= len(yy)) error stop 40
+ if (3 /= len(zz)) error stop 40
+ if (3 /= size(xx)) error stop 41
+ if (3 /= size(yy)) error stop 41
+ if (3 /= size(zz)) error stop 41
+ if (1 /= rank(xx)) error stop 49
+ if (1 /= rank(yy)) error stop 49
+ if (1 /= rank(zz)) error stop 49
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 49
+ if (is_contiguous (yy)) error stop 49
+ if (is_contiguous (zz)) error stop 49
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 49
+ if (.not. is_contiguous (yy)) error stop 49
+ if (.not. is_contiguous (zz)) error stop 49
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 42
+ if (xx(2) /= "ghi") error stop 43
+ if (xx(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 45
+ if (xx(2) /= "ghi") error stop 46
+ if (xx(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ res%x = get_loc (xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 42
+ if (yy(2) /= "ghi") error stop 43
+ if (yy(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 45
+ if (yy(2) /= "ghi") error stop 46
+ if (yy(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ yy(1) = "ABC"
+ yy(2) = "DEF"
+ yy(3) = "GHI"
+ res%y = get_loc (yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 42
+ if (zz(2) /= "ghi") error stop 43
+ if (zz(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 45
+ if (zz(2) /= "ghi") error stop 46
+ if (zz(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ zz(1) = "ABC"
+ zz(2) = "DEF"
+ zz(3) = "GHI"
+ res%z = get_loc (zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_rank_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(..)
+ character(len=3) :: yy(..)
+ character(len=k) :: zz(..)
+ intent(in) :: xx, yy, zz
+ if (3 /= size(yy)) error stop 50
+ if (3 /= len(yy)) error stop 51
+ if (1 /= rank(yy)) error stop 59
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 59
+ if (is_contiguous (yy)) error stop 59
+ if (is_contiguous (zz)) error stop 59
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 59
+ if (.not. is_contiguous (yy)) error stop 59
+ if (.not. is_contiguous (zz)) error stop 59
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 52
+ if (xx(2) /= "ghi") error stop 53
+ if (xx(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 55
+ if (xx(2) /= "ghi") error stop 56
+ if (xx(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%x = get_loc(xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 52
+ if (yy(2) /= "ghi") error stop 53
+ if (yy(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 55
+ if (yy(2) /= "ghi") error stop 56
+ if (yy(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%y = get_loc(yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 52
+ if (zz(2) /= "ghi") error stop 53
+ if (zz(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 55
+ if (zz(2) /= "ghi") error stop 56
+ if (zz(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%z = get_loc(zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_rank_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(..)
+ character(len=3) :: yy(..)
+ character(len=k) :: zz(..)
+ contiguous :: xx, yy, zz
+ if (3 /= len(xx)) error stop 60
+ if (3 /= len(yy)) error stop 60
+ if (3 /= len(zz)) error stop 60
+ if (3 /= size(xx)) error stop 61
+ if (3 /= size(yy)) error stop 61
+ if (3 /= size(zz)) error stop 61
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 62
+ if (xx(2) /= "ghi") error stop 63
+ if (xx(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 65
+ if (xx(2) /= "ghi") error stop 66
+ if (xx(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 62
+ if (yy(2) /= "ghi") error stop 63
+ if (yy(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 65
+ if (yy(2) /= "ghi") error stop 66
+ if (yy(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ yy(1) = "ABC"
+ yy(2) = "DEF"
+ yy(3) = "GHI"
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 62
+ if (zz(2) /= "ghi") error stop 63
+ if (zz(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 65
+ if (zz(2) /= "ghi") error stop 66
+ if (zz(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ zz(1) = "ABC"
+ zz(2) = "DEF"
+ zz(3) = "GHI"
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_rank_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(..)
+ character(len=3) :: yy(..)
+ character(len=k) :: zz(..)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ if (3 /= size(xx)) error stop 30
+ if (3 /= size(yy)) error stop 30
+ if (3 /= size(zz)) error stop 30
+ if (3 /= len(xx)) error stop 31
+ if (3 /= len(yy)) error stop 31
+ if (3 /= len(zz)) error stop 31
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 62
+ if (xx(2) /= "ghi") error stop 63
+ if (xx(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 65
+ if (xx(2) /= "ghi") error stop 66
+ if (xx(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 62
+ if (yy(2) /= "ghi") error stop 63
+ if (yy(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 65
+ if (yy(2) /= "ghi") error stop 66
+ if (yy(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 62
+ if (zz(2) /= "ghi") error stop 63
+ if (zz(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 65
+ if (zz(2) /= "ghi") error stop 66
+ if (zz(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_shape_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(:)
+ character(len=3) :: yy(5:)
+ character(len=k) :: zz(-k:)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 70
+ if (3 /= len(yy)) error stop 70
+ if (3 /= len(zz)) error stop 70
+ if (3 /= size(xx)) error stop 71
+ if (3 /= size(yy)) error stop 71
+ if (3 /= size(zz)) error stop 71
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 79
+ if (is_contiguous (yy)) error stop 79
+ if (is_contiguous (zz)) error stop 79
+ if (xx(1) /= "abc") error stop 72
+ if (xx(2) /= "ghi") error stop 73
+ if (xx(3) /= "nop") error stop 74
+ if (yy(5) /= "abc") error stop 72
+ if (yy(6) /= "ghi") error stop 73
+ if (yy(7) /= "nop") error stop 74
+ if (zz(-k) /= "abc") error stop 72
+ if (zz(-k+1) /= "ghi") error stop 73
+ if (zz(-k+2) /= "nop") error stop 74
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 79
+ if (.not.is_contiguous (yy)) error stop 79
+ if (.not.is_contiguous (zz)) error stop 79
+ if (xx(1) /= "def") error stop 72
+ if (xx(2) /= "ghi") error stop 73
+ if (xx(3) /= "jlm") error stop 74
+ if (yy(5) /= "def") error stop 72
+ if (yy(6) /= "ghi") error stop 73
+ if (yy(7) /= "jlm") error stop 74
+ if (zz(-k) /= "def") error stop 72
+ if (zz(-k+1) /= "ghi") error stop 73
+ if (zz(-k+2) /= "jlm") error stop 74
+ else
+ error stop 78
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(5) = "ABC"
+ yy(6) = "DEF"
+ yy(7) = "GHI"
+ zz(-k) = "ABC"
+ zz(-k+1) = "DEF"
+ zz(-k+2) = "GHI"
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_shape_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(:)
+ character(len=3) :: yy(5:)
+ character(len=k) :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 80
+ if (3 /= size(yy)) error stop 80
+ if (3 /= size(zz)) error stop 80
+ if (3 /= len(xx)) error stop 81
+ if (3 /= len(yy)) error stop 81
+ if (3 /= len(zz)) error stop 81
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 89
+ if (is_contiguous (yy)) error stop 89
+ if (is_contiguous (zz)) error stop 89
+ if (xx(1) /= "abc") error stop 82
+ if (xx(2) /= "ghi") error stop 83
+ if (xx(3) /= "nop") error stop 84
+ if (yy(5) /= "abc") error stop 82
+ if (yy(6) /= "ghi") error stop 83
+ if (yy(7) /= "nop") error stop 84
+ if (zz(-k) /= "abc") error stop 82
+ if (zz(-k+1) /= "ghi") error stop 83
+ if (zz(-k+2) /= "nop") error stop 84
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 89
+ if (.not.is_contiguous (yy)) error stop 89
+ if (.not.is_contiguous (zz)) error stop 89
+ if (xx(1) /= "def") error stop 85
+ if (xx(2) /= "ghi") error stop 86
+ if (xx(3) /= "jlm") error stop 87
+ if (yy(5) /= "def") error stop 85
+ if (yy(6) /= "ghi") error stop 86
+ if (yy(7) /= "jlm") error stop 87
+ if (zz(-k) /= "def") error stop 85
+ if (zz(-k+1) /= "ghi") error stop 86
+ if (zz(-k+2) /= "jlm") error stop 87
+ else
+ error stop 88
+ endif
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_shape_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(:)
+ character(len=3) :: yy(5:)
+ character(len=k) :: zz(-k:)
+ contiguous :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 90
+ if (3 /= len(yy)) error stop 90
+ if (3 /= len(zz)) error stop 90
+ if (3 /= size(xx)) error stop 91
+ if (3 /= size(yy)) error stop 91
+ if (3 /= size(zz)) error stop 91
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 92
+ if (xx(2) /= "ghi") error stop 93
+ if (xx(3) /= "nop") error stop 94
+ if (yy(5) /= "abc") error stop 92
+ if (yy(6) /= "ghi") error stop 93
+ if (yy(7) /= "nop") error stop 94
+ if (zz(-k) /= "abc") error stop 92
+ if (zz(-k+1) /= "ghi") error stop 93
+ if (zz(-k+2) /= "nop") error stop 94
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 92
+ if (xx(2) /= "ghi") error stop 93
+ if (xx(3) /= "jlm") error stop 94
+ if (yy(5) /= "def") error stop 92
+ if (yy(6) /= "ghi") error stop 93
+ if (yy(7) /= "jlm") error stop 94
+ if (zz(-k) /= "def") error stop 92
+ if (zz(-k+1) /= "ghi") error stop 93
+ if (zz(-k+2) /= "jlm") error stop 94
+ else
+ error stop 98
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(5) = "ABC"
+ yy(6) = "DEF"
+ yy(7) = "GHI"
+ zz(-k) = "ABC"
+ zz(-k+1) = "DEF"
+ zz(-k+2) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_shape_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*) :: xx(:)
+ character(len=3) :: yy(5:)
+ character(len=k) :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 100
+ if (3 /= size(yy)) error stop 100
+ if (3 /= size(zz)) error stop 100
+ if (3 /= len(xx)) error stop 101
+ if (3 /= len(yy)) error stop 101
+ if (3 /= len(zz)) error stop 101
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 102
+ if (xx(2) /= "ghi") error stop 103
+ if (xx(3) /= "nop") error stop 104
+ if (yy(5) /= "abc") error stop 102
+ if (yy(6) /= "ghi") error stop 103
+ if (yy(7) /= "nop") error stop 104
+ if (zz(-k) /= "abc") error stop 102
+ if (zz(-k+1) /= "ghi") error stop 103
+ if (zz(-k+2) /= "nop") error stop 104
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 105
+ if (xx(2) /= "ghi") error stop 106
+ if (xx(3) /= "jlm") error stop 107
+ if (yy(5) /= "def") error stop 105
+ if (yy(6) /= "ghi") error stop 106
+ if (yy(7) /= "jlm") error stop 107
+ if (zz(-k) /= "def") error stop 105
+ if (zz(-k+1) /= "ghi") error stop 106
+ if (zz(-k+2) /= "jlm") error stop 107
+ else
+ error stop 108
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+end module
+
+
+use m
+implicit none (type, external)
+character(len=3) :: a(6), a2(6), a3(6), a_init(6)
+type(loc_t) :: loc3
+
+a_init = ['abc', 'def', 'ghi', 'jlm', 'nop', 'qrs']
+
+! -- Fortran: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+
+! --- character - call C directly --
+
+! -- C: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+end
+
+
+! { dg-output "At line 928 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 928 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 928 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-1.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f90 b/gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f90
new file mode 100644
index 0000000..5b54680
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-2.f90
@@ -0,0 +1,82 @@
+! { dg-additional-options "-fdump-tree-original" }
+
+integer function f(xx) bind(c) result(ii)
+ implicit none
+ integer, contiguous :: xx(..)
+ ii = rank(xx)
+end
+
+integer function h(yy) bind(c) result(jj)
+ implicit none
+ character(len=*), contiguous :: yy(:)
+ jj = rank(yy)
+end
+
+integer function g(zz) bind(c) result(kk)
+ implicit none
+ character(len=*) :: zz(*)
+ kk = rank(zz)
+end
+
+
+
+integer function f2(aa) bind(c) result(ii)
+ implicit none
+ integer, contiguous :: aa(..)
+ intent(in) :: aa
+ ii = rank(aa)
+end
+
+integer function h2(bb) bind(c) result(jj)
+ implicit none
+ character(len=*), contiguous :: bb(:)
+ intent(in) :: bb
+ jj = rank(bb)
+end
+
+integer function g2(cc) bind(c) result(kk)
+ implicit none
+ character(len=*) :: cc(*)
+ intent(in) :: cc
+ kk = rank(cc)
+end
+
+!
+! Copy-in/out variable:
+!
+! { dg-final { scan-tree-dump-times "xx->data =\[^;\]+ __builtin_malloc \\(_xx->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "yy->data =\[^;\]+ __builtin_malloc \\(_yy->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "zz =\[^;\]+ __builtin_malloc \\(_zz->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "aa->data =\[^;\]+ __builtin_malloc \\(_aa->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bb->data =\[^;\]+ __builtin_malloc \\(_bb->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "cc =\[^;\]+ __builtin_malloc \\(_cc->elem_len \\* size.\[0-9\]+\\);" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ xx->data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ yy->data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(zz\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ aa->data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(\[^;\]+ bb->data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(cc\\);" 1 "original" } }
+
+! Copy in + out
+
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) xx->data \\+ xx->dtype.elem_len \\* arrayidx.\[0-9\]+, _xx->base_addr \\+ shift.\[0-9\]+, xx->dtype.elem_len\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "xx->data = \\(void \\* restrict\\) _xx->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) xx->data \\+ xx->dtype.elem_len \\* arrayidx.\[0-9\]+, _xx->base_addr \\+ shift.\[0-9\]+, xx->dtype.elem_len\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) yy->data \\+ yy->dtype.elem_len \\* arrayidx.\[0-9\]+, _yy->base_addr \\+ shift.\[0-9\]+, yy->dtype.elem_len\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "yy->data = \\(void \\* restrict\\) _yy->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(_yy->base_addr \\+ shift.\[0-9\]+, \\(void \\*\\) yy->data \\+ yy->dtype.elem_len \\* arrayidx.\[0-9\]+, yy->dtype.elem_len\\);" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "zz = \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:zz.\[0-9\]+\\\] \\* restrict\\) _zz->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) zz \\+ _zz->elem_len \\* arrayidx.\[0-9\]+, _zz->base_addr \\+ shift.\[0-9\]+, _zz->elem_len\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(_zz->base_addr \\+ shift.\[0-9\]+, \\(void \\*\\) zz \\+ _zz->elem_len \\* arrayidx.\[0-9\]+, _zz->elem_len\\);" 1 "original" } }
+
+! Copy in only
+
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) aa->data \\+ aa->dtype.elem_len \\* arrayidx.\[0-9\]+, _aa->base_addr \\+ shift.\[0-9\]+, aa->dtype.elem_len\\);" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "aa->data = \\(void \\* restrict\\) _aa->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) bb->data \\+ bb->dtype.elem_len \\* arrayidx.\[0-9\]+, _bb->base_addr \\+ shift.\[0-9\]+, bb->dtype.elem_len\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bb->data = \\(void \\* restrict\\) _bb->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "cc = \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:cc.\[0-9\]+\\\] \\* restrict\\) _cc->base_addr;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy \\(\\(void \\*\\) cc \\+ _cc->elem_len \\* arrayidx.\[0-9\]+, _cc->base_addr \\+ shift.\[0-9\]+, _cc->elem_len\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c
new file mode 100644
index 0000000..506f753
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.c
@@ -0,0 +1,180 @@
+#include <ISO_Fortran_binding.h>
+
+intptr_t assumed_rank_alloc_f (CFI_cdesc_t *);
+intptr_t assumed_rank_pointer_f (CFI_cdesc_t *);
+intptr_t assumed_rank_f (CFI_cdesc_t *);
+intptr_t assumed_rank_cont_f (CFI_cdesc_t *);
+intptr_t assumed_shape_f (CFI_cdesc_t *);
+intptr_t assumed_shape_cont_f (CFI_cdesc_t *);
+intptr_t deferred_shape_alloc_f (CFI_cdesc_t *);
+intptr_t deferred_shape_pointer_f (CFI_cdesc_t *);
+
+
+static void
+basic_check(CFI_cdesc_t *x)
+{
+ if (!x->base_addr)
+ __builtin_abort ();
+ if (x->elem_len != sizeof(int32_t))
+ __builtin_abort ();
+ if (x->version != CFI_VERSION)
+ __builtin_abort ();
+ if (x->rank != 4)
+ __builtin_abort ();
+ if (x->type != CFI_type_int32_t)
+ __builtin_abort ();
+ if (x->attribute == CFI_attribute_other)
+ {
+ if (x->dim[0].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[1].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[2].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[3].lower_bound != 0)
+ __builtin_abort ();
+ }
+}
+
+intptr_t
+assumed_rank_alloc_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (!CFI_is_contiguous (x))
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_allocatable)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = assumed_rank_alloc_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+intptr_t
+assumed_rank_pointer_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (x->attribute != CFI_attribute_pointer)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = assumed_rank_pointer_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+
+intptr_t
+assumed_rank_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = assumed_rank_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+intptr_t
+assumed_rank_cont_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (!CFI_is_contiguous (x))
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = assumed_rank_cont_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+intptr_t
+assumed_shape_c (CFI_cdesc_t *x, int num)
+{
+ basic_check (x);
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2;
+ if (num == 1 || num == 2 || num == 3)
+ {
+ if (!CFI_is_contiguous (x))
+ __builtin_abort ();
+ }
+ else
+ {
+ if (CFI_is_contiguous (x))
+ __builtin_abort ();
+ }
+
+ if (num == 1 || num == 4)
+ addr2 = assumed_shape_f (x);
+ else if (num == 2 || num == 5)
+ addr2 = assumed_shape_cont_f (x);
+ else if (num == 3 || num == 6)
+ addr2 = assumed_rank_cont_f (x);
+ else
+ __builtin_abort ();
+
+ if (num == 1 || num == 2 || num == 3)
+ {
+ if (addr != addr2)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (CFI_is_contiguous (x))
+ __builtin_abort ();
+ }
+ if (addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr2;
+}
+
+intptr_t
+assumed_shape_cont_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (!CFI_is_contiguous (x))
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = assumed_shape_cont_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+intptr_t
+deferred_shape_alloc_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (!CFI_is_contiguous (x))
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_allocatable)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = deferred_shape_alloc_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
+
+intptr_t
+deferred_shape_pointer_c (CFI_cdesc_t *x)
+{
+ basic_check (x);
+ if (x->attribute != CFI_attribute_pointer)
+ __builtin_abort ();
+ intptr_t addr = (intptr_t) x->base_addr;
+ intptr_t addr2 = deferred_shape_pointer_f (x);
+ if (addr != addr2 || addr != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ return addr;
+}
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90 b/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90
new file mode 100644
index 0000000..6e479ff
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-3.f90
@@ -0,0 +1,656 @@
+! { dg-do run }
+! { dg-additional-sources bind-c-contiguous-3.c }
+
+! Test that multi-dim contiguous is properly handled.
+
+module m
+ use iso_c_binding, only: c_intptr_t, c_int
+ implicit none (type, external)
+
+interface
+ integer(c_intptr_t) function assumed_rank_alloc_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, allocatable :: xx(..)
+ end function
+ integer(c_intptr_t) function assumed_rank_pointer_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, pointer :: xx(..)
+ end function
+ integer(c_intptr_t) function assumed_rank_c (xx) bind(c)
+ import :: c_intptr_t
+ integer :: xx(..)
+ end function
+ integer(c_intptr_t) function assumed_rank_cont_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, contiguous :: xx(..)
+ end function
+ integer(c_intptr_t) function assumed_shape_c (xx, num) bind(c)
+ import :: c_intptr_t, c_int
+ integer :: xx(:,:,:,:)
+ integer(c_int), value :: num
+ end function
+ integer(c_intptr_t) function assumed_shape_cont_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, contiguous :: xx(:,:,:,:)
+ end function
+ integer(c_intptr_t) function deferred_shape_alloc_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, allocatable :: xx(:,:,:,:)
+ end function
+ integer(c_intptr_t) function deferred_shape_pointer_c (xx) bind(c)
+ import :: c_intptr_t
+ integer, pointer :: xx(:,:,:,:)
+ end function
+
+end interface
+
+contains
+
+integer function get_n (idx, lbound, extent) result(res)
+ integer, contiguous :: idx(:), lbound(:), extent(:)
+ integer :: i
+ if (size(idx) /= size(lbound) .or. size(idx) /= size(extent)) &
+ error stop 20
+ res = idx(1) - lbound(1) + 1
+ do i = 2, size(idx)
+ res = res + product(extent(:i-1)) * (idx(i)-lbound(i))
+ end do
+end
+
+integer(c_intptr_t) function assumed_rank_alloc_f (xx) bind(c) result(res)
+ integer, allocatable :: xx(..)
+ integer :: i, j, k, l, lb(4)
+ select rank (xx)
+ rank (4)
+ do l = lbound(xx, dim=4), ubound(xx, dim=4)
+ do k = lbound(xx, dim=3), ubound(xx, dim=3)
+ do j = lbound(xx, dim=2), ubound(xx, dim=2)
+ do i = lbound(xx, dim=1), ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ lb = lbound(xx)
+ res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+integer(c_intptr_t) function assumed_rank_pointer_f (xx) bind(c) result(res)
+ integer, pointer :: xx(..)
+ integer :: i, j, k, l, lb(4)
+ select rank (xx)
+ rank (4)
+ do l = lbound(xx, dim=4), ubound(xx, dim=4)
+ do k = lbound(xx, dim=3), ubound(xx, dim=3)
+ do j = lbound(xx, dim=2), ubound(xx, dim=2)
+ do i = lbound(xx, dim=1), ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ lb = lbound(xx)
+ res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+
+integer(c_intptr_t) function assumed_rank_f (xx) bind(c) result(res)
+ integer :: xx(..)
+ integer :: i, j, k, l
+ select rank (xx)
+ rank (4)
+ do l = 1, size(xx, dim=4)
+ do k = 1, size(xx, dim=3)
+ do j = 1, size(xx, dim=2)
+ do i = 1, size(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+integer(c_intptr_t) function assumed_rank_cont_f (xx) bind(c) result(res)
+ integer, contiguous :: xx(..)
+ integer :: i, j, k, l
+ select rank (xx)
+ rank (4)
+ do l = 1, size(xx, dim=4)
+ do k = 1, size(xx, dim=3)
+ do j = 1, size(xx, dim=2)
+ do i = 1, size(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+integer(c_intptr_t) function assumed_shape_f (xx) bind(c) result(res)
+ integer :: xx(:,:,:,:)
+ integer :: i, j, k, l
+ do l = 1, ubound(xx, dim=4)
+ do k = 1, ubound(xx, dim=3)
+ do j = 1, ubound(xx, dim=2)
+ do i = 1, ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
+end
+
+integer(c_intptr_t) function assumed_shape2_f (xx, n) bind(c) result(res)
+ integer, value :: n
+ integer :: xx(-n:, -n:, -n:, -n:)
+ integer :: i, j, k, l
+ do l = -n, ubound(xx, dim=4)
+ do k = -n, ubound(xx, dim=3)
+ do j = -n, ubound(xx, dim=2)
+ do i = -n, ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(-n,-n,-n,-n)) ! { dg-warning "Legacy Extension" }
+end
+
+integer(c_intptr_t) function assumed_shape_cont_f (xx) bind(c) result(res)
+ integer, contiguous :: xx(:,:,:,:)
+ integer :: i, j, k, l
+ do l = 1, ubound(xx, dim=4)
+ do k = 1, ubound(xx, dim=3)
+ do j = 1, ubound(xx, dim=2)
+ do i = 1, ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(1,1,1,1)) ! { dg-warning "Legacy Extension" }
+end
+
+integer(c_intptr_t) function assumed_shape2_cont_f (xx, n) bind(c) result(res)
+ integer, value :: n
+ integer, contiguous :: xx(-n:, -n:, -n:, -n:)
+ integer :: i, j, k, l
+ do l = -n, ubound(xx, dim=4)
+ do k = -n, ubound(xx, dim=3)
+ do j = -n, ubound(xx, dim=2)
+ do i = -n, ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ res = %loc(xx(-n,-n,-n,-n)) ! { dg-warning "Legacy Extension" }
+end
+
+integer(c_intptr_t) function deferred_shape_alloc_f (xx) bind(c) result(res)
+ integer, allocatable :: xx(:,:,:,:)
+ integer :: i, j, k, l, lb(4)
+ do l = lbound(xx, dim=4), ubound(xx, dim=4)
+ do k = lbound(xx, dim=3), ubound(xx, dim=3)
+ do j = lbound(xx, dim=2), ubound(xx, dim=2)
+ do i = lbound(xx, dim=1), ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ lb = lbound(xx)
+ res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
+end
+
+integer(c_intptr_t) function deferred_shape_pointer_f (xx) bind(c) result(res)
+ integer, pointer :: xx(:,:,:,:)
+ integer :: i, j, k, l, lb(4)
+ do l = lbound(xx, dim=4), ubound(xx, dim=4)
+ do k = lbound(xx, dim=3), ubound(xx, dim=3)
+ do j = lbound(xx, dim=2), ubound(xx, dim=2)
+ do i = lbound(xx, dim=1), ubound(xx, dim=1)
+ xx(i,j,k,l) = -get_n([i,j,k,l], lbound(xx), shape(xx))
+ end do
+ end do
+ end do
+ end do
+ lb = lbound(xx)
+ res = %loc(xx(lb(1),lb(2),lb(3),lb(4))) ! { dg-warning "Legacy Extension" }
+end
+end module
+
+
+use m
+implicit none (type, external)
+integer, dimension(10,10,10,10) :: var_init, var
+target :: var
+integer, allocatable, dimension(:,:,:,:) :: a1, a2
+integer, pointer, dimension(:,:,:,:) :: p1, p2
+integer(c_intptr_t) :: loc4
+integer :: i, k, j, l, cnt
+
+do l = 1, ubound(var_init, dim=4)
+ do k = 1, ubound(var_init, dim=3)
+ do j = 1, ubound(var_init, dim=2)
+ do i = 1, ubound(var_init, dim=1)
+ var_init(i,j,k,l) = get_n([i,j,k,l], lbound(var_init), shape(var_init))
+ end do
+ end do
+ end do
+end do
+
+! Fortran calls
+
+! ----- allocatable + pointer dummies -------
+
+allocate(a1, mold=var_init)
+allocate(p1, mold=var_init)
+allocate(a2(-5:4,-10:-1,1:10,11:20))
+allocate(p2(-5:4,-10:-1,1:10,11:20))
+
+a1(:,:,:,:) = var_init
+loc4 = assumed_rank_alloc_f (a1)
+cnt = size(a1) - check_unmod (a1)
+call check (a1, loc4, .true., cnt)
+call check2 (a1)
+
+a2(:,:,:,:) = var_init
+loc4 = assumed_rank_alloc_f (a2)
+cnt = size(a2) - check_unmod (a2)
+call check (a2, loc4, .true., cnt)
+call check2 (a2)
+
+a1(:,:,:,:) = var_init
+loc4 = deferred_shape_alloc_f (a1)
+cnt = size(a1) - check_unmod (a1)
+call check (a1, loc4, .true., cnt)
+call check2 (a1)
+
+a2(:,:,:,:) = var_init
+loc4 = deferred_shape_alloc_f (a2)
+cnt = size(a2) - check_unmod (a2)
+call check (a2, loc4, .true., cnt)
+call check2 (a2)
+
+deallocate(a1, a2)
+
+p1(:,:,:,:) = var_init
+loc4 = assumed_rank_pointer_f (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .true., cnt)
+call check2 (p1)
+
+p2(:,:,:,:) = var_init
+loc4 = assumed_rank_pointer_f (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .true., cnt)
+call check2 (p2)
+
+p1(:,:,:,:) = var_init
+loc4 = deferred_shape_pointer_f (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .true., cnt)
+call check2 (p1)
+
+p2(:,:,:,:) = var_init
+loc4 = deferred_shape_pointer_f (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .true., cnt)
+call check2 (p2)
+
+deallocate(p1, p2)
+
+! --- p => var(4:7,::3,::2,:)
+var = var_init
+p1 => var(4:7,::3,::2,:)
+loc4 = assumed_rank_pointer_f (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .false., cnt)
+call check2 (p1)
+
+var = var_init
+p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
+loc4 = assumed_rank_pointer_f (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .false., cnt)
+call check2 (p2)
+
+var = var_init
+p1 => var(4:7,::3,::2,:)
+loc4 = deferred_shape_pointer_f (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .false., cnt)
+call check2 (p1)
+
+var = var_init
+p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
+loc4 = deferred_shape_pointer_f (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .false., cnt)
+call check2 (p2)
+
+
+
+! ----- nonallocatable + nonpointer dummies -------
+
+var = var_init
+loc4 = assumed_rank_f (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .false., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_shape_f (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .false., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_shape2_f (var, 99)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .false., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_rank_cont_f (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_shape_cont_f (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_shape2_cont_f (var, 99)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+! --- var(4:7,::3,::2,:)
+
+var = var_init
+loc4 = assumed_rank_f (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .false., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_shape_f (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .false., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_shape2_f (var(4:7,::3,::2,:), 99)
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .false., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_rank_cont_f (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_shape_cont_f (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_shape2_cont_f (var(4:7,::3,::2,:), 99)
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+
+! C calls
+
+! ----- allocatable + pointer dummies -------
+
+allocate(a1, mold=var_init)
+allocate(p1, mold=var_init)
+allocate(a2(-5:4,-10:-1,1:10,11:20))
+allocate(p2(-5:4,-10:-1,1:10,11:20))
+
+a1(:,:,:,:) = var_init
+loc4 = assumed_rank_alloc_c (a1)
+cnt = size(a1) - check_unmod (a1)
+call check (a1, loc4, .true., cnt)
+call check2 (a1)
+
+a2(:,:,:,:) = var_init
+loc4 = assumed_rank_alloc_c (a2)
+cnt = size(a2) - check_unmod (a2)
+call check (a2, loc4, .true., cnt)
+call check2 (a2)
+
+a1(:,:,:,:) = var_init
+loc4 = deferred_shape_alloc_c (a1)
+cnt = size(a1) - check_unmod (a1)
+call check (a1, loc4, .true., cnt)
+call check2 (a1)
+
+a2(:,:,:,:) = var_init
+loc4 = deferred_shape_alloc_c (a2)
+cnt = size(a2) - check_unmod (a2)
+call check (a2, loc4, .true., cnt)
+call check2 (a2)
+
+deallocate(a1, a2)
+
+p1(:,:,:,:) = var_init
+loc4 = assumed_rank_pointer_c (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .true., cnt)
+call check2 (p1)
+
+p2(:,:,:,:) = var_init
+loc4 = assumed_rank_pointer_c (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .true., cnt)
+call check2 (p2)
+
+p1(:,:,:,:) = var_init
+loc4 = deferred_shape_pointer_c (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .true., cnt)
+call check2 (p1)
+
+p2(:,:,:,:) = var_init
+loc4 = deferred_shape_pointer_c (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .true., cnt)
+call check2 (p2)
+
+deallocate(p1, p2)
+
+! --- p => var(4:7,::3,::2,:)
+var = var_init
+p1 => var(4:7,::3,::2,:)
+loc4 = assumed_rank_pointer_c (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .false., cnt)
+call check2 (p1)
+
+var = var_init
+p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
+loc4 = assumed_rank_pointer_c (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .false., cnt)
+call check2 (p2)
+
+var = var_init
+p1 => var(4:7,::3,::2,:)
+loc4 = deferred_shape_pointer_c (p1)
+cnt = size(p1) - check_unmod (p1)
+call check (p1, loc4, .false., cnt)
+call check2 (p1)
+
+var = var_init
+p2(-5:,-10:,1:,11:) => var(4:7,::3,::2,:)
+loc4 = deferred_shape_pointer_c (p2)
+cnt = size(p2) - check_unmod (p2)
+call check (p2, loc4, .false., cnt)
+call check2 (p2)
+
+
+! ----- nonallocatable + nonpointer dummies -------
+
+var = var_init
+loc4 = assumed_rank_c (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .false., cnt)
+call check2 (var)
+
+var = var_init
+! calls assumed_shape_f
+loc4 = assumed_shape_c (var, num=1)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .false., cnt)
+call check2 (var)
+
+var = var_init
+! calls assumed_shape_cont_f
+loc4 = assumed_shape_c (var, num=2)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+var = var_init
+! calls assumed_rank_cont_f
+loc4 = assumed_shape_c (var, num=3)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_rank_cont_c (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+var = var_init
+loc4 = assumed_shape_cont_c (var)
+cnt = size(var) - check_unmod (var)
+call check (var, loc4, .true., cnt)
+call check2 (var)
+
+! --- var(4:7,::3,::2,:)
+
+var = var_init
+loc4 = assumed_rank_c (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .false., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+! calls assumed_shape_f
+loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=4)
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .false., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+! calls assumed_shape_cont_f
+loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=5)
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+! calls assumed_rank_cont_f
+loc4 = assumed_shape_c (var(4:7,::3,::2,:), num=6)
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_rank_cont_c (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+var = var_init
+loc4 = assumed_shape_cont_c (var(4:7,::3,::2,:))
+cnt = size(var) - check_unmod (var)
+call check (var(4:7,::3,::2,:), loc4, .true., cnt)
+call check2 (var(4:7,::3,::2,:))
+
+
+contains
+
+! Ensure that the rest is still okay
+! Returns the number of elements >= 0
+integer function check_unmod (x) result(cnt)
+ integer, contiguous, intent(in) :: x(:,:,:,:)
+ integer :: i, k, j, l
+ cnt = 0
+ do l = 1, ubound(x, dim=4)
+ do k = 1, ubound(x, dim=3)
+ do j = 1, ubound(x, dim=2)
+ do i = 1, ubound(x, dim=1)
+ if (x(i,j,k,l) >= 0) then
+ cnt = cnt + 1
+ if (x(i,j,k,l) /= get_n([i,j,k,l], lbound(x), shape(x))) &
+ error stop 5
+ endif
+ end do
+ end do
+ end do
+ end do
+end
+
+subroutine check(x, loc1, cont, cnt)
+ integer, intent(in) :: x(:,:,:,:)
+ integer(c_intptr_t), intent(in), optional :: loc1
+ logical, intent(in), optional :: cont ! dummy has CONTIGUOUS attr
+ integer, intent(in), optional :: cnt
+ integer(c_intptr_t) :: loc2
+ integer :: i, k, j, l
+ if (present (loc1)) then
+ loc2 = %loc(x(1,1,1,1)) ! { dg-warning "Legacy Extension" }
+ if (is_contiguous (x) .or. .not.cont) then
+ if (loc1 /= loc2) error stop 1
+ else
+ if (loc1 == loc2) error stop 2
+ end if
+ if (cnt /= size(x)) error stop 3
+ end if
+ do l = 1, ubound(x, dim=4)
+ do k = 1, ubound(x, dim=3)
+ do j = 1, ubound(x, dim=2)
+ do i = 1, ubound(x, dim=1)
+ if (x(i,j,k,l) /= -get_n([i,j,k,l], lbound(x), shape(x))) &
+ error stop 4
+ end do
+ end do
+ end do
+ end do
+end
+
+subroutine check2(x)
+ integer, contiguous, intent(in) :: x(:,:,:,:)
+ call check(x)
+end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c
new file mode 100644
index 0000000..cee1eb4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.c
@@ -0,0 +1,370 @@
+#include <ISO_Fortran_binding.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct loc_t {
+ intptr_t x, y, z;
+};
+
+typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+
+static void
+basic_check(CFI_cdesc_t *x, bool is_cont)
+{
+ if (!x->base_addr)
+ __builtin_abort ();
+ if (x->elem_len != 3*sizeof(char))
+ __builtin_abort ();
+ if (x->version != CFI_VERSION)
+ __builtin_abort ();
+ if (x->rank != 1)
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ if (x->type != CFI_type_char)
+ __builtin_abort ();
+ if (x->dim[0].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[0].extent != 3)
+ __builtin_abort ();
+ if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
+ __builtin_abort ();
+ if (is_cont != CFI_is_contiguous (x))
+ __builtin_abort ();
+}
+
+static void
+print_str (void *p, size_t len)
+{
+ __builtin_printf ("DEBUG: >");
+ for (size_t i = 0; i < len; ++i)
+ __builtin_printf ("%c", ((const char*) p)[i]);
+ __builtin_printf ("<\n");
+}
+
+static void
+check_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
+{
+ /* Avoid checking for '\0'. */
+ if (strncmp ((const char*) CFI_address (x, subscripts), str, strlen(str)) != 0)
+ __builtin_abort ();
+}
+
+static void
+set_str (CFI_cdesc_t *x, const char *str, const CFI_index_t subscripts[])
+{
+ char *p = CFI_address (x, subscripts);
+ size_t len = strlen (str);
+ if (x->elem_len != len)
+ __builtin_abort ();
+ for (size_t i = 0; i < len; ++i)
+ p[i] = str[i];
+}
+
+static struct loc_t
+do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+ struct loc_t addr1, addr2;
+ if (k != 3)
+ __builtin_abort ();
+
+ if (num == 3)
+ {
+ if (x != NULL)
+ __builtin_abort ();
+ if (y != NULL)
+ __builtin_abort ();
+ if (z != NULL)
+ __builtin_abort ();
+ addr2 = fn (x, y, z, 3, num);
+ if (addr2.x != -1 || addr2.y != -1 || addr2.z != -1)
+ __builtin_abort ();
+ return addr2;
+ }
+ if (x == NULL)
+ __builtin_abort ();
+ if (y == NULL)
+ __builtin_abort ();
+ if (z == NULL)
+ __builtin_abort ();
+ basic_check (x, is_cont || num == 2);
+ basic_check (y, is_cont || num == 2);
+ basic_check (z, is_cont || num == 2);
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "abc", zero);
+ check_str (x, "ghi", one);
+ check_str (x, "nop", two);
+ check_str (y, "abc", zero);
+ check_str (y, "ghi", one);
+ check_str (y, "nop", two);
+ check_str (z, "abc", zero);
+ check_str (z, "ghi", one);
+ check_str (z, "nop", two);
+ }
+ else if (num == 1)
+ {
+ if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (num == 2)
+ {
+ if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+ addr1.x = (intptr_t) x->base_addr;
+ addr1.y = (intptr_t) y->base_addr;
+ addr1.z = (intptr_t) z->base_addr;
+ addr2 = fn (x, y, z, 3, num);
+ if (!CFI_is_contiguous (x) && fort_cont)
+ {
+ /* Check for callee copy in/copy out. */
+ if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ // intent_in
+ if (intent_in && !is_cont && num == 1)
+ {
+ check_str (x, "abc", zero);
+ check_str (x, "ghi", one);
+ check_str (x, "nop", two);
+ check_str (y, "abc", zero);
+ check_str (y, "ghi", one);
+ check_str (y, "nop", two);
+ check_str (z, "abc", zero);
+ check_str (z, "ghi", one);
+ check_str (z, "nop", two);
+ }
+ else if (intent_in && num == 1)
+ {
+ if (strncmp ((const char*) x->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "abcghinop", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in && num == 2)
+ {
+ if (strncmp ((const char*) x->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "defghijlm", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in)
+ __builtin_abort ();
+ if (intent_in)
+ {
+ if (is_cont && num == 1)
+ {
+ /* Copy in - set the value to check that no copy out is done. */
+ memcpy ((char*) x->base_addr, "123456789", 9);
+ memcpy ((char*) y->base_addr, "123456789", 9);
+ memcpy ((char*) z->base_addr, "123456789", 9);
+ }
+ return addr1;
+ }
+ // !intent_in
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "ABC", zero);
+ check_str (x, "DEF", one);
+ check_str (x, "GHI", two);
+ check_str (y, "ABC", zero);
+ check_str (y, "DEF", one);
+ check_str (y, "GHI", two);
+ check_str (z, "ABC", zero);
+ check_str (z, "DEF", one);
+ check_str (z, "GHI", two);
+ }
+ else
+ {
+ if (strncmp ((const char*) x->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) y->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ if (strncmp ((const char*) z->base_addr, "ABCDEFGHI", 9) != 0)
+ __builtin_abort ();
+ }
+ return addr1;
+}
+
+struct loc_t
+char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
+}
+
+struct loc_t
+char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
+}
+
+struct loc_t
+char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
+}
+
+struct loc_t
+char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
+}
+
+static void
+reset_var (CFI_cdesc_t *x, int num)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+
+ if (num == 1)
+ {
+ set_str (x, "abc", zero);
+ set_str (x, "ghi", one);
+ set_str (x, "nop", two);
+ }
+ else if (num == 2)
+ {
+ set_str (x, "def", zero);
+ set_str (x, "ghi", one);
+ set_str (x, "jlm", two);
+ }
+ else if (num == 3)
+ {
+ if (x != NULL)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+}
+
+static void
+reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
+{
+ reset_var (x, num);
+ reset_var (y, num);
+ reset_var (z, num);
+}
+
+struct loc_t
+char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ /* Make use of having a noncontiguous argument to check that the callee
+ handles noncontiguous variables. */
+ do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
+ /* Actual func call. */
+ reset_vars (x, y, z, num);
+ return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
+}
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f90 b/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f90
new file mode 100644
index 0000000..ab59b0b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-4.f90
@@ -0,0 +1,1720 @@
+! { dg-do run }
+!
+! Same test as bind-c-contiguous-1.* but with OPTIONAL
+!
+! { dg-additional-sources bind-c-contiguous-4.c }
+! { dg-additional-options "-fcheck=all" }
+! { dg-prune-output "command-line option '-fcheck=.*' is valid for Fortran but not for C" }
+
+! Fortran demands that with bind(C), the callee ensure that for
+! * 'contiguous'
+! * len=* with explicit/assumed-size arrays
+! noncontiguous actual arguments are handled.
+! (in without bind(C) in gfortran, caller handles the copy in/out
+
+! Additionally, for a bind(C) callee, a Fortran-written caller
+! has to ensure the same (for contiguous + len=* to explicit-/assumed-size arrays)
+
+module m
+ use iso_c_binding, only: c_intptr_t, c_bool, c_loc, c_int
+ implicit none (type, external)
+
+ type, bind(C) :: loc_t
+ integer(c_intptr_t) :: x, y, z
+ end type loc_t
+
+interface
+ type(loc_t) function char_assumed_size_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), optional :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_assumed_size_in_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), intent(in), optional :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_expl_size_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), optional :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_expl_size_in_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(len=*), intent(in), optional :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_assumed_rank_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), optional :: xx(..)
+ character(len=3), optional :: yy(..)
+ character(len=k), optional :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), intent(in), optional :: xx(..)
+ character(len=3), intent(in), optional :: yy(..)
+ character(len=k), intent(in), optional :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, optional :: xx(..)
+ character(len=3), contiguous, optional :: yy(..)
+ character(len=k), contiguous, optional :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, intent(in), optional :: xx(..)
+ character(len=3), contiguous, intent(in), optional :: yy(..)
+ character(len=k), contiguous, intent(in), optional :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_shape_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), optional :: xx(:)
+ character(len=3), optional :: yy(5:)
+ character(len=k), optional :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), intent(in), optional :: xx(:)
+ character(len=3), intent(in), optional :: yy(5:)
+ character(len=k), intent(in), optional :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, optional :: xx(:)
+ character(len=3), contiguous, optional :: yy(5:)
+ character(len=k), contiguous, optional :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(len=*), contiguous, intent(in), optional :: xx(:)
+ character(len=3), contiguous, intent(in), optional :: yy(5:)
+ character(len=k), contiguous, intent(in), optional :: zz(-k:)
+ end function
+end interface
+
+contains
+
+type(loc_t) function char_assumed_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*), optional :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(3) = "ABC"
+ yy(4) = "DEF"
+ yy(5) = "GHI"
+ zz(6,n,3) = "ABC"
+ zz(6,n,4) = "DEF"
+ zz(6,n,5) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*), optional :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ intent(in) :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" } if (num == 1) then
+end
+
+type(loc_t) function char_expl_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*), optional :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(3) = "ABC"
+ yy(4) = "DEF"
+ yy(5) = "GHI"
+ zz(6,n,3) = "ABC"
+ zz(6,n,4) = "DEF"
+ zz(6,n,5) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_expl_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(len=*), optional :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ intent(in) :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "nop") error stop 4
+ if (yy(3) /= "abc") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "nop") error stop 4
+ if (zz(6,n,3) /= "abc") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 2
+ if (xx(2) /= "ghi") error stop 3
+ if (xx(3) /= "jlm") error stop 4
+ if (yy(3) /= "def") error stop 2
+ if (yy(4) /= "ghi") error stop 3
+ if (yy(5) /= "jlm") error stop 4
+ if (zz(6,n,3) /= "def") error stop 2
+ if (zz(6,n,4) /= "ghi") error stop 3
+ if (zz(6,n,5) /= "jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+
+type(loc_t) function char_assumed_rank_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(..)
+ character(len=3), optional :: yy(..)
+ character(len=k), optional :: zz(..)
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ if (3 /= len(xx)) error stop 40
+ if (3 /= len(yy)) error stop 40
+ if (3 /= len(zz)) error stop 40
+ if (3 /= size(xx)) error stop 41
+ if (3 /= size(yy)) error stop 41
+ if (3 /= size(zz)) error stop 41
+ if (1 /= rank(xx)) error stop 49
+ if (1 /= rank(yy)) error stop 49
+ if (1 /= rank(zz)) error stop 49
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 49
+ if (is_contiguous (yy)) error stop 49
+ if (is_contiguous (zz)) error stop 49
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 49
+ if (.not. is_contiguous (yy)) error stop 49
+ if (.not. is_contiguous (zz)) error stop 49
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 42
+ if (xx(2) /= "ghi") error stop 43
+ if (xx(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 45
+ if (xx(2) /= "ghi") error stop 46
+ if (xx(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ res%x = get_loc (xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 42
+ if (yy(2) /= "ghi") error stop 43
+ if (yy(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 45
+ if (yy(2) /= "ghi") error stop 46
+ if (yy(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ yy(1) = "ABC"
+ yy(2) = "DEF"
+ yy(3) = "GHI"
+ res%y = get_loc (yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 42
+ if (zz(2) /= "ghi") error stop 43
+ if (zz(3) /= "nop") error stop 44
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 45
+ if (zz(2) /= "ghi") error stop 46
+ if (zz(3) /= "jlm") error stop 47
+ else
+ error stop 48
+ endif
+ zz(1) = "ABC"
+ zz(2) = "DEF"
+ zz(3) = "GHI"
+ res%z = get_loc (zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_rank_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(..)
+ character(len=3), optional :: yy(..)
+ character(len=k), optional :: zz(..)
+ intent(in) :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ if (3 /= size(yy)) error stop 50
+ if (3 /= len(yy)) error stop 51
+ if (1 /= rank(yy)) error stop 59
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 59
+ if (is_contiguous (yy)) error stop 59
+ if (is_contiguous (zz)) error stop 59
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 59
+ if (.not. is_contiguous (yy)) error stop 59
+ if (.not. is_contiguous (zz)) error stop 59
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 52
+ if (xx(2) /= "ghi") error stop 53
+ if (xx(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 55
+ if (xx(2) /= "ghi") error stop 56
+ if (xx(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%x = get_loc(xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 52
+ if (yy(2) /= "ghi") error stop 53
+ if (yy(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 55
+ if (yy(2) /= "ghi") error stop 56
+ if (yy(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%y = get_loc(yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 52
+ if (zz(2) /= "ghi") error stop 53
+ if (zz(3) /= "nop") error stop 54
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 55
+ if (zz(2) /= "ghi") error stop 56
+ if (zz(3) /= "jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%z = get_loc(zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_rank_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(..)
+ character(len=3), optional :: yy(..)
+ character(len=k), optional :: zz(..)
+ contiguous :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ if (3 /= len(xx)) error stop 60
+ if (3 /= len(yy)) error stop 60
+ if (3 /= len(zz)) error stop 60
+ if (3 /= size(xx)) error stop 61
+ if (3 /= size(yy)) error stop 61
+ if (3 /= size(zz)) error stop 61
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 62
+ if (xx(2) /= "ghi") error stop 63
+ if (xx(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 65
+ if (xx(2) /= "ghi") error stop 66
+ if (xx(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 62
+ if (yy(2) /= "ghi") error stop 63
+ if (yy(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 65
+ if (yy(2) /= "ghi") error stop 66
+ if (yy(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ yy(1) = "ABC"
+ yy(2) = "DEF"
+ yy(3) = "GHI"
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 62
+ if (zz(2) /= "ghi") error stop 63
+ if (zz(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 65
+ if (zz(2) /= "ghi") error stop 66
+ if (zz(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ zz(1) = "ABC"
+ zz(2) = "DEF"
+ zz(3) = "GHI"
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_rank_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(..)
+ character(len=3), optional :: yy(..)
+ character(len=k), optional :: zz(..)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ if (3 /= size(xx)) error stop 30
+ if (3 /= size(yy)) error stop 30
+ if (3 /= size(zz)) error stop 30
+ if (3 /= len(xx)) error stop 31
+ if (3 /= len(yy)) error stop 31
+ if (3 /= len(zz)) error stop 31
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 62
+ if (xx(2) /= "ghi") error stop 63
+ if (xx(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 65
+ if (xx(2) /= "ghi") error stop 66
+ if (xx(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= "abc") error stop 62
+ if (yy(2) /= "ghi") error stop 63
+ if (yy(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= "def") error stop 65
+ if (yy(2) /= "ghi") error stop 66
+ if (yy(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= "abc") error stop 62
+ if (zz(2) /= "ghi") error stop 63
+ if (zz(3) /= "nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= "def") error stop 65
+ if (zz(2) /= "ghi") error stop 66
+ if (zz(3) /= "jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_shape_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(:)
+ character(len=3), optional :: yy(5:)
+ character(len=k), optional :: zz(-k:)
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 70
+ if (3 /= len(yy)) error stop 70
+ if (3 /= len(zz)) error stop 70
+ if (3 /= size(xx)) error stop 71
+ if (3 /= size(yy)) error stop 71
+ if (3 /= size(zz)) error stop 71
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 79
+ if (is_contiguous (yy)) error stop 79
+ if (is_contiguous (zz)) error stop 79
+ if (xx(1) /= "abc") error stop 72
+ if (xx(2) /= "ghi") error stop 73
+ if (xx(3) /= "nop") error stop 74
+ if (yy(5) /= "abc") error stop 72
+ if (yy(6) /= "ghi") error stop 73
+ if (yy(7) /= "nop") error stop 74
+ if (zz(-k) /= "abc") error stop 72
+ if (zz(-k+1) /= "ghi") error stop 73
+ if (zz(-k+2) /= "nop") error stop 74
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 79
+ if (.not.is_contiguous (yy)) error stop 79
+ if (.not.is_contiguous (zz)) error stop 79
+ if (xx(1) /= "def") error stop 72
+ if (xx(2) /= "ghi") error stop 73
+ if (xx(3) /= "jlm") error stop 74
+ if (yy(5) /= "def") error stop 72
+ if (yy(6) /= "ghi") error stop 73
+ if (yy(7) /= "jlm") error stop 74
+ if (zz(-k) /= "def") error stop 72
+ if (zz(-k+1) /= "ghi") error stop 73
+ if (zz(-k+2) /= "jlm") error stop 74
+ else
+ error stop 78
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(5) = "ABC"
+ yy(6) = "DEF"
+ yy(7) = "GHI"
+ zz(-k) = "ABC"
+ zz(-k+1) = "DEF"
+ zz(-k+2) = "GHI"
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_shape_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(:)
+ character(len=3), optional :: yy(5:)
+ character(len=k), optional :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 80
+ if (3 /= size(yy)) error stop 80
+ if (3 /= size(zz)) error stop 80
+ if (3 /= len(xx)) error stop 81
+ if (3 /= len(yy)) error stop 81
+ if (3 /= len(zz)) error stop 81
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 89
+ if (is_contiguous (yy)) error stop 89
+ if (is_contiguous (zz)) error stop 89
+ if (xx(1) /= "abc") error stop 82
+ if (xx(2) /= "ghi") error stop 83
+ if (xx(3) /= "nop") error stop 84
+ if (yy(5) /= "abc") error stop 82
+ if (yy(6) /= "ghi") error stop 83
+ if (yy(7) /= "nop") error stop 84
+ if (zz(-k) /= "abc") error stop 82
+ if (zz(-k+1) /= "ghi") error stop 83
+ if (zz(-k+2) /= "nop") error stop 84
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 89
+ if (.not.is_contiguous (yy)) error stop 89
+ if (.not.is_contiguous (zz)) error stop 89
+ if (xx(1) /= "def") error stop 85
+ if (xx(2) /= "ghi") error stop 86
+ if (xx(3) /= "jlm") error stop 87
+ if (yy(5) /= "def") error stop 85
+ if (yy(6) /= "ghi") error stop 86
+ if (yy(7) /= "jlm") error stop 87
+ if (zz(-k) /= "def") error stop 85
+ if (zz(-k+1) /= "ghi") error stop 86
+ if (zz(-k+2) /= "jlm") error stop 87
+ else
+ error stop 88
+ endif
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_shape_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(:)
+ character(len=3), optional :: yy(5:)
+ character(len=k), optional :: zz(-k:)
+ contiguous :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 90
+ if (3 /= len(yy)) error stop 90
+ if (3 /= len(zz)) error stop 90
+ if (3 /= size(xx)) error stop 91
+ if (3 /= size(yy)) error stop 91
+ if (3 /= size(zz)) error stop 91
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 92
+ if (xx(2) /= "ghi") error stop 93
+ if (xx(3) /= "nop") error stop 94
+ if (yy(5) /= "abc") error stop 92
+ if (yy(6) /= "ghi") error stop 93
+ if (yy(7) /= "nop") error stop 94
+ if (zz(-k) /= "abc") error stop 92
+ if (zz(-k+1) /= "ghi") error stop 93
+ if (zz(-k+2) /= "nop") error stop 94
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 92
+ if (xx(2) /= "ghi") error stop 93
+ if (xx(3) /= "jlm") error stop 94
+ if (yy(5) /= "def") error stop 92
+ if (yy(6) /= "ghi") error stop 93
+ if (yy(7) /= "jlm") error stop 94
+ if (zz(-k) /= "def") error stop 92
+ if (zz(-k+1) /= "ghi") error stop 93
+ if (zz(-k+2) /= "jlm") error stop 94
+ else
+ error stop 98
+ endif
+ xx(1) = "ABC"
+ xx(2) = "DEF"
+ xx(3) = "GHI"
+ yy(5) = "ABC"
+ yy(6) = "DEF"
+ yy(7) = "GHI"
+ zz(-k) = "ABC"
+ zz(-k+1) = "DEF"
+ zz(-k+2) = "GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_shape_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(len=*), optional :: xx(:)
+ character(len=3), optional :: yy(5:)
+ character(len=k), optional :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ if (num == 3) then
+ if (present (xx) .or. present (yy) .or. present (zz)) error stop 1
+ res%x = -1; res%y = -1; res%z = -1
+ return
+ end if
+ if (.not.present (xx) .or. .not.present (yy) .or. .not.present (zz)) error stop 1
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 100
+ if (3 /= size(yy)) error stop 100
+ if (3 /= size(zz)) error stop 100
+ if (3 /= len(xx)) error stop 101
+ if (3 /= len(yy)) error stop 101
+ if (3 /= len(zz)) error stop 101
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= "abc") error stop 102
+ if (xx(2) /= "ghi") error stop 103
+ if (xx(3) /= "nop") error stop 104
+ if (yy(5) /= "abc") error stop 102
+ if (yy(6) /= "ghi") error stop 103
+ if (yy(7) /= "nop") error stop 104
+ if (zz(-k) /= "abc") error stop 102
+ if (zz(-k+1) /= "ghi") error stop 103
+ if (zz(-k+2) /= "nop") error stop 104
+ else if (num == 2) then
+ if (xx(1) /= "def") error stop 105
+ if (xx(2) /= "ghi") error stop 106
+ if (xx(3) /= "jlm") error stop 107
+ if (yy(5) /= "def") error stop 105
+ if (yy(6) /= "ghi") error stop 106
+ if (yy(7) /= "jlm") error stop 107
+ if (zz(-k) /= "def") error stop 105
+ if (zz(-k+1) /= "ghi") error stop 106
+ if (zz(-k+2) /= "jlm") error stop 107
+ else
+ error stop 108
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+end module
+
+
+use m
+implicit none (type, external)
+character(len=3) :: a(6), a2(6), a3(6), a_init(6)
+type(loc_t) :: loc3
+
+a_init = ['abc', 'def', 'ghi', 'jlm', 'nop', 'qrs']
+
+! -- Fortran: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_size_f (n=size(a(2:4)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_size_in_f (n=size(a(2:4)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- Fortran: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_expl_size_f (n=size(a(2:4)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_expl_size_in_f (n=size(a(::2)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- Fortran: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_rank_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_rank_in_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- Fortran: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_rank_cont_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_rank_cont_in_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- Fortran: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_shape_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_shape_in_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- Fortran: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_shape_cont_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_shape_cont_in_f (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+
+! --- character - call C directly --
+
+! -- C: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_size_c (n=size(a(2:4)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_size_in_c (n=size(a(2:4)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- C: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_expl_size_c (n=size(a(::2)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_expl_size_in_c (n=size(a(::2)), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- C: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_rank_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_rank_in_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- C: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_rank_cont_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_rank_cont_in_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- C: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_shape_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_shape_in_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+! -- C: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a2 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+if (any (a3 /= ['ABC', 'def', 'DEF', 'jlm', 'GHI', 'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a2 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+if (any (a3 /= ['abc', 'ABC', 'DEF', 'GHI', 'nop', 'qrs'])) error stop 54
+
+loc3 = char_assumed_shape_cont_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+loc3 = char_assumed_shape_cont_in_c (k=len(a), num=3)
+if (loc3%x /= -1 .or. loc3%y /= -1 .or. loc3%z /= -1) error stop 2
+end
+
+! { dg-output "At line 1003 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1003 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1003 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1024 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1024 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1024 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1046 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1046 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1046 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1067 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1067 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1067 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1132 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1132 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1132 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1218 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1218 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1218 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1239 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1239 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1239 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1285 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1285 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1285 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1307 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1307 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1307 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1328 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1328 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1328 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1393 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1393 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1393 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1414 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1414 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1414 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1479 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1479 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1479 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1500 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1500 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1500 of file .*bind-c-contiguous-4.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c
new file mode 100644
index 0000000..48c03d4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c
@@ -0,0 +1,345 @@
+#include <ISO_Fortran_binding.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct loc_t {
+ intptr_t x, y, z;
+};
+
+typedef struct loc_t (*ftn_fn) (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_size_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_expl_size_in_f (CFI_cdesc_t *,CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_rank_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+struct loc_t char_assumed_shape_cont_in_f (CFI_cdesc_t *, CFI_cdesc_t *, CFI_cdesc_t *, int, int);
+
+static void
+basic_check(CFI_cdesc_t *x, bool is_cont)
+{
+ if (!x->base_addr)
+ __builtin_abort ();
+ if (x->elem_len != 3*(4*sizeof(char))) /* ucs4_char */
+ __builtin_abort ();
+ if (x->version != CFI_VERSION)
+ __builtin_abort ();
+ if (x->rank != 1)
+ __builtin_abort ();
+ if (x->attribute != CFI_attribute_other)
+ __builtin_abort ();
+ if (x->type != CFI_type_ucs4_char)
+ __builtin_abort ();
+ if (x->dim[0].lower_bound != 0)
+ __builtin_abort ();
+ if (x->dim[0].extent != 3)
+ __builtin_abort ();
+ if (CFI_is_contiguous (x) != (x->elem_len == x->dim[0].sm))
+ __builtin_abort ();
+ if (is_cont != CFI_is_contiguous (x))
+ __builtin_abort ();
+}
+
+static void
+print_str (void *p, size_t len)
+{
+ __builtin_printf ("DEBUG: >");
+ /* Use ' ' for '\0' */
+ for (size_t i = 0; i < len*4; ++i)
+ __builtin_printf ("%c", ((const char*) p)[i] ? ((const char*) p)[i] : ' ');
+ __builtin_printf ("<\n");
+}
+
+static void
+check_str (CFI_cdesc_t *x, const char *str, size_t n, const CFI_index_t subscripts[])
+{
+ /* Avoid checking for '\0'. */
+ if (memcmp ((const char*) CFI_address (x, subscripts), str, n) != 0)
+ __builtin_abort ();
+}
+
+static void
+set_str (CFI_cdesc_t *x, const char *str, size_t n, const CFI_index_t subscripts[])
+{
+ char *p = CFI_address (x, subscripts);
+ if (x->elem_len != n)
+ __builtin_abort ();
+ for (size_t i = 0; i < n; ++i)
+ p[i] = str[i];
+}
+
+static struct loc_t
+do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num, bool intent_in, ftn_fn fn, bool is_cont, bool fort_cont)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+ struct loc_t addr1, addr2;
+ if (k != 3)
+ __builtin_abort ();
+ basic_check (x, is_cont || num == 2);
+ basic_check (y, is_cont || num == 2);
+ basic_check (z, is_cont || num == 2);
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ check_str (y, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (y, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (y, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ }
+ else if (num == 1)
+ {
+ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ }
+ else if (num == 2)
+ {
+ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+ addr1.x = (intptr_t) x->base_addr;
+ addr1.y = (intptr_t) y->base_addr;
+ addr1.z = (intptr_t) z->base_addr;
+ addr2 = fn (x, y, z, 3, num);
+ if (!CFI_is_contiguous (x) && fort_cont)
+ {
+ /* Check for callee copy in/copy out. */
+ if (addr1.x == addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y == addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z == addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (addr1.x != addr2.x || addr1.x != (intptr_t) x->base_addr)
+ __builtin_abort ();
+ if (addr1.y != addr2.y || addr1.y != (intptr_t) y->base_addr)
+ __builtin_abort ();
+ if (addr1.z != addr2.z || addr1.z != (intptr_t) z->base_addr)
+ __builtin_abort ();
+ }
+ // intent_in
+ if (intent_in && !is_cont && num == 1)
+ {
+ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ check_str (y, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (y, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (y, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ }
+ else if (intent_in && num == 1)
+ {
+ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in && num == 2)
+ {
+ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0)
+ __builtin_abort ();
+ }
+ else if (intent_in)
+ __builtin_abort ();
+ if (intent_in)
+ {
+ if (is_cont && num == 1)
+ {
+ /* Copy in - set the value to check that no copy out is done. */
+ memcpy ((char*) x->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
+ memcpy ((char*) y->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
+ memcpy ((char*) z->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4);
+ }
+ return addr1;
+ }
+ // !intent_in
+ if (!is_cont && num == 1)
+ {
+ check_str (x, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
+ check_str (x, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
+ check_str (x, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
+ check_str (y, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
+ check_str (y, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
+ check_str (y, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
+ check_str (z, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero);
+ check_str (z, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one);
+ check_str (z, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two);
+ }
+ else
+ {
+ if (memcmp ((const char*) x->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) y->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ if (memcmp ((const char*) z->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0)
+ __builtin_abort ();
+ }
+ return addr1;
+}
+
+struct loc_t
+char_assumed_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_size_f, true, false);
+}
+
+struct loc_t
+char_assumed_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_size_in_f, true, false);
+}
+
+struct loc_t
+char_expl_size_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_expl_size_f, true, false);
+}
+
+struct loc_t
+char_expl_size_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_expl_size_in_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_rank_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, true, false);
+}
+
+static void
+reset_var (CFI_cdesc_t *x, int num)
+{
+ const CFI_index_t zero[1] = { 0 };
+ const CFI_index_t one[1] = { 1 };
+ const CFI_index_t two[1] = { 2 };
+
+ if (num == 1)
+ {
+ set_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero);
+ set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ set_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two);
+ }
+ else if (num == 2)
+ {
+ set_str (x, "d\0\0\0e\0\0\0f\0\0\0", 3*4, zero);
+ set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one);
+ set_str (x, "j\0\0\0l\0\0\0m\0\0\0", 3*4, two);
+ }
+ else
+ __builtin_abort ();
+}
+
+static void
+reset_vars (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, int num)
+{
+ reset_var (x, num);
+ reset_var (y, num);
+ reset_var (z, num);
+}
+
+struct loc_t
+char_assumed_shape_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ /* Make use of having a noncontiguous argument to check that the callee
+ handles noncontiguous variables. */
+ do_call (x, y, z, k, num, false, char_assumed_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_expl_size_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_expl_size_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_rank_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_rank_cont_in_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, false, true);
+ reset_vars (x, y, z, num);
+ do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, false, true);
+ /* Actual func call. */
+ reset_vars (x, y, z, num);
+ return do_call (x, y, z, k, num, false, char_assumed_shape_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_in_f, false, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, false, char_assumed_shape_cont_f, true, false);
+}
+
+struct loc_t
+char_assumed_shape_cont_in_c (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z,
+ int k, int num)
+{
+ return do_call (x, y, z, k, num, true, char_assumed_shape_cont_in_f, true, false);
+}
diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f90 b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f90
new file mode 100644
index 0000000..3eb2732
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.f90
@@ -0,0 +1,1574 @@
+! { dg-do run }
+! { dg-additional-sources bind-c-contiguous-5.c }
+! { dg-additional-options "-fcheck=all" }
+! { dg-prune-output "command-line option '-fcheck=.*' is valid for Fortran but not for C" }
+! ---- Same as bind-c-contiguous-1.f90 - but with kind=4 characters
+! Fortran demands that with bind(C), the callee ensure that for
+! * 'contiguous'
+! * len=* with explicit/assumed-size arrays
+! noncontiguous actual arguments are handled.
+! (in without bind(C) in gfortran, caller handles the copy in/out
+
+! Additionally, for a bind(C) callee, a Fortran-written caller
+! has to ensure the same (for contiguous + len=* to explicit-/assumed-size arrays)
+
+module m
+ use iso_c_binding, only: c_intptr_t, c_bool, c_loc, c_int
+ implicit none (type, external)
+
+ type, bind(C) :: loc_t
+ integer(c_intptr_t) :: x, y, z
+ end type loc_t
+
+interface
+ type(loc_t) function char_assumed_size_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(kind=4, len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_assumed_size_in_c (xx, yy, zz, n, num) bind(C)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(kind=4, len=*), intent(in) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ end function
+
+ type(loc_t) function char_expl_size_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(kind=4, len=*) :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_expl_size_in_c (xx, yy, zz, n, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer(c_int), value :: n, num
+ character(kind=4, len=*), intent(in) :: xx(n), yy(n:n+3), zz(6:6, 3:n, 3:n+3)
+ end function
+
+ type(loc_t) function char_assumed_rank_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*) :: xx(..)
+ character(kind=4, len=3) :: yy(..)
+ character(kind=4, len=k) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), intent(in) :: xx(..)
+ character(kind=4, len=3), intent(in) :: yy(..)
+ character(kind=4, len=k), intent(in) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), contiguous :: xx(..)
+ character(kind=4, len=3), contiguous :: yy(..)
+ character(kind=4, len=k), contiguous :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_rank_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), contiguous, intent(in) :: xx(..)
+ character(kind=4, len=3), contiguous, intent(in) :: yy(..)
+ character(kind=4, len=k), contiguous, intent(in) :: zz(..)
+ end function
+
+ type(loc_t) function char_assumed_shape_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*) :: xx(:)
+ character(kind=4, len=3) :: yy(5:)
+ character(kind=4, len=k) :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), intent(in) :: xx(:)
+ character(kind=4, len=3), intent(in) :: yy(5:)
+ character(kind=4, len=k), intent(in) :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), contiguous :: xx(:)
+ character(kind=4, len=3), contiguous :: yy(5:)
+ character(kind=4, len=k), contiguous :: zz(-k:)
+ end function
+
+ type(loc_t) function char_assumed_shape_cont_in_c (xx, yy, zz, k, num) bind(c)
+ import :: loc_t, c_bool, c_int
+ integer, value :: k, num
+ character(kind=4, len=*), contiguous, intent(in) :: xx(:)
+ character(kind=4, len=3), contiguous, intent(in) :: yy(5:)
+ character(kind=4, len=k), contiguous, intent(in) :: zz(-k:)
+ end function
+end interface
+
+contains
+
+type(loc_t) function char_assumed_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(kind=4, len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"nop") error stop 4
+ if (yy(3) /= 4_"abc") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"nop") error stop 4
+ if (zz(6,n,3) /= 4_"abc") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"jlm") error stop 4
+ if (yy(3) /= 4_"def") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"jlm") error stop 4
+ if (zz(6,n,3) /= 4_"def") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ yy(3) = 4_"ABC"
+ yy(4) = 4_"DEF"
+ yy(5) = 4_"GHI"
+ zz(6,n,3) = 4_"ABC"
+ zz(6,n,4) = 4_"DEF"
+ zz(6,n,5) = 4_"GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(kind=4, len=*) :: xx(*), yy(n:*), zz(6:6, 3:n, 3:*)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"nop") error stop 4
+ if (yy(3) /= 4_"abc") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"nop") error stop 4
+ if (zz(6,n,3) /= 4_"abc") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"jlm") error stop 4
+ if (yy(3) /= 4_"def") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"jlm") error stop 4
+ if (zz(6,n,3) /= 4_"def") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" } if (num == 1) then
+end
+
+type(loc_t) function char_expl_size_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(kind=4, len=*) :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"nop") error stop 4
+ if (yy(3) /= 4_"abc") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"nop") error stop 4
+ if (zz(6,n,3) /= 4_"abc") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"jlm") error stop 4
+ if (yy(3) /= 4_"def") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"jlm") error stop 4
+ if (zz(6,n,3) /= 4_"def") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"jlm") error stop 4
+ else
+ error stop 8
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ yy(3) = 4_"ABC"
+ yy(4) = 4_"DEF"
+ yy(5) = 4_"GHI"
+ zz(6,n,3) = 4_"ABC"
+ zz(6,n,4) = 4_"DEF"
+ zz(6,n,5) = 4_"GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_expl_size_in_f (xx, yy, zz, n, num) bind(c) result(res)
+ integer, value :: num, n
+ character(kind=4, len=*) :: xx(n), yy(n:n+2), zz(6:6, 3:n, 3:n+2)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 1
+ if (3 /= len(yy)) error stop 1
+ if (3 /= len(zz)) error stop 1
+ if (1 /= lbound(xx,dim=1)) error stop 1
+ if (3 /= lbound(yy,dim=1)) error stop 1
+ if (6 /= lbound(zz,dim=1)) error stop 1
+ if (3 /= lbound(zz,dim=2)) error stop 1
+ if (3 /= lbound(zz,dim=3)) error stop 1
+ if (3 /= size(xx,dim=1)) error stop 1
+ if (3 /= size(yy,dim=1)) error stop 1
+ if (1 /= size(zz,dim=1)) error stop 1
+ if (1 /= size(zz,dim=2)) error stop 1
+ if (3 /= size(zz,dim=3)) error stop 1
+ if (3 /= ubound(xx,dim=1)) error stop 1
+ if (5 /= ubound(yy,dim=1)) error stop 1
+ if (6 /= ubound(zz,dim=1)) error stop 1
+ if (3 /= ubound(zz,dim=2)) error stop 1
+ if (5 /= ubound(zz,dim=3)) error stop 1
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"nop") error stop 4
+ if (yy(3) /= 4_"abc") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"nop") error stop 4
+ if (zz(6,n,3) /= 4_"abc") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"nop") error stop 4
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 2
+ if (xx(2) /= 4_"ghi") error stop 3
+ if (xx(3) /= 4_"jlm") error stop 4
+ if (yy(3) /= 4_"def") error stop 2
+ if (yy(4) /= 4_"ghi") error stop 3
+ if (yy(5) /= 4_"jlm") error stop 4
+ if (zz(6,n,3) /= 4_"def") error stop 2
+ if (zz(6,n,4) /= 4_"ghi") error stop 3
+ if (zz(6,n,5) /= 4_"jlm") error stop 4
+ else
+ error stop 8
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+
+type(loc_t) function char_assumed_rank_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(..)
+ character(kind=4, len=3) :: yy(..)
+ character(kind=4, len=k) :: zz(..)
+ if (3 /= len(xx)) error stop 40
+ if (3 /= len(yy)) error stop 40
+ if (3 /= len(zz)) error stop 40
+ if (3 /= size(xx)) error stop 41
+ if (3 /= size(yy)) error stop 41
+ if (3 /= size(zz)) error stop 41
+ if (1 /= rank(xx)) error stop 49
+ if (1 /= rank(yy)) error stop 49
+ if (1 /= rank(zz)) error stop 49
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 49
+ if (is_contiguous (yy)) error stop 49
+ if (is_contiguous (zz)) error stop 49
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 49
+ if (.not. is_contiguous (yy)) error stop 49
+ if (.not. is_contiguous (zz)) error stop 49
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 42
+ if (xx(2) /= 4_"ghi") error stop 43
+ if (xx(3) /= 4_"nop") error stop 44
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 45
+ if (xx(2) /= 4_"ghi") error stop 46
+ if (xx(3) /= 4_"jlm") error stop 47
+ else
+ error stop 48
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ res%x = get_loc (xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= 4_"abc") error stop 42
+ if (yy(2) /= 4_"ghi") error stop 43
+ if (yy(3) /= 4_"nop") error stop 44
+ else if (num == 2) then
+ if (yy(1) /= 4_"def") error stop 45
+ if (yy(2) /= 4_"ghi") error stop 46
+ if (yy(3) /= 4_"jlm") error stop 47
+ else
+ error stop 48
+ endif
+ yy(1) = 4_"ABC"
+ yy(2) = 4_"DEF"
+ yy(3) = 4_"GHI"
+ res%y = get_loc (yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= 4_"abc") error stop 42
+ if (zz(2) /= 4_"ghi") error stop 43
+ if (zz(3) /= 4_"nop") error stop 44
+ else if (num == 2) then
+ if (zz(1) /= 4_"def") error stop 45
+ if (zz(2) /= 4_"ghi") error stop 46
+ if (zz(3) /= 4_"jlm") error stop 47
+ else
+ error stop 48
+ endif
+ zz(1) = 4_"ABC"
+ zz(2) = 4_"DEF"
+ zz(3) = 4_"GHI"
+ res%z = get_loc (zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(kind=4, len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_rank_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(..)
+ character(kind=4, len=3) :: yy(..)
+ character(kind=4, len=k) :: zz(..)
+ intent(in) :: xx, yy, zz
+ if (3 /= size(yy)) error stop 50
+ if (3 /= len(yy)) error stop 51
+ if (1 /= rank(yy)) error stop 59
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 59
+ if (is_contiguous (yy)) error stop 59
+ if (is_contiguous (zz)) error stop 59
+ else if (num == 2) then
+ if (.not. is_contiguous (xx)) error stop 59
+ if (.not. is_contiguous (yy)) error stop 59
+ if (.not. is_contiguous (zz)) error stop 59
+ else
+ error stop 48
+ end if
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 52
+ if (xx(2) /= 4_"ghi") error stop 53
+ if (xx(3) /= 4_"nop") error stop 54
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 55
+ if (xx(2) /= 4_"ghi") error stop 56
+ if (xx(3) /= 4_"jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%x = get_loc(xx)
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= 4_"abc") error stop 52
+ if (yy(2) /= 4_"ghi") error stop 53
+ if (yy(3) /= 4_"nop") error stop 54
+ else if (num == 2) then
+ if (yy(1) /= 4_"def") error stop 55
+ if (yy(2) /= 4_"ghi") error stop 56
+ if (yy(3) /= 4_"jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%y = get_loc(yy)
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= 4_"abc") error stop 52
+ if (zz(2) /= 4_"ghi") error stop 53
+ if (zz(3) /= 4_"nop") error stop 54
+ else if (num == 2) then
+ if (zz(1) /= 4_"def") error stop 55
+ if (zz(2) /= 4_"ghi") error stop 56
+ if (zz(3) /= 4_"jlm") error stop 57
+ else
+ error stop 58
+ endif
+ res%z = get_loc(zz)
+ rank default
+ error stop 99
+ end select
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(kind=4, len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_rank_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(..)
+ character(kind=4, len=3) :: yy(..)
+ character(kind=4, len=k) :: zz(..)
+ contiguous :: xx, yy, zz
+ if (3 /= len(xx)) error stop 60
+ if (3 /= len(yy)) error stop 60
+ if (3 /= len(zz)) error stop 60
+ if (3 /= size(xx)) error stop 61
+ if (3 /= size(yy)) error stop 61
+ if (3 /= size(zz)) error stop 61
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 62
+ if (xx(2) /= 4_"ghi") error stop 63
+ if (xx(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 65
+ if (xx(2) /= 4_"ghi") error stop 66
+ if (xx(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= 4_"abc") error stop 62
+ if (yy(2) /= 4_"ghi") error stop 63
+ if (yy(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= 4_"def") error stop 65
+ if (yy(2) /= 4_"ghi") error stop 66
+ if (yy(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ yy(1) = 4_"ABC"
+ yy(2) = 4_"DEF"
+ yy(3) = 4_"GHI"
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= 4_"abc") error stop 62
+ if (zz(2) /= 4_"ghi") error stop 63
+ if (zz(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= 4_"def") error stop 65
+ if (zz(2) /= 4_"ghi") error stop 66
+ if (zz(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ zz(1) = 4_"ABC"
+ zz(2) = 4_"DEF"
+ zz(3) = 4_"GHI"
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_rank_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(..)
+ character(kind=4, len=3) :: yy(..)
+ character(kind=4, len=k) :: zz(..)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ if (3 /= size(xx)) error stop 30
+ if (3 /= size(yy)) error stop 30
+ if (3 /= size(zz)) error stop 30
+ if (3 /= len(xx)) error stop 31
+ if (3 /= len(yy)) error stop 31
+ if (3 /= len(zz)) error stop 31
+ if (1 /= rank(xx)) error stop 69
+ if (1 /= rank(yy)) error stop 69
+ if (1 /= rank(zz)) error stop 69
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (1 /= lbound(yy, dim=1)) stop 49
+ if (1 /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (3 /= ubound(yy, dim=1)) stop 49
+ if (3 /= ubound(zz, dim=1)) stop 49
+ select rank (xx)
+ rank (1)
+ print *, xx(1:3)
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 62
+ if (xx(2) /= 4_"ghi") error stop 63
+ if (xx(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 65
+ if (xx(2) /= 4_"ghi") error stop 66
+ if (xx(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (yy)
+ rank (1)
+ print *, yy(1:3)
+ if (num == 1) then
+ if (yy(1) /= 4_"abc") error stop 62
+ if (yy(2) /= 4_"ghi") error stop 63
+ if (yy(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (yy(1) /= 4_"def") error stop 65
+ if (yy(2) /= 4_"ghi") error stop 66
+ if (yy(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+ select rank (zz)
+ rank (1)
+ print *, zz(1:3)
+ if (num == 1) then
+ if (zz(1) /= 4_"abc") error stop 62
+ if (zz(2) /= 4_"ghi") error stop 63
+ if (zz(3) /= 4_"nop") error stop 64
+ else if (num == 2) then
+ if (zz(1) /= 4_"def") error stop 65
+ if (zz(2) /= 4_"ghi") error stop 66
+ if (zz(3) /= 4_"jlm") error stop 67
+ else
+ error stop 68
+ endif
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+ rank default
+ error stop 99
+ end select
+end
+
+type(loc_t) function char_assumed_shape_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(:)
+ character(kind=4, len=3) :: yy(5:)
+ character(kind=4, len=k) :: zz(-k:)
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 70
+ if (3 /= len(yy)) error stop 70
+ if (3 /= len(zz)) error stop 70
+ if (3 /= size(xx)) error stop 71
+ if (3 /= size(yy)) error stop 71
+ if (3 /= size(zz)) error stop 71
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 79
+ if (is_contiguous (yy)) error stop 79
+ if (is_contiguous (zz)) error stop 79
+ if (xx(1) /= 4_"abc") error stop 72
+ if (xx(2) /= 4_"ghi") error stop 73
+ if (xx(3) /= 4_"nop") error stop 74
+ if (yy(5) /= 4_"abc") error stop 72
+ if (yy(6) /= 4_"ghi") error stop 73
+ if (yy(7) /= 4_"nop") error stop 74
+ if (zz(-k) /= 4_"abc") error stop 72
+ if (zz(-k+1) /= 4_"ghi") error stop 73
+ if (zz(-k+2) /= 4_"nop") error stop 74
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 79
+ if (.not.is_contiguous (yy)) error stop 79
+ if (.not.is_contiguous (zz)) error stop 79
+ if (xx(1) /= 4_"def") error stop 72
+ if (xx(2) /= 4_"ghi") error stop 73
+ if (xx(3) /= 4_"jlm") error stop 74
+ if (yy(5) /= 4_"def") error stop 72
+ if (yy(6) /= 4_"ghi") error stop 73
+ if (yy(7) /= 4_"jlm") error stop 74
+ if (zz(-k) /= 4_"def") error stop 72
+ if (zz(-k+1) /= 4_"ghi") error stop 73
+ if (zz(-k+2) /= 4_"jlm") error stop 74
+ else
+ error stop 78
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ yy(5) = 4_"ABC"
+ yy(6) = 4_"DEF"
+ yy(7) = 4_"GHI"
+ zz(-k) = 4_"ABC"
+ zz(-k+1) = 4_"DEF"
+ zz(-k+2) = 4_"GHI"
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(kind=4, len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+type(loc_t) function char_assumed_shape_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(:)
+ character(kind=4, len=3) :: yy(5:)
+ character(kind=4, len=k) :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 80
+ if (3 /= size(yy)) error stop 80
+ if (3 /= size(zz)) error stop 80
+ if (3 /= len(xx)) error stop 81
+ if (3 /= len(yy)) error stop 81
+ if (3 /= len(zz)) error stop 81
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (is_contiguous (xx)) error stop 89
+ if (is_contiguous (yy)) error stop 89
+ if (is_contiguous (zz)) error stop 89
+ if (xx(1) /= 4_"abc") error stop 82
+ if (xx(2) /= 4_"ghi") error stop 83
+ if (xx(3) /= 4_"nop") error stop 84
+ if (yy(5) /= 4_"abc") error stop 82
+ if (yy(6) /= 4_"ghi") error stop 83
+ if (yy(7) /= 4_"nop") error stop 84
+ if (zz(-k) /= 4_"abc") error stop 82
+ if (zz(-k+1) /= 4_"ghi") error stop 83
+ if (zz(-k+2) /= 4_"nop") error stop 84
+ else if (num == 2) then
+ if (.not.is_contiguous (xx)) error stop 89
+ if (.not.is_contiguous (yy)) error stop 89
+ if (.not.is_contiguous (zz)) error stop 89
+ if (xx(1) /= 4_"def") error stop 85
+ if (xx(2) /= 4_"ghi") error stop 86
+ if (xx(3) /= 4_"jlm") error stop 87
+ if (yy(5) /= 4_"def") error stop 85
+ if (yy(6) /= 4_"ghi") error stop 86
+ if (yy(7) /= 4_"jlm") error stop 87
+ if (zz(-k) /= 4_"def") error stop 85
+ if (zz(-k+1) /= 4_"ghi") error stop 86
+ if (zz(-k+2) /= 4_"jlm") error stop 87
+ else
+ error stop 88
+ endif
+ res%x = get_loc(xx)
+ res%y = get_loc(yy)
+ res%z = get_loc(zz)
+contains
+ integer (c_intptr_t) function get_loc (arg)
+ character(kind=4, len=*), target :: arg(:)
+ ! %loc does copy in/out if not simply contiguous
+ ! extra func needed because of 'target' attribute
+ get_loc = transfer (c_loc(arg), res%x)
+ end
+end
+
+
+
+type(loc_t) function char_assumed_shape_cont_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(:)
+ character(kind=4, len=3) :: yy(5:)
+ character(kind=4, len=k) :: zz(-k:)
+ contiguous :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= len(xx)) error stop 90
+ if (3 /= len(yy)) error stop 90
+ if (3 /= len(zz)) error stop 90
+ if (3 /= size(xx)) error stop 91
+ if (3 /= size(yy)) error stop 91
+ if (3 /= size(zz)) error stop 91
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 92
+ if (xx(2) /= 4_"ghi") error stop 93
+ if (xx(3) /= 4_"nop") error stop 94
+ if (yy(5) /= 4_"abc") error stop 92
+ if (yy(6) /= 4_"ghi") error stop 93
+ if (yy(7) /= 4_"nop") error stop 94
+ if (zz(-k) /= 4_"abc") error stop 92
+ if (zz(-k+1) /= 4_"ghi") error stop 93
+ if (zz(-k+2) /= 4_"nop") error stop 94
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 92
+ if (xx(2) /= 4_"ghi") error stop 93
+ if (xx(3) /= 4_"jlm") error stop 94
+ if (yy(5) /= 4_"def") error stop 92
+ if (yy(6) /= 4_"ghi") error stop 93
+ if (yy(7) /= 4_"jlm") error stop 94
+ if (zz(-k) /= 4_"def") error stop 92
+ if (zz(-k+1) /= 4_"ghi") error stop 93
+ if (zz(-k+2) /= 4_"jlm") error stop 94
+ else
+ error stop 98
+ endif
+ xx(1) = 4_"ABC"
+ xx(2) = 4_"DEF"
+ xx(3) = 4_"GHI"
+ yy(5) = 4_"ABC"
+ yy(6) = 4_"DEF"
+ yy(7) = 4_"GHI"
+ zz(-k) = 4_"ABC"
+ zz(-k+1) = 4_"DEF"
+ zz(-k+2) = 4_"GHI"
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+type(loc_t) function char_assumed_shape_cont_in_f (xx, yy, zz, k, num) bind(c) result(res)
+ integer, value :: num, k
+ character(kind=4, len=*) :: xx(:)
+ character(kind=4, len=3) :: yy(5:)
+ character(kind=4, len=k) :: zz(-k:)
+ intent(in) :: xx, yy, zz
+ contiguous :: xx, yy, zz
+ print *, xx(1:3)
+ if (3 /= size(xx)) error stop 100
+ if (3 /= size(yy)) error stop 100
+ if (3 /= size(zz)) error stop 100
+ if (3 /= len(xx)) error stop 101
+ if (3 /= len(yy)) error stop 101
+ if (3 /= len(zz)) error stop 101
+ if (1 /= lbound(xx, dim=1)) stop 49
+ if (5 /= lbound(yy, dim=1)) stop 49
+ if (-k /= lbound(zz, dim=1)) stop 49
+ if (3 /= ubound(xx, dim=1)) stop 49
+ if (7 /= ubound(yy, dim=1)) stop 49
+ if (-k+2 /= ubound(zz, dim=1)) stop 49
+ if (num == 1) then
+ if (xx(1) /= 4_"abc") error stop 102
+ if (xx(2) /= 4_"ghi") error stop 103
+ if (xx(3) /= 4_"nop") error stop 104
+ if (yy(5) /= 4_"abc") error stop 102
+ if (yy(6) /= 4_"ghi") error stop 103
+ if (yy(7) /= 4_"nop") error stop 104
+ if (zz(-k) /= 4_"abc") error stop 102
+ if (zz(-k+1) /= 4_"ghi") error stop 103
+ if (zz(-k+2) /= 4_"nop") error stop 104
+ else if (num == 2) then
+ if (xx(1) /= 4_"def") error stop 105
+ if (xx(2) /= 4_"ghi") error stop 106
+ if (xx(3) /= 4_"jlm") error stop 107
+ if (yy(5) /= 4_"def") error stop 105
+ if (yy(6) /= 4_"ghi") error stop 106
+ if (yy(7) /= 4_"jlm") error stop 107
+ if (zz(-k) /= 4_"def") error stop 105
+ if (zz(-k+1) /= 4_"ghi") error stop 106
+ if (zz(-k+2) /= 4_"jlm") error stop 107
+ else
+ error stop 108
+ endif
+ res%x = %loc(xx) ! { dg-warning "Legacy Extension" }
+ res%y = %loc(yy) ! { dg-warning "Legacy Extension" }
+ res%z = %loc(zz) ! { dg-warning "Legacy Extension" }
+end
+
+end module
+
+
+use m
+implicit none (type, external)
+character(kind=4, len=3) :: a(6), a2(6), a3(6), a_init(6)
+type(loc_t) :: loc3
+
+a_init = [4_'abc', 4_'def', 4_'ghi', 4_'jlm', 4_'nop', 4_'qrs']
+
+! -- Fortran: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_f (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- Fortran: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_f (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+
+! --- character - call C directly --
+
+! -- C: assumed size
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(2:4)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: explicit shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(::2), a2(::2), a3(::2), size(a(::2)), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_expl_size_in_c (a(2:4), a2(2:4), a3(2:4), size(a(::2)), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed rank
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed rank contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_rank_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed shape
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(::2), a2(::2), a3(::2), len(a), num=1)
+if (loc3%x /= %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+
+! -- C: assumed shape contiguous
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 51 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a2 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+if (any (a3 /= [4_'ABC', 4_'def', 4_'DEF', 4_'jlm', 4_'GHI', 4_'qrs'])) error stop 52
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 53 ! { dg-warning "Legacy Extension" }
+if (any (a /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a2 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+if (any (a3 /= [4_'abc', 4_'ABC', 4_'DEF', 4_'GHI', 4_'nop', 4_'qrs'])) error stop 54
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(::2), a2(::2), a3(::2), len(a), num=1) ! NOTE: run-time copy-in warning
+if (loc3%x == %loc(a)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%y == %loc(a2)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (loc3%z == %loc(a3)) error stop 55 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 56
+if (any (a2 /= a_init)) error stop 56
+if (any (a3 /= a_init)) error stop 56
+
+a = a_init; a2 = a_init; a3 = a_init
+loc3 = char_assumed_shape_cont_in_c (a(2:4), a2(2:4), a3(2:4), len(a), num=2)
+if (loc3%x /= %loc(a(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%y /= %loc(a2(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (loc3%z /= %loc(a3(2))) error stop 57 ! { dg-warning "Legacy Extension" }
+if (any (a /= a_init)) error stop 58
+if (any (a2 /= a_init)) error stop 58
+if (any (a3 /= a_init)) error stop 58
+end
+
+
+! { dg-output "At line 928 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 928 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 928 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 946 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 965 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 983 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1039 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1057 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1113 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output "At line 1131 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_f'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1153 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1171 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1190 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1208 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_expl_size_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1264 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1282 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_rank_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1338 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'xx' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'yy' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output "At line 1356 of file .*bind-c-contiguous-5.f90(\n|\r\n|\r)" }"
+! { dg-output "Fortran runtime warning: An array temporary was created for argument 'zz' of procedure 'char_assumed_shape_cont_in_c'(\n|\r\n|\r)" }"
+! { dg-output " abcghinop(\n|\r\n|\r)" }"
+! { dg-output " defghijlm(\n|\r\n|\r)" }"
diff --git a/gcc/testsuite/gfortran.dg/bind-c-intent-out.f90 b/gcc/testsuite/gfortran.dg/bind-c-intent-out.f90
index 39822c0..d416fa5 100644
--- a/gcc/testsuite/gfortran.dg/bind-c-intent-out.f90
+++ b/gcc/testsuite/gfortran.dg/bind-c-intent-out.f90
@@ -1,4 +1,4 @@
-! { dg-do compile }
+! { dg-do run }
! { dg-options "-fdump-tree-original" }
!
! PR fortran/91863
@@ -28,15 +28,20 @@ program p
if (.not.allocated(a)) stop 1
if (any(shape(a) /= [3])) stop 2
if (lbound(a,1) /= 3 .or. ubound(a,1) /= 5) stop 3
+ print *, a(0), a(1), a(2), a(3), a(4)
+ print *, a
if (any(a /= [1, 2, 3])) stop 4
end program p
! "cfi" only appears in context of "a" -> bind-C descriptor
-! the intent(out) implies freeing in the callee (!), hence the "free"
+! the intent(out) implies freeing in the callee (!) (when implemented in Fortran), hence the "free"
+! and also in the caller (when implemented in Fortran)
! It is the only 'free' as 'a' is part of the main program and, hence, implicitly has the SAVE attribute.
! The 'cfi = 0' appears before the call due to the deallocate and when preparing the C descriptor
! As cfi (i.e. the descriptor itself) is allocated in libgomp, it has to be freed after the call.
! { dg-final { scan-tree-dump-times "__builtin_free" 2 "original" } }
-! { dg-final { scan-tree-dump-times "__builtin_free \\(cfi\\.\[0-9\]+\\);" 2 "original" } }
-! { dg-final { scan-tree-dump-times "cfi\\.\[0-9\]+ = 0B;" 2 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(_x->base_addr\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_x->base_addr = 0B;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free \\(cfi\\.\[0-9\]+\\.base_addr\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "cfi\\.\[0-9\]+\\.base_addr = 0B;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90 b/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
index ede6eff..8dd7e8f 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
@@ -22,4 +22,32 @@ end
! { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,myBindC" 1 { target { s390*-*-* } } } }
! { dg-final { scan-assembler-times "bl \.myBindC" 1 { target { powerpc-ibm-aix* } } } }
! { dg-final { scan-assembler-times "add_u32\t\[sv\]\[0-9\]*, \[sv\]\[0-9\]*, myBindC@rel32@lo" 1 { target { amdgcn*-*-* } } } }
-! { dg-final { scan-tree-dump-times "gfc_desc_to_cfi_desc \\\(&cfi\\." 1 "original" } }
+
+
+! { dg-final { scan-tree-dump "parm...span = 4;" "original" } }
+! { dg-final { scan-tree-dump "parm...dtype = {.elem_len=4, .rank=2, .type=1};" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].lbound = 1;" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].ubound = 4;" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].stride = 1;" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].lbound = 1;" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].ubound = 4;" "original" } }
+! { dg-final { scan-tree-dump "parm...dim\\\[1\\\].stride = 4;" "original" } }
+! { dg-final { scan-tree-dump "parm...data = \\(void \\*\\) &aa\\\[0\\\];" "original" } }
+! { dg-final { scan-tree-dump "parm...offset = -5;" "original" } }
+! { dg-final { scan-tree-dump "cfi...version = 1;" "original" } }
+! { dg-final { scan-tree-dump "cfi...rank = 2;" "original" } }
+! { dg-final { scan-tree-dump "cfi...type = 1025;" "original" } }
+! { dg-final { scan-tree-dump "cfi...attribute = 2;" "original" } }
+! { dg-final { scan-tree-dump "cfi...base_addr = parm.0.data;" "original" } }
+! { dg-final { scan-tree-dump "cfi...elem_len = 4;" "original" } }
+! { dg-final { scan-tree-dump "idx.2 = 0;" "original" } }
+
+! { dg-final { scan-tree-dump "if \\(idx.. <= 1\\) goto L..;" "original" } }
+! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].lower_bound = 0;" "original" } }
+! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].extent = \\(parm...dim\\\[idx..\\\].ubound - parm...dim\\\[idx..\\\].lbound\\) \\+ 1;" "original" } }
+! { dg-final { scan-tree-dump "cfi...dim\\\[idx..\\\].sm = parm...dim\\\[idx..\\\].stride \\* parm...span;" "original" } }
+! { dg-final { scan-tree-dump "idx.. = idx.. \\+ 1;" "original" } }
+
+! { dg-final { scan-tree-dump "test \\(&cfi..\\);" "original" } }
+
+
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_10.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_10.f90
index 3595851..7c6f4dc 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_char_10.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_10.f90
@@ -466,15 +466,16 @@ program main
end
! All arguments shall use array descriptors
-! { dg-final { scan-tree-dump-times "void as1 \\(struct array01_character\\(kind=1\\) & restrict x1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void as2 \\(struct array01_character\\(kind=1\\) & restrict x2\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void as4 \\(struct array01_character\\(kind=1\\) & restrict xstar\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void as3 \\(struct array01_character\\(kind=1\\) & restrict xn, integer(kind=4) & restrict n)
-! { dg-final { scan-tree-dump-times "void ar1 \\(struct array15_character\\(kind=1\\) & restrict x1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void ar2 \\(struct array15_character\\(kind=1\\) & restrict x2\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void ar3 \\(struct array15_character\\(kind=1\\) & restrict xn, integer(kind=4) & restrict n)
-! { dg-final { scan-tree-dump-times "void ar4 \\(struct array15_character\\(kind=1\\) & restrict xstar\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void a5a \\(struct array01_character\\(kind=1\\) & restrict xcolon\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void a5ar \\(struct array15_character\\(kind=1\\) & restrict xcolon\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void a5p \\(struct array01_character\\(kind=1\\) & xcolon\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void a5pr \\(struct array15_character\\(kind=1\\) & xcolon\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void as1 \\(struct CFI_cdesc_t01 & restrict _x1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void as2 \\(struct CFI_cdesc_t01 & restrict _x2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void as3 \\(struct CFI_cdesc_t01 & restrict _xn, integer\\(kind=4\\) & restrict n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void as4 \\(struct CFI_cdesc_t01 & restrict _xstar\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void ar1 \\(struct CFI_cdesc_t & restrict _x1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void ar2 \\(struct CFI_cdesc_t & restrict _x2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void ar3 \\(struct CFI_cdesc_t & restrict _xn, integer\\(kind=4\\) & restrict n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void ar4 \\(struct CFI_cdesc_t & restrict _xstar\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void a5ar \\(struct CFI_cdesc_t & restrict _xcolon\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void a5a \\(struct CFI_cdesc_t01 & restrict _xcolon\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void a5pr \\(struct CFI_cdesc_t & _xcolon\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "void a5p \\(struct CFI_cdesc_t01 & _xcolon\\)" 1 "original" } }
+
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_6.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_6.f90
index 23e1d92..6bab295 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_char_6.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_6.f90
@@ -9,11 +9,11 @@ subroutine s1 (x1) bind(C)
character(len=1) :: x1
end
-subroutine s2 (x2) bind(C) ! { dg-error "Fortran 2008: Character dummy argument 'x2' at .1. with length greater than 1 for procedure 's2' with BIND\\(C\\) attribute" }
+subroutine s2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2
end
-subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
+subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn
end
@@ -28,19 +28,17 @@ subroutine as1 (x1) bind(C) ! { dg-error "Fortran 2018: Assumed-shape array 'x1
character(len=1) :: x1(:)
end
-subroutine as2 (x2) bind(C) ! { dg-error "Fortran 2008: Character dummy argument 'x2' at .1. with length greater than 1 for procedure 'as2' with BIND\\(C\\) attribute" }
- ! { dg-error "Fortran 2018: Assumed-shape array 'x2' at .1. as dummy argument to the BIND\\(C\\) procedure 'as2' at .2." "" { target *-*-* } .-1 }
+subroutine as2 (x2) bind(C) ! { dg-error "Fortran 2018: Assumed-shape array 'x2' at .1. as dummy argument to the BIND\\(C\\) procedure 'as2' at .2." }
character(len=2) :: x2(:,:)
end
-subroutine as3 (xn, n) bind(C) ! { dg-error "Fortran 2018: Character dummy argument 'xn' at .1. with nonconstant length as procedure 'as3' is BIND\\(C\\)" }
- ! { dg-error "Fortran 2018: Assumed-shape array 'xn' at .1. as dummy argument to the BIND\\(C\\) procedure 'as3' at .2." "" { target *-*-* } .-1 }
+subroutine as3 (xn, n) bind(C) ! { dg-error "Fortran 2018: Assumed-shape array 'xn' at .1. as dummy argument to the BIND\\(C\\) procedure 'as3' at .2." }
integer :: n
character(len=n) :: xn(:,:,:)
end
-subroutine as4 (xstar) bind(C) ! { dg-error "Fortran 2018: Assumed-length character dummy argument 'xstar' at .1. of procedure 'as4' with BIND\\(C\\) attribute" }
- ! { dg-error "Fortran 2018: Assumed-shape array 'xstar' at .1. as dummy argument to the BIND\\(C\\) procedure 'as4' at .2." "" { target *-*-* } .-1 }
+subroutine as4 (xstar) bind(C) ! { dg-error "Fortran 2018: Assumed-length character dummy argument 'xstar' at .1. of procedure 'as4' with BIND\\(C\\) attribute" }
+ ! { dg-error "Fortran 2018: Assumed-shape array 'xstar' at .1. as dummy argument to the BIND\\(C\\) procedure 'as4' at .2." "" { target *-*-* } .-1 }
character(len=*) :: xstar(:,:,:,:)
end
@@ -69,11 +67,11 @@ subroutine az1 (x1) bind(C)
character(len=1) :: x1(*)
end
-subroutine az2 (x2) bind(C) ! { dg-error "Fortran 2008: Character dummy argument 'x2' at .1. with length greater than 1 for procedure 'az2' with BIND\\(C\\) attribute" }
+subroutine az2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(*)
end
-subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
+subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(*)
end
@@ -88,11 +86,11 @@ subroutine ae1 (x1) bind(C)
character(len=1) :: x1(5)
end
-subroutine ae2 (x2) bind(C) ! { dg-error "Fortran 2008: Character dummy argument 'x2' at .1. with length greater than 1 for procedure 'ae2' with BIND\\(C\\) attribute" }
+subroutine ae2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(7)
end
-subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
+subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(9)
end
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_7.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_7.f90
index a9b8c3b..5a20b8f 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_char_7.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_7.f90
@@ -9,11 +9,11 @@ subroutine s1 (x1) bind(C)
character(len=1) :: x1
end
-subroutine s2 (x2) bind(C)
+subroutine s2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2
end
-subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
+subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn
end
@@ -32,8 +32,7 @@ subroutine as2 (x2) bind(C) ! { dg-error "Fortran 2018: Assumed-shape array 'x2'
character(len=2) :: x2(:,:)
end
-subroutine as3 (xn, n) bind(C) ! { dg-error "Fortran 2018: Character dummy argument 'xn' at .1. with nonconstant length as procedure 'as3' is BIND\\(C\\)" }
- ! { dg-error "Fortran 2018: Assumed-shape array 'xn' at .1. as dummy argument to the BIND\\(C\\) procedure 'as3' at .2." "" { target *-*-* } .-1 }
+subroutine as3 (xn, n) bind(C) ! { dg-error "Fortran 2018: Assumed-shape array 'xn' at .1. as dummy argument to the BIND\\(C\\) procedure 'as3' at .2." }
integer :: n
character(len=n) :: xn(:,:,:)
end
@@ -68,11 +67,11 @@ subroutine az1 (x1) bind(C)
character(len=1) :: x1(*)
end
-subroutine az2 (x2) bind(C)
+subroutine az2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(*)
end
-subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
+subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(*)
end
@@ -87,11 +86,11 @@ subroutine ae1 (x1) bind(C)
character(len=1) :: x1(5)
end
-subroutine ae2 (x2) bind(C)
+subroutine ae2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(7)
end
-subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
+subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(9)
end
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_8.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_8.f90
index 1d566c0..8e6413d 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_char_8.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_8.f90
@@ -19,16 +19,16 @@ subroutine s1 (x1) bind(C)
character(len=1) :: x1
end
-subroutine s2 (x2) bind(C)
+subroutine s2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2
end
-subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
+subroutine s3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 's3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn
end
-subroutine s4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 's4' with BIND\\(C\\) attribute" }
+subroutine s4 (xstar) bind(C)
character(len=*) :: xstar
end
@@ -76,16 +76,16 @@ subroutine az1 (x1) bind(C)
character(len=1) :: x1(*)
end
-subroutine az2 (x2) bind(C)
+subroutine az2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(*)
end
-subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
+subroutine az3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'az3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(*)
end
-subroutine az4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 'az4' with BIND\\(C\\) attribute" }
+subroutine az4 (xstar) bind(C)
character(len=*) :: xstar(*)
end
@@ -95,16 +95,16 @@ subroutine ae1 (x1) bind(C)
character(len=1) :: x1(5)
end
-subroutine ae2 (x2) bind(C)
+subroutine ae2 (x2) bind(C) ! { dg-error "Character dummy argument 'x2' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae2' has the BIND\\(C\\) attribute" }
character(len=2) :: x2(7)
end
-subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
+subroutine ae3 (xn, n) bind(C) ! { dg-error "Character dummy argument 'xn' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'ae3' has the BIND\\(C\\) attribute" }
integer :: n
character(len=n) :: xn(9)
end
-subroutine ae4 (xstar) bind(C) ! { dg-error "Sorry, character dummy argument 'xstar' at .1. with assumed length is not yet supported for procedure 'ae4' with BIND\\(C\\) attribute" }
+subroutine ae4 (xstar) bind(C)
character(len=*) :: xstar(3)
end
@@ -128,7 +128,7 @@ subroutine s4a (xstar) bind(C) ! { dg-error "Allocatable character dummy argumen
character(len=*), allocatable :: xstar
end
-subroutine s5a (xcolon) bind(C) ! { dg-error "Sorry, deferred-length scalar character dummy argument 'xcolon' at .1. of procedure 's5a' with BIND\\(C\\) not yet supported" }
+subroutine s5a (xcolon) bind(C)
character(len=:), allocatable :: xcolon
end
@@ -198,7 +198,7 @@ subroutine s4p (xstar) bind(C) ! { dg-error "Pointer character dummy argument 'x
character(len=*), pointer :: xstar
end
-subroutine s5p (xcolon) bind(C) ! { dg-error "Sorry, deferred-length scalar character dummy argument 'xcolon' at .1. of procedure 's5p' with BIND\\(C\\) not yet supported" }
+subroutine s5p (xcolon) bind(C)
character(len=:), pointer :: xcolon
end
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_9.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_9.f90
index d31862c..64d7340 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_char_9.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_9.f90
@@ -18,12 +18,18 @@ subroutine s1 (x1) bind(C)
x1 = 'A'
end
-subroutine s2 (x2) bind(C)
- character(kind=c_char, len=2) :: x2
- if (len (x2) /= 2) stop
- if (x2 /= '42') stop
- x2 = '64'
-end
+! Valid as Fortran code - but with BIND(C)
+! 18.3.6 (5) (bullet 5) requires interoperability, i.e. len=1
+! which is not fullfilled.
+!
+! [It would work as with len=<const> the length is known
+! and only a bytestream is passed around.]
+!subroutine s2 (x2) bind(C)
+! character(kind=c_char, len=2) :: x2
+! if (len (x2) /= 2) stop
+! if (x2 /= '42') stop
+! x2 = '64'
+!end
! Assumed-size array, nonallocatable/nonpointer
@@ -44,22 +50,28 @@ subroutine az1 (x1) bind(C)
'h']
end
-subroutine az2 (x2) bind(C)
- character(kind=c_char, len=2) :: x2(*)
- if (len(x2) /= 2) stop
- if (any (x2(:6) /= ['ab', &
- 'fd', &
- 'D4', &
- '54', &
- 'ga', &
- 'hg'])) stop
- x2(:6) = ['ab', &
- 'hd', &
- 'fj', &
- 'a4', &
- '4a', &
- 'hf']
-end
+! Valid as Fortran code - but with BIND(C)
+! 18.3.6 (5) (bullet 5) requires interoperability, i.e. len=1
+! which is not fullfilled.
+!
+! [It would work as with len=<const> the length is known
+! and only a bytestream is passed around.]
+!subroutine az2 (x2) bind(C)
+! character(kind=c_char, len=2) :: x2(*)
+! if (len(x2) /= 2) stop
+! if (any (x2(:6) /= ['ab', &
+! 'fd', &
+! 'D4', &
+! '54', &
+! 'ga', &
+! 'hg'])) stop
+! x2(:6) = ['ab', &
+! 'hd', &
+! 'fj', &
+! 'a4', &
+! '4a', &
+! 'hf']
+!end
! Explicit-size array, nonallocatable/nonpointer
@@ -81,23 +93,29 @@ subroutine ae1 (x1) bind(C)
'h']
end
-subroutine ae2 (x2) bind(C)
- character(kind=c_char, len=2) :: x2(6)
- if (size(x2) /= 6) stop
- if (len(x2) /= 2) stop
- if (any (x2 /= ['ab', &
- 'fd', &
- 'D4', &
- '54', &
- 'ga', &
- 'hg'])) stop
- x2 = ['ab', &
- 'hd', &
- 'fj', &
- 'a4', &
- '4a', &
- 'hf']
-end
+! Valid as Fortran code - but with BIND(C)
+! 18.3.6 (5) (bullet 5) requires interoperability, i.e. len=1
+! which is not fullfilled.
+!
+! [It would work as with len=<const> the length is known
+! and only a bytestream is passed around.]
+!subroutine ae2 (x2) bind(C)
+! character(kind=c_char, len=2) :: x2(6)
+! if (size(x2) /= 6) stop
+! if (len(x2) /= 2) stop
+! if (any (x2 /= ['ab', &
+! 'fd', &
+! 'D4', &
+! '54', &
+! 'ga', &
+! 'hg'])) stop
+! x2 = ['ab', &
+! 'hd', &
+! 'fj', &
+! 'a4', &
+! '4a', &
+! 'hf']
+!end
end module m
@@ -116,9 +134,9 @@ program main
call s1 (str1)
if (str1 /= 'A') stop
- str2 = '42'
- call s2 (str2)
- if (str2 /= '64') stop
+! str2 = '42'
+! call s2 (str2)
+! if (str2 /= '64') stop
! assumed size - without array descriptor
@@ -135,19 +153,20 @@ program main
'3', &
'4', &
'h'])) stop
- str2a6 = ['ab', &
- 'fd', &
- 'D4', &
- '54', &
- 'ga', &
- 'hg']
- call az2 (str2a6)
- if (any (str2a6 /= ['ab', &
- 'hd', &
- 'fj', &
- 'a4', &
- '4a', &
- 'hf'])) stop
+! str2a6 = ['ab', &
+! 'fd', &
+! 'D4', &
+! '54', &
+! 'ga', &
+! 'hg']
+! call az2 (str2a6)
+! if (any (str2a6 /= ['ab', &
+! 'hd', &
+! 'fj', &
+! 'a4', &
+! '4a', &
+! 'hf'])) stop
+
! explicit size - without array descriptor
str1a6 = ['g', &
@@ -163,26 +182,26 @@ program main
'3', &
'4', &
'h'])) stop
- str2a6 = ['ab', &
- 'fd', &
- 'D4', &
- '54', &
- 'ga', &
- 'hg']
- call ae2 (str2a6)
- if (any (str2a6 /= ['ab', &
- 'hd', &
- 'fj', &
- 'a4', &
- '4a', &
- 'hf'])) stop
+! str2a6 = ['ab', &
+! 'fd', &
+! 'D4', &
+! '54', &
+! 'ga', &
+! 'hg']
+! call ae2 (str2a6)
+! if (any (str2a6 /= ['ab', &
+! 'hd', &
+! 'fj', &
+! 'a4', &
+! '4a', &
+! 'hf'])) stop
end
! All argument shall be passed without descriptor
! { dg-final { scan-tree-dump-not "dtype" "original" } }
! { dg-final { scan-tree-dump-times "void s1 \\(character\\(kind=1\\)\\\[1:1\\\] & restrict x1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void s2 \\(character\\(kind=1\\)\\\[1:2\\\] & restrict x2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-not "void s2 " "original" } }
! { dg-final { scan-tree-dump-times "void az1 \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict x1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void az2 \\(character\\(kind=1\\)\\\[0:\\\]\\\[1:2\\\] \\* restrict x2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-not "void az2 " "original" } }
! { dg-final { scan-tree-dump-times "void ae1 \\(character\\(kind=1\\)\\\[6\\\]\\\[1:1\\\] \\* restrict x1\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times "void ae2 \\(character\\(kind=1\\)\\\[6\\\]\\\[1:2\\\] \\* restrict x2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-not "void ae2 " "original" } }
diff --git a/gcc/testsuite/gfortran.dg/bind_c_contiguous.f90 b/gcc/testsuite/gfortran.dg/bind_c_contiguous.f90
new file mode 100644
index 0000000..fc0d092
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_contiguous.f90
@@ -0,0 +1,33 @@
+module m
+ use iso_c_binding
+ implicit none (type, external)
+contains
+
+! All of the following use an array descriptor
+! F2018, 18.3.7 (5) applies:
+
+subroutine f1 (x) bind(c) ! { dg-error "Dummy argument 'x' at .1. may not be a pointer with CONTIGUOUS attribute as procedure 'f1' is BIND\\(C\\)" }
+ character(len=:, kind=c_char), pointer, contiguous :: x(:)
+end
+
+subroutine f2 (x) bind(c) ! { dg-error "Dummy argument 'x' at .1. may not be a pointer with CONTIGUOUS attribute as procedure 'f2' is BIND\\(C\\)" }
+ integer(c_int), pointer, contiguous :: x(:)
+end
+
+subroutine f3 (x) bind(c)
+ character(len=:, kind=c_char), pointer :: x(:) ! OK - pointer but not contiguous
+end
+
+subroutine f4 (x) bind(c)
+ character(len=*, kind=c_char), contiguous :: x(:) ! OK - contiguous but not a pointer
+end
+
+subroutine f5 (x) bind(c)
+ integer(c_int), pointer :: x(:) ! OK - pointer but not contigous
+end
+
+subroutine f6 (x) bind(c)
+ integer(c_int), contiguous :: x(:) ! OK - contiguous but not a pointer
+end
+
+end
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_23.f90 b/gcc/testsuite/gfortran.dg/bounds_check_23.f90
new file mode 100644
index 0000000..8de90c7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bounds_check_23.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-options "-fcheck=bounds -fdump-tree-original" }
+! PR fortran/98490 - out of bounds in array constructor with implied do loop
+
+program test
+ implicit none
+ call sub('Lorem ipsum')
+contains
+ subroutine sub( text )
+ character(len=*), intent(in) :: text
+ character(len=1), allocatable :: c(:)
+ integer :: i
+ c = [ ( text(i:i), i = 1, len(text) ) ]
+ if (c(1) /= 'L') stop 1
+ end subroutine sub
+end program test
+
+! { dg-final { scan-tree-dump-times "Substring out of bounds:" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy-c.c b/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy-c.c
new file mode 100644
index 0000000..0ed09b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy-c.c
@@ -0,0 +1,54 @@
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct t {
+ float xyz[3];
+ int id;
+};
+
+extern void testit_f_bind_c (CFI_cdesc_t *a, float x, float y, float z);
+extern void testit_c (CFI_cdesc_t *a, float x, float y, float z);
+
+void testit_c (CFI_cdesc_t *a, float x, float y, float z)
+{
+ struct t *tp;
+
+ /* Check that the allocatable dummy is unallocated on entry and do
+ some other sanity checks. */
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->rank)
+ abort ();
+ if (a->base_addr)
+ abort ();
+
+ /* Allocate and initialize the output argument. */
+ CFI_allocate (a, NULL, NULL, 0);
+ if (!a->base_addr)
+ abort ();
+ tp = (struct t *) CFI_address (a, NULL);
+ tp->id = 42;
+ tp->xyz[0] = 0.0;
+ tp->xyz[1] = 0.0;
+ tp->xyz[2] = 0.0;
+
+ /* Now call the Fortran function, which is supposed to automatically
+ deallocate the object we just created above and point the descriptor
+ at a different object. */
+ testit_f_bind_c (a, x, y, z);
+
+ /* Make sure we've got an allocated object, initialized as we
+ expect. */
+ if (!a->base_addr)
+ abort ();
+ tp = (struct t *) CFI_address (a, NULL);
+ if (tp->id != -1)
+ abort ();
+ if (tp->xyz[0] != x || tp->xyz[1] != y || tp->xyz[2] != z)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy.f90 b/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy.f90
new file mode 100644
index 0000000..1d0cf65
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocatable-dummy.f90
@@ -0,0 +1,98 @@
+! PR 101308
+! PR 92621(?)
+! { dg-do run }
+! { dg-additional-sources "allocatable-dummy-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! TS 29113
+! 6.3 Argument association
+!
+! When a Fortran procedure that has an INTENT(OUT) allocatable dummy
+! argument is invoked by a C function, and the actual argument in the C
+! function is the address of a C descriptor that describes an allocated
+! allocatable variable, the variable is deallocated on entry to the
+! Fortran procedure.
+
+! When a C function is invoked from a Fortran procedure via an interface
+! with an INTENT(OUT) allocatable dummy argument, and the actual
+! argument in the reference to the C function is an allocated
+! allocatable variable, the variable is deallocated on invocation
+! (before execution of the C function begins).
+
+module m
+ use iso_c_binding
+
+ type, bind (c) :: t
+ real(C_FLOAT) :: xyz(3)
+ integer(C_INT) :: id
+ end type
+
+ interface
+ subroutine testit_c (a, x, y, z) bind (c)
+ use iso_c_binding
+ import :: t
+ type (t), allocatable, intent(out) :: a
+ real(C_FLOAT), value, intent(in) :: x, y, z
+ end subroutine
+ end interface
+
+ contains
+
+ subroutine testit_f (a, x, y, z)
+ type (t), allocatable, intent(out) :: a
+ real(C_FLOAT), value, intent(in) :: x, y, z
+ if (allocated (a)) stop 201
+ allocate (a)
+ a%id = 69
+ a%xyz(1) = x
+ a%xyz(2) = y
+ a%xyz(3) = z
+ end subroutine
+
+ subroutine testit_f_bind_c (a, x, y, z) bind (c)
+ type (t), allocatable, intent(out) :: a
+ real(C_FLOAT), value, intent(in) :: x, y, z
+ if (allocated (a)) stop 301
+ allocate (a)
+ a%id = -1
+ a%xyz(1) = x
+ a%xyz(2) = y
+ a%xyz(3) = z
+ end subroutine
+
+end module
+
+program test
+ use iso_c_binding
+ use m
+
+ type (t), allocatable :: b
+
+ if (allocated (b)) stop 401
+
+ ! Try the regular Fortran test routine.
+ allocate (b)
+ call testit_f (b, 1.0, 2.0, 3.0)
+ if (.not. allocated (b)) stop 402
+ deallocate (b)
+ if (allocated (b)) stop 403
+
+ ! Try the test routine written in Fortran with C binding.
+ allocate (b)
+ call testit_f_bind_c (b, 1.0, 2.0, 3.0)
+ if (.not. allocated (b)) stop 404
+ deallocate (b)
+ if (allocated (b)) stop 405
+
+ ! Try the test routine written in C. This calls testit_f_bind_c
+ ! before returning, so make sure that's what we've got when returning.
+ allocate (b)
+ call testit_c (b, -1.0, -2.0, -3.0)
+ if (.not. allocated (b)) stop 406
+ if (b%id .ne. -1) stop 407
+ if (b%xyz(1) .ne. -1.0) stop 408
+ if (b%xyz(2) .ne. -2.0) stop 408
+ if (b%xyz(3) .ne. -3.0) stop 408
+ deallocate (b)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocatable-optional-pointer.f90 b/gcc/testsuite/gfortran.dg/c-interop/allocatable-optional-pointer.f90
new file mode 100644
index 0000000..5a785b8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocatable-optional-pointer.f90
@@ -0,0 +1,23 @@
+! { dg-do compile}
+!
+! TS 29113
+! 5.3 ALLOCATABLE, OPTIONAL, and POINTER attributes
+! The ALLOCATABLE, OPTIONAL, and POINTER attributes may be specified
+! for a dummy argument in a procedure interface that has the BIND
+! attribute.
+
+subroutine test (a, b, c)
+ integer, allocatable :: a
+ integer, optional :: b
+ integer, pointer :: c
+
+ interface
+ subroutine ctest (aa, bb, cc) bind (c)
+ integer, allocatable :: aa
+ integer, optional :: bb
+ integer, pointer :: cc
+ end subroutine
+ end interface
+
+ call ctest (a, b, c)
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocate-c.c b/gcc/testsuite/gfortran.dg/c-interop/allocate-c.c
new file mode 100644
index 0000000..ed2d84f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocate-c.c
@@ -0,0 +1,168 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct s {
+ int i;
+ double d;
+};
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ CFI_CDESC_T(3) desc;
+ CFI_cdesc_t *dv = (CFI_cdesc_t *) &desc;
+ CFI_index_t ex[3], lb[3], ub[3];
+ CFI_index_t sm;
+ int i;
+
+ /* Allocate and deallocate a scalar. */
+ sm = sizeof (struct s);
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_allocatable,
+ CFI_type_struct, sm,
+ 0, NULL));
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (dv, NULL, NULL, 69));
+ dump_CFI_cdesc_t (dv);
+ if (dv->base_addr == NULL)
+ abort ();
+ /* The elem_len argument only overrides the initial value in the
+ descriptor for character types. */
+ if (dv->elem_len != sm)
+ abort ();
+ check_CFI_status ("CFI_deallocate",
+ CFI_deallocate (dv));
+ /* The base_addr member of the C descriptor becomes a null pointer. */
+ if (dv->base_addr != NULL)
+ abort ();
+
+ /* Try an array. We are going to test the requirement that:
+ The supplied lower and upper bounds override any current
+ dimension information in the C descriptor.
+ so we'll stuff different values in the descriptor to start with. */
+ ex[0] = 3;
+ ex[1] = 4;
+ ex[2] = 5;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_pointer,
+ CFI_type_double, 0, 3, ex));
+ lb[0] = 1;
+ lb[1] = 2;
+ lb[2] = 3;
+ ub[0] = 10;
+ ub[1] = 5;
+ ub[2] = 10;
+ sm = sizeof (double);
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (dv, lb, ub, 20));
+ dump_CFI_cdesc_t (dv);
+ if (dv->base_addr == NULL)
+ abort ();
+ /* The element sizes passed to both CFI_establish and CFI_allocate should
+ have been ignored in favor of using the constant size of the type. */
+ if (dv->elem_len != sm)
+ abort ();
+
+ /* Check extents and strides; we expect the allocated array to
+ be contiguous so the stride computation should be straightforward
+ no matter what the lower bound is. */
+ for (i = 0; i < 3; i++)
+ {
+ CFI_index_t extent = ub[i] - lb[i] + 1;
+ if (dv->dim[i].lower_bound != lb[i])
+ abort ();
+ if (dv->dim[i].extent != extent)
+ abort ();
+ /* pr93524 */
+ if (dv->dim[i].sm != sm)
+ abort ();
+ sm *= extent;
+ }
+ check_CFI_status ("CFI_deallocate",
+ CFI_deallocate (dv));
+ if (dv->base_addr != NULL)
+ abort ();
+
+ /* Similarly for a character array, except that we expect the
+ elem_len provided to CFI_allocate to prevail. We set the elem_len
+ to the same size as the array element in the previous example, so
+ the bounds and strides should all be the same. */
+ ex[0] = 3;
+ ex[1] = 4;
+ ex[2] = 5;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_allocatable,
+ CFI_type_char, 4, 3, ex));
+ lb[0] = 1;
+ lb[1] = 2;
+ lb[2] = 3;
+ ub[0] = 10;
+ ub[1] = 5;
+ ub[2] = 10;
+ sm = sizeof (double);
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (dv, lb, ub, sm));
+ dump_CFI_cdesc_t (dv);
+ if (dv->base_addr == NULL)
+ abort ();
+ if (dv->elem_len != sm)
+ abort ();
+
+ /* Check extents and strides; we expect the allocated array to
+ be contiguous so the stride computation should be straightforward
+ no matter what the lower bound is. */
+ for (i = 0; i < 3; i++)
+ {
+ CFI_index_t extent = ub[i] - lb[i] + 1;
+ if (dv->dim[i].lower_bound != lb[i])
+ abort ();
+ if (dv->dim[i].extent != extent)
+ abort ();
+ /* pr93524 */
+ if (dv->dim[i].sm != sm)
+ abort ();
+ sm *= extent;
+ }
+ check_CFI_status ("CFI_deallocate",
+ CFI_deallocate (dv));
+ if (dv->base_addr != NULL)
+ abort ();
+
+ /* Signed char is not a Fortran character type. Here we expect it to
+ ignore the elem_len argument and use the size of the type. */
+ ex[0] = 3;
+ ex[1] = 4;
+ ex[2] = 5;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_allocatable,
+ CFI_type_signed_char, 4, 3, ex));
+ lb[0] = 1;
+ lb[1] = 2;
+ lb[2] = 3;
+ ub[0] = 10;
+ ub[1] = 5;
+ ub[2] = 10;
+ sm = sizeof (double);
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (dv, lb, ub, sm));
+ dump_CFI_cdesc_t (dv);
+ if (dv->base_addr == NULL)
+ abort ();
+ if (dv->elem_len != sizeof (signed char))
+ abort ();
+
+ check_CFI_status ("CFI_deallocate",
+ CFI_deallocate (dv));
+ if (dv->base_addr != NULL)
+ abort ();
+
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocate-errors-c.c b/gcc/testsuite/gfortran.dg/c-interop/allocate-errors-c.c
new file mode 100644
index 0000000..3a81049
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocate-errors-c.c
@@ -0,0 +1,109 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct s {
+ int i;
+ double d;
+};
+
+static long buf[5][4][3];
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ int bad = 0;
+ int status;
+ CFI_CDESC_T(3) desc;
+ CFI_cdesc_t *dv = (CFI_cdesc_t *) &desc;
+ CFI_index_t ex[3], lb[3], ub[3];
+ CFI_index_t sm;
+
+ /* On entry, the base_addr member of the C descriptor shall be a null
+ pointer. */
+ sm = sizeof (struct s);
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_allocatable,
+ CFI_type_struct, sm,
+ 0, NULL));
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (dv, NULL, NULL, 69));
+ status = CFI_allocate (dv, NULL, NULL, 42);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_allocate of already-allocated object\n");
+ bad ++;
+ }
+ check_CFI_status ("CFI_deallocate",
+ CFI_deallocate (dv));
+
+ /* The attribute member of the C descriptor shall have a value of
+ CFI_attribute_allocatable or CFI_attribute_pointer. */
+ ex[0] = 3;
+ ex[1] = 4;
+ ex[2] = 5;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_other,
+ CFI_type_long, 0, 3, ex));
+ lb[0] = 1;
+ lb[1] = 2;
+ lb[2] = 3;
+ ub[0] = 10;
+ ub[1] = 5;
+ ub[2] = 10;
+ sm = sizeof (long);
+ status = CFI_allocate (dv, lb, ub, 20);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_allocate of CFI_attribute_other object\n");
+ bad ++;
+ }
+
+ /* dv shall be the address of a C descriptor describing the object.
+ It shall have been allocated using the same mechanism as the
+ Fortran ALLOCATE statement. */
+ ex[0] = 3;
+ ex[1] = 4;
+ ex[2] = 5;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, NULL, CFI_attribute_pointer,
+ CFI_type_long, 0, 3, ex));
+ status = CFI_deallocate (dv);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_deallocate with null pointer\n");
+ bad ++;
+ }
+
+ /* This variant is disabled. In theory it should be possible for
+ the memory allocator to easily check for pointers outside the
+ heap region, but libfortran just calls free() which has no provision
+ for returning an error, and there is no other standard C interface
+ to check the validity of a pointer in the C heap either. */
+#if 0
+ check_CFI_status ("CFI_establish",
+ CFI_establish (dv, buf, CFI_attribute_pointer,
+ CFI_type_long, 0, 3, ex));
+ status = CFI_deallocate (dv);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_deallocate with non-allocated pointer\n");
+ bad ++;
+ }
+#endif
+
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocate-errors.f90 b/gcc/testsuite/gfortran.dg/c-interop/allocate-errors.f90
new file mode 100644
index 0000000..a58d05a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocate-errors.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! { dg-additional-sources "allocate-errors-c.c dump-descriptors.c" }
+! { dg-additional-options "-Wno-error -fcheck=all" }
+! { dg-warning "command-line option '-fcheck=all' is valid for Fortran but not for C" "" { target *-*-* } 0 }
+!
+! This program tests that the CFI_allocate and CFI_deallocate functions
+! properly detect invalid arguments. All the interesting things happen
+! in the corresponding C code.
+!
+! The situation here seems to be that while TS29113 defines error codes for
+! these functions, it doesn't actually require the implementation to detect
+! those errors by saying the arguments "shall be" such-and-such, e.g. it is
+! undefined behavior if they are not. In gfortran you can enable some
+! run-time checking by building with -fcheck=all.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/allocate.f90 b/gcc/testsuite/gfortran.dg/c-interop/allocate.f90
new file mode 100644
index 0000000..6878f04
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/allocate.f90
@@ -0,0 +1,19 @@
+! { dg-do run }
+! { dg-additional-sources "allocate-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests the CFI_allocate and CFI_deallocate functions.
+! All the interesting things happen in the corresponding C code.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-1.f90
new file mode 100644
index 0000000..ee06cc7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-1.f90
@@ -0,0 +1,31 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. If the actual argument has rank zero, the dummy argument has
+! rank zero; the shape is a zero-sized array and the LBOUND and UBOUND
+! intrinsic functions, with no DIM argument, return zero-sized
+! arrays. [...]
+
+program test
+
+ call testit (42)
+
+contains
+
+ subroutine testit (x0)
+ integer :: x0(..)
+
+ ! expect to have rank 0
+ if (rank (x0) .ne. 0) stop 101
+
+ ! expect shape to be a zero-sized array
+ if (size (shape (x0)) .ne. 0) stop 102
+
+ ! expect lbound and ubound functions to return zero-sized arrays
+ if (size (lbound (x0)) .ne. 0) stop 103
+ if (size (ubound (x0)) .ne. 0) stop 104
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-2.f90
new file mode 100644
index 0000000..4beeb81
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-2.f90
@@ -0,0 +1,48 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer :: a(3, 4, 5)
+ integer :: b(-3:3, 0:4, 2:5, 10:20)
+
+ call testit (a, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (b, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u)
+ integer :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. 1)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u - l + 1)) stop 107
+ if (any (ubound (x) .ne. s)) stop 108
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-3.f90
new file mode 100644
index 0000000..c4b1010
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-3.f90
@@ -0,0 +1,51 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer, target :: a(3, 4, 5)
+ integer, target :: b(-3:3, 0:4, 2:5, 10:20)
+ integer, pointer :: aa(:,:,:)
+ integer, pointer :: bb(:,:,:,:)
+ aa => a
+ bb => b
+
+ call testit (aa, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (bb, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u)
+ integer, pointer :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. l)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u)) stop 107
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-4.f90
new file mode 100644
index 0000000..9c92718
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-4.f90
@@ -0,0 +1,50 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer, allocatable :: a(:,:,:)
+ integer, allocatable :: b(:,:,:,:)
+
+ allocate (a(3, 4, 5))
+ allocate (b(-3:3, 0:4, 2:5, 10:20))
+
+ call testit (a, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (b, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u)
+ integer, allocatable :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. l)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u)) stop 107
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-5.f90
new file mode 100644
index 0000000..fd87225
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-5.f90
@@ -0,0 +1,31 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. If the actual argument has rank zero, the dummy argument has
+! rank zero; the shape is a zero-sized array and the LBOUND and UBOUND
+! intrinsic functions, with no DIM argument, return zero-sized
+! arrays. [...]
+
+program test
+
+ call testit (42)
+
+contains
+
+ subroutine testit (x0) bind (c)
+ integer :: x0(..)
+
+ ! expect to have rank 0
+ if (rank (x0) .ne. 0) stop 101
+
+ ! expect shape to be a zero-sized array
+ if (size (shape (x0)) .ne. 0) stop 102
+
+ ! expect lbound and ubound functions to return zero-sized arrays
+ if (size (lbound (x0)) .ne. 0) stop 103
+ if (size (ubound (x0)) .ne. 0) stop 104
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-6.f90
new file mode 100644
index 0000000..a65d436
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-6.f90
@@ -0,0 +1,48 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer :: a(3, 4, 5)
+ integer :: b(-3:3, 0:4, 2:5, 10:20)
+
+ call testit (a, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (b, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u) bind (c)
+ integer :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. 1)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u - l + 1)) stop 107
+ if (any (ubound (x) .ne. s)) stop 108
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-7.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-7.f90
new file mode 100644
index 0000000..819ee4f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-7.f90
@@ -0,0 +1,51 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer, target :: a(3, 4, 5)
+ integer, target :: b(-3:3, 0:4, 2:5, 10:20)
+ integer, pointer :: aa(:,:,:)
+ integer, pointer :: bb(:,:,:,:)
+ aa => a
+ bb => b
+
+ call testit (aa, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (bb, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u) bind (c)
+ integer, pointer :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. l)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u)) stop 107
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-8.f90 b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-8.f90
new file mode 100644
index 0000000..d94a71b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/argument-association-assumed-rank-8.f90
@@ -0,0 +1,50 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.3 Argument association
+! An assumed-rank dummy argument may correspond to an actual argument of
+! any rank. [...] If the actual argument has rank greater than zero, the
+! rank and extents of the dummy argument are assumed from the actual
+! argument, including the lack of a final extent in the case of an
+! assumed-size array. If the actual argument is an array and the dummy
+! argument is allocatable or a pointer, the bounds of the dummy argument
+! are assumed from the actual argument.
+
+program test
+
+ integer, allocatable :: a(:,:,:)
+ integer, allocatable :: b(:,:,:,:)
+
+ allocate (a(3, 4, 5))
+ allocate (b(-3:3, 0:4, 2:5, 10:20))
+
+ call testit (a, rank(a), shape(a), lbound(a), ubound(a))
+ call testit (b, rank(b), shape(b), lbound(b), ubound(b))
+
+contains
+
+ subroutine testit (x, r, s, l, u) bind (c)
+ integer, allocatable :: x(..)
+ integer :: r
+ integer :: s(r)
+ integer :: l(r)
+ integer :: u(r)
+
+ ! expect rank to match
+ if (rank (x) .ne. r) stop 101
+
+ ! expect shape to match
+ if (size (shape (x)) .ne. r) stop 102
+ if (any (shape (x) .ne. s)) stop 103
+
+ ! expect lbound and ubound functions to return rank-sized arrays.
+ ! for non-pointer/non-allocatable arrays, bounds are normalized
+ ! to be 1-based.
+ if (size (lbound (x)) .ne. r) stop 104
+ if (any (lbound (x) .ne. l)) stop 105
+
+ if (size (ubound (x)) .ne. r) stop 106
+ if (any (ubound (x) .ne. u)) stop 107
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90 b/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90
new file mode 100644
index 0000000..24bdf2b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/assumed-type-dummy.f90
@@ -0,0 +1,84 @@
+! PR 101319
+! { dg-do compile }
+!
+! TS 29113
+! 6.3 Argument association
+!
+! An assumed-type dummy argument shall not correspond to an actual argument
+! that is of a derived type that has type parameters, type-bound procedures,
+! or final subroutines.
+!
+! In the 2018 Fortran standard, this requirement appears as:
+!
+! 15.5.2.4 Ordinary dummy variables
+!
+! If the actual argument is of a derived type that has type parameters,
+! type-bound procedures, or final subroutines, the dummy argument shall
+! not be assumed-type.
+!
+! This file contains code that is expected to produce errors.
+
+module m
+
+ ! basic derived type
+ type :: t1
+ real*8 :: xyz (3)
+ end type
+
+ ! derived type with type parameters
+ type t2 (k, l)
+ integer, kind :: k
+ integer, len :: l
+ real(k) :: a(l)
+ end type
+
+ ! derived type with a type-bound procedure
+ type :: t3
+ integer :: xyz(3)
+ contains
+ procedure, pass :: frob => frob_t3
+ end type
+
+ ! derived type with a final subroutine
+ type :: t4
+ integer :: xyz(3)
+ contains
+ final :: final_t4
+ end type
+
+contains
+
+ ! implementation of the type-bound procedure for t3 above
+ subroutine frob_t3 (a)
+ class (t3) :: a
+ a%xyz = 0
+ end subroutine
+
+ ! implementation of the final subroutine for t4 above
+ subroutine final_t4 (a)
+ type (t4) :: a
+ a%xyz = 0
+ end subroutine
+
+ ! useless subroutine with an assumed-type dummy.
+ subroutine s1 (a)
+ type(*) :: a
+ end subroutine
+
+ ! test procedure
+ subroutine testit
+ type(t1) :: a1
+ type(t2(8,20)) :: a2
+ type(t3) :: a3
+ type(t4) :: a4
+
+ call s1 (a1) ! OK
+ call s1 (a2) ! { dg-error "assumed-type dummy" }
+ call s1 (a3) ! { dg-error "assumed-type dummy" }
+ call s1 (a4) ! { dg-error "assumed-type dummy" }
+ end subroutine
+
+end module
+
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c-interop.exp b/gcc/testsuite/gfortran.dg/c-interop/c-interop.exp
new file mode 100644
index 0000000..3bc2a9f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c-interop.exp
@@ -0,0 +1,57 @@
+# Copyright (C) 2005-2021 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
+
+# Initialize `dg'.
+dg-init
+
+global gfortran_test_path
+global gfortran_aux_module_flags
+set gfortran_test_path $srcdir/$subdir
+set gfortran_aux_module_flags "-Werror -std=f2018"
+proc dg-compile-aux-modules { args } {
+ global gfortran_test_path
+ global gfortran_aux_module_flags
+ if { [llength $args] != 2 } {
+ error "dg-compile-aux-modules: needs one argument"
+ return
+ }
+
+ set level [info level]
+ if { [info procs dg-save-unknown] != [list] } {
+ rename dg-save-unknown dg-save-unknown-level-$level
+ }
+
+ dg-test $gfortran_test_path/[lindex $args 1] "" $gfortran_aux_module_flags
+ # cleanup-modules is intentionally not invoked here.
+
+ if { [info procs dg-save-unknown-level-$level] != [list] } {
+ rename dg-save-unknown-level-$level dg-save-unknown
+ }
+}
+
+# Main loop.
+gfortran-dg-runtest [lsort \
+ [find $srcdir/$subdir *.\[fF\]{,90,95,03,08} ] ] "" "-Werror"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c1255-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c1255-1.f90
new file mode 100644
index 0000000..fb91107
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c1255-1.f90
@@ -0,0 +1,83 @@
+! PR92482
+! { dg-do compile }
+!
+! TS 29113
+! C1255 (R1230) If proc-language-binding-spec is specified for a procedure,
+! each dummy argument shall be an interoperable procedure (15.3.7)
+! or a variable that is interoperable (15.3.5, 15.3.6), assumed shape,
+! assumed rank, assumed type, of assumed character length, or has the
+! ALLOCATABLE or POINTER attribute. If proc-language-binding-spec is
+! specified for a function, the function result shall be an interoperable
+! scalar variable.
+
+module m
+
+ interface
+
+ ! dummy is interoperable procedure
+ subroutine s1 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ interface
+ function x (a, b) bind (c)
+ use ISO_C_BINDING
+ integer(C_INT) :: a, b
+ integer(C_INT) :: x
+ end function
+ end interface
+ end subroutine
+
+ ! dummy is interoperable variable
+ subroutine s2 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x
+ end subroutine
+
+ ! dummy is assumed-shape array variable
+ subroutine s3 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x(:)
+ end subroutine
+
+ ! dummy is an assumed-rank array variable
+ subroutine s4 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x(..)
+ end subroutine
+
+ ! dummy is assumed-type variable
+ subroutine s5 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ type(*) :: x
+ end subroutine
+
+ ! dummy is assumed length character variable
+ subroutine s6 (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ character(len=*) :: x
+ end subroutine
+
+ ! dummy has allocatable or pointer attribute
+ subroutine s7 (x, y) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT), allocatable :: x
+ integer(C_INT), pointer :: y
+ end subroutine
+
+ ! function result shall be an interoperable scalar variable
+ function f (x) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x
+ integer(C_INT) :: f
+ end function
+
+ end interface
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90
new file mode 100644
index 0000000..0e5505a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c1255-2.f90
@@ -0,0 +1,106 @@
+! { dg-do compile }
+!
+! TS 29113
+! C1255 (R1230) If proc-language-binding-spec is specified for a procedure,
+! each dummy argument shall be an interoperable procedure (15.3.7)
+! or a variable that is interoperable (15.3.5, 15.3.6), assumed shape,
+! assumed rank, assumed type, of assumed character length, or has the
+! ALLOCATABLE or POINTER attribute. If proc-language-binding-spec is
+! specified for a function, the function result shall be an interoperable
+! scalar variable.
+!
+! This file contains code that is expected to produce errors.
+
+
+module m1
+ ! type to use for examples below
+ type t
+ integer :: foo
+ real :: bar
+ end type
+end module
+
+module m2
+
+ interface
+
+ ! dummy is a procedure that is not interoperable
+ subroutine s1 (x) bind (c)
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ interface
+ function x (a, b) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ integer(C_INT) :: a
+ class(t) :: b !
+ integer(C_INT) :: x
+ end function
+ end interface
+ end subroutine
+
+ ! dummy is of a type that is not interoperable
+ subroutine s2 (x) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ class(t) :: x
+ end subroutine
+
+ ! dummy is an array that is not of interoperable type and not
+ ! assumed-shape or assumed-rank
+ subroutine s3 (x) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ class(t) :: x(3, 3)
+ end subroutine
+
+ subroutine s4 (n, x) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ integer(C_INT) :: n
+ class(t) :: x(n)
+ end subroutine
+
+ ! This fails with a bogus error even without C binding.
+ subroutine s5 (x) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ class(t) :: x(*) ! { dg-bogus "not yet been implemented" "pr46991" }
+ ! { dg-bogus "has no IMPLICIT type" "pr46991" { target "*-*-*" } 68 }
+ end subroutine
+
+ subroutine s5a (x)
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ class(t) :: x(*) ! { dg-bogus "not yet been implemented" "pr46991" }
+ ! { dg-bogus "has no IMPLICIT type" "pr46991" { target "*-*-*" } 76 }
+ end subroutine
+
+ ! function result is not a scalar
+ function f (x) bind (c) ! { dg-error "not C interoperable" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ integer(C_INT) :: x
+ type(t) :: f
+ end function
+
+ ! function result is a type that is not interoperable
+ function g (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use ISO_C_BINDING
+ use m1
+ implicit none
+ integer(C_INT) :: x
+ integer(C_INT), allocatable :: g
+ end function
+
+ end interface
+
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c1255a.f90 b/gcc/testsuite/gfortran.dg/c-interop/c1255a.f90
new file mode 100644
index 0000000..470ccac
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c1255a.f90
@@ -0,0 +1,40 @@
+! { dg-do compile }
+!
+! TS 29113
+! C1255a (R1230) A dummy argument of a procedure that has a
+! proc-language-binding-spec shall not have both the OPTIONAL and
+! VALUE attributes.
+!
+! This file contains code that is expected to produce errors.
+
+module m
+
+ interface
+
+ ! This one is OK.
+ subroutine s1 (x, y) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x
+ integer(C_INT), optional :: y
+ end subroutine
+
+ ! This one is OK too.
+ subroutine s2 (x, y) bind (c)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x
+ integer(C_INT), value :: y
+ end subroutine
+
+ ! This one is bad.
+ subroutine s3 (x, y) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT) :: x
+ integer(C_INT), optional, value :: y
+ end subroutine
+
+ end interface
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407a-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407a-1.f90
new file mode 100644
index 0000000..f239a1e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407a-1.f90
@@ -0,0 +1,55 @@
+! { dg-do compile}
+!
+! TS 29113
+! C407a An assumed-type entity shall be a dummy variable that does not
+! have the ALLOCATABLE, CODIMENSION, INTENT(OUT), POINTER, or VALUE
+! attribute and is not an explicit-shape array.
+!
+! This test file contains tests that are expected to all pass.
+
+! Check basic usage with no attributes.
+
+module m
+ interface
+ subroutine g (a, b)
+ implicit none
+ type(*) :: a
+ integer :: b
+ end subroutine
+ end interface
+end module
+
+subroutine s0 (x)
+ use m
+ implicit none
+ type(*) :: x
+
+ call g (x, 1)
+end subroutine
+
+! Check that other attributes that can normally apply to dummy variables
+! are allowed.
+
+subroutine s1 (a, b, c, d, e, f, g, h)
+ implicit none
+ type(*), asynchronous :: a
+ type(*), contiguous :: b(:,:)
+ type(*), dimension (:) :: c
+ type(*), intent(in) :: d
+ type(*), intent(inout) :: e
+ type(*), optional :: f
+ type(*), target :: g
+ type(*), volatile :: h
+
+end subroutine
+
+! Check that non-explicit-shape arrays are allowed.
+
+subroutine s2 (a, b, c)
+ implicit none
+ type(*) :: a(:) ! assumed-shape
+ type(*) :: b(*) ! assumed-size
+ type(*) :: c(..) ! assumed-rank
+
+end subroutine
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407a-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407a-2.f90
new file mode 100644
index 0000000..9d8824d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407a-2.f90
@@ -0,0 +1,88 @@
+! { dg-do compile }
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C407a An assumed-type entity shall be a dummy variable that does not
+! have the ALLOCATABLE, CODIMENSION, INTENT(OUT), POINTER, or VALUE
+! attribute and is not an explicit-shape array.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+! Check that diagnostics are issued when type(*) is used to declare things
+! that are not dummy variables.
+
+subroutine s0 (a)
+ implicit none
+ integer :: a
+
+ integer :: goodlocal
+ type(*) :: badlocal ! { dg-error "Assumed.type" }
+
+ integer :: goodcommon
+ type(*) :: badcommon ! { dg-error "Assumed.type" }
+ common /frob/ goodcommon, badcommon
+
+ integer :: goodstatic
+ type(*) :: badstatic ! { dg-error "Assumed.type" }
+ save goodstatic, badstatic
+
+ block
+ integer :: goodlocal2
+ type(*) :: badlocal2 ! { dg-error "Assumed.type" }
+ end block
+
+end subroutine
+
+module m
+ integer :: goodmodvar
+ type(*) :: badmodvar ! { dg-error "Assumed.type" }
+ save goodmodvar, badmodvar
+
+ type :: t
+ integer :: goodcomponent
+ type(*) :: badcomponent ! { dg-error "Assumed.type" }
+ end type
+end module
+
+! Check that diagnostics are issued when type(*) is used in combination
+! with the forbidden attributes.
+
+subroutine s1 (a) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*), allocatable :: a
+end subroutine
+
+subroutine s2 (b) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*), codimension[*] :: b(:,:)
+end subroutine
+
+subroutine s3 (c) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*), intent(out) :: c
+end subroutine
+
+subroutine s4 (d) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*), pointer :: d
+end subroutine
+
+subroutine s5 (e) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*), value :: e
+end subroutine
+
+! Check that diagnostics are issued when type(*) is used to declare
+! a dummy variable that is an explicit-shape array.
+
+subroutine s6 (n, f) ! { dg-error "Assumed.type" }
+ implicit none
+ integer n
+ type(*) :: f(n,n)
+end subroutine
+
+subroutine s7 (g) ! { dg-error "Assumed.type" }
+ implicit none
+ type(*) :: g(10)
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407b-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407b-1.f90
new file mode 100644
index 0000000..c9fc2b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407b-1.f90
@@ -0,0 +1,107 @@
+! { dg-do compile}
+!
+! TS 29113
+! C407b An assumed-type variable name shall not appear in a designator
+! or expression except as an actual argument corresponding to a dummy
+! argument that is assumed-type, or as the first argument to any of
+! the intrinsic and intrinsic module functions IS_CONTIGUOUS, LBOUND,
+! PRESENT, RANK, SHAPE, SIZE, UBOUND, and C_LOC.
+!
+! This test file contains tests that are expected to all pass.
+
+! Check that passing an assumed-type variable as an actual argument
+! corresponding to an assumed-type dummy works.
+
+module m
+ interface
+ subroutine g (a, b)
+ implicit none
+ type(*) :: a
+ integer :: b
+ end subroutine
+ end interface
+end module
+
+subroutine s0 (x)
+ use m
+ implicit none
+ type(*) :: x
+
+ call g (x, 1)
+end subroutine
+
+! Check that calls to the permitted intrinsic functions work.
+
+function test_is_contiguous (a)
+ implicit none
+ type(*) :: a(*)
+ logical :: test_is_contiguous
+
+ test_is_contiguous = is_contiguous (a)
+end function
+
+function test_lbound (a)
+ implicit none
+ type(*) :: a(:)
+ integer :: test_lbound
+
+ test_lbound = lbound (a, 1)
+end function
+
+function test_present (a)
+ implicit none
+ type(*), optional :: a(*)
+ logical :: test_present
+
+ test_present = present (a)
+end function
+
+function test_rank (a)
+ implicit none
+ type(*) :: a(*)
+ integer :: test_rank
+
+ test_rank = rank (a)
+end function
+
+function test_shape (a)
+ implicit none
+ type(*) :: a(:) ! assumed-shape array so shape intrinsic works
+ integer :: test_shape
+
+ integer :: temp, i
+ integer, dimension (rank (a)) :: ashape
+
+ temp = 1
+ ashape = shape (a)
+ do i = 1, rank (a)
+ temp = temp * ashape (i)
+ end do
+ test_shape = temp
+end function
+
+function test_size (a)
+ implicit none
+ type(*) :: a(:)
+ integer :: test_size
+
+ test_size = size (a)
+end function
+
+function test_ubound (a)
+ implicit none
+ type(*) :: a(:)
+ integer :: test_ubound
+
+ test_ubound = ubound (a, 1)
+end function
+
+function test_c_loc (a)
+ use iso_c_binding
+ implicit none
+ type(*), target :: a(*)
+ type(c_ptr) :: test_c_loc
+
+ test_c_loc = c_loc (a)
+end function
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90
new file mode 100644
index 0000000..3d3cd63
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90
@@ -0,0 +1,150 @@
+! PR 101337
+! { dg-do compile}
+!
+! TS 29113
+! C407b An assumed-type variable name shall not appear in a designator
+! or expression except as an actual argument corresponding to a dummy
+! argument that is assumed-type, or as the first argument to any of
+! the intrinsic and intrinsic module functions IS_CONTIGUOUS, LBOUND,
+! PRESENT, RANK, SHAPE, SIZE, UBOUND, and C_LOC.
+!
+! This file contains tests that are expected to give diagnostics.
+
+! Check that passing an assumed-type variable as an actual argument
+! corresponding to a non-assumed-type dummy gives a diagnostic.
+
+module m
+ interface
+ subroutine f (a, b)
+ implicit none
+ integer :: a
+ integer :: b
+ end subroutine
+ subroutine g (a, b)
+ implicit none
+ type(*) :: a
+ integer :: b
+ end subroutine
+ subroutine h (a, b)
+ implicit none
+ type(*) :: a(*)
+ integer :: b
+ end subroutine
+ end interface
+end module
+
+subroutine s0 (x)
+ use m
+ implicit none
+ type(*) :: x
+
+ call g (x, 1)
+ call f (x, 1) ! { dg-error "Type mismatch" }
+ call h (x, 1) ! { dg-error "Rank mismatch" }
+end subroutine
+
+! Check that you can't use an assumed-type array variable in an array
+! element or section designator.
+
+subroutine s1 (x, y)
+ use m
+ implicit none
+ integer :: x(*)
+ type(*) :: y(*)
+
+ call f (x(1), 1)
+ call g (y(1), 1) ! { dg-error "Assumed.type" }
+ call h (y, 1) ! ok
+ call h (y(1:3:1), 1) ! { dg-error "Assumed.type" }
+end subroutine
+
+! Check that you can't use an assumed-type array variable in other
+! expressions. This is clearly not exhaustive since few operations
+! are even plausible from a type perspective.
+
+subroutine s2 (x, y)
+ implicit none
+ type(*) :: x, y
+ integer :: i
+
+ ! select type
+ select type (x) ! { dg-error "Assumed.type|Selector shall be polymorphic" }
+ type is (integer)
+ i = 0
+ type is (real)
+ i = 1
+ class default
+ i = -1
+ end select
+
+ ! relational operations
+ if (x & ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .eq. y) then ! { dg-error "Assumed.type" }
+ return
+ end if
+ if (.not. (x & ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .ne. y)) then ! { dg-error "Assumed.type" }
+ return
+ end if
+ if (.not. x) then ! { dg-error "Assumed.type" }
+ return
+ end if
+
+ ! assignment
+ x & ! { dg-error "Assumed.type" }
+ = y ! { dg-error "Assumed.type" }
+ i = x ! { dg-error "Assumed.type" }
+ y = i ! { dg-error "Assumed.type" }
+
+ ! arithmetic
+ i = x + 1 ! { dg-error "Assumed.type" }
+ i = -y ! { dg-error "Assumed.type" }
+ i = (x & ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ + y) ! { dg-error "Assumed.type" }
+
+ ! computed go to
+ goto (10, 20, 30), x ! { dg-error "Assumed.type|must be a scalar integer" }
+10 continue
+20 continue
+30 continue
+
+ ! do loops
+ do i = 1, x ! { dg-error "Assumed.type" }
+ continue
+ end do
+ do x = 1, i ! { dg-error "Assumed.type" }
+ continue
+ end do
+
+end subroutine
+
+! Check that calls to disallowed intrinsic functions produce a diagnostic.
+! Again, this isn't exhaustive, there are just too many intrinsics and
+! hardly any of them are plausible.
+
+subroutine s3 (x, y)
+ implicit none
+ type(*) :: x, y
+ integer :: i
+
+ i = bit_size (x) ! { dg-error "Assumed.type" }
+ i = exponent (x) ! { dg-error "Assumed.type" }
+
+ if (extends_type_of (x, & ! { dg-error "Assumed.type" }
+ y)) then ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ return
+ end if
+
+ if (same_type_as (x, & ! { dg-error "Assumed.type" }
+ y)) then ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ return
+ end if
+
+ i = storage_size (x) ! { dg-error "Assumed.type" }
+
+ i = iand (x, & ! { dg-error "Assumed.type" }
+ y) ! { dg-error "Assumed.type" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+
+ i = kind (x) ! { dg-error "Assumed.type" }
+
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90
new file mode 100644
index 0000000..699f75f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c407c-1.f90
@@ -0,0 +1,63 @@
+! PR101333
+! { dg-do compile}
+!
+! TS 29113
+! C407c An assumed-type actual argument that corresponds to an
+! assumed-rank dummy argument shall be assumed-shape or assumed-rank.
+!
+! This constraint is renumbered C711 in the 2018 Fortran standard.
+
+module m
+ interface
+ subroutine g (a, b)
+ implicit none
+ type(*) :: a(..)
+ integer :: b
+ end subroutine
+ end interface
+end module
+
+! Check that assumed-shape works.
+
+subroutine s0 (x)
+ use m
+ implicit none
+ type(*) :: x(:)
+
+ call g (x, 1)
+end subroutine
+
+! Check that assumed-rank works.
+
+subroutine s1 (x)
+ use m
+ implicit none
+ type(*) :: x(..)
+
+ call g (x, 1)
+end subroutine
+
+! Check that assumed-size gives an error.
+
+subroutine s2 (x)
+ use m
+ implicit none
+ type(*) :: x(*)
+
+ call g (x, 1) ! { dg-error "Assumed-type actual argument at .1. corresponding to assumed-rank dummy argument 'a' must be assumed-shape or assumed-rank" }
+end subroutine
+
+! Check that a scalar gives an error.
+subroutine s3 (x)
+ use m
+ implicit none
+ type(*) :: x
+
+ call g (x, 1) ! { dg-error "Assumed.type" }
+end subroutine
+
+! Explicit-shape assumed-type actual arguments are forbidden implicitly
+! by c407a (C709 in the 2018 standard). They're not allowed as dummy
+! arguments, and assumed-type entities can only be declared as dummy
+! arguments, so there is no other way to construct one to pass as an
+! actual argument.
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c516.f90 b/gcc/testsuite/gfortran.dg/c-interop/c516.f90
new file mode 100644
index 0000000..d6a65af
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c516.f90
@@ -0,0 +1,109 @@
+! PR 101320
+! { dg-do compile }
+!
+! TS 29113
+! C516 The ALLOCATABLE or POINTER attribute shall not be specified for
+! a default-initialized dummy argument of a procedure that has a
+! proc-language-binding-spec.
+!
+! This file contains code that is expected to produce errors.
+
+module m1
+
+ type, bind(c) :: t1
+ integer :: a
+ integer :: b
+ end type
+
+
+ type, bind(c) :: t2
+ integer :: a = 0
+ integer :: b = -1
+ end type
+
+end module
+
+module m2
+
+ interface
+
+ ! First test versions with optional attributes on the argument.
+ ! TS29113 removed the constraint disallowing optional arguments
+ ! that previously used to be in C516.
+
+ ! good, no default initialization, no pointer/allocatable attribute
+ subroutine s1a (x) bind (c)
+ use m1
+ type(t1), optional :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s1b (x) bind (c)
+ use m1
+ type(t1), allocatable, optional :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s1c (x) bind (c)
+ use m1
+ type(t1), pointer, optional :: x
+ end subroutine
+
+ ! good, default initialization but no pointer/allocatable attribute
+ subroutine s2a (x) bind (c)
+ use m1
+ type(t2), optional :: x
+ end subroutine
+
+ ! bad, default initialization + allocatable
+ subroutine s2b (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), allocatable, optional :: x
+ end subroutine
+
+ ! bad, default initialization + pointer
+ subroutine s2c (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), pointer, optional :: x
+ end subroutine
+
+ ! Now do all the same tests without the optional attribute.
+
+ ! good, no default initialization, no pointer/allocatable attribute
+ subroutine s3a (x) bind (c)
+ use m1
+ type(t1) :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s3b (x) bind (c)
+ use m1
+ type(t1), allocatable :: x
+ end subroutine
+
+ ! good, no default initialization
+ subroutine s3c (x) bind (c)
+ use m1
+ type(t1), pointer :: x
+ end subroutine
+
+ ! good, default initialization but no pointer/allocatable attribute
+ subroutine s4a (x) bind (c)
+ use m1
+ type(t2) :: x
+ end subroutine
+
+ ! bad, default initialization + allocatable
+ subroutine s4b (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), allocatable :: x
+ end subroutine
+
+ ! bad, default initialization + pointer
+ subroutine s4c (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use m1
+ type(t2), pointer :: x
+ end subroutine
+
+ end interface
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c524a.f90 b/gcc/testsuite/gfortran.dg/c-interop/c524a.f90
new file mode 100644
index 0000000..34abb72
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c524a.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C524a A coarray shall not be a dummy argument of a procedure that has
+! a proc-language-binding-spec.
+!
+! This file contains code that is expected to produce errors.
+
+module m
+
+ interface
+
+ ! No C binding, this should be OK.
+ subroutine s1 (x)
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT), codimension[*] :: x(:,:)
+ end subroutine
+
+ ! This one is bad.
+ subroutine s2 (x) bind (c) ! { dg-error "BIND\\(C\\)" }
+ use ISO_C_BINDING
+ implicit none
+ integer(C_INT), codimension[*] :: x(:,:)
+ end subroutine
+
+ end interface
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535a-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535a-1.f90
new file mode 100644
index 0000000..5550cf2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535a-1.f90
@@ -0,0 +1,65 @@
+! { dg-do compile}
+!
+! TS 29113
+! C535a An assumed-rank entity shall be a dummy variable that does not
+! have the CODIMENSION or VALUE attribute.
+! An assumed-rank object may have the CONTIGUOUS attribute.
+!
+! This test file contains tests that are expected to all pass.
+
+! Check basic usage with no attributes.
+
+module m
+ type :: t
+ integer :: i
+ real :: f
+ end type
+end module
+
+subroutine s0 (a, b, c, d)
+ use m
+ implicit none
+ integer :: a(..)
+ real :: b(..)
+ type(t) :: c(..)
+ type(*) :: d(..)
+end subroutine
+
+! Likewise with dimension attribute.
+
+subroutine s1 (a, b, c, d)
+ use m
+ implicit none
+ integer, dimension(..) :: a
+ real, dimension(..) :: b
+ type(t), dimension(..) :: c
+ type(*), dimension(..) :: d
+end subroutine
+
+! Likewise with dimension statement.
+
+subroutine s2 (a, b, c, d)
+ use m
+ implicit none
+ integer :: a
+ real :: b
+ type(t) :: c
+ type(*) :: d
+ dimension a(..), b(..), c(..), d(..)
+end subroutine
+
+! Test that various other attributes are accepted.
+
+subroutine s3 (a, b, c, d, e, f, g, h, i, j)
+ implicit none
+ integer, allocatable :: a(..)
+ integer, asynchronous :: b(..)
+ integer, contiguous :: c(..)
+ integer, intent(in) :: d(..)
+ integer, intent(out) :: e(..)
+ integer, intent(inout) :: f(..)
+ integer, optional :: g(..)
+ integer, pointer :: h(..)
+ integer, target :: i(..)
+ integer, volatile :: j(..)
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535a-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535a-2.f90
new file mode 100644
index 0000000..026be4a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535a-2.f90
@@ -0,0 +1,78 @@
+! { dg-do compile}
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C535a An assumed-rank entity shall be a dummy variable that does not
+! have the CODIMENSION or VALUE attribute.
+! An assumed-rank object may have the CONTIGUOUS attribute.
+!
+
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+! Check that diagnostics are issued when dimension(..) is used to declare
+! things that are not dummy variables.
+
+subroutine s0 (a)
+ implicit none
+ integer :: a
+
+ integer :: goodlocal
+ integer :: badlocal1(..) ! { dg-error "Assumed.rank" }
+ integer, dimension(..) :: badlocal2 ! { dg-error "Assumed.rank" }
+ integer :: badlocal3 ! { dg-error "Assumed.rank" }
+ dimension badlocal3(..)
+
+ integer :: goodcommon
+ integer :: badcommon1(..) ! { dg-error "Assumed.rank" }
+ integer, dimension(..) :: badcommon2 ! { dg-error "Assumed.rank" }
+ integer :: badcommon3 ! { dg-error "Assumed.rank" }
+ dimension badcommon3(..)
+ common /frob/ goodcommon, badcommon1, badcommon2, badcommon3
+
+ integer :: goodstatic
+ integer :: badstatic1(..) ! { dg-error "Assumed.rank" }
+ integer, dimension(..) :: badstatic2 ! { dg-error "Assumed.rank" }
+ integer :: badstatic3 ! { dg-error "Assumed.rank" }
+ dimension badstatic3(..)
+ save goodstatic, badstatic1, badstatic2, badstatic3
+
+ block
+ integer :: goodblocklocal
+ integer :: badblocklocal1(..) ! { dg-error "Assumed.rank" }
+ integer, dimension(..) :: badblocklocal2 ! { dg-error "Assumed.rank" }
+ integer :: badblocklocal3 ! { dg-error "Assumed.rank" }
+ dimension badblocklocal3(..)
+ end block
+
+end subroutine
+
+module m
+ integer :: goodmodvar
+ integer :: badmodvar1(..) ! { dg-error "Assumed.rank" }
+ integer, dimension(..) :: badmodvar2 ! { dg-error "Assumed.rank" }
+ integer :: badmodvar3 ! { dg-error "Assumed.rank" }
+ dimension badmodvar3(..)
+
+ save goodmodvar, badmodvar1, badmodvar2, badmodvar3
+
+ type :: t
+ integer :: goodcomponent
+ integer :: badcomponent1(..) ! { dg-error "must have an explicit shape" }
+ integer, dimension(..) :: badcomponent2 ! { dg-error "must have an explicit shape" }
+ end type
+end module
+
+! Check that diagnostics are issued when dimension(..) is used in combination
+! with the forbidden attributes.
+
+subroutine s2 (b) ! { dg-error "has no IMPLICIT type" }
+ implicit none
+ integer, codimension[*] :: b(..) ! { dg-error "assumed-rank array" }
+end subroutine
+
+subroutine s5 (e) ! { dg-error "has no IMPLICIT type" }
+ implicit none
+ integer, value :: e(..) ! { dg-error "VALUE attribute conflicts with DIMENSION" }
+end subroutine
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90
new file mode 100644
index 0000000..748e027
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-1.f90
@@ -0,0 +1,331 @@
+! { dg-do compile}
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C535b An assumed-rank variable name shall not appear in a designator
+! or expression except as an actual argument corresponding to a dummy
+! argument that is assumed-rank, the argument of the C_LOC function
+! in the ISO_C_BINDING intrinsic module, or the first argument in a
+! reference to an intrinsic inquiry function.
+!
+! This has been renamed C838 in the Fortran 2018 standard, with C_SIZEOF
+! and SELECT_RANK additionally added.
+!
+! This test file contains tests that are expected to all pass.
+
+! Check that passing an assumed-rank variable as an actual argument
+! corresponding to an assumed-rank dummy works.
+
+module m
+ interface
+ subroutine g (a, b)
+ implicit none
+ real :: a(..)
+ integer :: b
+ end subroutine
+ end interface
+end module
+
+subroutine s0 (x)
+ use m
+ implicit none
+ real :: x(..)
+
+ call g (x, 1)
+end subroutine
+
+! Check that calls to the permitted intrinsic functions work.
+
+function test_c_loc (a)
+ use iso_c_binding
+ implicit none
+ integer, target :: a(..)
+ type(c_ptr) :: test_c_loc
+
+ test_c_loc = c_loc (a)
+end function
+
+function test_allocated (a)
+ implicit none
+ integer, allocatable :: a(..)
+ logical :: test_allocated
+
+ test_allocated = allocated (a)
+end function
+
+! 2-argument forms of the associated intrinsic are tested in c535b-3.f90.
+function test_associated (a)
+ implicit none
+ integer, pointer :: a(..)
+ logical :: test_associated
+
+ test_associated = associated (a)
+end function
+
+function test_bit_size (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_bit_size
+
+ test_bit_size = bit_size (a)
+end function
+
+function test_digits (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_digits
+
+ test_digits = digits (a)
+end function
+
+function test_epsilon (a)
+ implicit none
+ real :: a(..)
+ real :: test_epsilon
+
+ test_epsilon = epsilon (a)
+end function
+
+function test_huge (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_huge
+
+ test_huge = huge (a)
+end function
+
+function test_is_contiguous (a)
+ implicit none
+ integer :: a(..)
+ logical :: test_is_contiguous
+
+ test_is_contiguous = is_contiguous (a)
+end function
+
+function test_kind (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_kind
+
+ test_kind = kind (a)
+end function
+
+function test_lbound (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_lbound
+
+ test_lbound = lbound (a, 1)
+end function
+
+function test_len1 (a)
+ implicit none
+ character(len=5) :: a(..)
+ integer :: test_len1
+
+ test_len1 = len (a)
+end function
+
+function test_len2 (a)
+ implicit none
+ character(len=*) :: a(..)
+ integer :: test_len2
+
+ test_len2 = len (a)
+end function
+
+function test_len3 (a)
+ implicit none
+ character(len=5), pointer :: a(..)
+ integer :: test_len3
+
+ test_len3 = len (a)
+end function
+
+function test_len4 (a)
+ implicit none
+ character(len=*), pointer :: a(..)
+ integer :: test_len4
+
+ test_len4 = len (a)
+end function
+
+function test_len5 (a)
+ implicit none
+ character(len=:), pointer :: a(..)
+ integer :: test_len5
+
+ test_len5 = len (a)
+end function
+
+function test_len6 (a)
+ implicit none
+ character(len=5), allocatable :: a(..)
+ integer :: test_len6
+
+ test_len6 = len (a)
+end function
+
+function test_len7 (a)
+ implicit none
+ character(len=*), allocatable :: a(..)
+ integer :: test_len7
+
+ test_len7 = len (a)
+end function
+
+function test_len8 (a)
+ implicit none
+ character(len=:), allocatable :: a(..)
+ integer :: test_len8
+
+ test_len8 = len (a)
+end function
+
+function test_maxexponent (a)
+ implicit none
+ real :: a(..)
+ integer :: test_maxexponent
+
+ test_maxexponent = maxexponent (a)
+end function
+
+function test_minexponent (a)
+ implicit none
+ real :: a(..)
+ integer :: test_minexponent
+
+ test_minexponent = minexponent (a)
+end function
+
+function test_new_line (a)
+ implicit none
+ character :: a(..)
+ character :: test_new_line
+
+ test_new_line = new_line (a)
+end function
+
+function test_precision (a)
+ implicit none
+ real :: a(..)
+ integer :: test_precision
+
+ test_precision = precision (a)
+end function
+
+function test_present (a, b, c)
+ implicit none
+ integer :: a, b
+ integer, optional :: c(..)
+ integer :: test_present
+
+ if (present (c)) then
+ test_present = a
+ else
+ test_present = b
+ end if
+end function
+
+function test_radix (a)
+ implicit none
+ real :: a(..)
+ integer :: test_radix
+
+ test_radix = radix (a)
+end function
+
+function test_range (a)
+ implicit none
+ real :: a(..)
+ integer :: test_range
+
+ test_range = range (a)
+end function
+
+function test_rank (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_rank
+
+ test_rank = rank (a)
+end function
+
+function test_shape (a)
+ implicit none
+ integer :: a(..)
+ logical :: test_shape
+
+ test_shape = (rank (a) .eq. size (shape (a)))
+end function
+
+function test_size (a)
+ implicit none
+ integer :: a(..)
+ logical :: test_size
+
+ test_size = (size (a) .eq. product (shape (a)))
+end function
+
+function test_storage_size (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_storage_size
+
+ test_storage_size = storage_size (a)
+end function
+
+function test_tiny (a)
+ implicit none
+ real :: a(..)
+ real :: test_tiny
+
+ test_tiny = tiny (a)
+end function
+
+function test_ubound (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_ubound
+
+ test_ubound = ubound (a, 1)
+end function
+
+! Note: there are no tests for these inquiry functions that can't
+! take an assumed-rank array argument for other reasons:
+!
+! coshape, lcobound, ucobound: requires CODIMENSION attribute, which is
+! not permitted on an assumed-rank variable.
+!
+
+! F2018 additionally permits the first arg to C_SIZEOF to be
+! assumed-rank (C838).
+
+function test_c_sizeof (a)
+ use iso_c_binding
+ implicit none
+ integer :: a(..)
+ integer :: test_c_sizeof
+
+ test_c_sizeof = c_sizeof (a)
+end function
+
+! F2018 additionally permits an assumed-rank array as the selector
+! in a SELECT RANK construct (C838).
+
+function test_select_rank (a)
+ implicit none
+ integer :: a(..)
+ integer :: test_select_rank
+
+ select rank (a)
+ rank (0)
+ test_select_rank = 0
+ rank (1)
+ test_select_rank = 1
+ rank (2)
+ test_select_rank = 2
+ rank default
+ test_select_rank = -1
+ end select
+end function
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90
new file mode 100644
index 0000000..2dafd44
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-2.f90
@@ -0,0 +1,386 @@
+! PR 101334
+! PR 101337
+! { dg-do compile}
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C535b An assumed-rank variable name shall not appear in a designator
+! or expression except as an actual argument corresponding to a dummy
+! argument that is assumed-rank, the argument of the C_LOC function
+! in the ISO_C_BINDING intrinsic module, or the first argument in a
+! reference to an intrinsic inquiry function.
+!
+! This has been renamed C838 in the Fortran 2018 standard, with C_SIZEOF
+! and SELECT_RANK additionally added.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+! Check that passing an assumed-rank variable as an actual argument
+! corresponding to a non-assumed-rank dummy gives a diagnostic.
+
+module m
+ interface
+ subroutine f (a, b)
+ implicit none
+ integer :: a
+ integer :: b
+ end subroutine
+ subroutine g (a, b)
+ implicit none
+ integer :: a(..)
+ integer :: b(..)
+ end subroutine
+ subroutine h (a, b)
+ implicit none
+ integer :: a(*)
+ integer :: b(*)
+ end subroutine
+ subroutine i (a, b)
+ implicit none
+ integer :: a(:)
+ integer :: b(:)
+ end subroutine
+ subroutine j (a, b)
+ implicit none
+ integer :: a(3,3)
+ integer :: b(3,3)
+ end subroutine
+ end interface
+end module
+
+subroutine test_calls (x, y)
+ use m
+ implicit none
+ integer :: x(..), y(..)
+
+ ! Make sure each invalid argument produces a diagnostic.
+ ! scalar dummies
+ call f (x, & ! { dg-error "(A|a)ssumed.rank" }
+ y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ ! assumed-rank dummies
+ call g (x, y) ! OK
+ ! assumed-size dummies
+ call h (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" }
+ y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ ! assumed-shape dummies
+ call i (x, & ! { dg-error "(A|a)ssumed.rank" }
+ y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ ! fixed-size array dummies
+ call j (x, & ! { dg-error "(A|a)ssumed.rank" "pr101334" }
+ y) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+end subroutine
+
+! Check that you can't use an assumed-rank array variable in an array
+! element or section designator.
+
+subroutine test_designators (x)
+ use m
+ implicit none
+ integer :: x(..)
+
+ call f (x(1), 1) ! { dg-error "(A|a)ssumed.rank" }
+ call g (x(1:3:1), & ! { dg-error "(A|a)ssumed.rank" }
+ x) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+end subroutine
+
+! Check that you can't use an assumed-rank array variable in elemental
+! expressions. Make sure binary operators produce the error for either or
+! both operands.
+
+subroutine test_expressions (a, b, c, l, m, n, x, y, z, p, q, r, s, i, j)
+ implicit none
+ integer :: a(..), b(..), c(..)
+ logical :: l(..), m(..), n(..)
+ integer :: x(s), y(s), z(s)
+ logical :: p(s), q(s), r(s)
+ integer :: s
+ integer :: i
+ logical :: j
+
+ ! Assignment
+
+ z = x ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a ! { dg-error "(A|a)ssumed.rank" }
+ z = i ! OK
+ c = i ! { dg-error "(A|a)ssumed.rank" }
+
+ r = p ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l ! { dg-error "(A|a)ssumed.rank" }
+ r = j ! OK
+ n = j ! { dg-error "(A|a)ssumed.rank" }
+
+ ! Arithmetic
+
+ z = -x ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = -a ! { dg-error "(A|a)ssumed.rank" }
+ z = -i ! OK
+ c = -i ! { dg-error "(A|a)ssumed.rank" }
+
+ z = x + y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ + b ! { dg-error "(A|a)ssumed.rank" }
+ z = x + i ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a + i ! { dg-error "(A|a)ssumed.rank" }
+ z = i + y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = i + b ! { dg-error "(A|a)ssumed.rank" }
+
+ z = x - y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ - b ! { dg-error "(A|a)ssumed.rank" }
+ z = x - i ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a - i ! { dg-error "(A|a)ssumed.rank" }
+ z = i - y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = i - b ! { dg-error "(A|a)ssumed.rank" }
+
+ z = x * y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ * b ! { dg-error "(A|a)ssumed.rank" }
+ z = x * i ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a * i ! { dg-error "(A|a)ssumed.rank" }
+ z = i * y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = i * b ! { dg-error "(A|a)ssumed.rank" }
+
+ z = x / y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ / b ! { dg-error "(A|a)ssumed.rank" }
+ z = x / i ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a / i ! { dg-error "(A|a)ssumed.rank" }
+ z = i / y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = i / b ! { dg-error "(A|a)ssumed.rank" }
+
+ z = x ** y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ ** b ! { dg-error "(A|a)ssumed.rank" }
+ z = x ** i ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = a ** i ! { dg-error "(A|a)ssumed.rank" }
+ z = i ** y ! OK
+ c & ! { dg-error "(A|a)ssumed.rank" }
+ = i ** b ! { dg-error "(A|a)ssumed.rank" }
+
+ ! Comparisons
+
+ r = x .eq. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .eq. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .eq. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .eq. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .eq. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .eq. b ! { dg-error "(A|a)ssumed.rank" }
+
+ r = x .ne. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .ne. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .ne. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .ne. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .ne. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .ne. b ! { dg-error "(A|a)ssumed.rank" }
+
+ r = x .lt. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .lt. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .lt. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .lt. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .lt. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .lt. b ! { dg-error "(A|a)ssumed.rank" }
+
+ r = x .le. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .le. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .le. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .le. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .le. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .le. b ! { dg-error "(A|a)ssumed.rank" }
+
+ r = x .gt. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .gt. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .gt. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .gt. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .gt. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .gt. b ! { dg-error "(A|a)ssumed.rank" }
+
+ r = x .ge. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .ge. b ! { dg-error "(A|a)ssumed.rank" }
+ r = x .ge. i ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = a .ge. i ! { dg-error "(A|a)ssumed.rank" }
+ r = i .ge. y ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = i .ge. b ! { dg-error "(A|a)ssumed.rank" }
+
+ ! Logical operators
+
+ r = .not. p ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = .not. l ! { dg-error "(A|a)ssumed.rank" }
+ r = .not. j ! OK
+ n = .not. j ! { dg-error "(A|a)ssumed.rank" }
+
+ r = p .and. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .and. m ! { dg-error "(A|a)ssumed.rank" }
+ r = p .and. j ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l .and. j ! { dg-error "(A|a)ssumed.rank" }
+ r = j .and. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = j .and. m ! { dg-error "(A|a)ssumed.rank" }
+
+ r = p .or. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .or. m ! { dg-error "(A|a)ssumed.rank" }
+ r = p .or. j ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l .or. j ! { dg-error "(A|a)ssumed.rank" }
+ r = j .or. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = j .or. m ! { dg-error "(A|a)ssumed.rank" }
+
+ r = p .eqv. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .eqv. m ! { dg-error "(A|a)ssumed.rank" }
+ r = p .eqv. j ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l .eqv. j ! { dg-error "(A|a)ssumed.rank" }
+ r = j .eqv. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = j .eqv. m ! { dg-error "(A|a)ssumed.rank" }
+
+ r = p .neqv. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l & ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ .neqv. m ! { dg-error "(A|a)ssumed.rank" }
+ r = p .neqv. j ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = l .neqv. j ! { dg-error "(A|a)ssumed.rank" }
+ r = j .neqv. q ! OK
+ n & ! { dg-error "(A|a)ssumed.rank" }
+ = j .neqv. m ! { dg-error "(A|a)ssumed.rank" }
+
+end subroutine
+
+! Check that calls to disallowed intrinsic functions produce a diagnostic.
+! There are 100+ "elemental" intrinsics defined in the standard, and
+! 25+ "transformational" intrinsics that accept array operands, and that
+! doesn't include intrinsics in the standard modules. To keep the length of
+! this test to something sane, check only a handful of these functions on
+! the theory that related functions are probably implemented similarly and
+! probably share the same argument-processing code.
+
+subroutine test_intrinsics (i1, i2, r1, r2, c1, c2, l1, l2, s1, s2)
+ implicit none
+ integer :: i1(..), i2(..)
+ real :: r1(..), r2(..)
+ complex :: c1(..), c2(..)
+ logical :: l1(..), l2(..)
+ character :: s1(..), s2(..)
+
+ integer :: i
+ real :: r
+ logical :: l
+
+ ! trig, hyperbolic, other math functions
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = atan2 (r1, & ! { dg-error "(A|a)ssumed.rank" }
+ r2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = atan (r2) ! { dg-error "(A|a)ssumed.rank" }
+ c1 & ! { dg-error "(A|a)ssumed.rank" }
+ = atan (c2) ! { dg-error "(A|a)ssumed.rank" }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = cos (r2) ! { dg-error "(A|a)ssumed.rank" }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = exp (r2) ! { dg-error "(A|a)ssumed.rank" }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = sinh (r2) ! { dg-error "(A|a)ssumed.rank" }
+
+ ! bit operations
+ l1 & ! { dg-error "(A|a)ssumed.rank" }
+ = blt (i1, & ! { dg-error "(A|a)ssumed.rank" }
+ i2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ l1 & ! { dg-error "(A|a)ssumed.rank" }
+ = btest (i1, 0) ! { dg-error "(A|a)ssumed.rank" }
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = not (i2) ! { dg-error "(A|a)ssumed.rank" }
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = popcnt (i2) ! { dg-error "(A|a)ssumed.rank" }
+
+ ! type conversions
+ s1 & ! { dg-error "(A|a)ssumed.rank" }
+ = char (i1) ! { dg-error "(A|a)ssumed.rank" }
+ c1 & ! { dg-error "(A|a)ssumed.rank" }
+ = cmplx (r1, & ! { dg-error "(A|a)ssumed.rank" }
+ r2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = floor (r1) ! { dg-error "(A|a)ssumed.rank" }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = real (c1) ! { dg-error "(A|a)ssumed.rank" }
+
+ ! reductions
+ l = any (l2) ! { dg-error "(A|a)ssumed.rank" }
+ r = dot_product (r1, & ! { dg-error "(A|a)ssumed.rank" }
+ r2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ i = iall (i2, & ! { dg-error "(A|a)ssumed.rank" }
+ l2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+
+ ! string operations
+ s1 & ! { dg-error "(A|a)ssumed.rank" }
+ = adjustr (s2) ! { dg-error "(A|a)ssumed.rank" }
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = index (c1, & ! { dg-error "(A|a)ssumed.rank" }
+ c2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+
+ ! misc
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = cshift (i2, 4) ! { dg-error "(A|a)ssumed.rank" }
+ i = findloc (r1, 0.0) ! { dg-error "(A|a)ssumed.rank" }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = matmul (r1, & ! { dg-error "(A|a)ssumed.rank" }
+ r2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ r1 & ! { dg-error "(A|a)ssumed.rank" }
+ = reshape (r2, [10, 3]) ! { dg-error "(A|a)ssumed.rank" }
+ i1 & ! { dg-error "(A|a)ssumed.rank" }
+ = sign (i1, & ! { dg-error "(A|a)ssumed.rank" }
+ i2) ! { dg-error "(A|a)ssumed.rank" "pr101337, failure to diagnose both operands" { xfail *-*-*} }
+ s1 & ! { dg-error "(A|a)ssumed.rank" }
+ = transpose (s2) ! { dg-error "(A|a)ssumed.rank" }
+
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90
new file mode 100644
index 0000000..23862e5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535b-3.f90
@@ -0,0 +1,79 @@
+! PR 101334
+! { dg-do compile}
+! { dg-additional-options "-fcoarray=single" }
+!
+! TS 29113
+! C535b An assumed-rank variable name shall not appear in a designator
+! or expression except as an actual argument corresponding to a dummy
+! argument that is assumed-rank, the argument of the C_LOC function
+! in the ISO_C_BINDING intrinsic module, or the first argument in a
+! reference to an intrinsic inquiry function.
+!
+! This has been renamed C838 in the Fortran 2018 standard, with C_SIZEOF
+! and SELECT_RANK additionally added.
+!
+! This tests various forms of the 2-argument associated intrinsic.
+
+function test_associated2 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, target :: b(..)
+ logical :: test_associated2
+
+ test_associated2 = associated (a, b) ! { dg-error "Assumed.rank" }
+end function
+
+function test_associated3 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, target :: b
+ logical :: test_associated3
+
+ test_associated3 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
+end function
+
+function test_associated4 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, target :: b(:)
+ logical :: test_associated4
+
+ test_associated4 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
+end function
+
+function test_associated5 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, target :: b(20)
+ logical :: test_associated5
+
+ test_associated5 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
+end function
+
+function test_associated6 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, pointer :: b(..)
+ logical :: test_associated6
+
+ test_associated6 = associated (a, b) ! { dg-error "Assumed.rank" }
+end function
+
+function test_associated7 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, pointer :: b
+ logical :: test_associated7
+
+ test_associated7 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
+end function
+
+function test_associated8 (a, b)
+ implicit none
+ integer, pointer :: a(..)
+ integer, pointer :: b(:)
+ logical :: test_associated8
+
+ test_associated8 = associated (a, b) ! { dg-bogus "must be of rank -1" "pr101334" }
+end function
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535c-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535c-1.f90
new file mode 100644
index 0000000..2158c35
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535c-1.f90
@@ -0,0 +1,164 @@
+! PR 54753
+! { dg-do compile}
+!
+! TS 29113
+! C535c If an assumed-size or nonallocatable nonpointer assumed-rank
+! array is an actual argument corresponding to a dummy argument that
+! is an INTENT(OUT) assumed-rank array, it shall not be polymorphic, [...].
+!
+! This constraint is numbered C839 in the Fortran 2018 standard.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+module t
+ type :: t1
+ integer :: id
+ real :: xyz(3)
+ end type
+end module
+
+module m
+ use t
+
+ ! Assumed-type dummies are (unlimited) polymorphic too, but F2018:C709
+ ! already prohibits them from being declared intent(out). So we only
+ ! test dummies of class type that are polymorphic or unlimited
+ ! polymorphic.
+ interface
+ subroutine poly (x, y)
+ use t
+ class(t1) :: x(..)
+ class(t1), intent (out) :: y(..)
+ end subroutine
+ subroutine upoly (x, y)
+ class(*) :: x(..)
+ class(*), intent (out) :: y(..)
+ end subroutine
+ end interface
+
+contains
+
+ ! The known-size calls should all be OK as they do not involve
+ ! assumed-size or assumed-rank actual arguments.
+ subroutine test_known_size_nonpolymorphic (a1, a2, n)
+ integer :: n
+ type(t1) :: a1(n,n), a2(n)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_known_size_polymorphic (a1, a2, n)
+ integer :: n
+ class(t1) :: a1(n,n), a2(n)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_known_size_unlimited_polymorphic (a1, a2, n)
+ integer :: n
+ class(*) :: a1(n,n), a2(n)
+ call upoly (a1, a2)
+ end subroutine
+
+ ! Likewise passing a scalar as the assumed-rank argument.
+ subroutine test_scalar_nonpolymorphic (a1, a2)
+ type(t1) :: a1, a2
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_scalar_polymorphic (a1, a2)
+ class(t1) :: a1, a2
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_scalar_unlimited_polymorphic (a1, a2)
+ class(*) :: a1, a2
+ call upoly (a1, a2)
+ end subroutine
+
+ ! The polymorphic cases for assumed-size are bad.
+ subroutine test_assumed_size_nonpolymorphic (a1, a2)
+ type(t1) :: a1(*), a2(*)
+ call poly (a1, a2) ! OK
+ call upoly (a1, a2) ! OK
+ end subroutine
+ subroutine test_assumed_size_polymorphic (a1, a2)
+ class(t1) :: a1(*), a2(*)
+ call poly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ call upoly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ call poly (a1(5), a2(4:7))
+ end subroutine
+ subroutine test_assumed_size_unlimited_polymorphic (a1, a2)
+ class(*) :: a1(*), a2(*)
+ call upoly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+ ! The arguments being passed to poly/upoly in this set are *not*
+ ! assumed size and should not error.
+ subroutine test_not_assumed_size_nonpolymorphic (a1, a2)
+ type(t1) :: a1(*), a2(*)
+ call poly (a1(5), a2(4:7))
+ call upoly (a1(5), a2(4:7))
+ call poly (a1(:10), a2(:-5))
+ call upoly (a1(:10), a2(:-5))
+ end subroutine
+ subroutine test_not_assumed_size_polymorphic (a1, a2)
+ class(t1) :: a1(*), a2(*)
+ call poly (a1(5), a2(4:7))
+ call upoly (a1(5), a2(4:7))
+ call poly (a1(:10), a2(:-5))
+ call upoly (a1(:10), a2(:-5))
+ end subroutine
+ subroutine test_not_assumed_size_unlimited_polymorphic (a1, a2)
+ class(*) :: a1(*), a2(*)
+ call upoly (a1(5), a2(4:7))
+ call upoly (a1(:10), a2(:-5))
+ end subroutine
+
+ ! Polymorphic assumed-rank without pointer/allocatable is also bad.
+ subroutine test_assumed_rank_nonpolymorphic (a1, a2)
+ type(t1) :: a1(..), a2(..)
+ call poly (a1, a2) ! OK
+ call upoly (a1, a2) ! OK
+ end subroutine
+ subroutine test_assumed_rank_polymorphic (a1, a2)
+ class(t1) :: a1(..), a2(..)
+ call poly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ call upoly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+ subroutine test_assumed_rank_unlimited_polymorphic (a1, a2)
+ class(*) :: a1(..), a2(..)
+ call upoly (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+ ! Pointer/allocatable assumed-rank should be OK.
+ subroutine test_pointer_nonpolymorphic (a1, a2)
+ type(t1), pointer :: a1(..), a2(..)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_pointer_polymorphic (a1, a2)
+ class(t1), pointer :: a1(..), a2(..)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_pointer_unlimited_polymorphic (a1, a2)
+ class(*), pointer :: a1(..), a2(..)
+ call upoly (a1, a2)
+ end subroutine
+
+ subroutine test_allocatable_nonpolymorphic (a1, a2)
+ type(t1), allocatable :: a1(..), a2(..)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_allocatable_polymorphic (a1, a2)
+ class(t1), allocatable :: a1(..), a2(..)
+ call poly (a1, a2)
+ call upoly (a1, a2)
+ end subroutine
+ subroutine test_allocatable_unlimited_polymorphic (a1, a2)
+ class(*), allocatable :: a1(..), a2(..)
+ call upoly (a1, a2)
+ end subroutine
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535c-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535c-2.f90
new file mode 100644
index 0000000..f232efa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535c-2.f90
@@ -0,0 +1,74 @@
+! PR 54753
+! { dg-do compile}
+!
+! TS 29113
+! C535c If an assumed-size or nonallocatable nonpointer assumed-rank
+! array is an actual argument corresponding to a dummy argument that
+! is an INTENT(OUT) assumed-rank array, it shall not be [...]
+! finalizable [...].
+!
+! This constraint is numbered C839 in the Fortran 2018 standard.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+module m
+
+ type :: t1
+ integer :: id
+ real :: xyz(3)
+ contains
+ final :: finalize_t1
+ end type
+
+contains
+
+ subroutine finalize_t1 (obj)
+ type(t1) :: obj
+ end subroutine
+
+ subroutine s1 (x, y)
+ type(t1) :: x(..)
+ type(t1), intent(out) :: y(..)
+ end subroutine
+
+ ! This call should be OK as it does not involve assumed-size or
+ ! assumed-rank actual arguments.
+ subroutine test_known_size (a1, a2, n)
+ integer :: n
+ type(t1) :: a1(n,n), a2(n)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! Calls with an assumed-size array argument should be rejected.
+ subroutine test_assumed_size (a1, a2)
+ type(t1) :: a1(*), a2(*)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_pointer (a1, a2)
+ type(t1), pointer :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_allocatable (a1, a2)
+ type(t1), allocatable :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! The call should be rejected with a nonallocatable nonpointer
+ ! assumed-rank actual argument.
+ subroutine test_assumed_rank_plain (a1, a2)
+ type(t1) :: a1(..), a2(..)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535c-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535c-3.f90
new file mode 100644
index 0000000..50840a1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535c-3.f90
@@ -0,0 +1,72 @@
+! PR 54753
+! { dg-do compile }
+!
+! TS 29113
+! C535c If an assumed-size or nonallocatable nonpointer assumed-rank
+! array is an actual argument corresponding to a dummy argument that
+! is an INTENT(OUT) assumed-rank array, it shall not be [...]
+! of a type with an allocatable ultimate component [...].
+!
+! This constraint is numbered C839 in the Fortran 2018 standard.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+module m
+
+ type :: t1
+ integer :: id
+ real :: xyz(3)
+ character, allocatable :: notes
+ end type
+
+contains
+
+ subroutine finalize_t1 (obj)
+ type(t1) :: obj
+ end subroutine
+
+ subroutine s1 (x, y)
+ type(t1) :: x(..)
+ type(t1), intent(out) :: y(..)
+ end subroutine
+
+ ! This call should be OK as it does not involve assumed-size or
+ ! assumed-rank actual arguments.
+ subroutine test_known_size (a1, a2, n)
+ integer :: n
+ type(t1) :: a1(n,n), a2(n)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! Calls with an assumed-size array argument should be rejected.
+ subroutine test_assumed_size (a1, a2)
+ type(t1) :: a1(*), a2(*)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_pointer (a1, a2)
+ type(t1), pointer :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_allocatable (a1, a2)
+ type(t1), allocatable :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! The call should be rejected with a nonallocatable nonpointer
+ ! assumed-rank actual argument.
+ subroutine test_assumed_rank_plain (a1, a2)
+ type(t1) :: a1(..), a2(..)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/c535c-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/c535c-4.f90
new file mode 100644
index 0000000..dc380ba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/c535c-4.f90
@@ -0,0 +1,72 @@
+! PR 54753
+! { dg-do compile }
+!
+! TS 29113
+! C535c If an assumed-size or nonallocatable nonpointer assumed-rank
+! array is an actual argument corresponding to a dummy argument that
+! is an INTENT(OUT) assumed-rank array, it shall not be [...]
+! of a type for which default initialization is specified.
+!
+! This constraint is numbered C839 in the Fortran 2018 standard.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+module m
+
+ type :: t1
+ integer :: id
+ real :: xyz(3)
+ integer :: tag = -1
+ end type
+
+contains
+
+ subroutine finalize_t1 (obj)
+ type(t1) :: obj
+ end subroutine
+
+ subroutine s1 (x, y)
+ type(t1) :: x(..)
+ type(t1), intent(out) :: y(..)
+ end subroutine
+
+ ! This call should be OK as it does not involve assumed-size or
+ ! assumed-rank actual arguments.
+ subroutine test_known_size (a1, a2, n)
+ integer :: n
+ type(t1) :: a1(n,n), a2(n)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! Calls with an assumed-size array argument should be rejected.
+ subroutine test_assumed_size (a1, a2)
+ type(t1) :: a1(*), a2(*)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_pointer (a1, a2)
+ type(t1), pointer :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! This call should be OK.
+ subroutine test_assumed_rank_allocatable (a1, a2)
+ type(t1), allocatable :: a1(..), a2(..)
+
+ call s1 (a1, a2)
+ end subroutine
+
+ ! The call should be rejected with a nonallocatable nonpointer
+ ! assumed-rank actual argument.
+ subroutine test_assumed_rank_plain (a1, a2)
+ type(t1) :: a1(..), a2(..)
+
+ call s1 (a1, a2) ! { dg-error "(A|a)ssumed.rank" }
+ end subroutine
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1-c.c
new file mode 100644
index 0000000..3ff3a8d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1-c.c
@@ -0,0 +1,91 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+extern void ftest (CFI_cdesc_t *a, CFI_cdesc_t *b);
+
+struct m {
+ int i;
+ int j;
+};
+
+#define imax 10
+#define jmax 5
+
+void
+ctest (CFI_cdesc_t *a)
+{
+
+ struct m bdata[imax][jmax];
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ int i, j;
+ CFI_index_t subscripts[2];
+ struct m* mp;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ /* Transpose a's contents into bdata. */
+ for (j = 0; j < jmax; j++)
+ {
+ subscripts[1] = j;
+ for (i = 0; i < imax; i++)
+ {
+ subscripts[0] = i;
+ mp = (struct m *) CFI_address (a, subscripts);
+ if (mp->i != i + 1)
+ abort ();
+ if (mp->j != j + 1)
+ abort ();
+ bdata[i][j].i = mp->i;
+ bdata[i][j].j = mp->j;
+ }
+ }
+
+ /* Fill in bdesc. */
+ subscripts[0] = jmax;
+ subscripts[1] = imax;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, bdata, CFI_attribute_other,
+ CFI_type_struct,
+ sizeof (struct m), 2, subscripts));
+
+ /* Sanity checking to make sure the descriptor has been initialized
+ properly. */
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ /* Call back into Fortran, passing both the a and b arrays. */
+ ftest (a, b);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1.f90
new file mode 100644
index 0000000..f52a631
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-1.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-1-c.c dump-descriptors.c" }
+!
+! This program checks that building a descriptor for a fixed-size array
+! in C works and that you can use it to call back into a Fortran function
+! declared to have c binding, as an assumed-shape argument.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+subroutine ftest (a, b) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ integer :: i, j
+
+ if (size (a,1) .ne. imax) stop 101
+ if (size (a,2) .ne. jmax) stop 102
+ if (size (b,1) .ne. jmax) stop 103
+ if (size (b,2) .ne. imax) stop 104
+
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 201
+ if (a(i,j)%j .ne. j) stop 202
+ if (b(j,i)%i .ne. i) stop 203
+ if (b(j,i)%j .ne. j) stop 204
+ end do
+ end do
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ ! Pass the initialized array to a C function ctest, which will generate its
+ ! transpose and call ftest with it.
+
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2-c.c
new file mode 100644
index 0000000..a4be5a7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2-c.c
@@ -0,0 +1,91 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+extern void ftest (CFI_cdesc_t *a, CFI_cdesc_t *b);
+
+struct m {
+ int i;
+ int j;
+};
+
+#define imax 10
+#define jmax 5
+
+void
+ctest (CFI_cdesc_t *a)
+{
+
+ struct m bdata[imax][jmax];
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ int i, j;
+ CFI_index_t subscripts[2];
+ struct m* mp;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ /* Transpose a's contents into bdata. */
+ for (j = 0; j < jmax; j++)
+ {
+ subscripts[1] = j;
+ for (i = 0; i < imax; i++)
+ {
+ subscripts[0] = i;
+ mp = (struct m *) CFI_address (a, subscripts);
+ if (mp->i != i + 1)
+ abort ();
+ if (mp->j != j + 1)
+ abort ();
+ bdata[i][j].i = mp->i;
+ bdata[i][j].j = mp->j;
+ }
+ }
+
+ /* Fill in bdesc. */
+ subscripts[0] = jmax;
+ subscripts[1] = imax;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, bdata, CFI_attribute_other,
+ CFI_type_struct,
+ sizeof (struct m), 2, subscripts));
+
+ /* Sanity checking to make sure the descriptor has been initialized
+ properly. */
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ /* Call back into Fortran, passing both the a and b arrays. */
+ ftest (a, b);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2.f90
new file mode 100644
index 0000000..a4231fa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-2.f90
@@ -0,0 +1,82 @@
+! PR 93308
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-2-c.c dump-descriptors.c" }
+!
+! This program checks that building a descriptor for a fixed-size array
+! in C works and that you can use it to call back into a Fortran function
+! declared to have c binding, as an assumed-rank argument.
+!
+! Fixed by
+! https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572725.html
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+subroutine ftest (a, b) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..), b(..)
+ integer :: i, j
+
+ select rank (a)
+ rank (2)
+ select rank (b)
+ rank (2)
+ ! print *, lbound(a,1), ubound(a,1), lbound(a,2), ubound(a,2)
+ ! print *, lbound(b,1), ubound(b,1), lbound(b,2), ubound(b,2)
+ if (lbound (a,1) .ne. 1 .or. ubound (a,1) .ne. imax) stop 101
+ if (lbound (a,2) .ne. 1 .or. ubound (a,2) .ne. jmax) stop 102
+ if (lbound (b,1) .ne. 1 .or. ubound (b,1) .ne. jmax) stop 103
+ if (lbound (b,2) .ne. 1 .or. ubound (b,2) .ne. imax) stop 104
+ do j = 1, jmax
+ do i = 1, imax
+ print *, a(i,j)%i, a(i,j)%j, b(j,i)%i, b(j,i)%j
+ if (a(i,j)%i .ne. i) stop 105
+ if (a(i,j)%j .ne. j) stop 106
+ if (b(j,i)%i .ne. i) stop 107
+ if (b(j,i)%j .ne. j) stop 108
+ end do
+ end do
+ rank default
+ stop 106
+ end select
+ rank default
+ stop 107
+ end select
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ ! Pass the initialized array to a C function ctest, which will generate its
+ ! transpose and call ftest with it.
+
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3-c.c
new file mode 100644
index 0000000..b947377
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3-c.c
@@ -0,0 +1,92 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imagic, int jmagic);
+extern void ftest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imagic, int jmagic)
+{
+ CFI_CDESC_T(0) adesc;
+ CFI_CDESC_T(0) bdesc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &adesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ struct m* mp;
+
+ /* Create the descriptor for a, then sanity-check it. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ dump_CFI_cdesc_t (a);
+ if (a->version != CFI_VERSION)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Likewise for b. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 0)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Call back into Fortran, passing the unallocated descriptors. */
+ ftest (a, b, 0);
+
+ /* Allocate and initialize both variables, and try again. */
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (a, NULL, NULL, 0));
+ dump_CFI_cdesc_t (a);
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+ ((struct m *)a->base_addr)->i = imagic;
+ ((struct m *)a->base_addr)->j = jmagic;
+
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (b, NULL, NULL, 0));
+ dump_CFI_cdesc_t (b);
+ if (!b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+ ((struct m *)b->base_addr)->i = imagic + 1;
+ ((struct m *)b->base_addr)->j = jmagic + 1;
+
+ ftest (a, b, 1);
+
+ /* Deallocate both objects and try again. */
+ check_CFI_status ("CFI_deallocate", CFI_deallocate (a));
+ if (a->base_addr)
+ abort ();
+ check_CFI_status ("CFI_deallocate", CFI_deallocate (b));
+ if (b->base_addr)
+ abort ();
+ ftest (a, b, 0);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3.f90
new file mode 100644
index 0000000..7a08395
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-3.f90
@@ -0,0 +1,58 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that building a descriptor for an allocatable
+! or pointer scalar argument in C works and that you can use it to call
+! back into a Fortran function declared to have c binding.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer(C_INT), parameter :: imagic = 42, jmagic = 69
+end module
+
+subroutine ftest (a, b, initp) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a
+ type(m), pointer :: b
+ integer(C_INT), value :: initp
+
+ if (rank(a) .ne. 0) stop 101
+ if (rank(b) .ne. 0) stop 101
+
+ if (initp .ne. 0 .and. .not. allocated(a)) stop 102
+ if (initp .eq. 0 .and. allocated(a)) stop 103
+ if (initp .ne. 0 .and. .not. associated(b)) stop 104
+ if (initp .eq. 0 .and. associated(b)) stop 105
+
+ if (initp .ne. 0) then
+ if (a%i .ne. imagic) stop 201
+ if (a%j .ne. jmagic) stop 202
+ if (b%i .ne. imagic + 1) stop 203
+ if (b%j .ne. jmagic + 1) stop 204
+ end if
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (i, j) bind (c)
+ use iso_c_binding
+ integer(C_INT), value :: i, j
+ end subroutine
+ end interface
+
+ ! ctest will call ftest with both an unallocated and allocated argument.
+
+ call ctest (imagic, jmagic)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4-c.c
new file mode 100644
index 0000000..b941318
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4-c.c
@@ -0,0 +1,112 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imagic, int jmagic);
+extern void ftest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imax, int jmax)
+{
+ CFI_CDESC_T(2) adesc;
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &adesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ struct m* mp;
+ CFI_index_t lower[2], upper[2], subscripts[2];
+ CFI_index_t i, j;
+
+ /* Create the descriptor for a, then sanity-check it. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ dump_CFI_cdesc_t (a);
+ if (a->version != CFI_VERSION)
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Likewise for b. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Call back into Fortran, passing the unallocated descriptors. */
+ ftest (a, b, 0);
+
+ /* Allocate and initialize both variables, and try again. */
+ lower[0] = 1;
+ lower[1] = 1;
+ upper[0] = imax;
+ upper[1] = jmax;
+
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (a, lower, upper, 0));
+ dump_CFI_cdesc_t (a);
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+
+ upper[0] = jmax;
+ upper[1] = imax;
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (b, lower, upper, 0));
+ dump_CFI_cdesc_t (b);
+ if (!b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+
+ for (i = 1; i <= imax; i++)
+ for (j = 1; j <= jmax; j++)
+ {
+ subscripts[0] = i;
+ subscripts[1] = j;
+ mp = (struct m *) CFI_address (a, subscripts);
+ mp->i = i;
+ mp->j = j;
+ subscripts[0] = j;
+ subscripts[1] = i;
+ mp = (struct m *) CFI_address (b, subscripts);
+ mp->i = i;
+ mp->j = j;
+ }
+
+ ftest (a, b, 1);
+
+ /* Deallocate both objects and try again. */
+ check_CFI_status ("CFI_deallocate", CFI_deallocate (a));
+ if (a->base_addr)
+ abort ();
+ check_CFI_status ("CFI_deallocate", CFI_deallocate (b));
+ if (b->base_addr)
+ abort ();
+ ftest (a, b, 0);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4.f90
new file mode 100644
index 0000000..c05f2e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-4.f90
@@ -0,0 +1,73 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-4-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that building a descriptor for an allocatable
+! or pointer array argument in C works and that you can use it to call
+! back into a Fortran function declared to have c binding.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer(C_INT), parameter :: imax=3, jmax=6
+end module
+
+subroutine ftest (a, b, initp) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:,:)
+ type(m), pointer :: b(:,:)
+ integer(C_INT), value :: initp
+ integer :: i, j
+
+ if (rank(a) .ne. 2) stop 101
+ if (rank(b) .ne. 2) stop 101
+
+ if (initp .ne. 0 .and. .not. allocated(a)) stop 102
+ if (initp .eq. 0 .and. allocated(a)) stop 103
+ if (initp .ne. 0 .and. .not. associated(b)) stop 104
+ if (initp .eq. 0 .and. associated(b)) stop 105
+
+ if (initp .ne. 0) then
+ if (lbound (a, 1) .ne. 1) stop 201
+ if (lbound (a, 2) .ne. 1) stop 202
+ if (lbound (b, 2) .ne. 1) stop 203
+ if (lbound (b, 1) .ne. 1) stop 204
+ if (ubound (a, 1) .ne. imax) stop 205
+ if (ubound (a, 2) .ne. jmax) stop 206
+ if (ubound (b, 2) .ne. imax) stop 207
+ if (ubound (b, 1) .ne. jmax) stop 208
+
+ do i = 1, imax
+ do j = 1, jmax
+ if (a(i,j)%i .ne. i) stop 301
+ if (a(i,j)%j .ne. j) stop 302
+ if (b(j,i)%i .ne. i) stop 303
+ if (b(j,i)%j .ne. j) stop 303
+ end do
+ end do
+
+ end if
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (i, j) bind (c)
+ use iso_c_binding
+ integer(C_INT), value :: i, j
+ end subroutine
+ end interface
+
+ ! ctest will call ftest with both an unallocated and allocated argument.
+
+ call ctest (imax, jmax)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c
new file mode 100644
index 0000000..12464b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5-c.c
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <alloca.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int n);
+extern void ftest (CFI_cdesc_t *a, int n);
+
+void
+ctest (int n)
+{
+ CFI_CDESC_T(0) adesc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &adesc;
+ char *adata = (char *) alloca (n);
+
+ /* Fill in adesc. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, adata, CFI_attribute_other,
+ CFI_type_char, n, 0, NULL));
+
+ /* Sanity checking to make sure the descriptor has been initialized
+ properly. */
+ dump_CFI_cdesc_t (a);
+ if (a->version != CFI_VERSION)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->elem_len != n)
+ abort ();
+
+ /* Call back into Fortran. */
+ ftest (a, n);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5.f90
new file mode 100644
index 0000000..b5edf52
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-5.f90
@@ -0,0 +1,31 @@
+! PR92482
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-5-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that building a descriptor for a character object
+! in C works and that you can use it to call back into a Fortran function
+! with an assumed-length dummy that is declared with C binding.
+
+subroutine ftest (a, n) bind (c, name="ftest")
+ use iso_c_binding
+ character(kind=C_CHAR, len=*) :: a
+ integer(C_INT), value :: n
+
+ if (len (a) .ne. n) stop 101
+end subroutine
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (n) bind (c)
+ use iso_c_binding
+ integer(C_INT), value :: n
+ end subroutine
+ end interface
+
+ call ctest (42)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6-c.c
new file mode 100644
index 0000000..168087b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6-c.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, int lb1, int lb2, int ub1, int ub2, int step1, int step2);
+extern void ftest (CFI_cdesc_t *b);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (CFI_cdesc_t *a, int lb1, int lb2, int ub1, int ub2,
+ int step1, int step2)
+{
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ CFI_index_t lb[2], ub[2], step[2];
+ int i, j;
+
+ fprintf (stderr, "got new bound info (%d:%d:%d, %d:%d:%d)\n",
+ lb1, ub1, step1, lb2, ub2, step2);
+ lb[0] = lb1 - 1;
+ lb[1] = lb2 - 1;
+ ub[0] = ub1 - 1;
+ ub[1] = ub2 - 1;
+ step[0] = step1;
+ step[1] = step2;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+
+ /* Fill in bdesc. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ check_CFI_status ("CFI_section",
+ CFI_section (b, a, lb, ub, step));
+
+ /* Sanity checking to make sure the descriptor has been initialized
+ properly. */
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (!b->base_addr)
+ abort ();
+ if (CFI_is_contiguous (b))
+ abort ();
+
+ for (j = b->dim[1].lower_bound;
+ j < b->dim[1].lower_bound + b->dim[1].extent;
+ j++)
+ {
+ for (i = b->dim[0].lower_bound;
+ i < b->dim[0].lower_bound + b->dim[0].extent;
+ i++)
+ {
+ CFI_index_t subscripts[2];
+ struct m *mp;
+ subscripts[0] = i;
+ subscripts[1] = j;
+ mp = (struct m *) CFI_address (b, subscripts);
+ fprintf (stderr, "b(%d,%d) = (%d,%d)\n", i, j, mp->i, mp->j);
+ }
+ }
+
+ /* Call back into Fortran. */
+ ftest (b);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6.f90
new file mode 100644
index 0000000..5716494
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-6.f90
@@ -0,0 +1,72 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-6-c.c dump-descriptors.c" }
+!
+! This program tests passing the result of the CFI_section C library
+! routine back to Fortran. Most of the work happens on the C side.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+ integer, parameter :: ilb=2, jlb=1
+ integer, parameter :: iub=8, jub=5
+ integer, parameter :: istep=3, jstep=2
+ integer, parameter :: isize=3, jsize=3
+end module
+
+subroutine ftest (b) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m), pointer :: b(:,:)
+ integer :: i, j, ii, jj
+
+ if (size (b, 1) .ne. isize) stop 103
+ if (size (b, 2) .ne. jsize) stop 104
+
+ ! ii and jj iterate over the elements of b
+ ! i and j iterate over the original array
+ jj = lbound (b, 2)
+ do j = jlb, jub, jstep
+ ii = lbound (b, 1)
+ do i = ilb, iub, istep
+ if (b (ii, jj)%i .ne. i) stop 203
+ if (b (ii, jj)%j .ne. j) stop 204
+ ii = ii + 1
+ end do
+ jj = jj + 1
+ end do
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a, lb1, lb2, ub1, ub2, step1, step2) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ integer(C_INT), value :: lb1, lb2, ub1, ub2, step1, step2
+ end subroutine
+ end interface
+
+ type(m), target :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ ! Pass the initialized array to a C function ctest, which will take
+ ! a section of it and pass it to ftest.
+
+ call ctest (aa, ilb, jlb, iub, jub, istep, jstep)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7-c.c
new file mode 100644
index 0000000..1f23a64
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7-c.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+extern void ftest (CFI_cdesc_t *iarray, CFI_cdesc_t *jarray);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ CFI_CDESC_T(2) idesc;
+ CFI_cdesc_t *iarray = (CFI_cdesc_t *) &idesc;
+ CFI_CDESC_T(2) jdesc;
+ CFI_cdesc_t *jarray = (CFI_cdesc_t *) &jdesc;
+ int i, j;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+
+ /* Fill in the new descriptors. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (iarray, NULL, CFI_attribute_pointer,
+ CFI_type_int,
+ sizeof (int), 2, NULL));
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (iarray, a, offsetof (struct m, i),
+ sizeof (int)));
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (jarray, NULL, CFI_attribute_pointer,
+ CFI_type_int,
+ sizeof (int), 2, NULL));
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (jarray, a, offsetof (struct m, j),
+ sizeof (int)));
+
+ /* Sanity checking to make sure the descriptor has been initialized
+ properly. */
+ dump_CFI_cdesc_t (iarray);
+ if (iarray->version != CFI_VERSION)
+ abort ();
+ if (iarray->rank != 2)
+ abort ();
+ if (iarray->attribute != CFI_attribute_pointer)
+ abort ();
+ if (!iarray->base_addr)
+ abort ();
+ if (iarray->dim[0].extent != a->dim[0].extent)
+ abort ();
+ if (iarray->dim[1].extent != a->dim[1].extent)
+ abort ();
+
+ dump_CFI_cdesc_t (jarray);
+ if (jarray->version != CFI_VERSION)
+ abort ();
+ if (jarray->rank != 2)
+ abort ();
+ if (jarray->attribute != CFI_attribute_pointer)
+ abort ();
+ if (!jarray->base_addr)
+ abort ();
+ if (jarray->dim[0].extent != a->dim[0].extent)
+ abort ();
+ if (jarray->dim[1].extent != a->dim[1].extent)
+ abort ();
+
+ /* Call back into Fortran. */
+ ftest (iarray, jarray);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7.f90
new file mode 100644
index 0000000..bc76b0e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-7.f90
@@ -0,0 +1,74 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-7-c.c dump-descriptors.c" }
+!
+! This program tests passing the result of the CFI_select_part C library
+! routine back to Fortran. Most of the work happens on the C side.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+subroutine ftest (iarray, jarray) bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ integer(C_INT), pointer :: iarray(:,:), jarray(:,:)
+
+ integer :: i, j, i1, i2, j1, j2
+
+ ! iarray and jarray must have the same shape as the original array,
+ ! but might be zero-indexed instead of one-indexed.
+ if (size (iarray, 1) .ne. imax) stop 101
+ if (size (iarray, 2) .ne. jmax) stop 102
+ if (size (jarray, 1) .ne. imax) stop 103
+ if (size (jarray, 2) .ne. jmax) stop 104
+
+ j1 = lbound(iarray, 2)
+ j2 = lbound(jarray, 2)
+ do j = 1, jmax
+ i1 = lbound(iarray, 1)
+ i2 = lbound(jarray, 1)
+ do i = 1, imax
+ if (iarray (i1, j1) .ne. i) stop 201
+ if (jarray (i2, j2) .ne. j) stop 202
+ i1 = i1 + 1
+ i2 = i2 + 1
+ end do
+ j1 = j1 + 1
+ j2 = j2 + 1
+ end do
+end subroutine
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ end subroutine
+ end interface
+
+ type(m), target :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ ! Pass the initialized array to a C function ctest, which will split it
+ ! into i and j component arrays and pass them to ftest.
+
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8-c.c
new file mode 100644
index 0000000..49beee7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8-c.c
@@ -0,0 +1,73 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+extern void ftest1 (CFI_cdesc_t *a, int lb1, int lb2);
+extern void ftest2 (CFI_cdesc_t *a);
+
+struct m {
+ int i;
+ int j;
+};
+
+#define imax 10
+#define jmax 5
+
+void
+ctest (CFI_cdesc_t *a)
+{
+
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ int i, j;
+ CFI_index_t subscripts[2];
+ struct m* mp;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+
+ /* Fill in bdesc. */
+ subscripts[0] = a->dim[0].extent;
+ subscripts[1] = a->dim[1].extent;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 2, subscripts));
+
+ /* Pass the unassociated pointer descriptor b back to Fortran for
+ checking. */
+ dump_CFI_cdesc_t (b);
+ ftest2 (b);
+
+ /* Point the descriptor b at the input argument array, and check that
+ on the Fortran side. */
+ subscripts[0] = a->dim[0].lower_bound;
+ subscripts[1] = a->dim[1].lower_bound;
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (b, a, subscripts));
+ dump_CFI_cdesc_t (b);
+ ftest1 (b, (int)subscripts[0], (int)subscripts[1]);
+
+ /* Diddle the lower bounds and try again. */
+ subscripts[0] = 42;
+ subscripts[1] = -69;
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (b, b, subscripts));
+ dump_CFI_cdesc_t (b);
+ ftest1 (b, 42, -69);
+
+ /* Disassociate the pointer and check that. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (b, NULL, NULL));
+ dump_CFI_cdesc_t (b);
+ ftest2 (b);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8.f90
new file mode 100644
index 0000000..6b35e6e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-descriptor-8.f90
@@ -0,0 +1,78 @@
+! { dg-do run }
+! { dg-additional-sources "cf-descriptor-8-c.c dump-descriptors.c" }
+!
+! This program tests passing the result of the CFI_setpointer C library
+! function back to Fortran. Most of the work happens on the C side.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+subroutine ftest1 (a, lb1, lb2) bind (c, name="ftest1")
+ use iso_c_binding
+ use mm
+ type(m), pointer :: a(:,:)
+ integer(C_INT), value :: lb1, lb2
+ integer :: i, j, ii, jj
+
+ if (size (a,1) .ne. imax) stop 101
+ if (size (a,2) .ne. jmax) stop 102
+ if (lbound (a, 1) .ne. lb1) stop 103
+ if (lbound (a, 2) .ne. lb2) stop 104
+
+ if (.not. associated (a)) stop 105
+
+ jj = lb2
+ do j = 1, jmax
+ ii = lb1
+ do i = 1, imax
+ if (a(ii,jj)%i .ne. i) stop 201
+ if (a(ii,jj)%j .ne. j) stop 202
+ ii = ii + 1
+ end do
+ jj = jj + 1
+ end do
+end subroutine
+
+subroutine ftest2 (a) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m), pointer :: a(:,:)
+
+ if (associated (a)) stop 301
+end subroutine
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ end subroutine
+ end interface
+
+ type(m), target :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ ! Pass the initialized array to a C function ctest, which will use it
+ ! as the target of a pointer array with various bounds, calling
+ ! ftest1 and ftest2 to check that CFI_setpointer did the right thing.
+
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1-c.c
new file mode 100644
index 0000000..366ec2b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1-c.c
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, CFI_cdesc_t *b);
+extern void ftest2 (CFI_cdesc_t *a, CFI_cdesc_t *b);
+
+struct m {
+ int i;
+ int j;
+};
+
+#define imax 10
+#define jmax 5
+
+void
+ctest (CFI_cdesc_t *a, CFI_cdesc_t *b)
+{
+ CFI_index_t i, j;
+ CFI_index_t s[2];
+ struct m *mpa, *mpb;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ dump_CFI_cdesc_t (b);
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ /* Call back into Fortran, passing both the a and b arrays. */
+ ftest2 (a, b);
+
+ /* Check that we got a valid b array back. */
+ dump_CFI_cdesc_t (b);
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ for (j = 0; j < jmax; j++)
+ for (i = 0; i < imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mpa = (struct m *) CFI_address (a, s);
+ s[0] = j;
+ s[1] = i;
+ mpb = (struct m *) CFI_address (b, s);
+ if (mpa->i != mpb->i)
+ abort ();
+ if (mpa->j != mpb->j)
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1.f90
new file mode 100644
index 0000000..05fe26c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-1.f90
@@ -0,0 +1,174 @@
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-1-c.c dump-descriptors.c" }
+!
+! This program checks that calling a Fortran function with C binding and
+! an intent(out) argument works from both C and Fortran. For this
+! test case the argument is an assumed-shape array.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+! frob has regular Fortran binding. It transposes input array argument
+! a into the intent(out) argument b.
+
+subroutine frob (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+ integer :: i, j
+
+ if (lbound (a, 1) .ne. lbound (b, 2)) stop 101
+ if (lbound (a, 2) .ne. lbound (b, 1)) stop 102
+ if (ubound (a, 1) .ne. ubound (b, 2)) stop 103
+ if (ubound (a, 2) .ne. ubound (b, 1)) stop 104
+
+ do j = lbound (a, 2), ubound (a, 2)
+ do i = lbound (a, 1), ubound (a, 1)
+ b(j,i) = a(i,j)
+ end do
+ end do
+end subroutine
+
+! check also has regular Fortran binding, and two input arguments.
+
+subroutine check (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ integer :: i, j
+
+ if (lbound (a, 1) .ne. 1 .or. lbound (b, 2) .ne. 1) stop 101
+ if (lbound (a, 2) .ne. 1 .or. lbound (b, 1) .ne. 1) stop 102
+ if (ubound (a, 1) .ne. ubound (b, 2)) stop 103
+ if (ubound (a, 2) .ne. ubound (b, 1)) stop 104
+
+ do j = 1, ubound (a, 2)
+ do i = 1, ubound (a, 1)
+ if (b(j,i)%i .ne. a(i,j)%i) stop 105
+ if (b(j,i)%j .ne. a(i,j)%j) stop 106
+ end do
+ end do
+end subroutine
+
+! ftest1 has C binding and calls frob. This allows us to test intent(out)
+! arguments passed back from Fortran binding to a Fortran function with C
+! binding.
+
+subroutine ftest1 (a, b) bind (c, name="ftest1")
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+
+ interface
+ subroutine frob (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+ end subroutine
+ subroutine check (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ end subroutine
+ end interface
+
+ call frob (a, b)
+ call check (a, b)
+end subroutine
+
+! ftest2 has C binding and calls ftest1. This allows us to test intent(out)
+! arguments passed between two Fortran functions with C binding.
+
+subroutine ftest2 (a, b) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+
+ interface
+ subroutine ftest1 (a, b) bind (c, name="ftest1")
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+ end subroutine
+ subroutine check (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ end subroutine
+ end interface
+
+ call ftest1 (a, b)
+ call check (a, b)
+end subroutine
+
+! main calls ftest2 directly and also indirectly from a C function ctest.
+! The former allows us to test intent(out) arguments passed back from a
+! Fortran routine with C binding to a regular Fortran routine, and the
+! latter tests passing them back from Fortran to C and C to Fortran.
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ftest2 (a, b) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+ end subroutine
+ subroutine ctest (a, b) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m), intent(out) :: b(:,:)
+ end subroutine
+ subroutine check (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax), bb(jmax,imax)
+ integer :: i, j
+
+ ! initialize
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ bb(j,i)%i = -1
+ bb(j,i)%j = -2
+ end do
+ end do
+
+ call ftest2 (aa, bb)
+ call check (aa, bb)
+
+ ! initialize again
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ bb(j,i)%i = -1
+ bb(j,i)%j = -2
+ end do
+ end do
+
+ call ctest (aa, bb)
+ call check (aa, bb)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2-c.c
new file mode 100644
index 0000000..366ec2b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2-c.c
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, CFI_cdesc_t *b);
+extern void ftest2 (CFI_cdesc_t *a, CFI_cdesc_t *b);
+
+struct m {
+ int i;
+ int j;
+};
+
+#define imax 10
+#define jmax 5
+
+void
+ctest (CFI_cdesc_t *a, CFI_cdesc_t *b)
+{
+ CFI_index_t i, j;
+ CFI_index_t s[2];
+ struct m *mpa, *mpb;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ dump_CFI_cdesc_t (b);
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ /* Call back into Fortran, passing both the a and b arrays. */
+ ftest2 (a, b);
+
+ /* Check that we got a valid b array back. */
+ dump_CFI_cdesc_t (b);
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_other)
+ abort ();
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+
+ for (j = 0; j < jmax; j++)
+ for (i = 0; i < imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mpa = (struct m *) CFI_address (a, s);
+ s[0] = j;
+ s[1] = i;
+ mpb = (struct m *) CFI_address (b, s);
+ if (mpa->i != mpb->i)
+ abort ();
+ if (mpa->j != mpb->j)
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2.f90
new file mode 100644
index 0000000..3b166f4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-2.f90
@@ -0,0 +1,157 @@
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-2-c.c dump-descriptors.c" }
+!
+! This program checks that calling a Fortran function with C binding and
+! an intent(out) argument works from both C and Fortran. For this
+! test case the argument is an assumed-rank array.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+! The call chains we'll be testing will be
+! main -> ctest -> ftest1
+! main -> ftest2 -> ftest1
+! main -> ftest1
+! where everything has "c" binding except main.
+
+! ftest1 has C binding and transposes a into b.
+
+subroutine ftest1 (a, b) bind (c, name="ftest1")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+
+ select rank (a)
+ rank (2)
+ select rank (b)
+ rank (2)
+ b = transpose (a)
+ rank default
+ stop 101
+ end select
+ rank default
+ stop 102
+ end select
+end subroutine
+
+! ftest2 has C binding and calls ftest1.
+
+subroutine ftest2 (a, b) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+
+ interface
+ subroutine ftest1 (a, b) bind (c, name="ftest1")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+ end subroutine
+ end interface
+
+ call ftest1 (a, b)
+ if (rank (a) .ne. 2) stop 201
+ if (rank (b) .ne. 2) stop 202
+end subroutine
+
+! main calls ftest2 directly and also indirectly from a C function ctest.
+! The former allows us to test intent(out) arguments passed back from a
+! Fortran routine with C binding to a regular Fortran routine, and the
+! latter tests passing them back from Fortran to C and C to Fortran.
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ftest1 (a, b) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+ end subroutine
+ subroutine ftest2 (a, b) bind (c, name="ftest2")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+ end subroutine
+ subroutine ctest (a, b) bind (c, name="ctest")
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m), intent(out) :: b(..)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax), bb(jmax,imax)
+ integer :: i, j
+
+ ! initialize
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ bb(j,i)%i = -1
+ bb(j,i)%j = -2
+ end do
+ end do
+
+ ! frob and check
+ call ftest1 (aa, bb)
+ do j = 1, jmax
+ do i = 1, imax
+ if (aa(i,j)%i .ne. bb(j,i)%i) stop 301
+ if (aa(i,j)%j .ne. bb(j,i)%j) stop 302
+ end do
+ end do
+
+ ! initialize again
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ bb(j,i)%i = -1
+ bb(j,i)%j = -2
+ end do
+ end do
+
+ ! frob and check
+ call ftest2 (aa, bb)
+ do j = 1, jmax
+ do i = 1, imax
+ if (aa(i,j)%i .ne. bb(j,i)%i) stop 401
+ if (aa(i,j)%j .ne. bb(j,i)%j) stop 402
+ end do
+ end do
+
+ ! initialize again
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ bb(j,i)%i = -1
+ bb(j,i)%j = -2
+ end do
+ end do
+
+ ! frob and check
+ call ctest (aa, bb)
+ do j = 1, jmax
+ do i = 1, imax
+ if (aa(i,j)%i .ne. bb(j,i)%i) stop 501
+ if (aa(i,j)%j .ne. bb(j,i)%j) stop 502
+ end do
+ end do
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3-c.c
new file mode 100644
index 0000000..b04293e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3-c.c
@@ -0,0 +1,108 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imagic, int jmagic);
+extern void frob (CFI_cdesc_t *a, CFI_cdesc_t *aa, CFI_cdesc_t *p);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imagic, int jmagic)
+{
+ CFI_CDESC_T(0) adesc;
+ CFI_CDESC_T(0) aadesc;
+ CFI_CDESC_T(0) bdesc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &adesc;
+ CFI_cdesc_t *aa = (CFI_cdesc_t *) &aadesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+
+ /* Create and sanity-check descriptors. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ dump_CFI_cdesc_t (a);
+ if (a->version != CFI_VERSION)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (aa, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ dump_CFI_cdesc_t (aa);
+ if (aa->version != CFI_VERSION)
+ abort ();
+ if (aa->rank != 0)
+ abort ();
+ if (aa->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (aa->base_addr)
+ abort ();
+ if (aa->elem_len != sizeof (struct m))
+ abort ();
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (aa, NULL, NULL, 0));
+ ((struct m *)aa->base_addr)->i = 0;
+ ((struct m *)aa->base_addr)->j = 0;
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 0)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Call back into Fortran, which will allocate and initialize the
+ objects. */
+ frob (a, aa, b);
+
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+ if (((struct m *)a->base_addr)->i != imagic)
+ abort ();
+ if (((struct m *)a->base_addr)->j != jmagic)
+ abort ();
+
+ if (!aa->base_addr)
+ abort ();
+ if (aa->elem_len != sizeof (struct m))
+ abort ();
+ if (((struct m *)aa->base_addr)->i != imagic)
+ abort ();
+ if (((struct m *)aa->base_addr)->j != jmagic)
+ abort ();
+
+ if (!b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+ if (((struct m *)b->base_addr)->i != imagic)
+ abort ();
+ if (((struct m *)b->base_addr)->j != jmagic)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3.f90
new file mode 100644
index 0000000..d85a78a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-3.f90
@@ -0,0 +1,134 @@
+! PR 92621 (?)
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that calling a Fortran function with C binding and
+! an intent(out) argument works from both C and Fortran. For this
+! test case the argument is an allocatable or pointer scalar.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imagic=-1, jmagic=42
+
+end module
+
+! The call chains being tested here are
+! main -> frob
+! main -> ftest -> frob
+! main -> ctest -> frob
+! where everything other than main has C binding.
+
+! frob allocates and initializes its arguments.
+! There are two allocatable dummies so that we can pass both
+! unallocated (a) and allocated (aa).
+
+subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a, aa
+ type(m), intent(out), pointer :: p
+
+ if (allocated (a)) stop 101
+ allocate (a)
+ a%i = imagic
+ a%j = jmagic
+
+ if (allocated (aa)) stop 102
+ allocate (aa)
+ aa%i = imagic
+ aa%j = jmagic
+
+ ! association status of p is undefined on entry
+ allocate (p)
+ p%i = imagic
+ p%j = jmagic
+end subroutine
+
+subroutine ftest () bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a, aa
+ type(m), pointer :: p
+
+ interface
+ subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a, aa
+ type(m), intent(out), pointer :: p
+ end subroutine
+ end interface
+
+ p => NULL ()
+ allocate (aa)
+ aa%i = 0
+ aa%j = 0
+ call frob (a, aa, p)
+
+ if (.not. allocated (a)) stop 201
+ if (a%i .ne. imagic) stop 202
+ if (a%j .ne. jmagic) stop 203
+
+ if (.not. allocated (aa)) stop 204
+ if (a%i .ne. imagic) stop 205
+ if (a%j .ne. jmagic) stop 206
+
+ if (.not. associated (p)) stop 207
+ if (p%i .ne. imagic) stop 208
+ if (p%j .ne. jmagic) stop 209
+
+end subroutine
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a, aa
+ type(m), intent(out), pointer :: p
+ end subroutine
+ subroutine ftest () bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ end subroutine
+ subroutine ctest (ii, jj) bind (c, name="ctest")
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ end subroutine
+ end interface
+
+ type(m), allocatable :: a, aa
+ type(m), pointer :: p
+
+ p => NULL ()
+ allocate (aa)
+ aa%i = 0
+ aa%j = 0
+ call frob (a, aa, p)
+
+ if (.not. allocated (a)) stop 201
+ if (a%i .ne. imagic) stop 202
+ if (a%j .ne. jmagic) stop 203
+
+ if (.not. allocated (aa)) stop 204
+ if (a%i .ne. imagic) stop 205
+ if (a%j .ne. jmagic) stop 206
+
+ if (.not. associated (p)) stop 207
+ if (p%i .ne. imagic) stop 208
+ if (p%j .ne. jmagic) stop 209
+
+ call ftest
+ call ctest (imagic, jmagic)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4-c.c
new file mode 100644
index 0000000..bf5db6f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4-c.c
@@ -0,0 +1,175 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imax, int jmax);
+extern void frob (CFI_cdesc_t *a, CFI_cdesc_t *aa, CFI_cdesc_t *p);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imax, int jmax)
+{
+ CFI_CDESC_T(2) adesc;
+ CFI_CDESC_T(2) aadesc;
+ CFI_CDESC_T(2) bdesc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &adesc;
+ CFI_cdesc_t *aa = (CFI_cdesc_t *) &aadesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ CFI_index_t i, j;
+ CFI_index_t s[2];
+ CFI_index_t lb[2], ub[2];
+ struct m* mp;
+
+ /* Create and sanity-check a. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ dump_CFI_cdesc_t (a);
+ if (a->version != CFI_VERSION)
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (aa, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ dump_CFI_cdesc_t (aa);
+ if (aa->version != CFI_VERSION)
+ abort ();
+ if (aa->rank != 2)
+ abort ();
+ if (aa->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (aa->base_addr)
+ abort ();
+ if (aa->elem_len != sizeof (struct m))
+ abort ();
+
+ /* aa is allocated/initialized so that we can confirm that it's
+ magically deallocated when passed as intent(out). */
+ lb[0] = 0;
+ lb[1] = 0;
+ ub[0] = jmax;
+ ub[1] = jmax;
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (aa, lb, ub, 0));
+ for (j = 1; j <= jmax; j++)
+ for (i = 1; i <= imax; i++)
+ {
+ s[0] = j;
+ s[1] = i;
+ mp = (struct m *)CFI_address (aa, s);
+ mp->i = 0;
+ mp->j = 0;
+ }
+
+ /* Likewise create and sanity-check b. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ dump_CFI_cdesc_t (b);
+ if (b->version != CFI_VERSION)
+ abort ();
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+
+ /* Call back into Fortran, which will allocate and initialize the
+ objects. */
+ frob (a, aa, b);
+
+ dump_CFI_cdesc_t (a);
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof (struct m))
+ abort ();
+ if (a->dim[0].lower_bound != 1)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 1)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+ for (j = 1; j <= jmax; j++)
+ for (i = 1; i <= imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mp = (struct m *)CFI_address (a, s);
+ if (mp->i != i)
+ abort ();
+ if (mp->j != j)
+ abort ();
+ }
+
+ dump_CFI_cdesc_t (aa);
+ if (!aa->base_addr)
+ abort ();
+ if (aa->elem_len != sizeof (struct m))
+ abort ();
+ if (aa->dim[0].lower_bound != 1)
+ abort ();
+ if (aa->dim[0].extent != imax)
+ abort ();
+ if (aa->dim[1].lower_bound != 1)
+ abort ();
+ if (aa->dim[1].extent != jmax)
+ abort ();
+ for (j = 1; j <= jmax; j++)
+ for (i = 1; i <= imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mp = (struct m *)CFI_address (aa, s);
+ if (mp->i != i)
+ abort ();
+ if (mp->j != j)
+ abort ();
+ }
+
+ dump_CFI_cdesc_t (b);
+ if (!b->base_addr)
+ abort ();
+ if (b->elem_len != sizeof (struct m))
+ abort ();
+ if (b->dim[0].lower_bound != 1)
+ abort ();
+ if (b->dim[0].extent != jmax)
+ abort ();
+ if (b->dim[1].lower_bound != 1)
+ abort ();
+ if (b->dim[1].extent != imax)
+ abort ();
+ for (j = 1; j <= jmax; j++)
+ for (i = 1; i <= imax; i++)
+ {
+ s[0] = j;
+ s[1] = i;
+ mp = (struct m *)CFI_address (b, s);
+ if (mp->i != i)
+ abort ();
+ if (mp->j != j)
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4.f90
new file mode 100644
index 0000000..e14c757
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-4.f90
@@ -0,0 +1,207 @@
+! PR 92621 (?)
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-4-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that calling a Fortran function with C binding and
+! an intent(out) argument works from both C and Fortran. For this
+! test case the argument is an allocatable or pointer array.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=5, jmax=10
+
+end module
+
+! The call chains being tested here are
+! main -> frob
+! main -> ftest -> frob
+! main -> ctest -> frob
+! where everything other than main has C binding.
+
+! frob allocates and initializes its arguments.
+! There are two allocatable dummies so that we can pass both
+! unallocated (a) and allocated (aa).
+
+subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a(:,:), aa(:,:)
+ type(m), intent(out), pointer :: p(:,:)
+ integer :: i, j
+
+ if (allocated (a)) stop 101
+ allocate (a (imax, jmax))
+ do j = 1, jmax
+ do i = 1, imax
+ a(i,j)%i = i
+ a(i,j)%j = j
+ end do
+ end do
+
+ if (allocated (aa)) stop 102
+ allocate (aa (imax, jmax))
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ allocate (p (jmax, imax))
+ do j = 1, jmax
+ do i = 1, imax
+ p(j,i)%i = i
+ p(j,i)%j = j
+ end do
+ end do
+end subroutine
+
+subroutine ftest () bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:,:), aa(:,:)
+ type(m), pointer :: p(:,:)
+
+ integer :: i, j
+
+ interface
+ subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a(:,:), aa(:,:)
+ type(m), intent(out), pointer :: p(:,:)
+ end subroutine
+ end interface
+
+ p => NULL ()
+ if (allocated (a) .or. allocated (aa)) stop 200
+ allocate (aa (jmax, imax))
+ do j = 1, jmax
+ do i = 1, imax
+ aa(j,i)%i = 0
+ aa(j,i)%j = 0
+ end do
+ end do
+ call frob (a, aa, p)
+
+ if (.not. allocated (a)) stop 201
+ if (lbound (a, 1) .ne. 1) stop 202
+ if (lbound (a, 2) .ne. 1) stop 203
+ if (ubound (a, 1) .ne. imax) stop 204
+ if (ubound (a, 2) .ne. jmax) stop 205
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 206
+ if (a(i,j)%j .ne. j) stop 207
+ end do
+ end do
+
+ if (.not. allocated (aa)) stop 211
+ if (lbound (aa, 1) .ne. 1) stop 212
+ if (lbound (aa, 2) .ne. 1) stop 213
+ if (ubound (aa, 1) .ne. imax) stop 214
+ if (ubound (aa, 2) .ne. jmax) stop 215
+ do j = 1, jmax
+ do i = 1, imax
+ if (aa(i,j)%i .ne. i) stop 216
+ if (aa(i,j)%j .ne. j) stop 217
+ end do
+ end do
+
+ if (.not. associated (p)) stop 221
+ if (lbound (p, 1) .ne. 1) stop 222
+ if (lbound (p, 2) .ne. 1) stop 223
+ if (ubound (p, 1) .ne. jmax) stop 224
+ if (ubound (p, 2) .ne. imax) stop 225
+ do j = 1, jmax
+ do i = 1, imax
+ if (p(j,i)%i .ne. i) stop 226
+ if (p(j,i)%j .ne. j) stop 227
+ end do
+ end do
+
+end subroutine
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine frob (a, aa, p) bind (c, name="frob")
+ use iso_c_binding
+ use mm
+ type(m), intent(out), allocatable :: a(:,:), aa(:,:)
+ type(m), intent(out), pointer :: p(:,:)
+ end subroutine
+ subroutine ftest () bind (c, name="ftest")
+ use iso_c_binding
+ use mm
+ end subroutine
+ subroutine ctest (ii, jj) bind (c, name="ctest")
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ end subroutine
+ end interface
+
+ type(m), allocatable :: a(:,:), aa(:,:)
+ type(m), pointer :: p(:,:)
+ integer :: i, j
+
+ p => NULL ()
+ if (allocated (a) .or. allocated (aa)) stop 300
+ allocate (aa (jmax, imax))
+ do j = 1, jmax
+ do i = 1, imax
+ aa(j,i)%i = 0
+ aa(j,i)%j = 0
+ end do
+ end do
+ call frob (a, aa, p)
+
+ if (.not. allocated (a)) stop 301
+ if (lbound (a, 1) .ne. 1) stop 302
+ if (lbound (a, 2) .ne. 1) stop 303
+ if (ubound (a, 1) .ne. imax) stop 304
+ if (ubound (a, 2) .ne. jmax) stop 305
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 306
+ if (a(i,j)%j .ne. j) stop 307
+ end do
+ end do
+
+ if (.not. allocated (aa)) stop 311
+ if (lbound (aa, 1) .ne. 1) stop 312
+ if (lbound (aa, 2) .ne. 1) stop 313
+ if (ubound (aa, 1) .ne. imax) stop 314
+ if (ubound (aa, 2) .ne. jmax) stop 315
+ do j = 1, jmax
+ do i = 1, imax
+ if (aa(i,j)%i .ne. i) stop 316
+ if (aa(i,j)%j .ne. j) stop 317
+ end do
+ end do
+
+ if (.not. associated (p)) stop 321
+ if (lbound (p, 1) .ne. 1) stop 322
+ if (lbound (p, 2) .ne. 1) stop 323
+ if (ubound (p, 1) .ne. jmax) stop 324
+ if (ubound (p, 2) .ne. imax) stop 325
+ do j = 1, jmax
+ do i = 1, imax
+ if (p(j,i)%i .ne. i) stop 326
+ if (p(j,i)%j .ne. j) stop 327
+ end do
+ end do
+
+ call ftest
+ call ctest (imax, jmax)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5-c.c
new file mode 100644
index 0000000..e5b37f3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5-c.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, int n);
+extern void ftest (CFI_cdesc_t *a, int n);
+
+void
+ctest (CFI_cdesc_t *a, int n)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The actual argument object on the Fortran side has length n and
+ was passed as character(len=*).
+ Make sure that matches what's in the descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != n)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->type != CFI_type_char)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ ftest (a, n);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5.f90
new file mode 100644
index 0000000..b0dd20c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-5.f90
@@ -0,0 +1,48 @@
+! PR92482
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-5-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks use of an assumed-length character dummy argument
+! as an intent(out) parameter in subroutines with C binding.
+
+subroutine ftest (a, n) bind (c, name="ftest")
+ use iso_c_binding
+ character(kind=C_CHAR, len=*), intent(out) :: a
+ integer(C_INT), value :: n
+
+ if (len (a) .ne. n) stop 101
+ a = 'abcdefghijklmnopqrstuvwxyz'
+end subroutine
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a, n) bind (c)
+ use iso_c_binding
+ character(kind=C_CHAR, len=*), intent(out) :: a
+ integer(C_INT), value :: n
+ end subroutine
+
+ subroutine ftest (a, n) bind (c)
+ use iso_c_binding
+ character(kind=C_CHAR, len=*), intent(out) :: a
+ integer(C_INT), value :: n
+ end subroutine
+ end interface
+
+ character(kind=C_CHAR, len=42) :: aa
+
+ ! call ftest directly
+ aa = '12345678910'
+ call ftest (aa, 42)
+ print *, aa
+
+ ! ctest calls ftest indirectly
+ aa = '12345678910'
+ call ctest (aa, 42)
+ print *, aa
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6-c.c b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6-c.c
new file mode 100644
index 0000000..f8724b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6-c.c
@@ -0,0 +1,42 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, int n);
+extern void ftest (CFI_cdesc_t *a, int n);
+
+void
+ctest (CFI_cdesc_t *a, int n)
+{
+ int i;
+ CFI_index_t s[1];
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != -1)
+ abort ();
+
+ ftest (a, n);
+
+ for (i = 0; i < n; i++)
+ {
+ s[0] = i;
+ if (*((int *)CFI_address (a, s)) != i + 1)
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90
new file mode 100644
index 0000000..bc19a71
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/cf-out-descriptor-6.f90
@@ -0,0 +1,115 @@
+! Reported as pr94070.
+! { dg-do run }
+! { dg-additional-sources "cf-out-descriptor-6-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks passing an assumed-size array as an intent(out)
+! argument to a bind (c) Fortran function from both C and Fortran.
+
+! Assumed-size arrays are not passed by descriptor. What we'll do
+! for this test function is pass the assumed-size array as the actual
+! argument corresponding to an assumed-rank dummy. This is supposed to
+! fill in the descriptor with information about the array present at
+! the call site.
+
+subroutine ftest (a, n) bind (c, name="ftest")
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(..)
+ integer(C_INT), value :: n
+ integer :: i
+
+ ! TS 29113
+ ! 6.4.2 SIZE
+ ! (1) for an assumed-rank object that is associated with an
+ ! assumed-size array, the result has the value −1 if DIM is
+ ! present and equal to the rank of ARRAY
+ if (rank (a) .ne. 1) stop 102
+ if (size (a, rank (a)) .ne. -1) stop 100
+ if (lbound (a, rank (a)) .ne. 1) stop 101
+
+ select rank (a)
+ rank (*)
+ do i = 1, n
+ a(i) = i
+ end do
+ rank default
+ stop 102
+ end select
+end subroutine
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a, n) bind (c, name="ctest")
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(..)
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine ftest (a, n) bind (c, name="ftest")
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(..)
+ integer(C_INT), value :: n
+ end subroutine
+ end interface
+
+ integer(C_INT), target :: aa(10)
+
+ ! To get an assumed-size array descriptor, we have to first pass the
+ ! fixed-size array to a Fortran function with an assumed-size dummy,
+ call ftest1 (aa, 10) ! calls ftest
+ call ftest2 (aa, 10) ! has c binding, calls ftest
+ call ftest3 (aa, 10) ! calls ctest -> ftest
+ call ftest4 (aa, 10) ! has c binding, calls ctest -> ftest
+
+contains
+
+ subroutine ftest1 (a, n)
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(*)
+ integer(C_INT), value :: n
+ integer :: i
+ a(1:n) = 0
+ call ftest (a, n)
+ do i = 1, n
+ if (a (i) .ne. i) stop 200
+ end do
+ end subroutine
+
+ subroutine ftest2 (a, n) bind (c)
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(*)
+ integer(C_INT), value :: n
+ integer :: i
+ a(1:n) = 0
+ call ftest (a, n)
+ do i = 1, n
+ if (a (i) .ne. i) stop 201
+ end do
+ end subroutine
+
+ subroutine ftest3 (a, n)
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(*)
+ integer(C_INT), value :: n
+ integer :: i
+ a(1:n) = 0
+ call ctest (a, n)
+ do i = 1, n
+ if (a (i) .ne. i) stop 202
+ end do
+ end subroutine
+
+ subroutine ftest4 (a, n) bind (c)
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(*)
+ integer(C_INT), value :: n
+ integer :: i
+ a(1:n) = 0
+ call ctest (a, n)
+ do i = 1, n
+ if (a (i) .ne. i) stop 203
+ end do
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/contiguous-1-c.c
new file mode 100644
index 0000000..6b30da4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-1-c.c
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest1 (CFI_cdesc_t *a);
+extern void ctest2 (CFI_cdesc_t *a);
+
+static void
+ctest (CFI_cdesc_t *a)
+{
+ int i;
+ int *p;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* Make sure we got a valid descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].sm != sizeof(int))
+ abort ();
+ if (!CFI_is_contiguous (a))
+ abort ();
+
+ /* Negate the elements of the array. */
+ p = (int *)a->base_addr;
+ for (i = 0; i < a->dim[0].extent; i++)
+ p[i] = -p[i];
+}
+
+
+/* The two entry points are declared differently on the C side, but both
+ should do the same thing. */
+
+void
+ctest1 (CFI_cdesc_t *a)
+{
+ ctest (a);
+}
+
+void
+ctest2 (CFI_cdesc_t *a)
+{
+ ctest (a);
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/contiguous-1.f90
new file mode 100644
index 0000000..fe1c982
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-1.f90
@@ -0,0 +1,67 @@
+! { dg-do run }
+! { dg-additional-sources "contiguous-1-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! TS 29113
+! 8.7 In an invocation of an interoperable procedure whose Fortran
+! interface has an assumed-shape or assumed-rank dummy argument with the
+! CONTIGUOUS attribute, the associated effective argument may be an
+! array that is not contiguous or the address of a C descriptor for such
+! an array. If the procedure is invoked from Fortran or the procedure is
+! a Fortran procedure, the Fortran processor will handle the difference
+! in contiguity. If the procedure is invoked from C and the procedure is
+! a C procedure, the C code within the procedure shall be prepared to
+! handle the situation of receiving a discontiguous argument.
+!
+! This program tests the cases where Fortran code passes a non-contiguous
+! array section to a C function whose interface has the contiguous
+! attribute.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ ! ctest1 and ctest2 both negate the elements of their input array.
+ subroutine ctest1 (a) bind (c)
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(:)
+ end subroutine
+ subroutine ctest2 (a) bind (c)
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(..)
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(32)
+ integer :: i
+
+ ! assumed-shape
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest1 (aa(4:12:2))
+ do i = 1, 32
+ if (i .ge. 4 .and. i .le. 12 .and. mod (i-4,2) .eq. 0) then
+ if (aa (i) .ne. -i) stop 101
+ else
+ if (aa (i) .ne. i) stop 102
+ end if
+ end do
+
+ ! assumed-rank
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest2 (aa(7:19:3))
+ do i = 1, 32
+ if (i .ge. 7 .and. i .le. 19 .and. mod (i-7,3) .eq. 0) then
+ if (aa (i) .ne. -i) stop 201
+ else
+ if (aa (i) .ne. i) stop 202
+ end if
+ end do
+
+end program
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/contiguous-2-c.c
new file mode 100644
index 0000000..5a8f3d6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-2-c.c
@@ -0,0 +1,113 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest1 (CFI_cdesc_t *a);
+extern void ctest2 (CFI_cdesc_t *a);
+extern void ftest1 (CFI_cdesc_t *a, int first, int last, int step);
+extern void ftest2 (CFI_cdesc_t *a, int first, int last, int step);
+
+#if 0
+static void
+dump_array (CFI_cdesc_t *a, const char *name, const char *note)
+{
+ int i;
+
+ fprintf (stderr, "%s\n", note);
+ for (i = 0; i < a->dim[0].extent; i++)
+ {
+ int j = i + a->dim[0].lower_bound;
+ int elt;
+ CFI_index_t sub[1];
+ sub[0] = j;
+ elt = *((int *) CFI_address (a, sub));
+ fprintf (stderr, "%s[%d] = %d\n", name, j, elt);
+ }
+ fprintf (stderr, "\n");
+}
+#else
+#define dump_array(a, name, note)
+#endif
+
+static void
+ctest (CFI_cdesc_t *a, int lb, int ub, int s,
+ void (*fn) (CFI_cdesc_t *, int, int, int))
+{
+ CFI_CDESC_T(1) bdesc;
+ CFI_cdesc_t *b = (CFI_cdesc_t *) &bdesc;
+ CFI_index_t lb_array[1], ub_array[1], s_array[1];
+ int i;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* Make sure we got a valid descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+
+ /* Create an array section and pass it to fn. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (b, NULL, CFI_attribute_other,
+ CFI_type_int,
+ sizeof (int), 1, NULL));
+ lb_array[0] = lb - 1 + a->dim[0].lower_bound;
+ ub_array[0] = ub - 1 + a->dim[0].lower_bound;
+ s_array[0] = s;
+ check_CFI_status ("CFI_section",
+ CFI_section (b, a, lb_array, ub_array, s_array));
+ dump_CFI_cdesc_t (b);
+ dump_array (b, "b", "b after CFI_section");
+
+ /* Pass it to the Fortran function fn. */
+ if (CFI_is_contiguous (b))
+ abort ();
+ (*fn) (b, lb, ub, s);
+ dump_CFI_cdesc_t (b);
+ dump_array (b, "b", "b after calling Fortran fn");
+
+ /* fn is supposed to negate the elements of the array section it
+ receives. Check that the original array has been updated. */
+ dump_array (a, "a", "a after calling Fortran fn");
+ for (i = 0; i < a->dim[0].extent; i++)
+ {
+ int elt;
+ int j = i + a->dim[0].lower_bound;
+ CFI_index_t sub[1];
+ sub[0] = j;
+ elt = *((int *) CFI_address (a, sub));
+ if (i + 1 >= lb && i + 1 <= ub && (i + 1 - lb) % s == 0)
+ {
+ if (elt != - (i + 1))
+ abort ();
+ }
+ else if (elt != (i + 1))
+ abort ();
+ }
+}
+
+
+/* Entry points for the Fortran side. */
+
+void
+ctest1 (CFI_cdesc_t *a)
+{
+ ctest (a, 5, 13, 2, ftest1);
+}
+
+void
+ctest2 (CFI_cdesc_t *a)
+{
+ ctest (a, 8, 20, 3, ftest2);
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/contiguous-2.f90
new file mode 100644
index 0000000..195ec8c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-2.f90
@@ -0,0 +1,152 @@
+! PR 101304
+! { dg-do run }
+! { dg-additional-sources "contiguous-2-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! TS 29113
+! 8.7 In an invocation of an interoperable procedure whose Fortran
+! interface has an assumed-shape or assumed-rank dummy argument with the
+! CONTIGUOUS attribute, the associated effective argument may be an
+! array that is not contiguous or the address of a C descriptor for such
+! an array. If the procedure is invoked from Fortran or the procedure is
+! a Fortran procedure, the Fortran processor will handle the difference
+! in contiguity. If the procedure is invoked from C and the procedure is
+! a C procedure, the C code within the procedure shall be prepared to
+! handle the situation of receiving a discontiguous argument.
+!
+! The wording is different in the 2018 standard, but the intent is more
+! or less the same:
+!
+! When an interoperable Fortran procedure that is invoked from C has a
+! dummy argument with the CONTIGUOUS attribute or that is an assumed-length
+! CHARACTER explicit-shape or assumed-size array, and the actual argument
+! is the address of a C descriptor for a discontiguous object, the Fortran
+! processor shall handle the difference in contiguity.
+!
+! This program tests the cases where a Fortran procedure with C binding and
+! a dummy array argument with the contiguous attribute is invoked from
+! both C or Fortran.
+
+! ftest1 and ftest2 both negate the elements of their input array;
+! this allows testing that modifications to the array contents get
+! propagated back to the base array.
+
+module m
+
+ contains
+
+ subroutine ftest1 (a, first, last, step) bind (c)
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(:)
+ integer(C_INT), value :: first, last, step
+ integer :: i, ival
+
+ ! Sanity checking that we got a contiguous array. The direct call
+ ! to is_contiguous might be optimized away, but the indirect one
+ ! in check_contiguous shouldn't be.
+ ! FIXME: is this correct? "the Fortran processor will handle the
+ ! difference in contiguity" may not mean that it's required to make
+ ! the array contiguous, just that it can access it correctly?
+ if (.not. is_contiguous (a)) stop 301
+ call check_contiguous (a)
+
+ ! Sanity checking that we got the right input array contents.
+ ! print *, 'a on entry to ftest1'
+ ! do i = lbound(a, 1), ubound(a, 1)
+ ! print *, 'a(', i, ') = ', a(i)
+ ! end do
+ ival = first
+ do i = lbound(a, 1), ubound(a, 1)
+ if (a (i) .ne. ival) then
+ print *, 'a(', i, ') = ', a(i), ' expected ', ival
+ stop 302
+ end if
+ a(i) = - a(i)
+ ival = ival + step
+ end do
+ end subroutine
+
+ subroutine ftest2 (a, first, last, step) bind (c)
+ use iso_c_binding
+
+ integer(C_INT), contiguous :: a(..)
+ integer(C_INT), value :: first, last, step
+
+ select rank (a)
+ rank (1)
+ call ftest1 (a(:), first, last, step)
+ rank default
+ stop 303
+ end select
+ end subroutine
+
+ subroutine check_contiguous (a)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ if (.not. is_contiguous (a)) stop 304
+ end subroutine
+
+end module
+
+
+program testit
+ use iso_c_binding
+ use m
+ implicit none
+
+ interface
+ subroutine ctest1 (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:)
+ end subroutine
+ subroutine ctest2 (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(32)
+ integer :: i
+
+ ! assumed-shape, called from Fortran
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ftest1 (aa(4:12:2), 4, 12, 2)
+ do i = 1, 32
+ if (i .ge. 4 .and. i .le. 12 .and. mod (i-4,2) .eq. 0) then
+ if (aa (i) .ne. -i) stop 101
+ else
+ if (aa (i) .ne. i) stop 102
+ end if
+ end do
+
+ ! assumed-shape, called from C code which will use the C interface
+ ! to create a non-contiguous array section and pass it to ftest1.
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest1 (aa)
+
+ ! assumed-rank, called from Fortran
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ftest2 (aa(7:19:3), 7, 19, 3)
+ do i = 1, 32
+ if (i .ge. 7 .and. i .le. 19 .and. mod (i-7,3) .eq. 0) then
+ if (aa (i) .ne. -i) stop 201
+ else
+ if (aa (i) .ne. i) stop 202
+ end if
+ end do
+
+ ! assumed-rank, called from C code which will use the C interface
+ ! to create a non-contiguous array section and pass it to ftest2.
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest2 (aa)
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/contiguous-3-c.c
new file mode 100644
index 0000000..b124476
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-3-c.c
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest1 (CFI_cdesc_t *a, int first, int last, int step);
+extern void ctest2 (CFI_cdesc_t *a, int first, int last, int step);
+extern void ftest1 (CFI_cdesc_t *a, int first, int last, int step);
+extern void ftest2 (CFI_cdesc_t *a, int first, int last, int step);
+
+#if 0
+static void
+dump_array (CFI_cdesc_t *a, const char *name, const char *note)
+{
+ int i;
+
+ fprintf (stderr, "%s\n", note);
+ for (i = 0; i < a->dim[0].extent; i++)
+ {
+ int j = i + a->dim[0].lower_bound;
+ int elt;
+ CFI_index_t sub[1];
+ sub[0] = j;
+ elt = *((int *) CFI_address (a, sub));
+ fprintf (stderr, "%s[%d] = %d\n", name, j, elt);
+ }
+ fprintf (stderr, "\n");
+}
+#else
+#define dump_array(a, name, note)
+#endif
+
+static void
+ctest (CFI_cdesc_t *a, int first, int last, int step,
+ void (*fn) (CFI_cdesc_t *, int, int, int))
+{
+ int i;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+ dump_array (a, "a", "a on input to ctest");
+
+ /* Make sure we got a valid descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+
+ /* Pass it to the Fortran function fn. */
+ (*fn) (a, first, last, step);
+ dump_CFI_cdesc_t (a);
+ dump_array (a, "a", "a after calling Fortran fn");
+}
+
+/* Entry points for the Fortran side.
+ Note that the Fortran code has already created the array section
+ and these functions were declared without the CONTIGUOUS attribute
+ so they receive a non-contiguous array. The magic is supposed to
+ happen when we pass them back into a Fortran function declared with
+ the CONTIGUOUS attribute. */
+
+void
+ctest1 (CFI_cdesc_t *a, int first, int last, int step)
+{
+ ctest (a, first, last, step, ftest1);
+}
+
+void
+ctest2 (CFI_cdesc_t *a, int first, int last, int step)
+{
+ ctest (a, first, last, step, ftest2);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/contiguous-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/contiguous-3.f90
new file mode 100644
index 0000000..0a29572
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/contiguous-3.f90
@@ -0,0 +1,171 @@
+! PR 101304
+! { dg-do run }
+! { dg-additional-sources "contiguous-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! TS 29113
+! 8.7 In an invocation of an interoperable procedure whose Fortran
+! interface has an assumed-shape or assumed-rank dummy argument with the
+! CONTIGUOUS attribute, the associated effective argument may be an
+! array that is not contiguous or the address of a C descriptor for such
+! an array. If the procedure is invoked from Fortran or the procedure is
+! a Fortran procedure, the Fortran processor will handle the difference
+! in contiguity. If the procedure is invoked from C and the procedure is
+! a C procedure, the C code within the procedure shall be prepared to
+! handle the situation of receiving a discontiguous argument.
+!
+! The wording is different in the 2018 standard, but the intent is more
+! or less the same:
+!
+! When an interoperable Fortran procedure that is invoked from C has a
+! dummy argument with the CONTIGUOUS attribute or that is an assumed-length
+! CHARACTER explicit-shape or assumed-size array, and the actual argument
+! is the address of a C descriptor for a discontiguous object, the Fortran
+! processor shall handle the difference in contiguity.
+!
+! This program tests the cases where a Fortran procedure with C binding and
+! a dummy array argument with the contiguous attribute is invoked from
+! both C or Fortran. It is similar to contiguous-2.f90 but here the array
+! sections are created in Fortran even in the called-from-C case, rather
+! than by calling CFI_section.
+
+! ftest1 and ftest2 both negate the elements of their input array;
+! this allows testing that modifications to the array contents get
+! propagated back to the base array.
+
+module m
+
+ contains
+
+ subroutine ftest1 (a, first, last, step) bind (c)
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(:)
+ integer(C_INT), value :: first, last, step
+ integer :: i, ival
+
+ ! Sanity checking that we got a contiguous array. The direct call
+ ! to is_contiguous might be optimized away, but the indirect one
+ ! in check_contiguous shouldn't be.
+ ! FIXME: is this correct? "the Fortran processor will handle the
+ ! difference in contiguity" may not mean that it's required to make
+ ! the array contiguous, just that it can access it correctly?
+ if (.not. is_contiguous (a)) stop 301
+ call check_contiguous (a)
+
+ ! Sanity checking that we got the right input array contents.
+ ! print *, 'a on entry to ftest1'
+ ! do i = lbound(a, 1), ubound(a, 1)
+ ! print *, 'a(', i, ') = ', a(i)
+ ! end do
+ ival = first
+ do i = lbound(a, 1), ubound(a, 1)
+ if (a (i) .ne. ival) then
+ print *, 'a(', i, ') = ', a(i), ' expected ', ival
+ stop 302
+ end if
+ a(i) = - a(i)
+ ival = ival + step
+ end do
+ end subroutine
+
+ subroutine ftest2 (a, first, last, step) bind (c)
+ use iso_c_binding
+
+ integer(C_INT), contiguous :: a(..)
+ integer(C_INT), value :: first, last, step
+
+ select rank (a)
+ rank (1)
+ call ftest1 (a(:), first, last, step)
+ rank default
+ stop 303
+ end select
+ end subroutine
+
+ subroutine check_contiguous (a)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ if (.not. is_contiguous (a)) stop 304
+ end subroutine
+
+end module
+
+
+program testit
+ use iso_c_binding
+ use m
+ implicit none
+
+ ! Note ctest1 and ctest2 do not have the contiguous attribute on a.
+ interface
+ subroutine ctest1 (a, first, last, step) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:)
+ integer(C_INT), value :: first, last, step
+ end subroutine
+ subroutine ctest2 (a, first, last, step) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ integer(C_INT), value :: first, last, step
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(32)
+ integer :: i
+
+ ! assumed-shape, called from Fortran
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ftest1 (aa(4:12:2), 4, 12, 2)
+ do i = 1, 32
+ if (i .ge. 4 .and. i .le. 12 .and. mod (i-4,2) .eq. 0) then
+ if (aa (i) .ne. -i) stop 101
+ else
+ if (aa (i) .ne. i) stop 102
+ end if
+ end do
+
+ ! assumed-shape, called indirectly from C code, using an array
+ ! section created in Fortran instead of by CFI_section
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest1 (aa(5:13:2), 5, 13, 2)
+ do i = 1, 32
+ if (i .ge. 5 .and. i .le. 13 .and. mod (i-5,2) .eq. 0) then
+ if (aa (i) .ne. -i) stop 103
+ else
+ if (aa (i) .ne. i) stop 104
+ end if
+ end do
+
+ ! assumed-rank, called from Fortran
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ftest2 (aa(7:19:3), 7, 19, 3)
+ do i = 1, 32
+ if (i .ge. 7 .and. i .le. 19 .and. mod (i-7,3) .eq. 0) then
+ if (aa (i) .ne. -i) stop 201
+ else
+ if (aa (i) .ne. i) stop 202
+ end if
+ end do
+
+ ! assumed-rank, called indirectly from C code, using an array
+ ! section created in Fortran instead of by CFI_section
+ do i = 1, 32
+ aa(i) = i
+ end do
+ call ctest2 (aa(8:20:3), 8, 20, 3)
+ do i = 1, 32
+ if (i .ge. 8 .and. i .le. 20 .and. mod (i-8,3) .eq. 0) then
+ if (aa (i) .ne. -i) stop 203
+ else
+ if (aa (i) .ne. i) stop 204
+ end if
+ end do
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/deferred-character-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-1.f90
new file mode 100644
index 0000000..3c3c257
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-1.f90
@@ -0,0 +1,76 @@
+! PR92482
+! { dg-do compile}
+!
+! TS 29113
+! 8.7 Interoperability of procedures and procedure interfaces
+!
+! If a dummy argument in an interoperable interface is of type
+! CHARACTER and is allocatable or a pointer, its character length shall
+! be deferred.
+!
+! This test checks that this error is diagnosed and is supposed to fail.
+
+module m
+ use iso_c_binding
+
+ interface
+
+ ! These are supposed to be OK
+ subroutine good1 (x, n) bind (c)
+ use iso_c_binding
+ character (kind=C_CHAR, len=:), allocatable :: x
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine good2 (x, n) bind (c)
+ use iso_c_binding
+ character (kind=C_CHAR, len=:), pointer :: x
+ integer(C_INT), value :: n
+ end subroutine
+
+ ! These are supposed to fail.
+ subroutine bad1 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=*), allocatable :: x
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine bad2 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=*), pointer :: x
+ integer(C_INT), value :: n
+ end subroutine
+
+ subroutine bad3 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=80), allocatable :: x
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine bad4 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=80), pointer :: x
+ integer(C_INT), value :: n
+ end subroutine
+
+ subroutine bad5 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=1), allocatable :: x
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine bad6 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR, len=1), pointer :: x
+ integer(C_INT), value :: n
+ end subroutine
+
+ subroutine bad7 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR), allocatable :: x
+ integer(C_INT), value :: n
+ end subroutine
+ subroutine bad8 (x, n) bind (c) ! { dg-error "must have deferred length" }
+ use iso_c_binding
+ character (kind=C_CHAR), pointer :: x
+ integer(C_INT), value :: n
+ end subroutine
+ end interface
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90
new file mode 100644
index 0000000..356097a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90
@@ -0,0 +1,55 @@
+! PR 92482
+! { dg-do execute}
+!
+! TS 29113
+! 8.7 Interoperability of procedures and procedure interfaces
+!
+! If a dummy argument in an interoperable interface is of type
+! CHARACTER and is allocatable or a pointer, its character length shall
+! be deferred.
+
+program testit
+ use iso_c_binding
+
+ character (kind=C_CHAR, len=:), allocatable :: aa
+ character (kind=C_CHAR, len=:), pointer :: pp
+
+
+ pp => NULL ()
+
+ call frobf (aa, pp)
+ if (.not. allocated (aa)) stop 101
+ if (aa .ne. 'foo') stop 102
+ if (.not. associated (pp)) stop 103
+ if (pp .ne. 'bar') stop 104
+
+ pp => NULL ()
+
+ call frobc (aa, pp)
+ if (.not. allocated (aa)) stop 101
+ if (aa .ne. 'frog') stop 102
+ if (.not. associated (pp)) stop 103
+ if (pp .ne. 'toad') stop 104
+
+
+ contains
+
+ subroutine frobf (a, p)
+ use iso_c_binding
+ character (kind=C_CHAR, len=:), allocatable :: a
+ character (kind=C_CHAR, len=:), pointer :: p
+ allocate (character(len=3) :: p)
+ a = 'foo'
+ p = 'bar'
+ end subroutine
+
+ subroutine frobc (a, p) bind (c)
+ use iso_c_binding
+ character (kind=C_CHAR, len=:), allocatable :: a
+ character (kind=C_CHAR, len=:), pointer :: p
+ allocate (character(len=4) :: p)
+ a = 'frog'
+ p = 'toad'
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.c b/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.c
new file mode 100644
index 0000000..47e84e2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.c
@@ -0,0 +1,195 @@
+/* This file contains some useful routines for debugging problems with C
+ descriptors. Compiling it also acts as a test that the implementation of
+ ISO_Fortran_binding.h provides all the types and constants specified in
+ TS29113. */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "dump-descriptors.h"
+
+void
+dump_CFI_cdesc_t (CFI_cdesc_t *d)
+{
+ fprintf (stderr, "<CFI_cdesc_t base_addr=%p elem_len=%ld version=%d",
+ d->base_addr, (long)(d->elem_len), d->version);
+ fprintf (stderr, "\n rank=");
+ dump_CFI_rank_t (d->rank);
+ fprintf (stderr, " type=");
+ dump_CFI_type_t (d->type);
+ fprintf (stderr, " attribute=");
+ dump_CFI_attribute_t (d->attribute);
+
+ /* Dimension info may not be initialized if it's an allocatable
+ or pointer descriptor with a null base_addr. */
+ if (d->rank > 0 && d->base_addr)
+ {
+ CFI_rank_t i;
+ for (i = 0; i < d->rank; i++)
+ {
+ if (i == 0)
+ fprintf (stderr, "\n dim=[");
+ else
+ fprintf (stderr, ",\n ");
+ dump_CFI_dim_t (d->dim + i);
+ }
+ fprintf (stderr, "]");
+ }
+ fprintf (stderr, ">\n");
+}
+
+void
+dump_CFI_dim_t (CFI_dim_t *d)
+{
+ fprintf (stderr, "<CFI_dim_t lower_bound=");
+ dump_CFI_index_t (d->lower_bound);
+ fprintf (stderr, " extent=");
+ dump_CFI_index_t (d->extent);
+ fprintf (stderr, " sm=");
+ dump_CFI_index_t (d->sm);
+ fprintf (stderr, ">");
+}
+
+void
+dump_CFI_attribute_t (CFI_attribute_t a)
+{
+ switch (a)
+ {
+ case CFI_attribute_pointer:
+ fprintf (stderr, "CFI_attribute_pointer");
+ break;
+ case CFI_attribute_allocatable:
+ fprintf (stderr, "CFI_attribute_allocatable");
+ break;
+ case CFI_attribute_other:
+ fprintf (stderr, "CFI_attribute_other");
+ break;
+ default:
+ fprintf (stderr, "unknown(%d)", (int)a);
+ break;
+ }
+}
+
+void
+dump_CFI_index_t (CFI_index_t i)
+{
+ fprintf (stderr, "%ld", (long)i);
+}
+
+void
+dump_CFI_rank_t (CFI_rank_t r)
+{
+ fprintf (stderr, "%d", (int)r);
+}
+
+/* We can't use a switch statement to dispatch CFI_type_t because
+ the type name macros may not be unique. Iterate over a table
+ instead. */
+
+struct type_name_map {
+ CFI_type_t t;
+ const char *n;
+};
+
+struct type_name_map type_names[] =
+{
+ { CFI_type_signed_char, "CFI_type_signed_char" },
+ { CFI_type_short, "CFI_type_short" },
+ { CFI_type_int, "CFI_type_int" },
+ { CFI_type_long, "CFI_type_long" },
+ { CFI_type_long_long, "CFI_type_long_long" },
+ { CFI_type_size_t, "CFI_type_size_t" },
+ { CFI_type_int8_t, "CFI_type_int8_t" },
+ { CFI_type_int16_t, "CFI_type_int16_t" },
+ { CFI_type_int32_t, "CFI_type_int32_t" },
+ { CFI_type_int64_t, "CFI_type_int64_t" },
+ { CFI_type_int_least8_t, "CFI_type_int_least8_t" },
+ { CFI_type_int_least16_t, "CFI_type_int_least16_t" },
+ { CFI_type_int_least32_t, "CFI_type_int_least32_t" },
+ { CFI_type_int_least64_t, "CFI_type_int_least64_t" },
+ { CFI_type_int_fast8_t, "CFI_type_int_fast8_t" },
+ { CFI_type_int_fast16_t, "CFI_type_int_fast16_t" },
+ { CFI_type_int_fast32_t, "CFI_type_int_fast32_t" },
+ { CFI_type_int_fast64_t, "CFI_type_int_fast64_t" },
+ { CFI_type_intmax_t, "CFI_type_intmax_t" },
+ { CFI_type_intptr_t, "CFI_type_intptr_t" },
+ { CFI_type_ptrdiff_t, "CFI_type_ptrdiff_t" },
+ { CFI_type_float, "CFI_type_float" },
+ { CFI_type_double, "CFI_type_double" },
+ { CFI_type_long_double, "CFI_type_long_double" },
+ { CFI_type_float_Complex, "CFI_type_float_Complex" },
+ { CFI_type_double_Complex, "CFI_type_double_Complex" },
+ { CFI_type_long_double_Complex, "CFI_type_long_double_Complex" },
+ { CFI_type_Bool, "CFI_type_Bool" },
+ { CFI_type_char, "CFI_type_char" },
+ { CFI_type_cptr, "CFI_type_cptr" },
+ { CFI_type_struct, "CFI_type_struct" },
+ { CFI_type_other, "CFI_type_other" },
+ /* Extension types */
+ { CFI_type_int128_t, "CFI_type_int128_t" },
+ { CFI_type_int_least128_t, "CFI_type_int_least128_t" },
+ { CFI_type_int_fast128_t, "CFI_type_int_fast128_t" },
+ { CFI_type_ucs4_char, "CFI_type_ucs4_char" },
+ { CFI_type_float128, "CFI_type_float128" },
+ { CFI_type_float128_Complex, "CFI_type_float128_Complex" },
+ { CFI_type_cfunptr, "CFI_type_cfunptr" }
+};
+
+void
+dump_CFI_type_t (CFI_type_t t)
+{
+ int i;
+ for (i = 0; i < sizeof (type_names) / sizeof (struct type_name_map); i++)
+ if (type_names[i].t == t)
+ {
+ fprintf (stderr, "%s", type_names[i].n);
+ return;
+ }
+ fprintf (stderr, "unknown(%d)", (int)t);
+}
+
+void
+check_CFI_status (const char *fn, int code)
+{
+ const char *msg;
+ switch (code)
+ {
+ case CFI_SUCCESS:
+ return;
+ case CFI_ERROR_BASE_ADDR_NULL:
+ msg = "CFI_ERROR_BASE_ADDR_NULL";
+ break;
+ case CFI_ERROR_BASE_ADDR_NOT_NULL:
+ msg = "CFI_ERROR_BASE_ADDR_NOT_NULL";
+ break;
+ case CFI_INVALID_ELEM_LEN:
+ msg = "CFI_INVALID_ELEM_LEN";
+ break;
+ case CFI_INVALID_RANK:
+ msg = "CFI_INVALID_RANK";
+ break;
+ case CFI_INVALID_TYPE:
+ msg = "CFI_INVALID_TYPE";
+ break;
+ case CFI_INVALID_ATTRIBUTE:
+ msg = "CFI_INVALID_ATTRIBUTE";
+ break;
+ case CFI_INVALID_EXTENT:
+ msg = "CFI_INVALID_EXTENT";
+ break;
+ case CFI_INVALID_DESCRIPTOR:
+ msg = "CFI_INVALID_DESCRIPTOR";
+ break;
+ case CFI_ERROR_MEM_ALLOCATION:
+ msg = "CFI_ERROR_MEM_ALLOCATION";
+ break;
+ case CFI_ERROR_OUT_OF_BOUNDS:
+ msg = "CFI_ERROR_OUT_OF_BOUNDS";
+ break;
+ default:
+ msg = "unknown error";
+ break;
+ }
+ fprintf (stderr, "%s returned %s\n", fn, msg);
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.h b/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.h
new file mode 100644
index 0000000..52375a9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/dump-descriptors.h
@@ -0,0 +1,12 @@
+/* Definitions of functions in dump-descriptors.c. */
+
+#include "ISO_Fortran_binding.h"
+
+extern void dump_CFI_cdesc_t (CFI_cdesc_t *d);
+extern void dump_CFI_dim_t (CFI_dim_t *d);
+extern void dump_CFI_attribute_t (CFI_attribute_t a);
+extern void dump_CFI_index_t (CFI_index_t i);
+extern void dump_CFI_rank_t (CFI_rank_t r);
+extern void dump_CFI_type_t (CFI_type_t t);
+
+void check_CFI_status (const char *fn, int code);
diff --git a/gcc/testsuite/gfortran.dg/c-interop/establish-c.c b/gcc/testsuite/gfortran.dg/c-interop/establish-c.c
new file mode 100644
index 0000000..9e7900d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/establish-c.c
@@ -0,0 +1,134 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+/* For simplicity, point descriptors at a static buffer. BUFSIZE should
+ be large enough for any of the standard types and we'll use DIM0 and DIM1
+ for array dimensions. */
+#define BUFSIZE 64
+#define DIM0 3
+#define DIM1 10
+#define ARRAYBUFSIZE BUFSIZE * DIM0 * DIM1
+static char *buf[ARRAYBUFSIZE] __attribute__ ((aligned (8)));
+static CFI_index_t extents[] = {DIM0, DIM1};
+
+/* Magic number to use for elem_len field. */
+#define MAGIC_ELEM_LEN 20
+
+struct tc_info
+{
+ CFI_type_t typecode;
+ char *name;
+ size_t size;
+};
+
+static struct tc_info tc_table[] =
+{
+ { CFI_type_signed_char, "CFI_type_signed_char", sizeof (signed char) },
+ { CFI_type_short, "CFI_type_short", sizeof (short) },
+ { CFI_type_int, "CFI_type_int", sizeof (int) },
+ { CFI_type_long, "CFI_type_long", sizeof (long) },
+ { CFI_type_long_long, "CFI_type_long_long", sizeof (long long) },
+ { CFI_type_size_t, "CFI_type_size_t", sizeof (size_t) },
+ { CFI_type_int8_t, "CFI_type_int8_t", sizeof (int8_t) },
+ { CFI_type_int16_t, "CFI_type_int16_t", sizeof (int16_t) },
+ { CFI_type_int32_t, "CFI_type_int32_t", sizeof (int32_t) },
+ { CFI_type_int64_t, "CFI_type_int64_t", sizeof (int64_t) },
+ { CFI_type_int_least8_t, "CFI_type_int_least8_t", sizeof (int_least8_t) },
+ { CFI_type_int_least16_t, "CFI_type_int_least16_t", sizeof (int_least16_t) },
+ { CFI_type_int_least32_t, "CFI_type_int_least32_t", sizeof (int_least32_t) },
+ { CFI_type_int_least64_t, "CFI_type_int_least64_t", sizeof (int_least64_t) },
+ { CFI_type_int_fast8_t, "CFI_type_int_fast8_t", sizeof (int_fast8_t) },
+ { CFI_type_int_fast16_t, "CFI_type_int_fast16_t", sizeof (int_fast16_t) },
+ { CFI_type_int_fast32_t, "CFI_type_int_fast32_t", sizeof (int_fast32_t) },
+ { CFI_type_int_fast64_t, "CFI_type_int_fast64_t", sizeof (int_fast64_t) },
+ { CFI_type_intmax_t, "CFI_type_intmax_t", sizeof (intmax_t) },
+ { CFI_type_intptr_t, "CFI_type_intptr_t", sizeof (intptr_t) },
+ { CFI_type_ptrdiff_t, "CFI_type_ptrdiff_t", sizeof (ptrdiff_t) },
+ { CFI_type_float, "CFI_type_float", sizeof (float) },
+ { CFI_type_double, "CFI_type_double", sizeof (double) },
+ { CFI_type_long_double, "CFI_type_long_double", sizeof (long double) },
+ { CFI_type_float_Complex, "CFI_type_float_Complex",
+ sizeof (float _Complex) },
+ { CFI_type_double_Complex, "CFI_type_double_Complex",
+ sizeof (double _Complex) },
+ { CFI_type_long_double_Complex, "CFI_type_long_double_Complex",
+ sizeof (long double _Complex) },
+ { CFI_type_Bool, "CFI_type_Bool", sizeof (_Bool) },
+ { CFI_type_char, "CFI_type_char", sizeof (char) },
+ { CFI_type_cptr, "CFI_type_cptr", sizeof (void *) },
+ { CFI_type_struct, "CFI_type_struct", 0 },
+ { CFI_type_other, "CFI_type_other", -1 }
+};
+
+int
+test_array (struct tc_info *tc, void *ptr, CFI_attribute_t attr)
+{
+ CFI_CDESC_T(2) desc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &desc;
+ int bad = 0;
+ size_t elem_len;
+
+ /* Initialize the descriptor to garbage values so we can confirm it's
+ properly initialized with good ones later. */
+ memset (a, -1, sizeof(desc));
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (a, ptr, attr, tc->typecode,
+ MAGIC_ELEM_LEN, 2, extents));
+
+ /* elem_len is ignored unless type is CFI type struct, CFI type other,
+ or a character type. */
+ if (tc->typecode == CFI_type_char
+ || tc->typecode == CFI_type_struct
+ || tc->typecode == CFI_type_other)
+ elem_len = MAGIC_ELEM_LEN;
+ else
+ elem_len = tc->size;
+
+ if (a->elem_len != elem_len
+ || a->base_addr != ptr
+ || a->type != tc->typecode
+ || a->version != CFI_VERSION
+ || a->attribute != attr
+ || a->rank != 2
+ || (ptr &&
+ /* extents parameter is ignored if ptr is null */
+ (a->dim[0].lower_bound != 0
+ || a->dim[0].extent != DIM0
+ || a->dim[0].sm != elem_len
+ || a->dim[1].lower_bound != 0
+ || a->dim[1].extent != DIM1
+ || a->dim[1].sm != elem_len*DIM0)))
+ {
+ fprintf (stderr, "Bad array descriptor for %s:\n", tc->name);
+ dump_CFI_cdesc_t (a);
+ return 1;
+ }
+ return 0;
+}
+
+/* External entry point. */
+extern void ctest_establish (void);
+
+void
+ctest_establish (void)
+{
+ int ncodes = sizeof (tc_table) / sizeof (struct tc_info);
+ int i;
+ int bad = 0;
+
+ for (i = 0; i < ncodes; i++)
+ {
+ bad += test_array (&tc_table[i], (void *)buf, CFI_attribute_other);
+ bad += test_array (&tc_table[i], NULL, CFI_attribute_allocatable);
+ bad += test_array (&tc_table[i], (void *)buf, CFI_attribute_pointer);
+ }
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/establish-errors-c.c b/gcc/testsuite/gfortran.dg/c-interop/establish-errors-c.c
new file mode 100644
index 0000000..8097655
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/establish-errors-c.c
@@ -0,0 +1,120 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+/* For simplicity, point descriptors at a static buffer. BUFSIZE should
+ be large enough for any of the standard types and we'll use DIM0 and DIM1
+ for array dimensions. */
+#define BUFSIZE 64
+#define DIM0 3
+#define DIM1 10
+#define ARRAYBUFSIZE BUFSIZE * DIM0 * DIM1
+static char *buf[ARRAYBUFSIZE] __attribute__ ((aligned (8)));
+static CFI_index_t extents[] = {DIM0, DIM1};
+
+/* Magic number to use for elem_len field. */
+#define MAGIC_ELEM_LEN 20
+
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ int bad = 0;
+ int status;
+ CFI_CDESC_T(2) desc;
+ CFI_cdesc_t *a = (CFI_cdesc_t *) &desc;
+
+ /* If the attribute argument is CFI_attribute_allocatable,
+ base_addr shall be a null pointer. */
+ status = CFI_establish (a, (void *)buf, CFI_attribute_allocatable,
+ CFI_type_int, 0, 2, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for non-null pointer with CFI_attribute_allocatable\n");
+ bad ++;
+ }
+
+ /* type shall have the value of one of the type codes in Table 18.4,
+ or have a positive value corresponding to an interoperable C type. */
+ status = CFI_establish (a, (void *)buf, CFI_attribute_other,
+ CFI_type_other - 1, 0, 2, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for invalid negative type code\n");
+ bad ++;
+ }
+
+ /* If the type is CFI_type_struct, CFI_type_other, or a Fortran
+ character type, elem_len shall be greater than zero and equal to
+ the storage size in bytes of an element of the object. */
+ status = CFI_establish (a, (void *)buf, CFI_attribute_other,
+ CFI_type_struct, 0, 2, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for invalid size with CFI_type_struct\n");
+ bad ++;
+ }
+
+ status = CFI_establish (a, (void *)buf, CFI_attribute_other,
+ CFI_type_char, 0, 2, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for invalid size with CFI_type_char\n");
+ bad ++;
+ }
+
+ /* Rank shall be between 0 and CFI_MAX_RANK inclusive. */
+ status = CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, -1, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for negative rank\n");
+ bad ++;
+ }
+ status = CFI_establish (a, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, CFI_MAX_RANK + 1, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank > CFI_MAX_RANK\n");
+ bad ++;
+ }
+
+ /* extents is ignored if the rank r is zero or if base_addr is a
+ null pointer. Otherwise, it shall be the address of an array... */
+ status = CFI_establish (a, (void *)buf, CFI_attribute_other,
+ CFI_type_int, 0, 2, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for null extents\n");
+ bad ++;
+ }
+
+ /* Extents shall all be nonnegative. */
+ extents[1] = -extents[1];
+ status = CFI_establish (a, (void *)buf, CFI_attribute_other,
+ CFI_type_int, 0, 2, extents);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for negative extents\n");
+ bad ++;
+ }
+
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/establish-errors.f90 b/gcc/testsuite/gfortran.dg/c-interop/establish-errors.f90
new file mode 100644
index 0000000..307a266
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/establish-errors.f90
@@ -0,0 +1,30 @@
+! PR101317
+! { dg-do run }
+! { dg-additional-sources "establish-errors-c.c dump-descriptors.c" }
+! { dg-additional-options "-Wno-error -fcheck=all" }
+! { dg-warning "command-line option '-fcheck=all' is valid for Fortran but not for C" "" { target *-*-* } 0 }
+!
+! This program tests that the CFI_establish function properly detects
+! invalid arguments. All the interesting things happen in the
+! corresponding C code.
+!
+! The situation here seems to be that while TS29113 defines error codes
+! for CFI_establish, it doesn't actually require the implementation to detect
+! those errors by saying the arguments "shall be" such-and-such, e.g. it is
+! undefined behavior if they are not. In gfortran you can enable some
+! run-time checking by building with -fcheck=all.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest () bind (c)
+ end subroutine
+
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/establish.f90 b/gcc/testsuite/gfortran.dg/c-interop/establish.f90
new file mode 100644
index 0000000..5b263ab
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/establish.f90
@@ -0,0 +1,35 @@
+! PR 101305
+! { dg-do run }
+! { dg-additional-sources "establish-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests the CFI_establish function. All the interesting
+! things happen in the corresponding C code.
+
+! Eventually we might want to make the C code pass the descriptors back to
+! C-callable Fortran functions, but for now it just checks them internally.
+
+module mm
+ use iso_c_binding
+
+ type, bind (c) :: s
+ integer(C_INT) :: i, j
+ end type
+end module
+
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+
+ subroutine ctest_establish () bind (c)
+ end subroutine
+
+ end interface
+
+ call ctest_establish ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/explicit-interface.f90 b/gcc/testsuite/gfortran.dg/c-interop/explicit-interface.f90
new file mode 100644
index 0000000..a7eda82
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/explicit-interface.f90
@@ -0,0 +1,60 @@
+! { dg-do compile }
+!
+! TS 29113
+! 6.2 Explicit interface
+!
+! Additionally to the rules of subclause 12.4.2.2 of ISO/IEC 1539-1:2010,
+! a procedure shall have an explicit interface if it has a dummy argument
+! that is assumed-rank.
+!
+! NOTE 6.1
+! An explicit interface is also required for a procedure if it has a
+! dummy argument that is assumed-type because an assumed-type dummy
+! argument is polymorphic.
+!
+! This file contains code that is expected to produce errors.
+
+module m1
+
+ interface
+
+ subroutine s1 (a)
+ integer :: a(..)
+ end subroutine
+
+ subroutine s2 (b)
+ type(*) :: b
+ end subroutine
+
+ end interface
+
+end module
+
+module m2
+
+ contains
+
+ ! This subroutine has an explicit interface, and so do the things
+ ! it calls.
+ subroutine good (a, b)
+ use m1
+ integer :: a(..)
+ type (*) :: b
+
+ call s1 (a)
+ call s2 (b)
+ end subroutine
+
+ ! This subroutine has an explicit interface, but the things it calls don't.
+ subroutine bad (a, b)
+ use m1
+ integer :: a(..)
+ type (*) :: b
+ external :: s3, s4
+
+ call s3 (a) ! { dg-error "Assumed-rank argument" }
+ call s4 (b) ! { dg-error "Assumed-type argument" }
+ end subroutine
+
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1-c.c
new file mode 100644
index 0000000..674f0bd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1-c.c
@@ -0,0 +1,46 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The actual argument on the Fortran side was declared as
+ integer(C_INT) :: aa(10,-1:3)
+ Make sure that matches what's in the descriptor. Note that per
+ section 18.5.3 in the 2018 standard, for a nonallocatable nonpointer
+ array, the array dimensions in the descriptor reflect the shape of
+ the array rather than the actual bounds; the lower_bound is required
+ to be zero. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 10)
+ abort ();
+ if (a->dim[0].sm != sizeof(int))
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != 5)
+ abort ();
+ if (a->dim[1].sm != a->dim[0].extent * sizeof(int))
+ abort ();
+ if (!CFI_is_contiguous (a))
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1.f90
new file mode 100644
index 0000000..9a540ee
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-1.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-1-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This checks that a C function declared to have an assumed-shape array
+! argument can be called from Fortran and receives a correct descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(10,-1:3)
+
+ ! Test both passing the fixed-size array directly to the function
+ ! with a C interface, and indirectly via a Fortran function with an
+ ! assumed-shape dummy argument.
+ call ctest (aa)
+ call ftest (aa)
+
+contains
+ subroutine ftest (a)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ call ctest (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2-c.c
new file mode 100644
index 0000000..5ce0bfe
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2-c.c
@@ -0,0 +1,68 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, int n);
+
+void
+ctest (CFI_cdesc_t *a, int n)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(float))
+ abort ();
+ if (a->type != CFI_type_float)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+
+ if (n == 1)
+ {
+ /* The actual argument on the Fortran side was declared as
+ real(C_FLOAT):: aa(100) */
+ if (a->rank != 1)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 100)
+ abort ();
+ if (a->dim[0].sm != sizeof(float))
+ abort ();
+ if (!CFI_is_contiguous (a))
+ abort ();
+ }
+ else if (n == 3)
+ {
+ /* The actual argument on the Fortran side was declared as
+ real(C_FLOAT) :: bb(3,4,5) */
+ if (a->rank != 3)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 3)
+ abort ();
+ if (a->dim[0].sm != sizeof(float))
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != 4)
+ abort ();
+ if (a->dim[1].sm != a->dim[0].sm * a->dim[0].extent)
+ abort ();
+ if (a->dim[2].lower_bound != 0)
+ abort ();
+ if (a->dim[2].extent != 5)
+ abort ();
+ if (a->dim[2].sm != a->dim[1].sm * a->dim[1].extent)
+ abort ();
+ if (!CFI_is_contiguous (a))
+ abort ();
+ }
+ else
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2.f90
new file mode 100644
index 0000000..ec90735
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-2.f90
@@ -0,0 +1,40 @@
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-2-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that a C function declared to take an assumed-rank
+! array argument can be called from Fortran, and receives a correct
+! descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a, n) bind (c)
+ use iso_c_binding
+ real(C_FLOAT) :: a(..)
+ integer(C_INT), value :: n
+ end subroutine
+ end interface
+
+ real(C_FLOAT) :: aa(100)
+ real(C_FLOAT) :: bb(3,4,5)
+
+ ! Test both passing the fixed-size array directly to the function
+ ! with a C interface, and indirectly via a Fortran function with an
+ ! assumed-rank dummy argument.
+ call ctest (aa, 1)
+ call ctest (bb, 3)
+ call ftest (aa, 1)
+ call ftest (bb, 3)
+
+contains
+ subroutine ftest (a, n)
+ use iso_c_binding
+ real(C_FLOAT) :: a(..)
+ integer, value :: n
+ call ctest (a, n)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3-c.c
new file mode 100644
index 0000000..a432ee4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3-c.c
@@ -0,0 +1,42 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp);
+
+void
+ctest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (b);
+
+ /* Make sure the descriptors match what we are expecting. a is an
+ allocatable derived type object, b is a pointer which points at a
+ if initp is true. */
+ if (initp && !a->base_addr)
+ abort ();
+ else if (!initp && a->base_addr)
+ abort ();
+ if (a->base_addr != b->base_addr)
+ abort ();
+
+ if (a->rank != 0)
+ abort ();
+ if (b->rank != 0)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+ if (b->type != CFI_type_struct)
+ abort ();
+ if (a->elem_len != 3 * 3 * sizeof(double))
+ abort ();
+ if (b->elem_len != 3 * 3 * sizeof(double))
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3.f90
new file mode 100644
index 0000000..c65cb7a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-3.f90
@@ -0,0 +1,37 @@
+! PR 101308
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that pointer and allocatable scalar arguments are
+! correctly passed by descriptor from Fortran code into C.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ type, bind (c) :: m
+ real(C_DOUBLE) :: a(3, 3)
+ end type
+
+ interface
+ subroutine ctest (a, b, initp) bind (c)
+ use iso_c_binding
+ import m
+ type(m), allocatable :: a
+ type(m), pointer :: b
+ integer(C_INT), value :: initp
+ end subroutine
+ end interface
+
+ type (m), allocatable, target :: aa
+ type (m), pointer :: bb
+
+ ! Test both before and after allocation/pointer initialization.
+ bb => null()
+ call ctest (aa, bb, 0)
+ allocate (aa)
+ bb => aa
+ call ctest (aa, bb, 1)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4-c.c
new file mode 100644
index 0000000..579e66d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4-c.c
@@ -0,0 +1,57 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp);
+
+void
+ctest (CFI_cdesc_t *a, CFI_cdesc_t *b, int initp)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (b);
+
+ /* Make sure the descriptors match what we are expecting. a is an
+ allocatable derived type object, b is a pointer which points at a
+ if initp is true. */
+ if (initp && !a->base_addr)
+ abort ();
+ else if (!initp && a->base_addr)
+ abort ();
+ if (a->base_addr != b->base_addr)
+ abort ();
+
+ if (a->type != CFI_type_struct)
+ abort ();
+ if (b->type != CFI_type_struct)
+ abort ();
+ if (a->elem_len != 3 * 3 * sizeof(double))
+ abort ();
+ if (b->elem_len != 3 * 3 * sizeof(double))
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+
+ if (initp)
+ /* The actual array is allocated with
+ allocate (aa(3:7))
+ Per 8.3.3 of TS29113, the lower_bound must reflect that. */
+ {
+ if (a->rank != 1)
+ abort ();
+ if (b->rank != 1)
+ abort ();
+ if (a->dim[0].lower_bound != 3)
+ abort ();
+ if (b->dim[0].lower_bound != 3)
+ abort ();
+ if (a->dim[0].extent != 5)
+ abort ();
+ if (b->dim[0].extent != 5)
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4.f90
new file mode 100644
index 0000000..db73daf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-4.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-4-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that pointer and allocatable array arguments are
+! correctly passed by descriptor from Fortran code into C.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ type, bind (c) :: m
+ real(C_DOUBLE) :: a(3, 3)
+ end type
+
+ interface
+ subroutine ctest (a, b, initp) bind (c)
+ use iso_c_binding
+ import m
+ type(m), allocatable :: a(:)
+ type(m), pointer :: b(:)
+ integer(C_INT), value :: initp
+ end subroutine
+ end interface
+
+ type (m), allocatable, target :: aa(:)
+ type (m), pointer :: bb(:)
+
+ ! Test both before and after allocation/pointer initialization.
+ bb => NULL ()
+ call ctest (aa, bb, 0)
+ allocate (aa(3:7))
+ bb => aa
+ call ctest (aa, bb, 1)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5-c.c
new file mode 100644
index 0000000..6f27185
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5-c.c
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The actual argument on the Fortran side was declared as
+ character(len=20) :: aa
+ Make sure that matches what's in the descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != 20)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->type != CFI_type_char)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5.f90
new file mode 100644
index 0000000..eda65b4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-5.f90
@@ -0,0 +1,35 @@
+! PR92482
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-5-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests it works to call a C function from Fortran with
+! an assumed length character dummy.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+ end subroutine
+ end interface
+
+ character(len=20,kind=C_CHAR) :: aa
+
+ ! Test both passing the fixed-length string directly to the function
+ ! with a C interface, and indirectly via a Fortran function with an
+ ! assumed-length dummy argument.
+ call ctest (aa)
+ call ftest (aa)
+
+contains
+ subroutine ftest (a)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+ call ctest (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6-c.c
new file mode 100644
index 0000000..875dbb8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6-c.c
@@ -0,0 +1,51 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The actual argument on the Fortran side was declared as
+ integer(C_INT) :: aa(10,5:8)
+ but was passed via other functions that variously describe it as
+ having size (10,*), (10,1:*), or (10,5:*). But, the spec says:
+
+ For a C descriptor of a nonallocatable nonpointer object, the
+ value of the lower_bound member of each element of the dim member
+ of the descriptor is zero.
+
+ In a C descriptor of an assumed-size array, the extent member of
+ the last element of the dim member has the value −1. */
+
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 10)
+ abort ();
+ if (a->dim[0].sm != sizeof(int))
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != -1)
+ abort ();
+ if (a->dim[1].sm != a->dim[0].extent * sizeof(int))
+ abort ();
+}
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6.f90
new file mode 100644
index 0000000..1d6d006
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-6.f90
@@ -0,0 +1,50 @@
+! Reported as pr94070.
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-6-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that an assumed-size array argument can be passed
+! to a C function via a descriptor, and that the argument descriptor
+! received by C correctly identifies it as assumed-size.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ ! Assumed-size arrays are not passed by descriptor. What we'll do
+ ! for this test function is bind an assumed-rank dummy
+ ! to the assumed-size array. This is supposed to fill in the descriptor
+ ! with information about the array present at the call site.
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ end subroutine
+ end interface
+
+ integer(C_INT), target :: aa(10,5:8)
+
+ ! To get an assumed-size array descriptor, we have to first pass the
+ ! fixed-size array to a Fortran function with an assumed-size dummy,
+ call ftest1 (aa)
+ call ftest2 (aa)
+ call ftest3 (aa)
+
+contains
+ subroutine ftest1 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,*)
+ call ctest (a)
+ end subroutine
+ subroutine ftest2 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,5:*)
+ call ctest (a)
+ end subroutine
+ subroutine ftest3 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,1:*)
+ call ctest (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7-c.c
new file mode 100644
index 0000000..035de03
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7-c.c
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *, _Bool);
+
+void
+ctest (CFI_cdesc_t *a, _Bool is_cont)
+{
+ CFI_index_t subscripts[2];
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+
+#if DEBUG
+ dump_CFI_cdesc_t (a);
+#endif
+
+ /* We expect to get an array of shape (5,10) that may not be
+ contiguous. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 5)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != 10)
+ abort ();
+
+ if (is_cont != CFI_is_contiguous (a))
+ abort ();
+
+ if (abs (a->dim[0].sm) < a->elem_len)
+ abort ();
+
+ for (int j = 0; j < 5; ++j)
+ for (int i = 0; i < 10; ++i)
+ {
+ subscripts[0] = j; subscripts[1] = i;
+ if (*(int *) CFI_address (a, subscripts) != (i+1) + 100*(j+1))
+ abort ();
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7.f90
new file mode 100644
index 0000000..40f2e33
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-7.f90
@@ -0,0 +1,147 @@
+! PR 101309
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-7-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests passing arrays that may not be contiguous through
+! descriptors to C functions as assumed-shape arguments.
+
+program testit
+ use iso_c_binding
+ implicit none (type, external)
+
+ interface
+ subroutine ctest (a, is_cont) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ logical(C_Bool), value :: is_cont
+ end subroutine
+ subroutine ctest_cont (a, is_cont) bind (c, name="ctest")
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(:,:)
+ logical(C_Bool), value :: is_cont
+ end subroutine
+
+ subroutine ctest_ar (a, is_cont) bind (c, name="ctest")
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ logical(C_Bool), value :: is_cont
+ end subroutine
+ subroutine ctest_ar_cont (a, is_cont) bind (c, name="ctest")
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(..)
+ logical(C_Bool), value :: is_cont
+ end subroutine
+ end interface
+
+ integer :: i , j
+ integer(C_INT), target :: aa(10,5)
+ integer(C_INT), target :: bb(10,10)
+
+ ! Original array
+ do j = 1, 5
+ do i = 1, 10
+ aa(i,j) = i + 100*j
+ end do
+ end do
+
+ ! Transposed array
+ do j = 2, 10, 2
+ do i = 1, 10
+ bb(j, i) = i + 100*((j-2)/2 + 1)
+ end do
+ end do
+
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+
+ ! Test both calling the C function directly, and via another function
+ ! that takes an assumed-shape/assumed-rank argument.
+
+ call ftest (transpose (aa), is_cont=.true._c_bool) ! Implementation choice: copy in; hence, contiguous
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+
+ call ctest (transpose (aa), is_cont=.false._c_bool) ! Implementation choice: noncontigous / sm inversed
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_cont (transpose (aa), is_cont=.true._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_ar (transpose (aa), is_cont=.false._c_bool) ! Implementation choice: noncontigous / sm inversed
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_ar_cont (transpose (aa), is_cont=.true._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+
+
+ call ftest (bb(2:10:2, :), is_cont=.false._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+
+ call ctest (bb(2:10:2, :), is_cont=.false._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_cont (bb(2:10:2, :), is_cont=.true._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_ar (bb(2:10:2, :), is_cont=.false._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+ call ctest_ar_cont (bb(2:10:2, :), is_cont=.true._c_bool)
+ if (any (transpose (aa) /= bb(2:10:2, :))) error stop 1
+
+contains
+ subroutine ftest (a, is_cont)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ logical(c_bool), value, intent(in) :: is_cont
+ if (is_cont .NEQV. is_contiguous (a)) error stop 2
+ if (any (shape (a) /= [5, 10])) error stop 3
+ do j = 1, 5
+ do i = 1, 10
+ if (a(j, i) /= i + 100*j) error stop 4
+ if (a(j, i) /= aa(i,j)) error stop
+ end do
+ end do
+ call ctest (a, is_cont)
+ call ctest_cont (a, is_cont=.true._c_bool)
+ call ctest_ar (a, is_cont)
+ call ctest_ar_cont (a, is_cont=.true._c_bool)
+ end subroutine
+
+ subroutine ftest_ar (a, is_cont)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ logical(c_bool), value, intent(in) :: is_cont
+ if (is_cont .NEQV. is_contiguous (a)) error stop 2
+ if (any (shape (a) /= [5, 10])) error stop 3
+ select rank (a)
+ rank(2)
+ do j = 1, 5
+ do i = 1, 10
+ if (a(j, i) /= i + 100*j) error stop 4
+ if (a(j, i) /= aa(i,j)) error stop
+ end do
+ end do
+ call ctest (a, is_cont)
+ call ctest_cont (a, is_cont=.true._c_bool)
+ call ftest_ar_con (a, is_cont=.true._c_bool)
+ end select
+ call ctest_ar (a, is_cont)
+ ! call ctest_ar_cont (a, is_cont=.true._c_bool) ! TODO/FIXME: ICE, cf. PR fortran/102729
+ ! call ftest_ar_con (a, is_cont=.true._c_bool) ! TODO/FIXME: ICE, cf. PR fortran/102729
+ end subroutine
+
+ subroutine ftest_ar_con (a, is_cont)
+ use iso_c_binding
+ integer(C_INT), contiguous :: a(..)
+ logical(c_bool), value, intent(in) :: is_cont
+ if (is_cont .NEQV. is_contiguous (a)) error stop 2
+ if (any (shape (a) /= [5, 10])) error stop 3
+ select rank (a)
+ rank(2)
+ do j = 1, 5
+ do i = 1, 10
+ if (a(j, i) /= i + 100*j) error stop 4
+ if (a(j, i) /= aa(i,j)) error stop
+ end do
+ end do
+ call ctest (a, is_cont)
+ call ctest_cont (a, is_cont=.true._c_bool)
+ end select
+ call ctest_ar (a, is_cont)
+ call ctest_ar_cont (a, is_cont=.true._c_bool)
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8-c.c
new file mode 100644
index 0000000..8adf8e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8-c.c
@@ -0,0 +1,20 @@
+/* TS29113 8.3.1: ISO_Fortran_binding.h may be included more than once. */
+
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+#include <ISO_Fortran_binding.h>
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->version != CFI_VERSION)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8.f90
new file mode 100644
index 0000000..42345ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-8.f90
@@ -0,0 +1,22 @@
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-8-c.c dump-descriptors.c" }
+!
+! Check that C descriptors have the version field set correctly.
+! This program is just a stub to create a descriptor and pass it to the
+! C function, which does the actual test.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(10,-1:3)
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9-c.c
new file mode 100644
index 0000000..05e6581
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9-c.c
@@ -0,0 +1,42 @@
+/* 8.3.1: ISO_Fortran_binding.h may be included more than once. */
+
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+struct descriptor_fixed_part {
+ void *base_addr;
+ size_t elem_len;
+ int version;
+};
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ struct descriptor_fixed_part *f = (struct descriptor_fixed_part *) a;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The first three members of the structure shall be base_addr,
+ elem_len, and version in that order. */
+ if (&(a->base_addr) != &(f->base_addr))
+ abort ();
+ if (&(a->elem_len) != &(f->elem_len))
+ abort ();
+ if (&(a->version) != &(f->version))
+ abort ();
+
+ /* The final member shall be dim, with the other members after version
+ and before dim in any order. */
+ if ((void *)&(a->rank) >= (void *)a->dim)
+ abort ();
+ if ((void *)&(a->type) >= (void *)a->dim)
+ abort ();
+ if ((void *)&(a->attribute) >= (void *)a->dim)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9.f90
new file mode 100644
index 0000000..e54f677
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-descriptor-9.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! { dg-additional-sources "fc-descriptor-9-c.c dump-descriptors.c" }
+!
+! Check that C descriptors follow the layout restrictions described in
+! section 8.3.3 of TS29113.
+! This program is just a stub to create a descriptor and pass it to the
+! C function, which does the actual test.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:,:)
+ end subroutine
+ end interface
+
+ integer(C_INT) :: aa(10,-1:3)
+ call ctest (aa)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1-c.c
new file mode 100644
index 0000000..18b37e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1-c.c
@@ -0,0 +1,52 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imax, int jmax, CFI_cdesc_t *a);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imax, int jmax, CFI_cdesc_t *a)
+{
+
+ int i, j;
+ CFI_index_t subscripts[2];
+ struct m* mp;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ /* Fill in the contents of a. a is zero-based but we want the ->i and ->j
+ members of each element to be numbered starting from 1. */
+ for (j = 0; j < jmax; j++)
+ {
+ subscripts[1] = j;
+ for (i = 0; i < imax; i++)
+ {
+ subscripts[0] = i;
+ mp = (struct m *) CFI_address (a, subscripts);
+ mp->i = i + 1;
+ mp->j = j + 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1.f90
new file mode 100644
index 0000000..d0c30b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-1.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-1-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that passing a fixed-size array as an intent(out)
+! assumed-shape argument to a C function called from Fortran works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (ii, jj, a) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ type(m), intent(out) :: a(:,:)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+
+ ! initialize the array to all zeros; ctest will overwrite it.
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = 0
+ aa(i,j)%j = 0
+ end do
+ end do
+
+ call ctest (imax, jmax, aa)
+ call verify (aa)
+
+contains
+subroutine verify (a)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ integer :: i, j
+
+ if (rank (a) .ne. 2) stop 100
+ if (lbound (a, 1) .ne. 1) stop 101
+ if (lbound (a, 2) .ne. 1) stop 102
+ if (ubound (a, 1) .ne. imax) stop 103
+ if (ubound (a, 2) .ne. jmax) stop 104
+
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 201
+ if (a(i,j)%j .ne. j) stop 202
+ end do
+ end do
+end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2-c.c
new file mode 100644
index 0000000..18b37e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2-c.c
@@ -0,0 +1,52 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (int imax, int jmax, CFI_cdesc_t *a);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest (int imax, int jmax, CFI_cdesc_t *a)
+{
+
+ int i, j;
+ CFI_index_t subscripts[2];
+ struct m* mp;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != imax)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != jmax)
+ abort ();
+
+ /* Fill in the contents of a. a is zero-based but we want the ->i and ->j
+ members of each element to be numbered starting from 1. */
+ for (j = 0; j < jmax; j++)
+ {
+ subscripts[1] = j;
+ for (i = 0; i < imax; i++)
+ {
+ subscripts[0] = i;
+ mp = (struct m *) CFI_address (a, subscripts);
+ mp->i = i + 1;
+ mp->j = j + 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2.f90
new file mode 100644
index 0000000..87cfb6e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-2.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-2-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that passing a fixed-size array as an intent(out)
+! assumed-rank argument to a C function called from Fortran works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (ii, jj, a) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ type(m), intent(out) :: a(..)
+ end subroutine
+ end interface
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+
+ ! initialize the array to all zeros; ctest will overwrite it.
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = 0
+ aa(i,j)%j = 0
+ end do
+ end do
+
+ call ctest (imax, jmax, aa)
+ call verify (aa)
+
+contains
+subroutine verify (a)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ integer :: i, j
+
+ if (rank (a) .ne. 2) stop 100
+ if (lbound (a, 1) .ne. 1) stop 101
+ if (lbound (a, 2) .ne. 1) stop 102
+ if (ubound (a, 1) .ne. imax) stop 103
+ if (ubound (a, 2) .ne. jmax) stop 104
+
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 201
+ if (a(i,j)%j .ne. j) stop 202
+ end do
+ end do
+end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3-c.c
new file mode 100644
index 0000000..7de226e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3-c.c
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest1 (int iinit, int jinit, CFI_cdesc_t *p);
+extern void ctest2 (int iinit, int jinit, CFI_cdesc_t *a);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest1 (int iinit, int jinit, CFI_cdesc_t *p)
+{
+ struct m *mp;
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (p);
+
+ if (p->rank != 0)
+ abort ();
+ if (p->attribute != CFI_attribute_pointer)
+ abort ();
+ if (p->type != CFI_type_struct)
+ abort ();
+
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (p, NULL, NULL, sizeof (struct m)));
+
+ if (p->base_addr == NULL)
+ abort ();
+
+ mp = (struct m *) CFI_address (p, NULL);
+ mp->i = iinit;
+ mp->j = jinit;
+}
+
+
+void
+ctest2 (int iinit, int jinit, CFI_cdesc_t *a)
+{
+ struct m *mp;
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 0)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+
+ /* The intent(out) allocatable array is supposed to be deallocated
+ automatically on entry, if it was previously allocated. */
+ if (a->base_addr)
+ abort ();
+
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (a, NULL, NULL, sizeof (struct m)));
+
+ if (a->base_addr == NULL)
+ abort ();
+
+ mp = (struct m *) CFI_address (a, NULL);
+ mp->i = iinit;
+ mp->j = jinit;
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3.f90
new file mode 100644
index 0000000..00a083e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-3.f90
@@ -0,0 +1,59 @@
+! PR 101308
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that passing an allocatable or pointer scalar
+! as an intent(out) argument to a C function called from Fortran works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer(C_INT), parameter :: iinit = 42, jinit = 12345
+
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest1 (ii, jj, p) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ type(m), intent(out), pointer :: p
+ end subroutine
+ subroutine ctest2 (ii, jj, a) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: ii, jj
+ type(m), intent(out), allocatable :: a
+ end subroutine
+ end interface
+
+ type(m), pointer :: p
+ type(m), allocatable :: a
+
+ ! The association status of the intent(out) pointer argument is supposed
+ ! to become undefined on entry to the called procedure.
+ p => NULL ()
+ call ctest1 (iinit, jinit, p)
+ if (.not. associated (p)) stop 101
+ if (p%i .ne. iinit) stop 102
+ if (p%j .ne. jinit) stop 103
+
+ ! The intent(out) argument is supposed to be deallocated automatically
+ ! on entry to the called function.
+ allocate (a)
+ a%i = 0
+ a%j = 0
+ call ctest2 (iinit, jinit, a)
+ if (.not. allocated (a)) stop 201
+ if (a%i .ne. iinit) stop 202
+ if (a%j .ne. jinit) stop 203
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4-c.c
new file mode 100644
index 0000000..6e1324b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4-c.c
@@ -0,0 +1,96 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest1 (int imin, int imax, int jmin, int jmax, CFI_cdesc_t *p);
+extern void ctest2 (int imin, int imax, int jmin, int jmax, CFI_cdesc_t *a);
+
+struct m {
+ int i;
+ int j;
+};
+
+void
+ctest1 (int imin, int imax, int jmin, int jmax, CFI_cdesc_t *p)
+{
+ struct m *mp;
+ int i, j;
+ CFI_index_t lb[2], ub[2], s[2];
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (p);
+
+ if (p->rank != 2)
+ abort ();
+ if (p->attribute != CFI_attribute_pointer)
+ abort ();
+ if (p->type != CFI_type_struct)
+ abort ();
+
+ lb[0] = imin;
+ lb[1] = jmin;
+ ub[0] = imax;
+ ub[1] = jmax;
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (p, lb, ub, sizeof (struct m)));
+
+ if (p->base_addr == NULL)
+ abort ();
+
+ for (j = jmin; j <= jmax; j++)
+ for (i = imin; i <= imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mp = (struct m *) CFI_address (p, s);
+ mp->i = i;
+ mp->j = j;
+ }
+}
+
+void
+ctest2 (int imin, int imax, int jmin, int jmax, CFI_cdesc_t *a)
+{
+ struct m *mp;
+ int i, j;
+ CFI_index_t lb[2], ub[2], s[2];
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_allocatable)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+
+ /* Intent(out) argument is supposed to be deallocated automatically
+ on entry. */
+ if (a->base_addr)
+ abort ();
+
+ lb[0] = imin;
+ lb[1] = jmin;
+ ub[0] = imax;
+ ub[1] = jmax;
+ check_CFI_status ("CFI_allocate",
+ CFI_allocate (a, lb, ub, sizeof (struct m)));
+
+ if (a->base_addr == NULL)
+ abort ();
+
+ for (j = jmin; j <= jmax; j++)
+ for (i = imin; i <= imax; i++)
+ {
+ s[0] = i;
+ s[1] = j;
+ mp = (struct m *) CFI_address (a, s);
+ mp->i = i;
+ mp->j = j;
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4.f90
new file mode 100644
index 0000000..a26d495
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-4.f90
@@ -0,0 +1,75 @@
+! PR 92621 (?)
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-4-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that passing an allocatable or pointer array
+! as an intent(out) argument to a C function called from Fortran works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer(C_INT), parameter :: imin = 5, imax = 10, jmin = -10, jmax = -1
+
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest1 (i0, ii, j0, jj, p) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: i0, ii, j0, jj
+ type(m), intent(out), pointer :: p(:,:)
+ end subroutine
+ subroutine ctest2 (i0, ii, j0, jj, a) bind (c)
+ use iso_c_binding
+ use mm
+ integer(C_INT), value :: i0, ii, j0, jj
+ type(m), intent(out), allocatable :: a(:,:)
+ end subroutine
+ end interface
+
+ type(m), pointer :: p(:,:)
+ type(m), allocatable :: a(:,:)
+ integer :: i, j
+
+ p => NULL ()
+ call ctest1 (imin, imax, jmin, jmax, p)
+ if (.not. associated (p)) stop 101
+ if (rank(p) .ne. 2) stop 102
+ if (lbound (p, 1) .ne. imin) stop 103
+ if (ubound (p, 1) .ne. imax) stop 104
+ if (lbound (p, 2) .ne. jmin) stop 105
+ if (ubound (p, 2) .ne. jmax) stop 106
+ do j = jmin, jmax
+ do i = imin, imax
+ if (p(i,j)%i .ne. i) stop 107
+ if (p(i,j)%j .ne. j) stop 108
+ end do
+ end do
+
+ ! The intent(out) argument is supposed to be deallocated automatically
+ ! on entry to the called function.
+ allocate (a (jmin:jmax,imin:imax))
+ if (.not. allocated (a)) stop 201
+ call ctest2 (imin, imax, jmin, jmax, a)
+ if (.not. allocated (a)) stop 201
+ if (rank(a) .ne. 2) stop 202
+ if (lbound (a, 1) .ne. imin) stop 203
+ if (ubound (a, 1) .ne. imax) stop 204
+ if (lbound (a, 2) .ne. jmin) stop 205
+ if (ubound (a, 2) .ne. jmax) stop 206
+ do j = jmin, jmax
+ do i = imin, imax
+ if (a(i,j)%i .ne. i) stop 207
+ if (a(i,j)%j .ne. j) stop 208
+ end do
+ end do
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5-c.c
new file mode 100644
index 0000000..337bc22
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5-c.c
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The character object passed as the argument was declared on the
+ Fortran side as character(len=26) :: aa
+ Make sure that matches what's in the descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != 26)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (a->type != CFI_type_char)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ strncpy ((char *)a->base_addr, "0123456789", 10);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5.f90
new file mode 100644
index 0000000..63fc08f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-5.f90
@@ -0,0 +1,35 @@
+! PR92482
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-5-c.c dump-descriptors.c" }
+!
+! This program checks that you can call a C function declared with an
+! assumed-length character dummy from Fortran.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR), intent(out) :: a
+ end subroutine
+ end interface
+
+ character(len=26,kind=C_CHAR) :: aa
+ aa = 'abcdefghijklmnopqrstuvwxyz'
+
+ ! Test both passing the fixed-length-string directly to the function
+ ! with a C interface, and indirectly via a Fortran function with an
+ ! assumed-length dummy argument.
+ call ctest (aa)
+ call ftest (aa)
+
+contains
+ subroutine ftest (a) bind (c)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR), intent(out) :: a
+ call ctest (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6-c.c
new file mode 100644
index 0000000..2711a98
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6-c.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a);
+
+void
+ctest (CFI_cdesc_t *a)
+{
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ dump_CFI_cdesc_t (a);
+
+ /* The actual argument on the Fortran side was declared as
+ integer(C_INT) :: aa(10,5:8)
+ but was passed via other functions that variously describe it as
+ having size (10,*), (10,1:*), or (10,5:*) before calling this function
+ with an assumed-rank array dummy. But, the spec says:
+
+ For a C descriptor of a nonallocatable nonpointer object, the
+ value of the lower_bound member of each element of the dim member
+ of the descriptor is zero.
+
+ In a C descriptor of an assumed-size array, the extent member of
+ the last element of the dim member has the value −1. */
+
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 10)
+ abort ();
+ if (a->dim[0].sm != sizeof(int))
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != -1)
+ abort ();
+ if (a->dim[1].sm != a->dim[0].extent * sizeof(int))
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6.f90
new file mode 100644
index 0000000..da22615
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-6.f90
@@ -0,0 +1,49 @@
+! Reported as pr94070.
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-6-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks passing an assumed-size array argument via descriptor
+! from Fortran to C.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ ! Assumed-size arrays are not passed by descriptor. What we'll do
+ ! for this test function is bind an assumed-rank dummy to an
+ ! assumed-size array. This is supposed to fill in the descriptor
+ ! with information about the array present at the call site.
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT), intent(out) :: a(..)
+ end subroutine
+ end interface
+
+ integer(C_INT), target :: aa(10,5:8)
+
+ ! To get an assumed-size array descriptor, we have to first pass the
+ ! fixed-size array to a Fortran function with an assumed-size dummy.
+ call ftest1 (aa)
+ call ftest2 (aa)
+ call ftest3 (aa)
+
+contains
+ subroutine ftest1 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,*)
+ call ctest (a)
+ end subroutine
+ subroutine ftest2 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,5:*)
+ call ctest (a)
+ end subroutine
+ subroutine ftest3 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,1:*)
+ call ctest (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7-c.c b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7-c.c
new file mode 100644
index 0000000..be9fc92
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7-c.c
@@ -0,0 +1,136 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct m {
+ int i;
+ int j;
+};
+
+extern void ctest (CFI_cdesc_t *a, int lb1, int ub1, int s1,
+ int lb2, int ub2, int s2, CFI_cdesc_t *b);
+
+/* Check array b against the section of array a defined by the given
+ bounds. */
+static void
+check_array (CFI_cdesc_t *a, CFI_cdesc_t *b,
+ int lb1, int ub1, int s1, int lb2, int ub2, int s2)
+{
+ int bad = 0;
+ int i, ii, j, jj;
+ CFI_index_t sub[2];
+ struct m *ap, *bp;
+
+ for (j = lb2, jj = b->dim[1].lower_bound; j <= ub2; jj++, j += s2)
+ for (i = lb1, ii = b->dim[0].lower_bound; i <= ub1; ii++, i += s1)
+ {
+ sub[0] = i;
+ sub[1] = j;
+ ap = (struct m *) CFI_address (a, sub);
+ sub[0] = ii;
+ sub[1] = jj;
+ bp = (struct m *) CFI_address (b, sub);
+#if 0
+ fprintf (stderr, "b(%d,%d) = (%d,%d) expecting (%d,%d)\n",
+ ii, jj, bp->i, bp->j, ap->i, ap->j);
+#endif
+ if (ap->i != bp->i || ap->j != bp->j)
+ bad = 1;
+ }
+ if (bad)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *a, int lb1, int ub1, int s1,
+ int lb2, int ub2, int s2, CFI_cdesc_t *b)
+{
+ CFI_index_t lb[2], ub[2], s[2];
+ CFI_index_t i, j;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ fprintf (stderr, "input arrays\n");
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (b);
+
+ /* We expect to get a zero-based input array of shape (10,5). */
+ if (a->rank != 2)
+ abort ();
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ if (a->dim[0].extent != 10)
+ abort ();
+ if (a->dim[1].lower_bound != 0)
+ abort ();
+ if (a->dim[1].extent != 5)
+ abort ();
+
+ /* The output descriptor has to agree with the input descriptor. */
+ if (b->rank != 2)
+ abort ();
+ if (b->attribute != CFI_attribute_pointer)
+ abort ();
+ if (b->type != CFI_type_struct)
+ abort ();
+ if (b->elem_len != a->elem_len)
+ abort ();
+
+ /* Point b at a, keeping the 0-based bounds. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (b, a, NULL));
+ fprintf (stderr, "After initializing b\n");
+ dump_CFI_cdesc_t (b);
+ if (b->dim[0].lower_bound != 0)
+ abort ();
+ if (b->dim[1].lower_bound != 0)
+ abort ();
+ check_array (a, b,
+ a->dim[0].lower_bound,
+ a->dim[0].lower_bound + a->dim[0].extent - 1,
+ 1,
+ a->dim[1].lower_bound,
+ a->dim[1].lower_bound + a->dim[1].extent - 1,
+ 1);
+
+ /* Take a section of the array. The bounds passed in to this function
+ assume the array is 1-based in both dimensions, so subtract 1. */
+ lb[0] = b->dim[0].lower_bound + lb1 - 1;
+ lb[1] = b->dim[1].lower_bound + lb2 - 1;
+ ub[0] = b->dim[0].lower_bound + ub1 - 1;
+ ub[1] = b->dim[1].lower_bound + ub2 - 1;
+ s[0] = s1;
+ s[1] = s2;
+ check_CFI_status ("CFI_section",
+ CFI_section (b, b, lb, ub, s));
+ fprintf (stderr, "After CFI_section\n");
+ dump_CFI_cdesc_t (b);
+ check_array (a, b,
+ a->dim[0].lower_bound + lb1 - 1,
+ a->dim[0].lower_bound + ub1 - 1,
+ s1,
+ a->dim[1].lower_bound + lb2 - 1,
+ a->dim[1].lower_bound + ub2 - 1,
+ s2);
+
+ /* Adjust b to be 1-based. */
+ lb[0] = 1;
+ lb[1] = 1;
+ fprintf (stderr, "After rebasing b again\n");
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (b, b, lb));
+ dump_CFI_cdesc_t (b);
+ check_array (a, b,
+ a->dim[0].lower_bound + lb1 - 1,
+ a->dim[0].lower_bound + ub1 - 1,
+ s1,
+ a->dim[1].lower_bound + lb2 - 1,
+ a->dim[1].lower_bound + ub2 - 1,
+ s2);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7.f90 b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7.f90
new file mode 100644
index 0000000..209f96f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/fc-out-descriptor-7.f90
@@ -0,0 +1,71 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "fc-out-descriptor-7-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program checks that returning a noncontiguous array as an intent(out)
+! argument to a C function called from Fortran works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer(C_INT), parameter :: imax = 10, jmax=5
+
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ ! ctest points b at a section of array a defined by the
+ ! indicated bounds and steps. The returned array is 1-based.
+ subroutine ctest (a, lb1, ub1, s1, lb2, ub2, s2, b) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), target :: a(:,:)
+ integer(C_INT), value :: lb1, ub1, s1, lb2, ub2, s2
+ type(m), intent(out), pointer :: b(:,:)
+ end subroutine
+ end interface
+
+ type(m), target :: a(imax, jmax)
+ type(m), pointer :: b(:,:)
+ integer :: i, j, ii, jj
+
+ do j = 1, jmax
+ do i = 1, imax
+ a(i,j)%i = i
+ a(i,j)%j = j
+ end do
+ end do
+
+ b => NULL ()
+ ! resulting array is 1-based and has shape (3,3)
+ call ctest (a, 2, 8, 3, 1, 5, 2, b)
+ if (.not. associated (b)) stop 101
+ if (rank(b) .ne. 2) stop 102
+ if (lbound (b, 1) .ne. 1) stop 103
+ if (ubound (b, 1) .ne. 3) stop 104
+ if (lbound (b, 2) .ne. 1) stop 105
+ if (ubound (b, 2) .ne. 3) stop 106
+
+ ! check that the returned array b contains the expected elements
+ ! from array a.
+ jj = lbound (b, 2)
+ do j = 1, 5, 2
+ ii = lbound (b, 1)
+ do i = 2, 8, 3
+ if (b(ii,jj)%i .ne. i) stop 107
+ if (b(ii,jj)%j .ne. j) stop 108
+ ii = ii + 1
+ end do
+ jj = jj + 1
+ end do
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-1.f90
new file mode 100644
index 0000000..d429001
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-1.f90
@@ -0,0 +1,123 @@
+! { dg-do run }
+!
+! This program checks that passing arrays as assumed-shape dummies to
+! and from Fortran functions with C binding works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ call testc (aa)
+ call testf (aa)
+
+contains
+
+ ! C binding version
+
+ subroutine checkc (a, b) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ integer :: i, j
+
+ if (size (a,1) .ne. imax) stop 101
+ if (size (a,2) .ne. jmax) stop 102
+ if (size (b,1) .ne. jmax) stop 103
+ if (size (b,2) .ne. imax) stop 104
+
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 105
+ if (a(i,j)%j .ne. j) stop 106
+ if (b(j,i)%i .ne. i) stop 107
+ if (b(j,i)%j .ne. j) stop 108
+ end do
+ end do
+ end subroutine
+
+ ! Fortran binding version
+ subroutine checkf (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:), b(:,:)
+ integer :: i, j
+
+ if (size (a,1) .ne. imax) stop 201
+ if (size (a,2) .ne. jmax) stop 202
+ if (size (b,1) .ne. jmax) stop 203
+ if (size (b,2) .ne. imax) stop 204
+
+ do j = 1, jmax
+ do i = 1, imax
+ if (a(i,j)%i .ne. i) stop 205
+ if (a(i,j)%j .ne. j) stop 206
+ if (b(j,i)%i .ne. i) stop 207
+ if (b(j,i)%j .ne. j) stop 208
+ end do
+ end do
+ end subroutine
+
+ ! C binding version
+ subroutine testc (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m) :: b(jmax, imax)
+ integer :: i, j
+
+ if (size (a,1) .ne. imax) stop 301
+ if (size (a,2) .ne. jmax) stop 302
+ do j = 1, jmax
+ do i = 1, imax
+ b(j,i)%i = a(i,j)%i
+ b(j,i)%j = a(i,j)%j
+ end do
+ end do
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, b)
+ call checkf (a, b)
+ end subroutine
+
+ ! Fortran binding version
+ subroutine testf (a)
+ use iso_c_binding
+ use mm
+ type(m) :: a(:,:)
+ type(m) :: b(jmax, imax)
+ integer :: i, j
+
+ if (size (a,1) .ne. imax) stop 401
+ if (size (a,2) .ne. jmax) stop 402
+ do j = 1, jmax
+ do i = 1, imax
+ b(j,i)%i = a(i,j)%i
+ b(j,i)%j = a(i,j)%j
+ end do
+ end do
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, b)
+ call checkf (a, b)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-2.f90
new file mode 100644
index 0000000..d9b4957
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-2.f90
@@ -0,0 +1,97 @@
+! { dg-do run }
+!
+! This program checks that passing arrays as assumed-rank dummies to
+! and from Fortran functions with C binding works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imax=10, jmax=5
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ type(m) :: aa(imax,jmax)
+ integer :: i, j
+ do j = 1, jmax
+ do i = 1, imax
+ aa(i,j)%i = i
+ aa(i,j)%j = j
+ end do
+ end do
+
+ call testc (aa)
+ call testf (aa)
+
+contains
+
+ ! C binding version
+
+ subroutine checkc (a, b) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(..), b(..)
+
+ if (rank (a) .ne. 2) stop 101
+ if (rank (b) .ne. 2) stop 102
+ if (size (a,1) .ne. imax) stop 103
+ if (size (a,2) .ne. jmax) stop 104
+ if (size (b,1) .ne. jmax) stop 105
+ if (size (b,2) .ne. imax) stop 106
+
+ end subroutine
+
+ ! Fortran binding version
+ subroutine checkf (a, b)
+ use iso_c_binding
+ use mm
+ type(m) :: a(..), b(..)
+
+ if (rank (a) .ne. 2) stop 201
+ if (rank (b) .ne. 2) stop 202
+ if (size (a,1) .ne. imax) stop 203
+ if (size (a,2) .ne. jmax) stop 204
+ if (size (b,1) .ne. jmax) stop 205
+ if (size (b,2) .ne. imax) stop 206
+
+ end subroutine
+
+ ! C binding version
+ subroutine testc (a) bind (c)
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m) :: b(jmax, imax)
+
+ if (rank (a) .ne. 2) stop 301
+ if (size (a,1) .ne. imax) stop 302
+ if (size (a,2) .ne. jmax) stop 303
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, b)
+ call checkf (a, b)
+ end subroutine
+
+ ! Fortran binding version
+ subroutine testf (a)
+ use iso_c_binding
+ use mm
+ type(m) :: a(..)
+ type(m) :: b(jmax, imax)
+
+ if (rank (a) .ne. 2) stop 401
+ if (size (a,1) .ne. imax) stop 402
+ if (size (a,2) .ne. jmax) stop 403
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, b)
+ call checkf (a, b)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-3.f90
new file mode 100644
index 0000000..13ec851
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-3.f90
@@ -0,0 +1,148 @@
+! { dg-do run }
+!
+! This program checks that passing allocatable and pointer scalars to
+! and from Fortran functions with C binding works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+
+ integer, parameter :: imagic=-1, jmagic=42
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ type(m), allocatable :: a
+ type(m), target :: t
+ type(m), pointer :: p
+
+ p => NULL()
+
+ call testc (a, t, p)
+ call testf (a, t, p)
+
+contains
+
+ ! C binding version
+
+ subroutine checkc (a, t, p, initp) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a
+ type(m), target :: t
+ type(m), pointer :: p
+ logical, value :: initp
+
+ if (initp) then
+ if (.not. allocated (a)) stop 101
+ if (a%i .ne. imagic) stop 102
+ if (a%j .ne. jmagic) stop 103
+ if (.not. associated (p)) stop 104
+ if (.not. associated (p, t)) stop 105
+ if (p%i .ne. imagic) stop 106
+ if (p%j .ne. jmagic) stop 107
+ else
+ if (allocated (a)) stop 108
+ if (associated (p)) stop 109
+ end if
+
+ if (rank (a) .ne. 0) stop 110
+ if (rank (t) .ne. 0) stop 111
+ if (rank (p) .ne. 0) stop 112
+
+ end subroutine
+
+ ! Fortran binding version
+ subroutine checkf (a, t, p, initp)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a
+ type(m), target :: t
+ type(m), pointer :: p
+ logical, value :: initp
+
+ if (initp) then
+ if (.not. allocated (a)) stop 201
+ if (a%i .ne. imagic) stop 202
+ if (a%j .ne. jmagic) stop 203
+ if (.not. associated (p)) stop 204
+ if (.not. associated (p, t)) stop 205
+ if (p%i .ne. imagic) stop 206
+ if (p%j .ne. jmagic) stop 207
+ else
+ if (allocated (a)) stop 208
+ if (associated (p)) stop 209
+ end if
+
+ if (rank (a) .ne. 0) stop 210
+ if (rank (t) .ne. 0) stop 211
+ if (rank (p) .ne. 0) stop 212
+
+ end subroutine
+
+ ! C binding version
+ subroutine testc (a, t, p) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a
+ type(m), target :: t
+ type(m), pointer :: p
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate and check again.
+ allocate (a)
+ a%i = imagic
+ a%j = jmagic
+ p => t
+ t%i = imagic
+ t%j = jmagic
+ call checkc (a, t, p, .true.)
+ call checkf (a, t, p, .true.)
+
+ ! Reset and check a third time.
+ deallocate (a)
+ p => NULL ()
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ end subroutine
+
+ ! Fortran binding version
+ subroutine testf (a, t, p)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a
+ type(m), target :: t
+ type(m), pointer :: p
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate and check again.
+ allocate (a)
+ a%i = imagic
+ a%j = jmagic
+ p => t
+ t%i = imagic
+ t%j = jmagic
+ call checkc (a, t, p, .true.)
+ call checkf (a, t, p, .true.)
+
+ ! Reset and check a third time.
+ deallocate (a)
+ p => NULL ()
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-4.f90
new file mode 100644
index 0000000..fd15d06
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-4.f90
@@ -0,0 +1,198 @@
+! { dg-do run }
+!
+! This program checks that passing allocatable and pointer arrays to
+! and from Fortran functions with C binding works.
+
+module mm
+ use iso_c_binding
+ type, bind (c) :: m
+ integer(C_INT) :: i, j
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+
+ p => NULL()
+
+ call testc (a, t, p)
+ call testf (a, t, p)
+
+contains
+
+ ! C binding version
+
+ subroutine checkc (a, t, p, initp) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+ logical, value :: initp
+ integer :: i, j
+
+ if (rank (a) .ne. 1) stop 101
+ if (rank (t) .ne. 2) stop 102
+ if (rank (p) .ne. 2) stop 103
+
+ if (initp) then
+ if (.not. allocated (a)) stop 104
+ if (.not. associated (p)) stop 105
+ if (.not. associated (p, t)) stop 106
+ if (size (a, 1) .ne. 5) stop 107
+ if (size (p, 1) .ne. 3) stop 108
+ if (size (p, 2) .ne. 10) stop 109
+ else
+ if (allocated (a)) stop 121
+ if (associated (p)) stop 122
+ end if
+
+ end subroutine
+
+ ! Fortran binding version
+ subroutine checkf (a, t, p, initp)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+ logical, value :: initp
+ integer :: i, j
+
+ if (rank (a) .ne. 1) stop 201
+ if (rank (t) .ne. 2) stop 202
+ if (rank (p) .ne. 2) stop 203
+
+ if (initp) then
+ if (.not. allocated (a)) stop 204
+ if (.not. associated (p)) stop 205
+ if (.not. associated (p, t)) stop 206
+ if (size (a, 1) .ne. 5) stop 207
+ if (size (p, 1) .ne. 3) stop 208
+ if (size (p, 2) .ne. 10) stop 209
+ else
+ if (allocated (a)) stop 221
+ if (associated (p)) stop 222
+ end if
+
+ end subroutine
+
+ ! C binding version
+ subroutine allocatec (a, t, p) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+
+ allocate (a(10:20))
+ p => t
+ end subroutine
+
+ ! Fortran binding version
+ subroutine allocatef (a, t, p) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+
+ allocate (a(5:15))
+ p => t
+ end subroutine
+
+ ! C binding version
+ subroutine testc (a, t, p) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate and check again.
+ allocate (a(5))
+ p => t
+ call checkc (a, t, p, .true.)
+ call checkf (a, t, p, .true.)
+
+ ! Reset and check a third time.
+ deallocate (a)
+ p => NULL ()
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate inside a function with Fortran binding.
+ call allocatef (a, t, p)
+ if (.not. allocated (a)) stop 301
+ if (.not. associated (p)) stop 302
+ if (lbound (a, 1) .ne. 5) stop 303
+ if (ubound (a, 1) .ne. 15) stop 304
+ deallocate (a)
+ p => NULL ()
+
+ ! Allocate/associate inside a function with C binding.
+ call allocatec (a, t, p)
+ if (.not. allocated (a)) stop 311
+ if (.not. associated (p)) stop 312
+ if (lbound (a, 1) .ne. 10) stop 313
+ if (ubound (a, 1) .ne. 20) stop 314
+ deallocate (a)
+ p => NULL ()
+
+ end subroutine
+
+ ! Fortran binding version
+ subroutine testf (a, t, p)
+ use iso_c_binding
+ use mm
+ type(m), allocatable :: a(:)
+ type(m), target :: t(3,10)
+ type(m), pointer :: p(:,:)
+
+ ! Call both the C and Fortran binding check functions
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate and check again.
+ allocate (a(5))
+ p => t
+ call checkc (a, t, p, .true.)
+ call checkf (a, t, p, .true.)
+
+ ! Reset and check a third time.
+ deallocate (a)
+ p => NULL ()
+ call checkc (a, t, p, .false.)
+ call checkf (a, t, p, .false.)
+
+ ! Allocate/associate inside a function with Fortran binding.
+ call allocatef (a, t, p)
+ if (.not. allocated (a)) stop 401
+ if (.not. associated (p)) stop 402
+ if (lbound (a, 1) .ne. 5) stop 403
+ if (ubound (a, 1) .ne. 15) stop 404
+ deallocate (a)
+ p => NULL ()
+
+ ! Allocate/associate inside a function with C binding.
+ call allocatec (a, t, p)
+ if (.not. allocated (a)) stop 411
+ if (.not. associated (p)) stop 412
+ if (lbound (a, 1) .ne. 10) stop 413
+ if (ubound (a, 1) .ne. 20) stop 414
+ deallocate (a)
+ p => NULL ()
+
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-5.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-5.f90
new file mode 100644
index 0000000..e6d17a4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-5.f90
@@ -0,0 +1,61 @@
+! PR92482
+! { dg-do run }
+!
+! This program checks that passing arrays as assumed-length character
+! dummies to and from Fortran functions with C binding works.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ character(len=26,kind=C_CHAR) :: aa
+
+ call testc (aa)
+ call testf (aa)
+
+contains
+
+ ! C binding version
+
+ subroutine checkc (a) bind (c)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+
+ if (rank (a) .ne. 0) stop 101
+ if (len (a) .ne. 26) stop 102
+ if (a .ne. 'abcdefghijklmnopqrstuvwxyz') stop 103
+ end subroutine
+
+ ! Fortran binding version
+ subroutine checkf (a)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+
+ if (rank (a) .ne. 0) stop 201
+ if (len (a) .ne. 26) stop 202
+ if (a .ne. 'abcdefghijklmnopqrstuvwxyz') stop 203
+ end subroutine
+
+ ! C binding version
+ subroutine testc (a) bind (c)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+
+ ! Call both the C and Fortran binding check functions
+ a = 'abcdefghijklmnopqrstuvwxyz'
+ call checkc (a)
+ call checkf (a)
+ end subroutine
+
+ ! Fortran binding version
+ subroutine testf (a)
+ use iso_c_binding
+ character(len=*,kind=C_CHAR) :: a
+
+ ! Call both the C and Fortran binding check functions
+ a = 'abcdefghijklmnopqrstuvwxyz'
+ call checkc (a)
+ call checkf (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-6.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-6.f90
new file mode 100644
index 0000000..090bb15
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-6.f90
@@ -0,0 +1,71 @@
+! Reported as pr94070.
+! { dg-do run }
+!
+! This program checks that passing assumed-size arrays to
+! and from Fortran functions with C binding works.
+!
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ ! Assumed-size arrays are not passed by descriptor. What we'll do
+ ! for this test function is bind an assumed-rank dummy
+ ! to the assumed-size array. This is supposed to fill in the descriptor
+ ! with information about the array present at the call site.
+ interface
+ subroutine ctest (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ end subroutine
+ end interface
+
+ integer(C_INT), target :: aa(10,5:8)
+
+ ! To get an assumed-size array descriptor, we have to first pass the
+ ! fixed-size array to a Fortran function with an assumed-size dummy,
+ call ftest1 (aa)
+ call ftest2 (aa)
+ call ftest3 (aa)
+
+contains
+ subroutine ftest1 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,*)
+ call testf (a)
+ call testc (a)
+ end subroutine
+ subroutine ftest2 (a)
+ use iso_c_binding
+ integer(C_INT) :: a(10,5:*)
+ call testf (a)
+ call testc (a)
+ end subroutine
+ subroutine ftest3 (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(10,1:*)
+ call testf (a)
+ call testc (a)
+ end subroutine
+
+ subroutine testf (a)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ if (rank (a) .ne. 2) stop 101
+ print *, size (a, 1), size (a, 2)
+ if (size (a, 1) .ne. 10) stop 102
+ if (size (a, 2) .ne. -1) stop 103
+ if (any (lbound (a) .eq. 0)) stop 104
+ end subroutine
+
+ subroutine testc (a) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(..)
+ if (rank (a) .ne. 2) stop 201
+ print *, size (a, 1), size (a, 2)
+ if (size (a, 1) .ne. 10) stop 202
+ if (size (a, 2) .ne. -1) stop 203
+ if (any (lbound (a) .eq. 0)) stop 204
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-7.f90 b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-7.f90
new file mode 100644
index 0000000..3d3c772
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ff-descriptor-7.f90
@@ -0,0 +1,89 @@
+! { dg-do run }
+!
+! Test that arrays that may not be contiguous can be passed both ways
+! between Fortran subroutines with C and Fortran binding conventions.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ integer(C_INT), target :: aa(10,5)
+ integer(C_INT), target :: bb(10,10)
+
+ integer :: i, j, n
+
+ ! Test both C and Fortran binding.
+ n = 0
+ do j = 1, 10
+ do i = 1, 5
+ aa(j,i) = n
+ n = n + 1
+ end do
+ end do
+ call testc (transpose (aa))
+ call testf (transpose (aa))
+
+ bb = -1
+ n = 0
+ do j = 1, 10
+ do i = 2, 10, 2
+ bb(i,j) = n
+ n = n + 1
+ end do
+ end do
+ call testc (bb(2:10:2, :))
+ call testf (bb(2:10:2, :))
+
+contains
+
+ subroutine testc (a) bind (c)
+ use iso_c_binding
+ integer(C_INT), intent(in) :: a(:,:)
+ call checkc (a)
+ call checkf (a)
+ end subroutine
+
+ subroutine testf (a)
+ use iso_c_binding
+ integer(C_INT), intent(in) :: a(:,:)
+ call checkc (a)
+ call checkf (a)
+ end subroutine
+
+ subroutine checkc (a) bind (c)
+ use iso_c_binding
+ integer(C_INT), intent(in) :: a(:,:)
+ integer :: i, j, n
+
+ if (rank (a) .ne. 2) stop 101
+ if (size (a, 1) .ne. 5) stop 102
+ if (size (a, 2) .ne. 10) stop 103
+
+ n = 0
+ do j = 1, 10
+ do i = 1, 5
+ if (a(i,j) .ne. n) stop 104
+ n = n + 1
+ end do
+ end do
+ end subroutine
+
+ subroutine checkf (a)
+ use iso_c_binding
+ integer(C_INT), intent(in) :: a(:,:)
+ integer :: i, j, n
+
+ if (rank (a) .ne. 2) stop 101
+ if (size (a, 1) .ne. 5) stop 102
+ if (size (a, 2) .ne. 10) stop 103
+
+ n = 0
+ do j = 1, 10
+ do i = 1, 5
+ if (a(i,j) .ne. n) stop 104
+ n = n + 1
+ end do
+ end do
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/note-5-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/note-5-3.f90
new file mode 100644
index 0000000..253f0ef
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/note-5-3.f90
@@ -0,0 +1,55 @@
+! { dg-do run }
+!
+! TS 29113
+! NOTE 5.3
+! The intrinsic inquiry function RANK can be used to inquire about the
+! rank of a data object. The rank of an assumed-rank object is zero if
+! the rank of the corresponding actual argument is zero.
+
+program test
+
+ integer :: scalar, array_1d(10), array_2d(3, 3)
+
+ call testit (scalar, array_1d, array_2d)
+
+contains
+
+ function test_rank (a)
+ integer :: test_rank
+ integer :: a(..)
+
+ test_rank = rank (a)
+ end function
+
+ subroutine testit (a0, a1, a2)
+ integer :: a0(..), a1(..), a2(..)
+
+ integer, target :: b0, b1(10), b2(3, 3)
+ integer, allocatable :: c0, c1(:), c2(:,:)
+ integer, pointer :: d0, d1(:), d2(:,:)
+
+ ! array descriptor passed from caller through testit to test_rank
+ if (test_rank (a0) .ne. 0) stop 100
+ if (test_rank (a1) .ne. 1) stop 101
+ if (test_rank (a2) .ne. 2) stop 102
+
+ ! array descriptor created locally here, fixed size
+ if (test_rank (b0) .ne. 0) stop 200
+ if (test_rank (b1) .ne. 1) stop 201
+ if (test_rank (b2) .ne. 2) stop 202
+
+ ! allocatable arrays don't actually have to be allocated.
+ if (test_rank (c0) .ne. 0) stop 300
+ if (test_rank (c1) .ne. 1) stop 301
+ if (test_rank (c2) .ne. 2) stop 302
+
+ ! pointer arrays do need to point at something.
+ d0 => b0
+ d1 => b1
+ d2 => b2
+ if (test_rank (d0) .ne. 0) stop 400
+ if (test_rank (d1) .ne. 1) stop 401
+ if (test_rank (d2) .ne. 2) stop 402
+
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/note-5-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/note-5-4-c.c
new file mode 100644
index 0000000..ab27846
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/note-5-4-c.c
@@ -0,0 +1,10 @@
+#include <ISO_Fortran_binding.h>
+
+extern int test_rank (CFI_cdesc_t *a);
+
+int test_rank (CFI_cdesc_t *a)
+{
+ if (!a)
+ return -1; /* Should not happen. */
+ return a->rank;
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/note-5-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/note-5-4.f90
new file mode 100644
index 0000000..9f3fc8e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/note-5-4.f90
@@ -0,0 +1,63 @@
+! { dg-do run }
+! { dg-additional-sources note-5-4-c.c }
+!
+! TS 29113
+! NOTE 5.4
+! Assumed rank is an attribute of a Fortran dummy argument. When a C
+! function is invoked with an actual argument that corresponds to an
+! assumed-rank dummy argument in a Fortran interface for that C function,
+! the corresponding formal parameter is the address of a descriptor of
+! type CFI_cdesc_t (8.7). The rank member of the descriptor provides the
+! rank of the actual argument. The C function should therefore be able
+! to handle any rank. On each invocation, the rank is available to it.
+
+program test
+
+ interface
+ function test_rank (a) bind (c, name="test_rank")
+ integer :: test_rank
+ integer :: a(..)
+ end function
+ end interface
+
+ integer :: scalar, array_1d(10), array_2d(3, 3)
+
+ call testit (scalar, array_1d, array_2d)
+
+contains
+
+ subroutine testit (a0, a1, a2)
+ integer :: a0(..), a1(..), a2(..)
+
+ integer, target :: b0, b1(10), b2(3, 3)
+ integer, allocatable :: c0, c1(:), c2(:,:)
+ integer, pointer :: d0, d1(:), d2(:,:)
+
+ ! array descriptor passed from caller through testit to test_rank
+ if (test_rank (a0) .ne. 0) stop 100
+ if (test_rank (a1) .ne. 1) stop 101
+ if (test_rank (a2) .ne. 2) stop 102
+
+ ! array descriptor created locally here, fixed size
+ if (test_rank (b0) .ne. 0) stop 200
+ if (test_rank (b1) .ne. 1) stop 201
+ if (test_rank (b2) .ne. 2) stop 202
+
+ ! allocatables
+ allocate (c0)
+ allocate (c1 (10))
+ allocate (c2 (3, 3))
+ if (test_rank (c0) .ne. 0) stop 300
+ if (test_rank (c1) .ne. 1) stop 301
+ if (test_rank (c2) .ne. 2) stop 302
+
+ ! pointers
+ d0 => b0
+ d1 => b1
+ d2 => b2
+ if (test_rank (d0) .ne. 0) stop 400
+ if (test_rank (d1) .ne. 1) stop 401
+ if (test_rank (d2) .ne. 2) stop 402
+
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/optional-c.c b/gcc/testsuite/gfortran.dg/c-interop/optional-c.c
new file mode 100644
index 0000000..9612d28
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/optional-c.c
@@ -0,0 +1,82 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ftest (int n, CFI_cdesc_t *a, int *b, char *c, double *d);
+extern void ctest1 (CFI_cdesc_t *a, int *b, char *c, double *d);
+extern void ctest2 (int n, CFI_cdesc_t *a, int *b, char *c, double *d);
+
+static void *aa;
+static int *bb;
+static char *cc;
+static double *dd;
+
+extern void
+ctest1 (CFI_cdesc_t *a, int *b, char *c, double *d)
+{
+ /* Cache all the pointer arguments for later use by ctest2. */
+ aa = a->base_addr;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ /* Test calling back into Fortran. */
+ ftest (0, NULL, NULL, NULL, NULL);
+ ftest (1, a, NULL, NULL, NULL);
+ ftest (2, a, b, NULL, NULL);
+ ftest (3, a, b, c, NULL);
+ ftest (4, a, b, c, d);
+}
+
+extern void
+ctest2 (int n, CFI_cdesc_t *a, int *b, char *c, double *d)
+{
+ if (n >= 1)
+ {
+ if (!a)
+ abort ();
+ if (a->base_addr != aa)
+ abort ();
+ }
+ else
+ if (a)
+ abort ();
+
+ if (n >= 2)
+ {
+ if (!b)
+ abort ();
+ if (*b != *bb)
+ abort ();
+ }
+ else
+ if (b)
+ abort ();
+
+ if (n >= 3)
+ {
+ if (!c)
+ abort ();
+ if (*c != *cc)
+ abort ();
+ }
+ else
+ if (c)
+ abort ();
+
+ if (n >= 4)
+ {
+ if (!d)
+ abort ();
+ if (*d != *dd)
+ abort ();
+ }
+ else
+ if (d)
+ abort ();
+
+}
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/optional.f90 b/gcc/testsuite/gfortran.dg/c-interop/optional.f90
new file mode 100644
index 0000000..2a30410
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/optional.f90
@@ -0,0 +1,114 @@
+! { dg-do run }
+! { dg-additional-sources "optional-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! TS 29113
+! 8.7 An absent actual argument in a reference to an interoperable
+! procedure is indicated by a corresponding formal parameter with the
+! value of a null pointer. An absent optional dummy argument in a
+! reference to an interoperable procedure from a C function is indicated
+! by a corresponding argument with the value of a null pointer.
+
+module m
+ use iso_c_binding
+ integer(C_INT) :: aa(32)
+ integer(C_INT) :: bb
+ character(C_CHAR) :: cc
+ real(C_DOUBLE) :: dd
+end module
+
+subroutine ftest (n, a, b, c, d) bind (c)
+ use iso_c_binding
+ use m
+ implicit none
+ integer(C_INT), value :: n
+ integer(C_INT), optional :: a(:)
+ integer(C_INT), optional :: b
+ character(C_CHAR), optional :: c
+ real(C_DOUBLE), optional :: d
+
+ if (n .ge. 1) then
+ if (.not. present (a)) stop 101
+ if (any (a .ne. aa)) stop 201
+ else
+ if (present (a)) stop 301
+ end if
+
+ if (n .ge. 2) then
+ if (.not. present (b)) stop 102
+ if (b .ne. bb) stop 201
+ else
+ if (present (b)) stop 302
+ end if
+
+ if (n .ge. 3) then
+ if (.not. present (c)) stop 103
+ if (c .ne. cc) stop 201
+ else
+ if (present (c)) stop 303
+ end if
+
+ if (n .ge. 4) then
+ if (.not. present (d)) stop 104
+ if (d .ne. dd) stop 201
+ else
+ if (present (d)) stop 304
+ end if
+end subroutine
+
+program testit
+ use iso_c_binding
+ use m
+ implicit none
+
+ interface
+ subroutine ctest1 (a, b, c, d) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: a(:)
+ integer(C_INT) :: b
+ character(C_CHAR) :: c
+ real(C_DOUBLE) :: d
+ end subroutine
+ subroutine ctest2 (n, a, b, c, d) bind (c)
+ use iso_c_binding
+ integer(C_INT), value :: n
+ integer(C_INT), optional :: a(:)
+ integer(C_INT), optional :: b
+ character(C_CHAR), optional :: c
+ real(C_DOUBLE), optional :: d
+ end subroutine
+ subroutine ftest (n, a, b, c, d) bind (c)
+ use iso_c_binding
+ integer(C_INT), value :: n
+ integer(C_INT), optional :: a(:)
+ integer(C_INT), optional :: b
+ character(C_CHAR), optional :: c
+ real(C_DOUBLE), optional :: d
+ end subroutine
+ end interface
+
+
+ ! Initialize the variables above.
+ integer :: i
+ do i = 1, 32
+ aa(i) = i
+ end do
+ bb = 42
+ cc = '$'
+ dd = acos(-1.D0)
+
+ call ftest (0)
+ call ftest (1, aa)
+ call ftest (2, aa, bb)
+ call ftest (3, aa, bb, cc)
+ call ftest (4, aa, bb, cc, dd)
+
+ call ctest1 (aa, bb, cc, dd)
+ call ctest2 (0)
+ call ctest2 (1, aa)
+ call ctest2 (2, aa, bb)
+ call ctest2 (3, aa, bb, cc)
+ call ctest2 (4, aa, bb, cc, dd)
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/rank-class.f90 b/gcc/testsuite/gfortran.dg/c-interop/rank-class.f90
new file mode 100644
index 0000000..bbf1839
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/rank-class.f90
@@ -0,0 +1,88 @@
+! { dg-do run }
+!
+! TS 29113
+! 7.2 RANK (A)
+! Description. Rank of a data object.
+! Class. Inquiry function.
+! Argument.
+! A shall be a scalar or array of any type.
+! Result Characteristics. Default integer scalar.
+! Result Value. The result is the rank of A.
+
+module m
+
+ type :: base
+ integer :: a, b
+ end type
+
+ type, extends (base) :: derived
+ integer :: c
+ end type
+end module
+
+program test
+ use m
+
+ ! Define some arrays for testing.
+ type(derived), target :: x1(5)
+ type(derived) :: y1(0:9)
+ type(derived), pointer :: p1(:)
+ type(derived), allocatable :: a1(:)
+ type(derived), target :: x3(2,3,4)
+ type(derived) :: y3(0:1,-3:-1,4)
+ type(derived), pointer :: p3(:,:,:)
+ type(derived), allocatable :: a3(:,:,:)
+ type(derived) :: x
+
+ ! Test the 1-dimensional arrays.
+ if (rank (x1) .ne. 1) stop 201
+ call testit (x1, 1)
+ if (rank (y1) .ne. 1) stop 202
+ call testit (y1, 1)
+ if (rank (p1) .ne. 1) stop 203
+ p1 => x1
+ call testit (p1, 1)
+ if (rank (p1) .ne. 1) stop 204
+ if (rank (a1) .ne. 1) stop 205
+ allocate (a1(5))
+ if (rank (a1) .ne. 1) stop 206
+ call testit (a1, 1)
+
+ ! Test the multi-dimensional arrays.
+ if (rank (x3) .ne. 3) stop 207
+ call testit (x3, 3)
+ if (rank (y3) .ne. 3) stop 208
+ if (rank (p3) .ne. 3) stop 209
+ p3 => x3
+ call testit (p3, 3)
+ if (rank (p3) .ne. 3) stop 210
+ if (rank (a3) .ne. 3) stop 211
+ allocate (a3(2,3,4))
+ call testit (a3, 3)
+ if (rank (a3) .ne. 3) stop 212
+
+ ! Test scalars.
+ if (rank (x) .ne. 0) stop 213
+ call testit (x, 0)
+ call test0 (x)
+ if (rank (x1(1)) .ne. 0) stop 215
+ call test0 (x1(1))
+
+contains
+
+ subroutine testit (a, r)
+ use m
+ class(base) :: a(..)
+ integer :: r
+
+ if (r .ne. rank(a)) stop 101
+ end subroutine
+
+ subroutine test0 (a)
+ use m
+ class(base) :: a(..)
+ if (rank (a) .ne. 0) stop 103
+ call testit (a, 0)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/rank.f90 b/gcc/testsuite/gfortran.dg/c-interop/rank.f90
new file mode 100644
index 0000000..9bae575
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/rank.f90
@@ -0,0 +1,99 @@
+! { dg-do run }
+!
+! TS 29113
+! 7.2 RANK (A)
+! Description. Rank of a data object.
+! Class. Inquiry function.
+! Argument.
+! A shall be a scalar or array of any type.
+! Result Characteristics. Default integer scalar.
+! Result Value. The result is the rank of A.
+
+program test
+
+ ! Define some arrays for testing.
+ integer, target :: x1(5)
+ integer :: y1(0:9)
+ integer, pointer :: p1(:)
+ integer, allocatable :: a1(:)
+ integer, target :: x3(2,3,4)
+ integer :: y3(0:1,-3:-1,4)
+ integer, pointer :: p3(:,:,:)
+ integer, allocatable :: a3(:,:,:)
+ integer :: x
+
+ ! Test the 1-dimensional arrays.
+ if (rank (x1) .ne. 1) stop 201
+ call testit (x1, 1)
+ call test1 (x1)
+ if (rank (y1) .ne. 1) stop 202
+ call testit (y1, 1)
+ call test1 (y1)
+ if (rank (p1) .ne. 1) stop 203
+ p1 => x1
+ call testit (p1, 1)
+ if (rank (p1) .ne. 1) stop 204
+ call test1 (p1)
+ if (rank (a1) .ne. 1) stop 205
+ allocate (a1(5))
+ if (rank (a1) .ne. 1) stop 206
+ call testit (a1, 1)
+ call test1 (a1)
+
+ ! Test the multi-dimensional arrays.
+ if (rank (x3) .ne. 3) stop 207
+ call testit (x3, 3)
+ call test1 (x3)
+ call test3 (x3, 1, 2, 1, 3)
+ if (rank (y3) .ne. 3) stop 208
+ call test3 (y3, 0, 1, -3, -1)
+ if (rank (p3) .ne. 3) stop 209
+ p3 => x3
+ call testit (p3, 3)
+ call test1 (p3)
+ if (rank (p3) .ne. 3) stop 210
+ call test3 (p3, 1, 2, 1, 3)
+ if (rank (a3) .ne. 3) stop 211
+ allocate (a3(2,3,4))
+ call testit (a3, 3)
+ call test1 (a3)
+ if (rank (a3) .ne. 3) stop 212
+ call test3 (a3, 1, 2, 1, 3)
+
+ ! Test scalars.
+ if (rank (x) .ne. 0) stop 213
+ call testit (x, 0)
+ call test0 (x)
+ if (rank (-1) .ne. 0) stop 214
+ call test0 (-1)
+ if (rank (x1(1)) .ne. 0) stop 215
+ call test0 (x1(1))
+
+contains
+
+ subroutine testit (a, r)
+ integer :: a(..)
+ integer :: r
+
+ if (r .ne. rank(a)) stop 101
+ end subroutine
+
+ subroutine test0 (a)
+ integer :: a(..)
+ if (rank (a) .ne. 0) stop 103
+ call testit (a, 0)
+ end subroutine
+
+ subroutine test1 (a)
+ integer :: a(*)
+ call testit (a, 1)
+ end subroutine
+
+ subroutine test3 (a, l1, u1, l2, u2)
+ implicit none
+ integer :: l1, u1, l2, u2
+ integer :: a(l1:u1, l2:u2, *)
+ call testit (a, 3)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-1.f90
new file mode 100644
index 0000000..d2155ec
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-1.f90
@@ -0,0 +1,41 @@
+! { dg-do compile}
+!
+! TS 29113
+! 8.1 Removed restrictions on ISO_C_BINDING module procedures
+!
+! The subroutine C_F_POINTER from the intrinsic module ISO_C_BINDING has
+! the restriction in ISO/IEC 1539- 1:2010 that if FPTR is an array, it
+! shall be of interoperable type.
+!
+! [...]
+!
+! These restrictions are removed.
+
+module m
+ use ISO_C_BINDING
+ implicit none
+
+ ! An obvious example of a type that isn't interoperable is a
+ ! derived type without a bind(c) clause.
+
+ integer :: buflen
+ parameter (buflen=256)
+
+ type :: packet
+ integer :: size
+ integer(1) :: buf(buflen)
+ end type
+
+contains
+
+ subroutine test (ptr, n, packets)
+ type(C_PTR), intent(in) :: ptr
+ integer, intent(in) :: n
+ type(packet), pointer, intent(out) :: packets(:)
+
+ integer :: s(1)
+ s(1) = n
+
+ call c_f_pointer (ptr, packets, s)
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-2.f90
new file mode 100644
index 0000000..3c49de3715
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-2.f90
@@ -0,0 +1,35 @@
+! { dg-do compile}
+!
+! TS 29113
+! 8.1 Removed restrictions on ISO_C_BINDING module procedures
+!
+! The function C_F_PROCPOINTER from the intrinsic module ISO_C_BINDING
+! has the restriction in ISO/IEC 1539-1:2010 that CPTR and FPTR shall
+! not be the C address and interface of a noninteroperable Fortran
+! procedure.
+!
+! [...]
+!
+! These restrictions are removed.
+
+module m
+ use ISO_C_BINDING
+ implicit none
+
+ ! Declare a non-interoperable Fortran procedure interface.
+ abstract interface
+ function foo (x, y)
+ integer :: foo
+ integer, intent (in) :: x, y
+ end function
+ end interface
+
+contains
+
+ subroutine test (cptr, fptr)
+ type(C_FUNPTR), intent(in) :: cptr
+ procedure (foo), pointer, intent(out) :: fptr
+
+ call c_f_procpointer (cptr, fptr)
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-3.f90
new file mode 100644
index 0000000..b429e80
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-3.f90
@@ -0,0 +1,37 @@
+! { dg-do compile}
+!
+! TS 29113
+! 8.1 Removed restrictions on ISO_C_BINDING module procedures
+!
+! The function C_LOC from the intrinsic module ISO_C_BINDING has the
+! restriction in ISO/IEC 1539-1:2010 that if X is an array, it shall
+! be of interoperable type.
+!
+! [...]
+!
+! These restrictions are removed.
+
+module m
+ use ISO_C_BINDING
+ implicit none
+
+ ! An obvious example of a type that isn't interoperable is a
+ ! derived type without a bind(c) clause.
+
+ integer :: buflen
+ parameter (buflen=256)
+
+ type :: packet
+ integer :: size
+ integer(1) :: buf(buflen)
+ end type
+
+contains
+
+ subroutine test (packets, ptr)
+ type(packet), pointer, intent(in) :: packets(:)
+ type(C_PTR), intent(out) :: ptr
+
+ ptr = c_loc (packets)
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-4.f90
new file mode 100644
index 0000000..b44defd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/removed-restrictions-4.f90
@@ -0,0 +1,34 @@
+! { dg-do compile}
+!
+! TS 29113
+! 8.1 Removed restrictions on ISO_C_BINDING module procedures
+!
+! [...]
+!
+! The function C_FUNLOC from the intrinsic module ISO_C_BINDING has
+! the restriction in ISO/IEC 1539-1:2010 that its argument shall be
+! interoperable.
+!
+! These restrictions are removed.
+
+module m
+ use ISO_C_BINDING
+ implicit none
+
+ ! Declare a non-interoperable Fortran procedure interface.
+ abstract interface
+ function foo (x, y)
+ integer :: foo
+ integer, intent (in) :: x, y
+ end function
+ end interface
+
+contains
+
+ subroutine test (fptr, cptr)
+ procedure (foo), pointer, intent(in) :: fptr
+ type(C_FUNPTR), intent(out) :: cptr
+
+ cptr = c_funloc (fptr)
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-1-c.c b/gcc/testsuite/gfortran.dg/c-interop/section-1-c.c
new file mode 100644
index 0000000..7da86a4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-1-c.c
@@ -0,0 +1,135 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *a, int lb, int ub, int s, CFI_cdesc_t *r);
+
+/* Take a section of array A. OFF is the start index of A on the Fortran
+ side and the bounds LB and UB for the section to take are relative to
+ that base index. Store the result in R, which is supposed to be a pointer
+ array with lower bound 1. */
+
+void
+ctest (CFI_cdesc_t *a, int lb, int ub, int s, CFI_cdesc_t *r)
+{
+ CFI_index_t lb_array[1], ub_array[1], s_array[1];
+ CFI_index_t i, o;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ fprintf (stderr, "\n%s: lb=%d ub=%d s=%d\n",
+ (a->attribute == CFI_attribute_other) ? "non-pointer" : "pointer",
+ lb, ub, s);
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (r);
+
+ /* Make sure we got a valid input descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(int))
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (a->type != CFI_type_int)
+ abort ();
+ if (a->attribute == CFI_attribute_other)
+ {
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ /* Adjust the 1-based bounds. */
+ lb = lb - 1;
+ ub = ub - 1;
+ }
+ /* For pointer arrays, the bounds use the same indexing as the lower
+ bound in the array descriptor. */
+
+ /* Make sure we got a valid output descriptor. */
+ if (r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(int))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_int)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Create an array section. */
+ lb_array[0] = lb;
+ ub_array[0] = ub;
+ s_array[0] = s;
+
+ check_CFI_status ("CFI_section",
+ CFI_section (r, a, lb_array, ub_array, s_array));
+
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(int))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_int)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Check the contents of the output array. */
+#if 0
+ for (o = r->dim[0].lower_bound, i = lb;
+ (s > 0 ? i <= ub : i >= ub);
+ o++, i += s)
+ {
+ int *input = (int *) CFI_address (a, &i);
+ int *output = (int *) CFI_address (r, &o);
+ fprintf (stderr, "a(%d) = %d, r(%d) = %d\n",
+ (int)i, *input, (int)o, *output);
+ }
+#endif
+ for (o = r->dim[0].lower_bound, i = lb;
+ (s > 0 ? i <= ub : i >= ub);
+ o++, i += s)
+ {
+ int *input = (int *) CFI_address (a, &i);
+ int *output = (int *) CFI_address (r, &o);
+ if (*input != *output)
+ abort ();
+ }
+
+ /* Force the output array to be 1-based. */
+ lb_array[0] = 1;
+ check_CFI_status ("CFI_setpointer", CFI_setpointer (r, r, lb_array));
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(int))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_int)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+ if (r->dim[0].lower_bound != 1)
+ abort ();
+
+ /* Check the contents of the output array again. */
+ for (o = r->dim[0].lower_bound, i = lb;
+ (s > 0 ? i <= ub : i >= ub);
+ o++, i += s)
+ {
+ int *input = (int *) CFI_address (a, &i);
+ int *output = (int *) CFI_address (r, &o);
+ if (*input != *output)
+ abort ();
+ }
+
+}
+
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-1.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-1.f90
new file mode 100644
index 0000000..4e54116
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-1.f90
@@ -0,0 +1,71 @@
+! { dg-do run }
+! { dg-additional-sources "section-1-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function on
+! a 1-dimensional non-pointer/non-allocatable array, passed as an
+! assumed-shape dummy.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (a, lb, ub, s, r) bind (c)
+ use iso_c_binding
+ integer(C_INT), target :: a(:)
+ integer(C_INT), value :: lb, ub, s
+ integer(C_INT), pointer, intent(out) :: r(:)
+ end subroutine
+
+ end interface
+
+ integer(C_INT), target :: aa(32)
+ integer :: i
+
+ ! Initialize the test array by numbering its elements.
+ do i = 1, 32
+ aa(i) = i
+ end do
+
+ ! Try some cases with non-pointer input arrays.
+ call test (aa, 1, 32, 5, 13, 2) ! basic test
+ call test (aa, 4, 35, 5, 13, 2) ! non-default lower bound
+ call test (aa, 1, 32, 32, 16, -2) ! negative step
+
+contains
+
+ ! Test function for non-pointer array AA.
+ ! LO and HI are the bounds for the entire array.
+ ! LB, UB, and S describe the section to take, and use the
+ ! same indexing as LO and HI.
+ subroutine test (aa, lo, hi, lb, ub, s)
+ integer :: aa(lo:hi)
+ integer :: lo, hi, lb, ub, s
+
+ integer(C_INT), pointer :: rr(:)
+ integer :: i, o
+
+ ! Call the C function to put a section in rr.
+ ! The C function expects the section bounds to be 1-based.
+ nullify (rr)
+ call ctest (aa, lb - lo + 1, ub - lo + 1, s, rr)
+
+ ! Make sure the original array has not been modified.
+ do i = lo, hi
+ if (aa(i) .ne. i - lo + 1) stop 103
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 111
+ if (lbound (rr, 1) .ne. 1) stop 112
+ if (ubound (rr, 1) .ne. (ub - lb)/s + 1) stop 113
+ o = 1
+ do i = lb, ub, s
+ if (rr(o) .ne. i - lo + 1) stop 114
+ o = o + 1
+ end do
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-1p.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-1p.f90
new file mode 100644
index 0000000..e483126
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-1p.f90
@@ -0,0 +1,75 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "section-1-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function on
+! a 1-dimensional pointer array.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest (p, lb, ub, s, r) bind (c)
+ use iso_c_binding
+ integer(C_INT), pointer :: p(:)
+ integer(C_INT), value :: lb, ub, s
+ integer(C_INT), pointer, intent(out) :: r(:)
+ end subroutine
+
+ end interface
+
+ integer(C_INT), target :: aa(32)
+ integer :: i
+
+ ! Initialize the test array by numbering its elements.
+ do i = 1, 32
+ aa(i) = i
+ end do
+
+ call test_p (aa, 0, 31, 15, 24, 3) ! zero lower bound
+ call test_p (aa, 1, 32, 16, 25, 3) ! non-zero lower bound
+ call test_p (aa, 4, 35, 16, 25, 3) ! some other lower bound
+ call test_p (aa, 1, 32, 32, 16, -2) ! negative step
+ stop
+
+contains
+
+ ! Test function for non-pointer array AA.
+ ! LO and HI are the bounds for the entire array.
+ ! LB, UB, and S describe the section to take, and use the
+ ! same indexing as LO and HI.
+ subroutine test_p (aa, lo, hi, lb, ub, s)
+ integer, target :: aa(1:hi-lo+1)
+ integer :: lo, hi, lb, ub, s
+
+ integer(C_INT), pointer :: pp(:), rr(:)
+ integer :: i, o
+
+ pp(lo:hi) => aa
+ if (lbound (pp, 1) .ne. lo) stop 121
+ if (ubound (pp, 1) .ne. hi) stop 122
+ nullify (rr)
+ call ctest (pp, lb, ub, s, rr)
+
+ ! Make sure the input pointer array has not been modified.
+ if (lbound (pp, 1) .ne. lo) stop 144
+ if (ubound (pp, 1) .ne. hi) stop 145
+ do i = lo, hi
+ if (pp(i) .ne. i - lo + 1) stop 146
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 151
+ if (lbound (rr, 1) .ne. 1) stop 152
+ if (ubound (rr, 1) .ne. (ub - lb)/s + 1) stop 153
+ o = 1
+ do i = lb, ub, s
+ if (rr(o) .ne. i - lo + 1) stop 154
+ o = o + 1
+ end do
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-2-c.c b/gcc/testsuite/gfortran.dg/c-interop/section-2-c.c
new file mode 100644
index 0000000..f1ff1271
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-2-c.c
@@ -0,0 +1,175 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct m {
+ int x, y;
+};
+
+extern void ctest (CFI_cdesc_t *a, int lb0, int lb1,
+ int ub0, int ub1, int s0, int s1, CFI_cdesc_t *r);
+
+/* Take a section of array A. OFF is the start index of A on the Fortran
+ side and the bounds LB and UB for the section to take are relative to
+ that base index. Store the result in R, which is supposed to be a pointer
+ array with lower bound 1. */
+
+void
+ctest (CFI_cdesc_t *a, int lb0, int lb1,
+ int ub0, int ub1, int s0, int s1, CFI_cdesc_t *r)
+{
+ CFI_index_t lb_array[2], ub_array[2], s_array[2];
+ int i0, i1, o0, o1;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ fprintf (stderr, "\n%s: lb0=%d lb1=%d ub0=%d ub1=%d s0=%d s1=%d\n",
+ (a->attribute == CFI_attribute_other) ? "non-pointer" : "pointer",
+ lb0, lb1, ub0, ub1, s0, s1);
+ if (lb0 == ub0 || lb1 == ub1)
+ abort ();
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (r);
+
+ /* Make sure we got a valid input descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(struct m))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+ if (a->attribute == CFI_attribute_other)
+ {
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ /* Adjust the 1-based bounds. */
+ lb0 = lb0 - 1;
+ lb1 = lb1 - 1;
+ ub0 = ub0 - 1;
+ ub1 = ub1 - 1;
+ }
+ /* For pointer arrays, the bounds use the same indexing as the lower
+ bound in the array descriptor. */
+
+ /* Make sure we got a valid output descriptor. */
+ if (r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 2)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Create an array section. */
+ lb_array[0] = lb0;
+ lb_array[1] = lb1;
+ ub_array[0] = ub0;
+ ub_array[1] = ub1;
+ s_array[0] = s0;
+ s_array[1] = s1;
+
+ check_CFI_status ("CFI_section",
+ CFI_section (r, a, lb_array, ub_array, s_array));
+
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 2)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Check the contents of the output array. */
+#if 0
+ for (o1 = r->dim[1].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ index[1] = o1;
+ output = (struct m *) CFI_address (r, index);
+ fprintf (stderr, "a(%d,%d) = (%d,%d), r(%d,%d) = (%d,%d)\n",
+ i0, i1, input->x, input->y, o0, o1, output->x, output->y);
+ }
+#endif
+ for (o1 = r->dim[1].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ index[1] = o1;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+
+ /* Force the output array to be 1-based. */
+ lb_array[0] = 1;
+ lb_array[1] = 1;
+ check_CFI_status ("CFI_setpointer", CFI_setpointer (r, r, lb_array));
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 2)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+ if (r->dim[0].lower_bound != 1)
+ abort ();
+
+ /* Check the contents of the output array again. */
+ for (o1 = r->dim[1].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ index[1] = o1;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+}
+
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-2.f90
new file mode 100644
index 0000000..73ad9ec
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-2.f90
@@ -0,0 +1,102 @@
+! { dg-do run }
+! { dg-additional-sources "section-2-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function on
+! a 2-dimensional non-pointer array.
+
+module mm
+ use ISO_C_BINDING
+ type, bind (c) :: m
+ integer(C_INT) :: x, y
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a, lb0, lb1, ub0, ub1, s0, s1, r) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), target :: a(:,:)
+ integer(C_INT), value :: lb0, lb1, ub0, ub1, s0, s1
+ type(m), pointer, intent(out) :: r(:,:)
+ end subroutine
+
+ end interface
+
+ type(m), target :: aa(10, 20)
+ integer :: i0, i1
+
+ ! Initialize the test array by numbering its elements.
+ do i1 = 1, 20
+ do i0 = 1, 10
+ aa(i0, i1)%x = i0
+ aa(i0, i1)%y = i1
+ end do
+ end do
+
+ call test (aa, 4, 3, 10, 15, 2, 3) ! basic test
+ call test (aa, 10, 15, 4, 3, -2, -3) ! negative step
+ stop
+
+contains
+
+ ! Test function for non-pointer array AA.
+ ! LB, UB, and S describe the section to take.
+ subroutine test (aa, lb0, lb1, ub0, ub1, s0, s1)
+ use mm
+ type(m) :: aa(10,20)
+ integer :: lb0, lb1, ub0, ub1, s0, s1
+
+ type(m), pointer :: rr(:,:)
+ integer :: i0, i1, o0, o1
+ integer, parameter :: hi0 = 10
+ integer, parameter :: hi1 = 20
+
+ ! Make sure the original array is OK.
+ do i1 = 1, hi1
+ do i0 = 1, hi0
+ if (aa(i0,i1)%x .ne. i0) stop 101
+ if (aa(i0,i1)%y .ne. i1) stop 101
+ end do
+ end do
+
+ ! Call the C function to put a section in rr.
+ ! The C function expects the section bounds to be 1-based.
+ nullify (rr)
+ call ctest (aa, lb0, lb1, ub0, ub1, s0, s1, rr)
+
+ ! Make sure the original array has not been modified.
+ do i1 = 1, hi1
+ do i0 = 1, hi0
+ if (aa(i0,i1)%x .ne. i0) stop 103
+ if (aa(i0,i1)%y .ne. i1) stop 103
+ end do
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 111
+ if (lbound (rr, 1) .ne. 1) stop 112
+ if (lbound (rr, 2) .ne. 1) stop 112
+ if (ubound (rr, 1) .ne. (ub0 - lb0)/s0 + 1) stop 113
+ if (ubound (rr, 2) .ne. (ub1 - lb1)/s1 + 1) stop 113
+ o1 = 1
+ do i1 = lb1, ub1, s1
+ o0 = 1
+ do i0 = lb0, ub0, s0
+ ! print 999, o0, o1, rr(o0,o1)%x, rr(o0,01)%y
+ ! 999 format ('rr(', i3, ',', i3, ') = (', i3, ',', i3, ')')
+ if (rr(o0,o1)%x .ne. i0) stop 114
+ if (rr(o0,o1)%y .ne. i1) stop 114
+ o0 = o0 + 1
+ end do
+ o1 = o1 + 1
+ end do
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-2p.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-2p.f90
new file mode 100644
index 0000000..f8a1745
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-2p.f90
@@ -0,0 +1,104 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "section-2-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function on
+! a 2-dimensional pointer array.
+
+module mm
+ use ISO_C_BINDING
+ type, bind (c) :: m
+ integer(C_INT) :: x, y
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (p, lb0, lb1, ub0, ub1, s0, s1, r) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), pointer :: p(:,:)
+ integer(C_INT), value :: lb0, lb1, ub0, ub1, s0, s1
+ type(m), pointer, intent(out) :: r(:,:)
+ end subroutine
+
+ end interface
+
+ type(m), target :: aa(10, 20)
+ integer :: i0, i1
+
+ ! Initialize the test array by numbering its elements.
+ do i1 = 1, 20
+ do i0 = 1, 10
+ aa(i0, i1)%x = i0
+ aa(i0, i1)%y = i1
+ end do
+ end do
+
+ call test (aa, 0, 0, 3, 2, 9, 14, 2, 3) ! zero lower bound
+ call test (aa, 1, 1, 4, 3, 10, 15, 2, 3) ! lower bound 1
+ call test (aa, 6, 11, 9, 13, 15, 25, 2, 3) ! other lower bound
+ call test (aa, 1, 1, 10, 15, 4, 3, -2, -3) ! negative step
+ stop
+
+contains
+
+ ! Test function for pointer array AA.
+ ! The bounds of the array are adjusted so it is based at (LO0,LO1).
+ ! LB, UB, and S describe the section of the adjusted array to take.
+ subroutine test (aa, lo0, lo1, lb0, lb1, ub0, ub1, s0, s1)
+ use mm
+ type(m), target :: aa(1:10, 1:20)
+ integer :: lo0, lo1, lb0, lb1, ub0, ub1, s0, s1
+
+ type(m), pointer :: pp(:,:), rr(:,:)
+ integer :: i0, i1, o0, o1
+ integer :: hi0, hi1
+ hi0 = lo0 + 10 - 1
+ hi1 = lo1 + 20 - 1
+
+ pp(lo0:,lo1:) => aa
+ if (lbound (pp, 1) .ne. lo0) stop 121
+ if (lbound (pp, 2) .ne. lo1) stop 121
+ if (ubound (pp, 1) .ne. hi0) stop 122
+ if (ubound (pp, 2) .ne. hi1) stop 122
+ nullify (rr)
+ call ctest (pp, lb0, lb1, ub0, ub1, s0, s1, rr)
+
+ ! Make sure the input pointer array has not been modified.
+ if (lbound (pp, 1) .ne. lo0) stop 131
+ if (ubound (pp, 1) .ne. hi0) stop 132
+ if (lbound (pp, 2) .ne. lo1) stop 133
+ if (ubound (pp, 2) .ne. hi1) stop 134
+ do i1 = lo1, hi1
+ do i0 = lo0, hi0
+ if (pp(i0,i1)%x .ne. i0 - lo0 + 1) stop 135
+ if (pp(i0,i1)%y .ne. i1 - lo1 + 1) stop 136
+ end do
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 141
+ if (lbound (rr, 1) .ne. 1) stop 142
+ if (lbound (rr, 2) .ne. 1) stop 142
+ if (ubound (rr, 1) .ne. (ub0 - lb0)/s0 + 1) stop 143
+ if (ubound (rr, 2) .ne. (ub1 - lb1)/s1 + 1) stop 143
+ o1 = 1
+ do i1 = lb1, ub1, s1
+ o0 = 1
+ do i0 = lb0, ub0, s0
+ if (rr(o0,o1)%x .ne. i0 - lo0 + 1) stop 144
+ if (rr(o0,o1)%y .ne. i1 - lo1 + 1) stop 144
+ o0 = o0 + 1
+ end do
+ o1 = o1 + 1
+ end do
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-3-c.c b/gcc/testsuite/gfortran.dg/c-interop/section-3-c.c
new file mode 100644
index 0000000..819b58f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-3-c.c
@@ -0,0 +1,235 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct m {
+ int x, y;
+};
+
+extern void ctest (CFI_cdesc_t *a, int lb0, int lb1,
+ int ub0, int ub1, int s0, int s1, CFI_cdesc_t *r);
+
+/* Take a section of array A. OFF is the start index of A on the Fortran
+ side and the bounds LB and UB for the section to take are relative to
+ that base index. Store the result in R, which is supposed to be a pointer
+ array with lower bound 1. */
+
+void
+ctest (CFI_cdesc_t *a, int lb0, int lb1,
+ int ub0, int ub1, int s0, int s1, CFI_cdesc_t *r)
+{
+ CFI_index_t lb_array[2], ub_array[2], s_array[2];
+ int i0, i1, o0, o1;
+
+ /* Dump the descriptor contents to test that we can access the fields
+ correctly, etc. */
+ fprintf (stderr, "\n%s: lb0=%d lb1=%d ub0=%d ub1=%d s0=%d s1=%d\n",
+ (a->attribute == CFI_attribute_other) ? "non-pointer" : "pointer",
+ lb0, lb1, ub0, ub1, s0, s1);
+ if (! (lb0 == ub0 || lb1 == ub1))
+ abort ();
+ dump_CFI_cdesc_t (a);
+ dump_CFI_cdesc_t (r);
+
+ /* Make sure we got a valid input descriptor. */
+ if (!a->base_addr)
+ abort ();
+ if (a->elem_len != sizeof(struct m))
+ abort ();
+ if (a->rank != 2)
+ abort ();
+ if (a->type != CFI_type_struct)
+ abort ();
+ if (a->attribute == CFI_attribute_other)
+ {
+ if (a->dim[0].lower_bound != 0)
+ abort ();
+ /* Adjust the 1-based bounds. */
+ lb0 = lb0 - 1;
+ lb1 = lb1 - 1;
+ ub0 = ub0 - 1;
+ ub1 = ub1 - 1;
+ }
+ /* For pointer arrays, the bounds use the same indexing as the lower
+ bound in the array descriptor. */
+
+ /* Make sure we got a valid output descriptor. */
+ if (r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Create an array section. */
+ lb_array[0] = lb0;
+ lb_array[1] = lb1;
+ ub_array[0] = ub0;
+ ub_array[1] = ub1;
+ s_array[0] = s0;
+ s_array[1] = s1;
+
+ check_CFI_status ("CFI_section",
+ CFI_section (r, a, lb_array, ub_array, s_array));
+
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+
+ /* Check the contents of the output array. */
+#if 0
+ if (lb1 == ub1)
+ {
+ /* Output is 1-d array that varies in dimension 0. */
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = lb1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ output = (struct m *) CFI_address (r, index);
+ fprintf (stderr, "a(%d,%d) = (%d,%d), r(%d) = (%d,%d)\n",
+ i0, lb1, input->x, input->y, o0, output->x, output->y);
+ }
+ }
+ else if (lb0 == ub0)
+ {
+ /* Output is 1-d array that varies in dimension 1. */
+ for (o1 = r->dim[0].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = lb0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o1;
+ output = (struct m *) CFI_address (r, index);
+ fprintf (stderr, "a(%d,%d) = (%d,%d), r(%d) = (%d,%d)\n",
+ lb0, i1, input->x, input->y, o1, output->x, output->y);
+ }
+ }
+ else
+ abort ();
+#endif
+ if (lb1 == ub1)
+ {
+ /* Output is 1-d array that varies in dimension 0. */
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = lb1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+ }
+ else if (lb0 == ub0)
+ {
+ /* Output is 1-d array that varies in dimension 1. */
+ for (o1 = r->dim[0].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = lb0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o1;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+ }
+ else
+ abort ();
+
+ /* Force the output array to be 1-based. */
+ lb_array[0] = 1;
+ lb_array[1] = 1;
+ check_CFI_status ("CFI_setpointer", CFI_setpointer (r, r, lb_array));
+ /* Check that the output descriptor is correct. */
+ dump_CFI_cdesc_t (r);
+ if (!r->base_addr)
+ abort ();
+ if (r->elem_len != sizeof(struct m))
+ abort ();
+ if (r->rank != 1)
+ abort ();
+ if (r->type != CFI_type_struct)
+ abort ();
+ if (r->attribute != CFI_attribute_pointer)
+ abort ();
+ if (r->dim[0].lower_bound != 1)
+ abort ();
+
+ /* Check the contents of the output array again. */
+ if (lb1 == ub1)
+ {
+ /* Output is 1-d array that varies in dimension 0. */
+ for (o0 = r->dim[0].lower_bound, i0 = lb0;
+ (s0 > 0 ? i0 <= ub0 : i0 >= ub0);
+ o0++, i0 += s0)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = i0;
+ index[1] = lb1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o0;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+ }
+ else if (lb0 == ub0)
+ {
+ /* Output is 1-d array that varies in dimension 1. */
+ for (o1 = r->dim[0].lower_bound, i1 = lb1;
+ (s1 > 0 ? i1 <= ub1 : i1 >= ub1);
+ o1++, i1 += s1)
+ {
+ CFI_index_t index[2];
+ struct m *input, *output;
+ index[0] = lb0;
+ index[1] = i1;
+ input = (struct m *) CFI_address (a, index);
+ index[0] = o1;
+ output = (struct m *) CFI_address (r, index);
+ if (input->x != output->x || input->y != output->y)
+ abort ();
+ }
+ }
+ else
+ abort ();
+}
+
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-3.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-3.f90
new file mode 100644
index 0000000..c690c50
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-3.f90
@@ -0,0 +1,103 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "section-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function to
+! take a slice of a 2-dimensional non-pointer array.
+
+module mm
+ use ISO_C_BINDING
+ type, bind (c) :: m
+ integer(C_INT) :: x, y
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (a, lb0, lb1, ub0, ub1, s0, s1, r) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), target :: a(:,:)
+ integer(C_INT), value :: lb0, lb1, ub0, ub1, s0, s1
+ type(m), pointer, intent(out) :: r(:)
+ end subroutine
+
+ end interface
+
+ type(m), target :: aa(10, 20)
+ integer :: i0, i1
+
+ ! Initialize the test array by numbering its elements.
+ do i1 = 1, 20
+ do i0 = 1, 10
+ aa(i0, i1)%x = i0
+ aa(i0, i1)%y = i1
+ end do
+ end do
+
+ call test (aa, 3, 1, 3, 20, 0, 1) ! full slice 0
+ call test (aa, 1, 8, 10, 8, 1, 0) ! full slice 1
+ call test (aa, 3, 5, 3, 14, 0, 3) ! partial slice 0
+ call test (aa, 2, 8, 10, 8, 2, 0) ! partial slice 1
+ call test (aa, 3, 14, 3, 5, 0, -3) ! backwards slice 0
+ call test (aa, 10, 8, 2, 8, -2, 0) ! backwards slice 1
+
+contains
+
+ ! Test function for non-pointer array AA.
+ ! LB, UB, and S describe the section to take.
+ subroutine test (aa, lb0, lb1, ub0, ub1, s0, s1)
+ use mm
+ type(m) :: aa(10,20)
+ integer :: lb0, lb1, ub0, ub1, s0, s1
+
+ type(m), pointer :: rr(:)
+ integer :: i0, i1, o0, o1
+ integer, parameter :: hi0 = 10
+ integer, parameter :: hi1 = 20
+
+ ! Check the bounds actually specify a "slice" rather than a subarray.
+ if (lb0 .ne. ub0 .and. lb1 .ne. ub1) stop 100
+
+ ! Call the C function to put a section in rr.
+ ! The C function expects the section bounds to be 1-based.
+ nullify (rr)
+ call ctest (aa, lb0, lb1, ub0, ub1, s0, s1, rr)
+
+ ! Make sure the original array has not been modified.
+ do i1 = 1, hi1
+ do i0 = 1, hi0
+ if (aa(i0,i1)%x .ne. i0) stop 103
+ if (aa(i0,i1)%y .ne. i1) stop 103
+ end do
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 111
+ if (lbound (rr, 1) .ne. 1) stop 112
+ if (ub0 .eq. lb0) then
+ if (ubound (rr, 1) .ne. (ub1 - lb1)/s1 + 1) stop 113
+ o1 = 1
+ do i1 = lb1, ub1, s1
+ if (rr(o1)%x .ne. lb0) stop 114
+ if (rr(o1)%y .ne. i1) stop 114
+ o1 = o1 + 1
+ end do
+ else
+ if (ubound (rr, 1) .ne. (ub0 - lb0)/s0 + 1) stop 113
+ o0 = 1
+ do i0 = lb0, ub0, s0
+ if (rr(o0)%x .ne. i0) stop 114
+ if (rr(o0)%y .ne. lb1) stop 114
+ o0 = o0 + 1
+ end do
+ end if
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-3p.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-3p.f90
new file mode 100644
index 0000000..9562b03
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-3p.f90
@@ -0,0 +1,127 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "section-3-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests basic use of the CFI_section C library function to
+! take a slice of a 2-dimensional pointer array.
+
+module mm
+ use ISO_C_BINDING
+ type, bind (c) :: m
+ integer(C_INT) :: x, y
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+ subroutine ctest (p, lb0, lb1, ub0, ub1, s0, s1, r) bind (c)
+ use iso_c_binding
+ use mm
+ type(m), pointer :: p(:,:)
+ integer(C_INT), value :: lb0, lb1, ub0, ub1, s0, s1
+ type(m), pointer, intent(out) :: r(:)
+ end subroutine
+
+ end interface
+
+ type(m), target :: aa(10, 20)
+ integer :: i0, i1
+
+ ! Initialize the test array by numbering its elements.
+ do i1 = 1, 20
+ do i0 = 1, 10
+ aa(i0, i1)%x = i0
+ aa(i0, i1)%y = i1
+ end do
+ end do
+
+ ! Zero lower bound
+ call test (aa, 0, 0, 2, 0, 2, 19, 0, 1) ! full slice 0
+ call test (aa, 0, 0, 0, 7, 9, 7, 1, 0) ! full slice 1
+ call test (aa, 0, 0, 2, 4, 2, 13, 0, 3) ! partial slice 0
+ call test (aa, 0, 0, 1, 7, 9, 7, 2, 0) ! partial slice 1
+ call test (aa, 0, 0, 2, 13, 2, 4, 0, -3) ! backwards slice 0
+ call test (aa, 0, 0, 9, 7, 1, 7, -2, 0) ! backwards slice 1
+
+ ! Lower bound 1
+ call test (aa, 1, 1, 3, 1, 3, 20, 0, 1) ! full slice 0
+ call test (aa, 1, 1, 1, 8, 10, 8, 1, 0) ! full slice 1
+ call test (aa, 1, 1, 3, 5, 3, 14, 0, 3) ! partial slice 0
+ call test (aa, 1, 1, 2, 8, 10, 8, 2, 0) ! partial slice 1
+ call test (aa, 1, 1, 3, 14, 3, 5, 0, -3) ! backwards slice 0
+ call test (aa, 1, 1, 10, 8, 2, 8, -2, 0) ! backwards slice 1
+
+ ! Some other lower bound
+ call test (aa, 2, 3, 4, 3, 4, 22, 0, 1) ! full slice 0
+ call test (aa, 2, 3, 2, 10, 11, 10, 1, 0) ! full slice 1
+ call test (aa, 2, 3, 4, 7, 4, 16, 0, 3) ! partial slice 0
+ call test (aa, 2, 3, 3, 10, 11, 10, 2, 0) ! partial slice 1
+ call test (aa, 2, 3, 4, 16, 4, 7, 0, -3) ! backwards slice 0
+ call test (aa, 2, 3, 11, 10, 3, 10, -2, 0) ! backwards slice 1
+
+contains
+
+ subroutine test (aa, lo0, lo1, lb0, lb1, ub0, ub1, s0, s1)
+ use mm
+ type(m), target :: aa(10,20)
+ integer :: lo0, lo1, lb0, lb1, ub0, ub1, s0, s1
+
+ type(m), pointer :: pp(:,:), rr(:)
+ integer :: i0, i1, o0, o1
+
+ integer :: hi0, hi1
+ hi0 = lo0 + 10 - 1
+ hi1 = lo1 + 20 - 1
+
+ ! Check the bounds actually specify a "slice" rather than a subarray.
+ if (lb0 .ne. ub0 .and. lb1 .ne. ub1) stop 100
+
+ pp(lo0:,lo1:) => aa
+ if (lbound (pp, 1) .ne. lo0) stop 121
+ if (lbound (pp, 2) .ne. lo1) stop 121
+ if (ubound (pp, 1) .ne. hi0) stop 122
+ if (ubound (pp, 2) .ne. hi1) stop 122
+ nullify (rr)
+ call ctest (pp, lb0, lb1, ub0, ub1, s0, s1, rr)
+
+ ! Make sure the input pointer array has not been modified.
+ if (lbound (pp, 1) .ne. lo0) stop 131
+ if (ubound (pp, 1) .ne. hi0) stop 132
+ if (lbound (pp, 2) .ne. lo1) stop 133
+ if (ubound (pp, 2) .ne. hi1) stop 134
+ do i1 = lo1, hi1
+ do i0 = lo0, hi0
+ if (pp(i0,i1)%x .ne. i0 - lo0 + 1) stop 135
+ if (pp(i0,i1)%y .ne. i1 - lo1 + 1) stop 136
+ end do
+ end do
+
+ ! Make sure the output array has the expected bounds and elements.
+ if (.not. associated (rr)) stop 111
+ if (lbound (rr, 1) .ne. 1) stop 112
+ if (ub0 .eq. lb0) then
+ if (ubound (rr, 1) .ne. (ub1 - lb1)/s1 + 1) stop 113
+ o1 = 1
+ do i1 = lb1, ub1, s1
+ if (rr(o1)%x .ne. lb0 - lo0 + 1) stop 114
+ if (rr(o1)%y .ne. i1 - lo1 + 1) stop 114
+ o1 = o1 + 1
+ end do
+ else
+ if (ubound (rr, 1) .ne. (ub0 - lb0)/s0 + 1) stop 113
+ o0 = 1
+ do i0 = lb0, ub0, s0
+ if (rr(o0)%x .ne. i0 - lo0 + 1) stop 114
+ if (rr(o0)%y .ne. lb1 - lo1 + 1) stop 114
+ o0 = o0 + 1
+ end do
+ end if
+ end subroutine
+
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-4-c.c b/gcc/testsuite/gfortran.dg/c-interop/section-4-c.c
new file mode 100644
index 0000000..07248a5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-4-c.c
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+struct m {
+ int i, j, k, l;
+};
+
+extern void ctest (void);
+
+#define IMAX 6
+#define JMAX 8
+#define KMAX 10
+#define LMAX 12
+
+static struct m buffer[LMAX][KMAX][JMAX][IMAX];
+
+static void
+check_element (struct m *mp, int i, int j, int k, int l)
+{
+#if 0
+ fprintf (stderr, "expected (%d, %d, %d, %d), got (%d, %d, %d, %d)\n",
+ i, j, k, l, mp->i, mp->j, mp->k, mp->l);
+#endif
+ if (mp->i != i || mp->j != j || mp->k != k || mp->l != l)
+ abort ();
+}
+
+void
+ctest (void)
+{
+ CFI_CDESC_T(4) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(4) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+ CFI_index_t extents[4] = { IMAX, JMAX, KMAX, LMAX };
+ CFI_index_t lb[4], ub[4], s[4];
+ int i, j, k, l;
+ int ii, jj, kk, ll;
+
+ /* Initialize the buffer to uniquely label each element. */
+ for (i = 0; i < IMAX; i++)
+ for (j = 0; j < JMAX; j++)
+ for (k = 0; k < KMAX; k++)
+ for (l = 0; l < LMAX; l++)
+ {
+ buffer[l][k][j][i].i = i;
+ buffer[l][k][j][i].j = j;
+ buffer[l][k][j][i].k = k;
+ buffer[l][k][j][i].l = l;
+ }
+
+ /* Establish the source array. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)buffer,
+ CFI_attribute_pointer, CFI_type_struct,
+ sizeof (struct m), 4, extents));
+
+ /* Try taking a degenerate section (single element). */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL,
+ CFI_attribute_pointer, CFI_type_struct,
+ sizeof (struct m), 0, NULL));
+ lb[0] = 3; lb[1] = 4; lb[2] = 5; lb[3] = 6;
+ ub[0] = 3; ub[1] = 4; ub[2] = 5; ub[3] = 6;
+ s[0] = 0; s[1] = 0; s[2] = 0; s[3] = 0;
+ check_CFI_status ("CFI_section",
+ CFI_section (result, source, lb, ub, s));
+ dump_CFI_cdesc_t (result);
+ check_element ((struct m *)result->base_addr, 3, 4, 5, 6);
+
+ /* Try taking a 2d chunk out of the 4d array. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL,
+ CFI_attribute_pointer, CFI_type_struct,
+ sizeof (struct m), 2, NULL));
+ lb[0] = 1; lb[1] = 2; lb[2] = 3; lb[3] = 4;
+ ub[0] = 1; ub[1] = JMAX - 2; ub[2] = 3; ub[3] = LMAX - 2;
+ s[0] = 0; s[1] = 2; s[2] = 0; s[3] = 3;
+ check_CFI_status ("CFI_section",
+ CFI_section (result, source, lb, ub, s));
+ dump_CFI_cdesc_t (result);
+
+ i = lb[0];
+ k = lb[2];
+ for (j = lb[1], jj = result->dim[0].lower_bound;
+ j <= ub[1];
+ j += s[1], jj++)
+ for (l = lb[3], ll = result->dim[1].lower_bound;
+ l <= ub[3];
+ l += s[3], ll++)
+ {
+ CFI_index_t subscripts[2];
+ subscripts[0] = jj;
+ subscripts[1] = ll;
+ check_element ((struct m *) CFI_address (result, subscripts),
+ i, j, k, l);
+ }
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-4.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-4.f90
new file mode 100644
index 0000000..2300e61
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-4.f90
@@ -0,0 +1,23 @@
+! PR 101310
+! { dg-do run }
+! { dg-additional-sources "section-4-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests various scenarios with using CFI_section to extract
+! a section with rank less than the source array. Everything interesting
+! happens on the C side.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ use iso_c_binding
+ end subroutine
+
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-errors-c.c b/gcc/testsuite/gfortran.dg/c-interop/section-errors-c.c
new file mode 100644
index 0000000..67be7d5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-errors-c.c
@@ -0,0 +1,149 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+/* For simplicity, point descriptors at a static buffer. */
+#define BUFSIZE 256
+static char *buf[BUFSIZE] __attribute__ ((aligned (8)));
+static CFI_index_t extents[] = {10};
+
+/* External entry point. The arguments are descriptors for input arrays;
+ we'll construct new descriptors for the outputs of CFI_section. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ int bad = 0;
+ int status;
+ CFI_CDESC_T(1) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(3) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+ CFI_index_t lb = 2;
+ CFI_index_t ub = 8;
+ CFI_index_t step = 2;
+ CFI_index_t zstep = 0;
+
+ /* Use a 1-d integer source array for the first few tests. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)buf, CFI_attribute_other,
+ CFI_type_int, 0, 1, extents));
+
+ /* result shall be the address of a C descriptor with rank equal
+ to the rank of source minus the number of zero strides. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 0, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch (too small)\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_section (result, source, &lb, &lb, &zstep);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch (zero stride)\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch (too large)\n");
+ bad ++;
+ }
+
+ /* The attribute member [of result] shall have the value
+ CFI_attribute_other or CFI_attribute_pointer. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_attribute_allocatable result\n");
+ bad ++;
+ }
+
+ /* source shall be the address of a C descriptor that describes a
+ nonallocatable nonpointer array, an allocated allocatable array,
+ or an associated array pointer. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, 1, NULL));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for unallocated allocatable source array\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for unassociated pointer source array\n");
+ bad ++;
+ }
+
+ /* The corresponding values of the elem_len and type members shall
+ be the same in the C descriptors with the addresses source
+ and result. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)buf, CFI_attribute_other,
+ CFI_type_struct,
+ sizeof(int), 1, extents));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ 2*sizeof (int), 1, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for elem_len mismatch\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_section (result, source, &lb, &ub, &step);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for type mismatch\n");
+ bad ++;
+ }
+
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/section-errors.f90 b/gcc/testsuite/gfortran.dg/c-interop/section-errors.f90
new file mode 100644
index 0000000..28328b7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/section-errors.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! { dg-additional-sources "section-errors-c.c dump-descriptors.c" }
+! { dg-additional-options "-Wno-error -fcheck=all" }
+! { dg-warning "command-line option '-fcheck=all' is valid for Fortran but not for C" "" { target *-*-* } 0 }
+!
+! This program tests that the CFI_section function properly detects
+! invalid arguments. All the interesting things happen in the
+! corresponding C code.
+!
+! The situation here seems to be that while TS29113 defines error codes
+! for CFI_section, it doesn't actually require the implementation to detect
+! those errors by saying the arguments "shall be" such-and-such, e.g. it is
+! undefined behavior if they are not. In gfortran you can enable some
+! run-time checking by building with -fcheck=all.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/select-c.c b/gcc/testsuite/gfortran.dg/c-interop/select-c.c
new file mode 100644
index 0000000..663ac0d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/select-c.c
@@ -0,0 +1,138 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+/* Declare some source arrays. */
+struct ss {
+ char c[4];
+ signed char b[4];
+ int i, j, k;
+} s[10][5][3];
+
+char c[10][16];
+
+double _Complex dc[10];
+
+CFI_index_t extents3[] = {3,5,10};
+CFI_index_t extents1[] = {10};
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ CFI_CDESC_T(3) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(3) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+ size_t offset;
+
+ /* Extract an array of structure elements. */
+ offset = offsetof (struct ss, j);
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)s, CFI_attribute_other,
+ CFI_type_struct,
+ sizeof (struct ss), 3, extents3));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (result, source, offset, 0));
+ dump_CFI_cdesc_t (source);
+ dump_CFI_cdesc_t (result);
+
+ if (result->elem_len != sizeof (int))
+ abort ();
+ if (result->base_addr != source->base_addr + offset)
+ abort ();
+ if (result->dim[0].extent != source->dim[0].extent)
+ abort ();
+ if (result->dim[0].sm != source->dim[0].sm)
+ abort ();
+ if (result->dim[1].extent != source->dim[1].extent)
+ abort ();
+ if (result->dim[1].sm != source->dim[1].sm)
+ abort ();
+ if (result->dim[2].extent != source->dim[2].extent)
+ abort ();
+ if (result->dim[2].sm != source->dim[2].sm)
+ abort ();
+
+ /* Check that we use the given elem_size for char but not for
+ signed char, which is considered an integer type instead of a Fortran
+ character type. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_char, 4, 3, NULL));
+ if (result->elem_len != 4)
+ abort ();
+ offset = offsetof (struct ss, c);
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (result, source, offset, 4));
+ if (result->elem_len != 4)
+ abort ();
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_signed_char, 4, 3, NULL));
+ if (result->elem_len != sizeof (signed char))
+ abort ();
+ offset = offsetof (struct ss, c);
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (result, source, offset, 4));
+ if (result->elem_len != sizeof (signed char))
+ abort ();
+
+ /* Extract an array of character substrings. */
+ offset = 2;
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)c, CFI_attribute_other,
+ CFI_type_char, 16, 1, extents1));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_char, 8, 1, NULL));
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (result, source, offset, 8));
+ dump_CFI_cdesc_t (source);
+ dump_CFI_cdesc_t (result);
+
+ if (result->elem_len != 8)
+ abort ();
+ if (result->base_addr != source->base_addr + offset)
+ abort ();
+ if (result->dim[0].extent != source->dim[0].extent)
+ abort ();
+ if (result->dim[0].sm != source->dim[0].sm)
+ abort ();
+
+ /* Extract an array the imaginary parts of complex numbers.
+ Note that the use of __imag__ to obtain the imaginary part as
+ an lvalue is a GCC extension. */
+ offset = (void *)&(__imag__ dc[0]) - (void *)&(dc[0]);
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)dc, CFI_attribute_other,
+ CFI_type_double_Complex,
+ 0, 1, extents1));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_double, 0, 1, NULL));
+ check_CFI_status ("CFI_select_part",
+ CFI_select_part (result, source, offset, 0));
+ dump_CFI_cdesc_t (source);
+ dump_CFI_cdesc_t (result);
+
+ if (result->elem_len != sizeof (double))
+ abort ();
+ if (result->base_addr != source->base_addr + offset)
+ abort ();
+ if (result->dim[0].extent != source->dim[0].extent)
+ abort ();
+ if (result->dim[0].sm != source->dim[0].sm)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/select-errors-c.c b/gcc/testsuite/gfortran.dg/c-interop/select-errors-c.c
new file mode 100644
index 0000000..7eb815e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/select-errors-c.c
@@ -0,0 +1,125 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+/* Source is an array of structs. */
+struct ss {
+ int i, j;
+ char c[16];
+ double _Complex dc;
+} s[10];
+
+CFI_index_t extents[] = {10};
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ int bad = 0;
+ int status;
+ CFI_CDESC_T(1) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(3) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+
+ /* Create a descriptor for the source array. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)s, CFI_attribute_other,
+ CFI_type_struct,
+ sizeof (struct ss), 1, extents));
+
+ /* The attribute member of result shall have the value
+ CFI_attribute_other or CFI_attribute_pointer. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_select_part (result, source, offsetof (struct ss, j), 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_attribute_allocatable result\n");
+ bad ++;
+ }
+
+ /* The rank member of the result C descriptor shall have the same value
+ as the rank member of the C descriptor at the address specified
+ by source. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 0, NULL));
+ status = CFI_select_part (result, source, offsetof (struct ss, j), 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch (too small)\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_select_part (result, source, offsetof (struct ss, j), 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch (too large)\n");
+ bad ++;
+ }
+
+ /* The value of displacement shall be between 0 and source->elem_len - 1
+ inclusive. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 1, NULL));
+ status = CFI_select_part (result, source, -8, 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for negative displacement\n");
+ bad ++;
+ }
+ status = CFI_select_part (result, source, source->elem_len, 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for too-large displacement\n");
+ bad ++;
+ }
+
+ /* source shall be the address of a C descriptor for a nonallocatable
+ nonpointer array, an allocated allocatable array, or an associated
+ array pointer. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, NULL, CFI_attribute_allocatable,
+ CFI_type_struct,
+ sizeof (struct ss), 1, NULL));
+ status = CFI_select_part (result, source, offsetof (struct ss, j), 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for unallocated allocatable source array\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, NULL, CFI_attribute_pointer,
+ CFI_type_struct,
+ sizeof (struct ss), 1, NULL));
+ status = CFI_select_part (result, source, offsetof (struct ss, j), 0);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for unassociated pointer source array\n");
+ bad ++;
+ }
+
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/select-errors.f90 b/gcc/testsuite/gfortran.dg/c-interop/select-errors.f90
new file mode 100644
index 0000000..b719c9e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/select-errors.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! { dg-additional-sources "select-errors-c.c dump-descriptors.c" }
+! { dg-additional-options "-Wno-error -fcheck=all" }
+! { dg-warning "command-line option '-fcheck=all' is valid for Fortran but not for C" "" { target *-*-* } 0 }
+!
+! This program tests that the CFI_select_part function properly detects
+! invalid arguments. All the interesting things happen in the
+! corresponding C code.
+!
+! The situation here seems to be that while TS29113 defines error codes for
+! CFI_select_part, it doesn't actually require the implementation to detect
+! those errors by saying the arguments "shall be" such-and-such, e.g. it is
+! undefined behavior if they are not. In gfortran you can enable some
+! run-time checking by building with -fcheck=all.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/select.f90 b/gcc/testsuite/gfortran.dg/c-interop/select.f90
new file mode 100644
index 0000000..133385e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/select.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-additional-sources "select-c.c dump-descriptors.c" }
+!
+! This program tests the CFI_select_part function. All the interesting
+! things happen in the corresponding C code.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/setpointer-c.c b/gcc/testsuite/gfortran.dg/c-interop/setpointer-c.c
new file mode 100644
index 0000000..249cb2b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/setpointer-c.c
@@ -0,0 +1,78 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+static int a[10][5][3];
+static CFI_index_t extents[] = {3, 5, 10};
+static CFI_index_t lb1[] = {1, 2, 3};
+static CFI_index_t lb2[] = {0, 1, -10};
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ CFI_CDESC_T(3) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(3) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+
+ /* Create descriptors. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)a, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, extents));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+
+ /* Use setpointer to adjust the bounds of source in place. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (source, source, lb1));
+ dump_CFI_cdesc_t (source);
+ if (source->dim[0].lower_bound != lb1[0])
+ abort ();
+ if (source->dim[1].lower_bound != lb1[1])
+ abort ();
+ if (source->dim[2].lower_bound != lb1[2])
+ abort ();
+
+ /* Use setpointer to copy the pointer and bounds from source. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (result, source, NULL));
+ dump_CFI_cdesc_t (result);
+ if (result->base_addr != source->base_addr)
+ abort ();
+ if (result->dim[0].lower_bound != source->dim[0].lower_bound)
+ abort ();
+ if (result->dim[1].lower_bound != source->dim[1].lower_bound)
+ abort ();
+ if (result->dim[2].lower_bound != source->dim[2].lower_bound)
+ abort ();
+
+ /* Use setpointer to nullify result. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (result, NULL, NULL));
+ dump_CFI_cdesc_t (result);
+ if (result->base_addr)
+ abort ();
+
+ /* Use setpointer to copy the pointer from source, but use
+ different bounds. */
+ check_CFI_status ("CFI_setpointer",
+ CFI_setpointer (result, source, lb2));
+ dump_CFI_cdesc_t (source);
+ if (result->base_addr != source->base_addr)
+ abort ();
+ if (result->dim[0].lower_bound != lb2[0])
+ abort ();
+ if (result->dim[1].lower_bound != lb2[1])
+ abort ();
+ if (result->dim[2].lower_bound != lb2[2])
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors-c.c b/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors-c.c
new file mode 100644
index 0000000..7931e1e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors-c.c
@@ -0,0 +1,127 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+static int a[10][5][3];
+static CFI_index_t extents[] = {3, 5, 10};
+
+/* External entry point. */
+extern void ctest (void);
+
+void
+ctest (void)
+{
+ int bad = 0;
+ int status;
+ CFI_CDESC_T(3) sdesc;
+ CFI_cdesc_t *source = (CFI_cdesc_t *) &sdesc;
+ CFI_CDESC_T(3) rdesc;
+ CFI_cdesc_t *result = (CFI_cdesc_t *) &rdesc;
+
+ /* result shall be the address of a C descriptor for a Fortran pointer. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)a, CFI_attribute_other,
+ CFI_type_int, 0, 3, extents));
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_attribute_allocatable result\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_other,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for CFI_attribute_other result\n");
+ bad ++;
+ }
+
+ /* source shall be a null pointer or the address of a C descriptor
+ for an allocated allocatable object, a data pointer object, or a
+ nonallocatable nonpointer data object that is not an
+ assumed-size array. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, NULL, CFI_attribute_allocatable,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for unallocated allocatable source\n");
+ bad ++;
+ }
+
+ /* CFI_establish rejects negative extents, so we can't use it to make
+ an assumed-size array, so hack the descriptor by hand. Yuck. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)a, CFI_attribute_other,
+ CFI_type_int, 0, 3, extents));
+ source->dim[2].extent = -1;
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for assumed-size source array\n");
+ bad ++;
+ }
+
+ /* If source is not a null pointer, the corresponding values of the
+ elem_len, rank, and type members shall be the same in the C
+ descriptors with the addresses source and result. */
+ check_CFI_status ("CFI_establish",
+ CFI_establish (source, (void *)a, CFI_attribute_other,
+ CFI_type_char, sizeof(int), 3, extents));
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_char, 1, 3, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for elem_len mismatch\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_char, sizeof(int), 1, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for rank mismatch\n");
+ bad ++;
+ }
+
+ check_CFI_status ("CFI_establish",
+ CFI_establish (result, NULL, CFI_attribute_pointer,
+ CFI_type_int, 0, 3, NULL));
+ status = CFI_setpointer (result, source, NULL);
+ if (status == CFI_SUCCESS)
+ {
+ fprintf (stderr,
+ "no error for type mismatch\n");
+ bad ++;
+ }
+
+ if (bad)
+ abort ();
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors.f90 b/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors.f90
new file mode 100644
index 0000000..84a01ce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/setpointer-errors.f90
@@ -0,0 +1,28 @@
+! PR 101317
+! { dg-do run }
+! { dg-additional-sources "setpointer-errors-c.c dump-descriptors.c" }
+! { dg-additional-options "-Wno-error -fcheck=all" }
+! { dg-warning "command-line option '-fcheck=all' is valid for Fortran but not for C" "" { target *-*-* } 0 }
+!
+! This program tests that the CFI_setpointer function properly detects
+! invalid arguments. All the interesting things happen in the
+! corresponding C code.
+!
+! The situation here seems to be that while TS29113 defines error codes for
+! CFI_setpointer, it doesn't actually require the implementation to detect
+! those errors by saying the arguments "shall be" such-and-such, e.g. it is
+! undefined behavior if they are not. In gfortran you can enable some
+! run-time checking by building with -fcheck=all.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/setpointer.f90 b/gcc/testsuite/gfortran.dg/c-interop/setpointer.f90
new file mode 100644
index 0000000..57ef183
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/setpointer.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-additional-sources "setpointer-c.c dump-descriptors.c" }
+!
+! This program tests the CFI_setpointer function. All the interesting
+! things happen in the corresponding C code.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+ subroutine ctest () bind (c)
+ end subroutine
+ end interface
+
+ call ctest ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/shape.f90 b/gcc/testsuite/gfortran.dg/c-interop/shape.f90
new file mode 100644
index 0000000..d05de25
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/shape.f90
@@ -0,0 +1,77 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.4.1 SHAPE
+!
+! The description of the intrinsic function SHAPE in ISO/IEC 1539-1:2010
+! is changed for an assumed-rank array that is associated with an
+! assumed-size array; an assumed-size array has no shape, but in this
+! case the result has a value equal to
+! [ (SIZE (ARRAY, I, KIND), I=1,RANK (ARRAY)) ]
+! with KIND omitted from SIZE if it was omitted from SHAPE.
+!
+! The idea here is that the main program passes some arrays to a test
+! subroutine with an assumed-size dummy, which in turn passes that to a
+! subroutine with an assumed-rank dummy.
+
+program test
+ implicit none
+ ! Define some arrays for testing.
+ integer, target :: x1(5)
+ integer :: y1(0:9)
+ integer, pointer :: p1(:)
+ integer, allocatable :: a1(:)
+ integer, target :: x3(2,3,4)
+ integer :: y3(0:1,-3:-1,4)
+ integer, pointer :: p3(:,:,:)
+ integer, allocatable :: a3(:,:,:)
+
+ ! Test the 1-dimensional arrays.
+ call test1 (x1)
+ call test1 (y1)
+ p1 => x1
+ call test1 (p1)
+ allocate (a1(5))
+ call test1 (a1)
+
+ ! Test the multi-dimensional arrays.
+ call test3 (x3, 1, 2, 1, 3)
+ call test3 (y3, 0, 1, -3, -1)
+ p3 => x3
+ call test3 (p3, 1, 2, 1, 3)
+ allocate (a3(2,3,4))
+ call test3 (a3, 1, 2, 1, 3)
+
+contains
+
+ subroutine testit (a)
+ integer :: a(..)
+
+ integer :: r
+ r = rank(a)
+
+ block
+ integer :: s(r), i
+ s = shape(a)
+ do i = 1, r
+ if (s(i) .ne. size(a,i)) stop 101
+ end do
+ end block
+
+ end subroutine
+
+ subroutine test1 (a)
+ integer :: a(*)
+
+ call testit (a)
+ end subroutine
+
+ subroutine test3 (a, l1, u1, l2, u2)
+ implicit none
+ integer :: l1, u1, l2, u2
+ integer :: a(l1:u1, l2:u2, *)
+
+ call testit (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/size.f90 b/gcc/testsuite/gfortran.dg/c-interop/size.f90
new file mode 100644
index 0000000..58b32b0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/size.f90
@@ -0,0 +1,106 @@
+! Reported as pr94070.
+! { dg-do run }
+!
+! TS 29113
+! 6.4.2 SIZE
+!
+! The description of the intrinsic function SIZE in ISO/IEC 1539-1:2010
+! is changed in the following cases:
+!
+! (1) for an assumed-rank object that is associated with an assumed-size
+! array, the result has the value −1 if DIM is present and equal to the
+! rank of ARRAY, and a negative value that is equal to
+! PRODUCT ( [ (SIZE (ARRAY, I, KIND), I=1, RANK (ARRAY)) ] )
+! if DIM is not present;
+!
+! (2) for an assumed-rank object that is associated with a scalar, the
+! result has the value 1.
+!
+! The idea here is that the main program passes some arrays to a test
+! subroutine with an assumed-size dummy, which in turn passes that to a
+! subroutine with an assumed-rank dummy.
+
+program test
+
+ ! Define some arrays for testing.
+ integer, target :: x1(5)
+ integer :: y1(0:9)
+ integer, pointer :: p1(:)
+ integer, allocatable :: a1(:)
+ integer, target :: x3(2,3,4)
+ integer :: y3(0:1,-3:-1,4)
+ integer, pointer :: p3(:,:,:)
+ integer, allocatable :: a3(:,:,:)
+ integer :: x
+
+ ! Test the 1-dimensional arrays.
+ call test1 (x1)
+ call test1 (y1)
+ p1 => x1
+ call test1 (p1)
+ allocate (a1(5))
+ call test1 (a1)
+
+ ! Test the multi-dimensional arrays.
+ call test3 (x3, 1, 2, 1, 3)
+ call test3 (y3, 0, 1, -3, -1)
+ p3 => x3
+ call test3 (p3, 1, 2, 1, 3)
+ allocate (a3(2,3,4))
+ call test3 (a3, 1, 2, 1, 3)
+
+ ! Test scalars.
+ call test0 (x)
+ call test0 (-1)
+ call test0 (x1(1))
+
+contains
+
+ subroutine testit (a, r, sizes)
+ integer :: a(..)
+ integer :: r
+ integer :: sizes(r)
+
+ integer :: totalsize, thissize
+ totalsize = 1
+
+ if (r .ne. rank(a)) stop 101
+
+ do i = 1, r
+ thissize = size (a, i)
+ print *, 'got size ', thissize, ' expected ', sizes(i)
+ if (thissize .ne. sizes(i)) stop 102
+ totalsize = totalsize * thissize
+ end do
+
+ if (size(a) .ne. totalsize) stop 103
+ end subroutine
+
+ subroutine test0 (a)
+ integer :: a(..)
+
+ if (size (a) .ne. 1) stop 103
+ end subroutine
+
+ subroutine test1 (a)
+ integer :: a(*)
+
+ integer :: sizes(1)
+ sizes(1) = -1
+ call testit (a, 1, sizes)
+ end subroutine
+
+ subroutine test3 (a, l1, u1, l2, u2)
+ implicit none
+ integer :: l1, u1, l2, u2
+ integer :: a(l1:u1, l2:u2, *)
+
+ integer :: sizes(3)
+ sizes(1) = u1 - l1 + 1
+ sizes(2) = u2 - l2 + 1
+ sizes(3) = -1
+
+ call testit (a, 3, sizes)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/tkr.f90 b/gcc/testsuite/gfortran.dg/c-interop/tkr.f90
new file mode 100644
index 0000000..c0c0d7e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/tkr.f90
@@ -0,0 +1,46 @@
+! { dg-do compile}
+!
+! TS 29113
+! The definition of TKR compatible in paragraph 2 of subclause 12.4.3.4.5
+! of ISO/IEC 1539-1:2010 is changed to:
+!
+! A dummy argument is type, kind, and rank compatible, or TKR compatible,
+! with another dummy argument if the first is type compatible with the
+! second, the kind type parameters of the first have the same values as
+! the corresponding kind type parameters of the second, and both have the
+! same rank or either is assumed-rank.
+!
+! This test file contains tests that are expected to issue diagnostics
+! for invalid code.
+
+module m
+
+interface foo
+ subroutine foo_1 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x(..)
+ end subroutine
+ subroutine foo_2 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x(:, :)
+ end subroutine
+end interface
+
+interface bar
+ subroutine bar_1 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x(..)
+ end subroutine
+ subroutine bar_2 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x(..)
+ end subroutine
+end interface
+
+interface baz
+ subroutine baz_1 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x
+ end subroutine
+ subroutine baz_2 (x) ! { dg-error "Ambiguous interfaces" }
+ integer :: x(..)
+ end subroutine
+end interface
+
+end module
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic-c.c
new file mode 100644
index 0000000..34bf218
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic-c.c
@@ -0,0 +1,169 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest_int1 (CFI_cdesc_t *arg_int,
+ CFI_cdesc_t *arg_short,
+ CFI_cdesc_t *arg_long,
+ CFI_cdesc_t *arg_long_long,
+ CFI_cdesc_t *arg_signed_char);
+
+extern void ctest_int2 (CFI_cdesc_t *arg_int8,
+ CFI_cdesc_t *arg_int16,
+ CFI_cdesc_t *arg_int32,
+ CFI_cdesc_t *arg_int64);
+
+extern void ctest_int3 (CFI_cdesc_t *arg_least8,
+ CFI_cdesc_t *arg_least16,
+ CFI_cdesc_t *arg_least32,
+ CFI_cdesc_t *arg_least64);
+
+extern void ctest_int4 (CFI_cdesc_t *arg_fast8,
+ CFI_cdesc_t *arg_fast16,
+ CFI_cdesc_t *arg_fast32,
+ CFI_cdesc_t *arg_fast64);
+
+extern void ctest_int5 (CFI_cdesc_t *arg_size,
+ CFI_cdesc_t *arg_intmax,
+ CFI_cdesc_t *arg_intptr,
+ CFI_cdesc_t *arg_ptrdiff);
+
+extern void ctest_real (CFI_cdesc_t *arg_float,
+ CFI_cdesc_t *arg_double);
+
+extern void ctest_complex (CFI_cdesc_t *arg_float_complex,
+ CFI_cdesc_t *arg_double_complex);
+
+extern void ctest_misc (CFI_cdesc_t *arg_bool,
+ CFI_cdesc_t *arg_cptr,
+ CFI_cdesc_t *arg_cfunptr,
+ CFI_cdesc_t *arg_struct);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->base_addr == NULL)
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+
+/* Test that the basic integer types correspond correctly. */
+void
+ctest_int1 (CFI_cdesc_t *arg_int,
+ CFI_cdesc_t *arg_short,
+ CFI_cdesc_t *arg_long,
+ CFI_cdesc_t *arg_long_long,
+ CFI_cdesc_t *arg_signed_char)
+{
+ check (arg_int, sizeof (int), CFI_type_int);
+ check (arg_short, sizeof (short), CFI_type_short);
+ check (arg_long, sizeof (long), CFI_type_long);
+ check (arg_long_long, sizeof (long long int), CFI_type_long_long);
+ check (arg_signed_char, sizeof (signed char), CFI_type_signed_char);
+}
+
+/* Test the integer types of explicit sizes. */
+void
+ctest_int2 (CFI_cdesc_t *arg_int8,
+ CFI_cdesc_t *arg_int16,
+ CFI_cdesc_t *arg_int32,
+ CFI_cdesc_t *arg_int64)
+{
+ check (arg_int8, sizeof (int8_t), CFI_type_int8_t);
+ check (arg_int16, sizeof (int16_t), CFI_type_int16_t);
+ check (arg_int32, sizeof (int32_t), CFI_type_int32_t);
+ check (arg_int64, sizeof (int64_t), CFI_type_int64_t);
+}
+
+/* Check the int_least*_t types. */
+
+void
+ctest_int3 (CFI_cdesc_t *arg_least8,
+ CFI_cdesc_t *arg_least16,
+ CFI_cdesc_t *arg_least32,
+ CFI_cdesc_t *arg_least64)
+{
+ check (arg_least8, sizeof (int_least8_t), CFI_type_int_least8_t);
+ check (arg_least16, sizeof (int_least16_t), CFI_type_int_least16_t);
+ check (arg_least32, sizeof (int_least32_t), CFI_type_int_least32_t);
+ check (arg_least64, sizeof (int_least64_t), CFI_type_int_least64_t);
+}
+
+/* Check the int_fast*_t types. */
+void
+ctest_int4 (CFI_cdesc_t *arg_fast8,
+ CFI_cdesc_t *arg_fast16,
+ CFI_cdesc_t *arg_fast32,
+ CFI_cdesc_t *arg_fast64)
+{
+ check (arg_fast8, sizeof (int_fast8_t), CFI_type_int_fast8_t);
+ check (arg_fast16, sizeof (int_fast16_t), CFI_type_int_fast16_t);
+ check (arg_fast32, sizeof (int_fast32_t), CFI_type_int_fast32_t);
+ check (arg_fast64, sizeof (int_fast64_t), CFI_type_int_fast64_t);
+}
+
+/* Check the "purposeful" integer types. */
+void
+ctest_int5 (CFI_cdesc_t *arg_size,
+ CFI_cdesc_t *arg_intmax,
+ CFI_cdesc_t *arg_intptr,
+ CFI_cdesc_t *arg_ptrdiff)
+{
+ check (arg_size, sizeof (size_t), CFI_type_size_t);
+ check (arg_intmax, sizeof (intmax_t), CFI_type_intmax_t);
+ check (arg_intptr, sizeof (intptr_t), CFI_type_intptr_t);
+ check (arg_ptrdiff, sizeof (ptrdiff_t), CFI_type_ptrdiff_t);
+}
+
+/* Check the floating-point types. */
+void
+ctest_real (CFI_cdesc_t *arg_float,
+ CFI_cdesc_t *arg_double)
+{
+ check (arg_float, sizeof (float), CFI_type_float);
+ check (arg_double, sizeof (double), CFI_type_double);
+}
+
+/* Likewise for the complex types. */
+void
+ctest_complex (CFI_cdesc_t *arg_float_complex,
+ CFI_cdesc_t *arg_double_complex)
+{
+ check (arg_float_complex, sizeof (float _Complex),
+ CFI_type_float_Complex);
+ check (arg_double_complex, sizeof (double _Complex),
+ CFI_type_double_Complex);
+}
+
+/* Misc types. */
+void
+ctest_misc (CFI_cdesc_t *arg_bool,
+ CFI_cdesc_t *arg_cptr,
+ CFI_cdesc_t *arg_cfunptr,
+ CFI_cdesc_t *arg_struct)
+{
+ struct m
+ {
+ int i, j;
+ };
+
+ check (arg_bool, sizeof (_Bool), CFI_type_Bool);
+ check (arg_cptr, sizeof (void *), CFI_type_cptr);
+ check (arg_cfunptr, sizeof (void (*)(void)), CFI_type_cfunptr);
+ check (arg_struct, sizeof (struct m), CFI_type_struct);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic.f90
new file mode 100644
index 0000000..a91a6e8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-basic.f90
@@ -0,0 +1,151 @@
+! PR 101305
+! PR 100917
+! { dg-do run }
+! { dg-additional-sources "typecodes-array-basic-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that kind constants in the ISO_C_BINDING
+! module result in the right type field in arguments passed by descriptor,
+! also matching the size of the corresponding C type. We use
+! assumed-rank arrays to force the use of a descriptor.
+!
+! Some types are tested in their own testcases to allow conditionalization
+! for target-specific support or xfailing to track bugs.
+
+module mm
+ use iso_c_binding
+
+ type, bind (c) :: s
+ integer(C_INT) :: i, j
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+
+ subroutine ctest_int1 (arg_int, arg_short, arg_long, arg_long_long, &
+ arg_signed_char) bind (c)
+ use iso_c_binding
+ integer(C_INT) :: arg_int(:)
+ integer(C_SHORT) :: arg_short(:)
+ integer(C_LONG) :: arg_long(:)
+ integer(C_LONG_LONG) :: arg_long_long(:)
+ integer(C_SIGNED_CHAR) :: arg_signed_char(:)
+ end subroutine
+
+ subroutine ctest_int2 (arg_int8, arg_int16, arg_int32, arg_int64) bind (c)
+ use iso_c_binding
+ integer(C_INT8_T) :: arg_int8(:)
+ integer(C_INT16_T) :: arg_int16(:)
+ integer(C_INT32_T) :: arg_int32(:)
+ integer(C_INT64_T) :: arg_int64(:)
+ end subroutine
+
+ subroutine ctest_int3 (arg_least8, arg_least16, arg_least32, &
+ arg_least64) bind (c)
+ use iso_c_binding
+ integer(C_INT_LEAST8_T) :: arg_least8(:)
+ integer(C_INT_LEAST16_T) :: arg_least16(:)
+ integer(C_INT_LEAST32_T) :: arg_least32(:)
+ integer(C_INT_LEAST64_T) :: arg_least64(:)
+ end subroutine
+
+ subroutine ctest_int4 (arg_fast8, arg_fast16, arg_fast32, &
+ arg_fast64) bind (c)
+ use iso_c_binding
+ integer(C_INT_FAST8_T) :: arg_fast8(:)
+ integer(C_INT_FAST16_T) :: arg_fast16(:)
+ integer(C_INT_FAST32_T) :: arg_fast32(:)
+ integer(C_INT_FAST64_T) :: arg_fast64(:)
+ end subroutine
+
+ subroutine ctest_int5 (arg_size, arg_intmax, arg_intptr, &
+ arg_ptrdiff) bind (c)
+ use iso_c_binding
+ integer(C_SIZE_T) :: arg_size(:)
+ integer(C_INTMAX_T) :: arg_intmax(:)
+ integer(C_INTPTR_T) :: arg_intptr(:)
+ integer(C_PTRDIFF_T) :: arg_ptrdiff(:)
+ end subroutine
+
+ subroutine ctest_real (arg_float, arg_double) bind (c)
+ use iso_c_binding
+ real(C_FLOAT) :: arg_float(:)
+ real(C_DOUBLE) :: arg_double(:)
+ end subroutine
+
+ subroutine ctest_complex (arg_float_complex, arg_double_complex) &
+ bind (c)
+ use iso_c_binding
+ complex(C_FLOAT_COMPLEX) :: arg_float_complex(:)
+ complex(C_DOUBLE_COMPLEX) :: arg_double_complex(:)
+ end subroutine
+
+ subroutine ctest_misc (arg_bool, arg_cptr, arg_cfunptr, &
+ arg_struct) bind (c)
+ use iso_c_binding
+ use mm
+ logical(C_BOOL) :: arg_bool(:)
+ type(C_PTR) :: arg_cptr(:)
+ type(C_FUNPTR) :: arg_cfunptr(:)
+ type(s) :: arg_struct(:)
+ end subroutine
+
+ end interface
+
+ integer(C_INT) :: var_int(4)
+ integer(C_SHORT) :: var_short(4)
+ integer(C_LONG) :: var_long(4)
+ integer(C_LONG_LONG) :: var_long_long(4)
+ integer(C_SIGNED_CHAR) :: var_signed_char(4)
+ integer(C_INT8_T) :: var_int8(4)
+ integer(C_INT16_T) :: var_int16(4)
+ integer(C_INT32_T) :: var_int32(4)
+ integer(C_INT64_T) :: var_int64(4)
+ integer(C_INT_LEAST8_T) :: var_least8(4)
+ integer(C_INT_LEAST16_T) :: var_least16(4)
+ integer(C_INT_LEAST32_T) :: var_least32(4)
+ integer(C_INT_LEAST64_T) :: var_least64(4)
+ integer(C_INT_FAST8_T) :: var_fast8(4)
+ integer(C_INT_FAST16_T) :: var_fast16(4)
+ integer(C_INT_FAST32_T) :: var_fast32(4)
+ integer(C_INT_FAST64_T) :: var_fast64(4)
+ integer(C_SIZE_T) :: var_size(4)
+ integer(C_INTMAX_T) :: var_intmax(4)
+ integer(C_INTPTR_T) :: var_intptr(4)
+ integer(C_PTRDIFF_T) :: var_ptrdiff(4)
+ real(C_FLOAT) :: var_float(4)
+ real(C_DOUBLE) :: var_double(4)
+ complex(C_FLOAT_COMPLEX) :: var_float_complex(4)
+ complex(C_DOUBLE_COMPLEX) :: var_double_complex(4)
+ logical(C_BOOL) :: var_bool(4)
+ type(C_PTR) :: var_cptr(4)
+ type(C_FUNPTR) :: var_cfunptr(4)
+ type(s) :: var_struct(4)
+
+ call ctest_int1 (var_int, var_short, var_long, var_long_long, &
+ var_signed_char)
+
+ call ctest_int2 (var_int8, var_int16, var_int32, var_int64)
+
+ call ctest_int3 (var_least8, var_least16, var_least32, var_least64)
+
+ call ctest_int4 (var_fast8, var_fast16, var_fast32, var_fast64)
+
+ call ctest_int5 (var_size, var_intmax, var_intptr, var_ptrdiff)
+
+ call ctest_real (var_float, var_double)
+
+ call ctest_complex (var_float_complex, var_double_complex)
+
+ call ctest_misc (var_bool, var_cptr, var_cfunptr, var_struct)
+
+ ! FIXME: how do you pass something that corresponds to CFI_type_other?
+ ! The Fortran front end complains if you try to pass something that
+ ! isn't interoperable, such as a derived type object without bind(c).
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char-c.c
new file mode 100644
index 0000000..ca2f49d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char-c.c
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest_1 (CFI_cdesc_t *arg_char, CFI_cdesc_t *arg_ucs4);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->base_addr == NULL)
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest_1 (CFI_cdesc_t *arg_char, CFI_cdesc_t *arg_ucs4)
+{
+ check (arg_char, 1, CFI_type_char);
+ check (arg_ucs4, 4, CFI_type_ucs4_char);
+}
+
+void
+ctest_5 (CFI_cdesc_t *arg_char, CFI_cdesc_t *arg_ucs4)
+{
+ check (arg_char, 5*1, CFI_type_char);
+ check (arg_ucs4, 5*4, CFI_type_ucs4_char);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char.f90
new file mode 100644
index 0000000..71f84d0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-char.f90
@@ -0,0 +1,47 @@
+! PR 101305
+! PR 92482
+! { dg-do run }
+! { dg-additional-sources "typecodes-array-char-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that the character kind constants provided by
+! gfortran's ISO_C_BINDING module result in the right type field in
+! arguments passed by descriptor, also matching the size of the corresponding
+! C type. We use assumed-shape arrays to force the use of a descriptor.
+!
+! FIXME: because of PR92482, we can only test len=1 characters. This
+! test should be extended once that bug is fixed.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
+
+ interface
+
+ subroutine ctest_1 (arg_cchar, arg_ucs4) bind (c)
+ use iso_c_binding
+ integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
+ character(kind=C_CHAR) :: arg_cchar(:)
+ character(kind=ucs4) :: arg_ucs4(:)
+ end subroutine
+
+ subroutine ctest_5 (arg_cchar, arg_ucs4) bind (c)
+ use iso_c_binding
+ integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
+ character(kind=C_CHAR,len=*) :: arg_cchar(:)
+ character(kind=ucs4,len=*) :: arg_ucs4(:)
+ end subroutine
+
+ end interface
+
+ character(kind=C_CHAR) :: var_cchar(4)
+ character(kind=ucs4) :: var_ucs4(4)
+ character(kind=C_CHAR,len=5) :: var_cchar_5(4)
+ character(kind=ucs4,len=5) :: var_ucs4_5(4)
+
+ call ctest_1 (var_cchar, var_ucs4)
+ call ctest_5 (var_cchar_5, var_ucs4_5)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c
new file mode 100644
index 0000000..4fcb6e2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128-c.c
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_float128,
+ CFI_cdesc_t *arg_complex128);
+
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->base_addr == NULL)
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_float128,
+ CFI_cdesc_t *arg_complex128)
+{
+ check (arg_float128, sizeof (_Float128), CFI_type_float128);
+ check (arg_complex128, sizeof (_Float128) * 2,
+ CFI_type_float128_Complex);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128.f90
new file mode 100644
index 0000000..66737b2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-float128.f90
@@ -0,0 +1,34 @@
+! PR 101305
+! PR 100914
+! PR 100917
+! Fails on x86 targets where sizeof(long double) == 16 (PR100917).
+! { dg-do run }
+! { dg-require-effective-target fortran_real_c_float128 }
+! { dg-additional-sources "typecodes-array-float128-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that the vendor extension kind constants provided by
+! gfortran's ISO_C_BINDING module result in the right type field in
+! arguments passed by descriptor, also matching the size of the corresponding
+! C type. We use assumed-shape arrays to force the use of a descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_float128, arg_complex128) bind (c)
+ use iso_c_binding
+ real(C_FLOAT128) :: arg_float128(:)
+ complex(C_FLOAT128_COMPLEX) :: arg_complex128(:)
+ end subroutine
+
+ end interface
+
+ real(C_FLOAT128) :: var_float128(4)
+ complex(C_FLOAT128_COMPLEX) :: var_complex128(4)
+
+ call ctest (var_float128, var_complex128)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128-c.c
new file mode 100644
index 0000000..f6f8c75
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128-c.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_int128,
+ CFI_cdesc_t *arg_least128,
+ CFI_cdesc_t *arg_fast128);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->base_addr == NULL)
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_int128,
+ CFI_cdesc_t *arg_least128,
+ CFI_cdesc_t *arg_fast128)
+{
+ check (arg_int128, sizeof (__int128), CFI_type_int128_t);
+ check (arg_least128, sizeof (__int128), CFI_type_int_least128_t);
+ check (arg_fast128, sizeof (__int128), CFI_type_int_fast128_t);
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128.f90
new file mode 100644
index 0000000..671c544
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-int128.f90
@@ -0,0 +1,33 @@
+! PR 101305
+! { dg-do run }
+! { dg-require-effective-target fortran_integer_16 }
+! { dg-additional-sources "typecodes-array-int128-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that 128-bit integer kind constants provided by
+! gfortran's ISO_C_BINDING module result in the right type field in
+! arguments passed by descriptor, also matching the size of the corresponding
+! C type. We use assumed-shape arrays to force the use of a descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_int128, arg_least128, arg_fast128) bind (c)
+ use iso_c_binding
+ integer(C_INT128_T) :: arg_int128(:)
+ integer(C_INT_LEAST128_T) :: arg_least128(:)
+ integer(C_INT_FAST128_T) :: arg_fast128(:)
+ end subroutine
+
+ end interface
+
+ integer(C_INT128_T) :: var_int128(4)
+ integer(C_INT_LEAST128_T) :: var_least128(4)
+ integer(C_INT_FAST128_T) :: var_fast128(4)
+
+ call ctest (var_int128, var_least128, var_fast128)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble-c.c
new file mode 100644
index 0000000..e47e4e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble-c.c
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_long_double,
+ CFI_cdesc_t *arg_long_double_complex);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_other)
+ abort ();
+ if (a->base_addr == NULL)
+ abort ();
+ if (a->rank != 1)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_long_double,
+ CFI_cdesc_t *arg_long_double_complex)
+{
+ check (arg_long_double, sizeof (long double), CFI_type_long_double);
+ check (arg_long_double_complex, sizeof (long double _Complex),
+ CFI_type_long_double_Complex);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble.f90
new file mode 100644
index 0000000..100071f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-array-longdouble.f90
@@ -0,0 +1,32 @@
+! PR 101305
+! PR 100917
+! { dg-do run }
+! { dg-additional-sources "typecodes-array-longdouble-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that long double kind constants in the ISO_C_BINDING
+! module result in the right type field in arguments passed by descriptor,
+! also matching the size of the corresponding C type. We use
+! assumed-rank arrays to force the use of a descriptor.
+
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_long_double, arg_long_double_complex) bind (c)
+ use iso_c_binding
+ real(C_LONG_DOUBLE) :: arg_long_double(:)
+ complex(C_LONG_DOUBLE_COMPLEX) :: arg_long_double_complex(:)
+ end subroutine
+
+ end interface
+
+ real(C_LONG_DOUBLE) :: var_long_double(4)
+ complex(C_LONG_DOUBLE_COMPLEX) :: var_long_double_complex(4)
+
+ call ctest (var_long_double, var_long_double_complex)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c
new file mode 100644
index 0000000..90f0b20
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity-c.c
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+
+extern void ctest_typecodes (void);
+
+/* Do sanity checking on the CFI_type_* macros. In particular, make sure
+ that if two type codes have the same value, they represent objects of the
+ same size. */
+
+struct tc_info
+{
+ CFI_type_t typecode;
+ char *name;
+ size_t size;
+ int extension;
+};
+
+static struct tc_info tc_table[] =
+{
+ /* Extension types.
+ Note there is no portable C equivalent type for CFI_type_ucs4_char type
+ (4-byte Unicode characters), so this is kind of hacky... */
+#if CFI_type_int128_t > 0
+ { CFI_type_int128_t, "CFI_type_int128_t",
+ sizeof (__int128), 1 },
+ { CFI_type_int_least128_t, "CFI_type_int_least128_t",
+ sizeof (__int128), 1 },
+ { CFI_type_int_fast128_t, "CFI_type_int_fast128_t",
+ sizeof (__int128), 1 },
+#endif
+#if CFI_type_ucs4_char > 0
+ { CFI_type_ucs4_char, "CFI_type_ucs4_char", 4, 1 },
+#endif
+#if CFI_type_float128 > 0
+ { CFI_type_float128, "CFI_type_float128",
+ sizeof (_Float128), 1 },
+ { CFI_type_float128_Complex, "CFI_type_float128_Complex",
+ sizeof (_Float128 _Complex), 1 },
+#endif
+#if CFI_type_cfunptr > 0
+ { CFI_type_cfunptr, "CFI_type_cfunptr",
+ sizeof (void (*)(void)), 1 },
+#endif
+
+ /* Standard types. */
+ { CFI_type_signed_char, "CFI_type_signed_char",
+ sizeof (signed char), 0, },
+ { CFI_type_short, "CFI_type_short",
+ sizeof (short), 0 },
+ { CFI_type_int, "CFI_type_int",
+ sizeof (int), 0 },
+ { CFI_type_long, "CFI_type_long",
+ sizeof (long), 0 },
+ { CFI_type_long_long, "CFI_type_long_long",
+ sizeof (long long), 0 },
+ { CFI_type_size_t, "CFI_type_size_t",
+ sizeof (size_t), 0 },
+ { CFI_type_int8_t, "CFI_type_int8_t",
+ sizeof (int8_t), 0 },
+ { CFI_type_int16_t, "CFI_type_int16_t",
+ sizeof (int16_t), 0 },
+ { CFI_type_int32_t, "CFI_type_int32_t",
+ sizeof (int32_t), 0 },
+ { CFI_type_int64_t, "CFI_type_int64_t",
+ sizeof (int64_t), 0 },
+ { CFI_type_int_least8_t, "CFI_type_int_least8_t",
+ sizeof (int_least8_t), 0 },
+ { CFI_type_int_least16_t, "CFI_type_int_least16_t",
+ sizeof (int_least16_t), 0 },
+ { CFI_type_int_least32_t, "CFI_type_int_least32_t",
+ sizeof (int_least32_t), 0 },
+ { CFI_type_int_least64_t, "CFI_type_int_least64_t",
+ sizeof (int_least64_t), 0 },
+ { CFI_type_int_fast8_t, "CFI_type_int_fast8_t",
+ sizeof (int_fast8_t), 0 },
+ { CFI_type_int_fast16_t, "CFI_type_int_fast16_t",
+ sizeof (int_fast16_t), 0 },
+ { CFI_type_int_fast32_t, "CFI_type_int_fast32_t",
+ sizeof (int_fast32_t), 0 },
+ { CFI_type_int_fast64_t, "CFI_type_int_fast64_t",
+ sizeof (int_fast64_t), 0 },
+ { CFI_type_intmax_t, "CFI_type_intmax_t",
+ sizeof (intmax_t), 0 },
+ { CFI_type_intptr_t, "CFI_type_intptr_t",
+ sizeof (intptr_t), 0 },
+ { CFI_type_ptrdiff_t, "CFI_type_ptrdiff_t",
+ sizeof (ptrdiff_t), 0 },
+ { CFI_type_float, "CFI_type_float",
+ sizeof (float), 0 },
+ { CFI_type_double, "CFI_type_double",
+ sizeof (double), 0 },
+ { CFI_type_long_double, "CFI_type_long_double",
+ sizeof (long double), 0 },
+ { CFI_type_float_Complex, "CFI_type_float_Complex",
+ sizeof (float _Complex), 0 },
+ { CFI_type_double_Complex, "CFI_type_double_Complex",
+ sizeof (double _Complex), 0 },
+ { CFI_type_long_double_Complex, "CFI_type_long_double_Complex",
+ sizeof (long double _Complex), 0 },
+ { CFI_type_Bool, "CFI_type_Bool",
+ sizeof (_Bool), 0 },
+ { CFI_type_char, "CFI_type_char",
+ sizeof (char), 0 },
+ { CFI_type_cptr, "CFI_type_cptr",
+ sizeof (void *), 0 },
+ { CFI_type_struct, "CFI_type_struct", 0, 0 },
+ { CFI_type_other, "CFI_type_other", -1, 0, }
+};
+
+void
+ctest_typecodes (void)
+{
+ int ncodes = sizeof (tc_table) / sizeof (struct tc_info);
+ int i, j;
+ int bad = 0;
+
+ for (i = 0; i < ncodes; i++)
+ for (j = i + 1; j < ncodes; j++)
+ if (tc_table[i].typecode == tc_table[j].typecode
+ && tc_table[i].typecode > 0
+ && (tc_table[i].size != tc_table[j].size))
+ {
+ fprintf (stderr,
+ "type codes have the same value %d but different sizes\n",
+ (int) tc_table[i].typecode);
+ fprintf (stderr, " %s size %d\n",
+ tc_table[i].name, (int) tc_table[i].size);
+ fprintf (stderr, " %s size %d\n",
+ tc_table[j].name, (int) tc_table[j].size);
+ bad = 1;
+ }
+
+ /* TS29113 Section 8.3.4: The value for CFI_type_other shall be negative
+ and distinct from all other type specifiers. If a C type is not
+ interoperable with a Fortran type and kind supported by the
+ Fortran processor, its macro shall evaluate to a negative value.
+ Otherwise, the value for an intrinsic type shall be positive.
+
+ In the case of GCC, we expect that all the standard intrinsic
+ types are supported by both Fortran and C, so they should all be
+ positive except for CFI_type_other. Non-standard ones may have a
+ value -2. */
+
+ for (i = 0; i < ncodes; i++)
+ {
+ if (tc_table[i].typecode == CFI_type_other)
+ {
+ if (tc_table[i].typecode >= 0)
+ {
+ fprintf (stderr, "%s value %d is not negative\n",
+ tc_table[i].name, (int)tc_table[i].typecode);
+ bad = 1;
+ }
+ if (strcmp (tc_table[i].name, "CFI_type_other"))
+ {
+ fprintf (stderr, "%s has the same value %d as CFI_type_other\n",
+ tc_table[i].name, (int)CFI_type_other);
+ bad = 1;
+ }
+ }
+ else if (tc_table[i].typecode == -2 && tc_table[i].extension)
+ /* Unsupported extension type on this target; this is OK */
+ ;
+ else if (tc_table[i].typecode <= 0)
+ {
+ fprintf (stderr, "%s value %d is not positive\n",
+ tc_table[i].name, (int)tc_table[i].typecode);
+ bad = 1;
+ }
+ }
+
+ if (bad)
+ abort ();
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity.f90
new file mode 100644
index 0000000..7dcc62d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-sanity.f90
@@ -0,0 +1,24 @@
+! PR 101305
+! { dg-do run }
+! { dg-additional-sources "typecodes-sanity-c.c" }
+! { dg-additional-options "-g" }
+!
+! This program does sanity checking on the CFI_type_* macros. All
+! of the interesting things happen on the C side.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
+
+ interface
+
+ subroutine ctest_typecodes () bind (c)
+ end subroutine
+
+ end interface
+
+ call ctest_typecodes ()
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic-c.c
new file mode 100644
index 0000000..fe1a10a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic-c.c
@@ -0,0 +1,168 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest_int1 (CFI_cdesc_t *arg_int,
+ CFI_cdesc_t *arg_short,
+ CFI_cdesc_t *arg_long,
+ CFI_cdesc_t *arg_long_long,
+ CFI_cdesc_t *arg_signed_char);
+
+extern void ctest_int2 (CFI_cdesc_t *arg_int8,
+ CFI_cdesc_t *arg_int16,
+ CFI_cdesc_t *arg_int32,
+ CFI_cdesc_t *arg_int64);
+
+extern void ctest_int3 (CFI_cdesc_t *arg_least8,
+ CFI_cdesc_t *arg_least16,
+ CFI_cdesc_t *arg_least32,
+ CFI_cdesc_t *arg_least64);
+
+extern void ctest_int4 (CFI_cdesc_t *arg_fast8,
+ CFI_cdesc_t *arg_fast16,
+ CFI_cdesc_t *arg_fast32,
+ CFI_cdesc_t *arg_fast64);
+
+extern void ctest_int5 (CFI_cdesc_t *arg_size,
+ CFI_cdesc_t *arg_intmax,
+ CFI_cdesc_t *arg_intptr,
+ CFI_cdesc_t *arg_ptrdiff);
+
+extern void ctest_real (CFI_cdesc_t *arg_float,
+ CFI_cdesc_t *arg_double);
+
+extern void ctest_complex (CFI_cdesc_t *arg_float_complex,
+ CFI_cdesc_t *arg_double_complex);
+
+extern void ctest_misc (CFI_cdesc_t *arg_bool,
+ CFI_cdesc_t *arg_cptr,
+ CFI_cdesc_t *arg_cfunptr,
+ CFI_cdesc_t *arg_struct);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_pointer)
+ abort ();
+ if (a->base_addr != NULL)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+
+/* Test that the basic integer types correspond correctly. */
+void
+ctest_int1 (CFI_cdesc_t *arg_int,
+ CFI_cdesc_t *arg_short,
+ CFI_cdesc_t *arg_long,
+ CFI_cdesc_t *arg_long_long,
+ CFI_cdesc_t *arg_signed_char)
+{
+ check (arg_int, sizeof (int), CFI_type_int);
+ check (arg_short, sizeof (short), CFI_type_short);
+ check (arg_long, sizeof (long), CFI_type_long);
+ check (arg_long_long, sizeof (long long int), CFI_type_long_long);
+ check (arg_signed_char, sizeof (signed char), CFI_type_signed_char);
+}
+
+/* Test the integer types of explicit sizes. */
+void
+ctest_int2 (CFI_cdesc_t *arg_int8,
+ CFI_cdesc_t *arg_int16,
+ CFI_cdesc_t *arg_int32,
+ CFI_cdesc_t *arg_int64)
+{
+ check (arg_int8, sizeof (int8_t), CFI_type_int8_t);
+ check (arg_int16, sizeof (int16_t), CFI_type_int16_t);
+ check (arg_int32, sizeof (int32_t), CFI_type_int32_t);
+ check (arg_int64, sizeof (int64_t), CFI_type_int64_t);
+}
+
+/* Check the int_least*_t types. */
+
+void
+ctest_int3 (CFI_cdesc_t *arg_least8,
+ CFI_cdesc_t *arg_least16,
+ CFI_cdesc_t *arg_least32,
+ CFI_cdesc_t *arg_least64)
+{
+ check (arg_least8, sizeof (int_least8_t), CFI_type_int_least8_t);
+ check (arg_least16, sizeof (int_least16_t), CFI_type_int_least16_t);
+ check (arg_least32, sizeof (int_least32_t), CFI_type_int_least32_t);
+ check (arg_least64, sizeof (int_least64_t), CFI_type_int_least64_t);
+}
+
+/* Check the int_fast*_t types. */
+void
+ctest_int4 (CFI_cdesc_t *arg_fast8,
+ CFI_cdesc_t *arg_fast16,
+ CFI_cdesc_t *arg_fast32,
+ CFI_cdesc_t *arg_fast64)
+{
+ check (arg_fast8, sizeof (int_fast8_t), CFI_type_int_fast8_t);
+ check (arg_fast16, sizeof (int_fast16_t), CFI_type_int_fast16_t);
+ check (arg_fast32, sizeof (int_fast32_t), CFI_type_int_fast32_t);
+ check (arg_fast64, sizeof (int_fast64_t), CFI_type_int_fast64_t);
+}
+
+/* Check the "purposeful" integer types. */
+void
+ctest_int5 (CFI_cdesc_t *arg_size,
+ CFI_cdesc_t *arg_intmax,
+ CFI_cdesc_t *arg_intptr,
+ CFI_cdesc_t *arg_ptrdiff)
+{
+ check (arg_size, sizeof (size_t), CFI_type_size_t);
+ check (arg_intmax, sizeof (intmax_t), CFI_type_intmax_t);
+ check (arg_intptr, sizeof (intptr_t), CFI_type_intptr_t);
+ check (arg_ptrdiff, sizeof (ptrdiff_t), CFI_type_ptrdiff_t);
+}
+
+/* Check the floating-point types. */
+void
+ctest_real (CFI_cdesc_t *arg_float,
+ CFI_cdesc_t *arg_double)
+{
+ check (arg_float, sizeof (float), CFI_type_float);
+ check (arg_double, sizeof (double), CFI_type_double);
+}
+
+/* Likewise for the complex types. */
+void
+ctest_complex (CFI_cdesc_t *arg_float_complex,
+ CFI_cdesc_t *arg_double_complex)
+{
+ check (arg_float_complex, sizeof (float _Complex),
+ CFI_type_float_Complex);
+ check (arg_double_complex, sizeof (double _Complex),
+ CFI_type_double_Complex);
+}
+
+/* Misc types. */
+void
+ctest_misc (CFI_cdesc_t *arg_bool,
+ CFI_cdesc_t *arg_cptr,
+ CFI_cdesc_t *arg_cfunptr,
+ CFI_cdesc_t *arg_struct)
+{
+ struct m
+ {
+ int i, j;
+ };
+
+ check (arg_bool, sizeof (_Bool), CFI_type_Bool);
+ check (arg_cptr, sizeof (void *), CFI_type_cptr);
+ check (arg_struct, sizeof (struct m), CFI_type_struct);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic.f90
new file mode 100644
index 0000000..b586b1f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-basic.f90
@@ -0,0 +1,160 @@
+! PR 101305
+! PR 100917
+! xfailed due to PR 101308
+! { dg-do run }
+! { dg-additional-sources "typecodes-scalar-basic-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that kind constants in the ISO_C_BINDING
+! module result in the right type field in arguments passed by descriptor,
+! also matching the size of the corresponding C type. We use pointers
+! to force the use of a descriptor.
+!
+! Some types are tested in their own testcases to allow conditionalization
+! for target-specific support or xfailing to track bugs.
+
+module mm
+ use iso_c_binding
+
+ type, bind (c) :: s
+ integer(C_INT) :: i, j
+ end type
+end module
+
+program testit
+ use iso_c_binding
+ use mm
+ implicit none
+
+ interface
+
+ subroutine ctest_int1 (arg_int, arg_short, arg_long, arg_long_long, &
+ arg_signed_char) bind (c)
+ use iso_c_binding
+ integer(C_INT), pointer :: arg_int
+ integer(C_SHORT), pointer :: arg_short
+ integer(C_LONG), pointer :: arg_long
+ integer(C_LONG_LONG), pointer :: arg_long_long
+ integer(C_SIGNED_CHAR), pointer :: arg_signed_char
+ end subroutine
+
+ subroutine ctest_int2 (arg_int8, arg_int16, arg_int32, arg_int64) bind (c)
+ use iso_c_binding
+ integer(C_INT8_T), pointer :: arg_int8
+ integer(C_INT16_T), pointer :: arg_int16
+ integer(C_INT32_T), pointer :: arg_int32
+ integer(C_INT64_T), pointer :: arg_int64
+ end subroutine
+
+ subroutine ctest_int3 (arg_least8, arg_least16, arg_least32, &
+ arg_least64) bind (c)
+ use iso_c_binding
+ integer(C_INT_LEAST8_T), pointer :: arg_least8
+ integer(C_INT_LEAST16_T), pointer :: arg_least16
+ integer(C_INT_LEAST32_T), pointer :: arg_least32
+ integer(C_INT_LEAST64_T), pointer :: arg_least64
+ end subroutine
+
+ subroutine ctest_int4 (arg_fast8, arg_fast16, arg_fast32, &
+ arg_fast64) bind (c)
+ use iso_c_binding
+ integer(C_INT_FAST8_T), pointer :: arg_fast8
+ integer(C_INT_FAST16_T), pointer :: arg_fast16
+ integer(C_INT_FAST32_T), pointer :: arg_fast32
+ integer(C_INT_FAST64_T), pointer :: arg_fast64
+ end subroutine
+
+ subroutine ctest_int5 (arg_size, arg_intmax, arg_intptr, &
+ arg_ptrdiff) bind (c)
+ use iso_c_binding
+ integer(C_SIZE_T), pointer :: arg_size
+ integer(C_INTMAX_T), pointer :: arg_intmax
+ integer(C_INTPTR_T), pointer :: arg_intptr
+ integer(C_PTRDIFF_T), pointer :: arg_ptrdiff
+ end subroutine
+
+ subroutine ctest_real (arg_float, arg_double) bind (c)
+ use iso_c_binding
+ real(C_FLOAT), pointer :: arg_float
+ real(C_DOUBLE), pointer :: arg_double
+ end subroutine
+
+ subroutine ctest_complex (arg_float_complex, arg_double_complex) &
+ bind (c)
+ use iso_c_binding
+ complex(C_FLOAT_COMPLEX), pointer :: arg_float_complex
+ complex(C_DOUBLE_COMPLEX), pointer :: arg_double_complex
+ end subroutine
+
+ subroutine ctest_misc (arg_bool, arg_cptr, arg_cfunptr, arg_struct) &
+ bind (c)
+ use iso_c_binding
+ use mm
+ logical(C_BOOL), pointer :: arg_bool
+ type(C_PTR), pointer :: arg_cptr
+ type(C_FUNPTR), pointer :: arg_cfunptr
+ type(s), pointer :: arg_struct
+ end subroutine
+
+ end interface
+
+ integer(C_INT), pointer :: var_int
+ integer(C_SHORT), pointer :: var_short
+ integer(C_LONG), pointer :: var_long
+ integer(C_LONG_LONG), pointer :: var_long_long
+ integer(C_SIGNED_CHAR), pointer :: var_signed_char
+ integer(C_INT8_T), pointer :: var_int8
+ integer(C_INT16_T), pointer :: var_int16
+ integer(C_INT32_T), pointer :: var_int32
+ integer(C_INT64_T), pointer :: var_int64
+ integer(C_INT_LEAST8_T), pointer :: var_least8
+ integer(C_INT_LEAST16_T), pointer :: var_least16
+ integer(C_INT_LEAST32_T), pointer :: var_least32
+ integer(C_INT_LEAST64_T), pointer :: var_least64
+ integer(C_INT_FAST8_T), pointer :: var_fast8
+ integer(C_INT_FAST16_T), pointer :: var_fast16
+ integer(C_INT_FAST32_T), pointer :: var_fast32
+ integer(C_INT_FAST64_T), pointer :: var_fast64
+ integer(C_SIZE_T), pointer :: var_size
+ integer(C_INTMAX_T), pointer :: var_intmax
+ integer(C_INTPTR_T), pointer :: var_intptr
+ integer(C_PTRDIFF_T), pointer :: var_ptrdiff
+ real(C_FLOAT), pointer :: var_float
+ real(C_DOUBLE), pointer :: var_double
+ complex(C_FLOAT_COMPLEX), pointer :: var_float_complex
+ complex(C_DOUBLE_COMPLEX), pointer :: var_double_complex
+ logical(C_BOOL), pointer :: var_bool
+ type(C_PTR), pointer :: var_cptr
+ type(C_FUNPTR), pointer :: var_cfunptr
+ type(s), pointer :: var_struct
+
+ nullify (var_int, var_short, var_long, var_long_long, var_signed_char)
+ call ctest_int1 (var_int, var_short, var_long, var_long_long, &
+ var_signed_char)
+
+ nullify (var_int8, var_int16, var_int32, var_int64)
+ call ctest_int2 (var_int8, var_int16, var_int32, var_int64)
+
+ nullify (var_least8, var_least16, var_least32, var_least64)
+ call ctest_int3 (var_least8, var_least16, var_least32, var_least64)
+
+ nullify (var_fast8, var_fast16, var_fast32, var_fast64)
+ call ctest_int4 (var_fast8, var_fast16, var_fast32, var_fast64)
+
+ nullify (var_size, var_intmax, var_intptr, var_ptrdiff)
+ call ctest_int5 (var_size, var_intmax, var_intptr, var_ptrdiff)
+
+ nullify (var_float, var_double)
+ call ctest_real (var_float, var_double)
+
+ nullify (var_float_complex, var_double_complex)
+ call ctest_complex (var_float_complex, var_double_complex)
+
+ nullify (var_bool, var_cptr, var_cfunptr, var_struct)
+ call ctest_misc (var_bool, var_cptr, var_cfunptr, var_struct)
+
+ ! FIXME: how do you pass something that corresponds to CFI_type_other?
+ ! The Fortran front end complains if you try to pass something that
+ ! isn't interoperable, such as a derived type object without bind(c).
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c
new file mode 100644
index 0000000..7eafa93
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128-c.c
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_float128,
+ CFI_cdesc_t *arg_complex128);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_pointer)
+ abort ();
+ if (a->base_addr != NULL)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_float128,
+ CFI_cdesc_t *arg_complex128)
+{
+ check (arg_float128, sizeof (_Float128), CFI_type_float128);
+ check (arg_complex128, sizeof (_Float128) * 2,
+ CFI_type_float128_Complex);
+}
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128.f90
new file mode 100644
index 0000000..c2275c4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-float128.f90
@@ -0,0 +1,34 @@
+! xfailed due to PR 101308
+! PR 101305
+! PR 100914
+! { dg-do run }
+! { dg-require-effective-target fortran_real_c_float128 }
+! { dg-additional-sources "typecodes-scalar-float128-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that the vendor extension kind constants provided by
+! gfortran's ISO_C_BINDING module result in the right type field in
+! arguments passed by descriptor,also matching the size of the corresponding
+! C type. We use pointers to force the use of a descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_float128, arg_complex128) bind (c)
+ use iso_c_binding
+ real(C_FLOAT128), pointer :: arg_float128
+ complex(C_FLOAT128_COMPLEX), pointer :: arg_complex128
+ end subroutine
+
+ end interface
+
+ real(C_FLOAT128), pointer :: var_float128
+ complex(C_FLOAT128_COMPLEX), pointer :: var_complex128
+
+ nullify (var_float128, var_complex128)
+ call ctest (var_float128, var_complex128)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128-c.c
new file mode 100644
index 0000000..db07108
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128-c.c
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_int128,
+ CFI_cdesc_t *arg_least128,
+ CFI_cdesc_t *arg_fast128);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_pointer)
+ abort ();
+ if (a->base_addr != NULL)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_int128,
+ CFI_cdesc_t *arg_least128,
+ CFI_cdesc_t *arg_fast128)
+{
+ check (arg_int128, sizeof (__int128), CFI_type_int128_t);
+ check (arg_least128, sizeof (__int128), CFI_type_int_least128_t);
+ check (arg_fast128, sizeof (__int128), CFI_type_int_fast128_t);
+}
+
+
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128.f90
new file mode 100644
index 0000000..157c4ca
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-int128.f90
@@ -0,0 +1,35 @@
+! PR 101305
+! xfailed due to PR 101308
+! { dg-do run }
+! { dg-require-effective-target fortran_integer_16 }
+! { dg-additional-sources "typecodes-scalar-int128-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that 128-bit integer kind constants provided by
+! gfortran's ISO_C_BINDING module result in the right type field in
+! arguments passed by descriptor, also matching the size of the corresponding
+! C type. We use pointers to force the use of a descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_int128, arg_least128, arg_fast128) bind (c)
+ use iso_c_binding
+ integer(C_INT128_T), pointer :: arg_int128
+ integer(C_INT_LEAST128_T), pointer :: arg_least128
+ integer(C_INT_FAST128_T), pointer :: arg_fast128
+ end subroutine
+
+ end interface
+
+ integer(C_INT128_T), pointer :: var_int128
+ integer(C_INT_LEAST128_T), pointer :: var_least128
+ integer(C_INT_FAST128_T), pointer :: var_fast128
+
+ nullify (var_int128, var_least128, var_fast128)
+ call ctest (var_int128, var_least128, var_fast128)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble-c.c b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble-c.c
new file mode 100644
index 0000000..a52122f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble-c.c
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ISO_Fortran_binding.h>
+#include "dump-descriptors.h"
+
+extern void ctest (CFI_cdesc_t *arg_long_double,
+ CFI_cdesc_t *arg_long_double_complex);
+
+/* Sanity check the type info in the descriptor a. */
+
+static void
+check (CFI_cdesc_t *a, size_t size, int typecode)
+{
+ dump_CFI_cdesc_t (a);
+ if (a->attribute != CFI_attribute_pointer)
+ abort ();
+ if (a->base_addr != NULL)
+ abort ();
+ if (a->rank != 0)
+ abort ();
+ if (size && a->elem_len != size)
+ abort ();
+ if (a->type != typecode)
+ abort ();
+}
+
+void
+ctest (CFI_cdesc_t *arg_long_double,
+ CFI_cdesc_t *arg_long_double_complex)
+{
+ check (arg_long_double, sizeof (long double), CFI_type_long_double);
+ check (arg_long_double_complex, sizeof (long double _Complex),
+ CFI_type_long_double_Complex);
+}
diff --git a/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble.f90 b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble.f90
new file mode 100644
index 0000000..ddc54f4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/typecodes-scalar-longdouble.f90
@@ -0,0 +1,33 @@
+! xfailed due to PR 101308
+! PR 101305
+! PR 100917
+! { dg-do run }
+! { dg-additional-sources "typecodes-scalar-longdouble-c.c dump-descriptors.c" }
+! { dg-additional-options "-g" }
+!
+! This program tests that long double kind constants in the ISO_C_BINDING
+! module result in the right type field in arguments passed by descriptor,
+! also matching the size of the corresponding C type. We use pointers
+! to force the use of a descriptor.
+
+program testit
+ use iso_c_binding
+ implicit none
+
+ interface
+
+ subroutine ctest (arg_long_double, arg_long_double_complex) bind (c)
+ use iso_c_binding
+ real(C_LONG_DOUBLE), pointer :: arg_long_double
+ complex(C_LONG_DOUBLE_COMPLEX), pointer :: arg_long_double_complex
+ end subroutine
+
+ end interface
+
+ real(C_LONG_DOUBLE), pointer :: var_long_double
+ complex(C_LONG_DOUBLE_COMPLEX), pointer :: var_long_double_complex
+
+ nullify (var_long_double, var_long_double_complex)
+ call ctest (var_long_double, var_long_double_complex)
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/c-interop/ubound.f90 b/gcc/testsuite/gfortran.dg/c-interop/ubound.f90
new file mode 100644
index 0000000..37e073f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c-interop/ubound.f90
@@ -0,0 +1,129 @@
+! { dg-do run }
+!
+! TS 29113
+! 6.4.3 UBOUND
+!
+! The description of the intrinsic function UBOUND in ISO/IEC
+! 1539-1:2010 is changed for an assumed-rank object that is associated
+! with an assumed-size array; the result of UBOUND (ARRAY, RANK(ARRAY),
+! KIND) has a value equal to LBOUND (ARRAY, RANK (ARRAY), KIND) −2 with
+! KIND omitted from LBOUND if it was omitted from UBOUND.
+!
+! NOTE 6.2
+! If LBOUND or UBOUND is invoked for an assumed-rank object that is
+! associated with a scalar and DIM is absent, the result is a zero-sized
+! array. LBOUND or UBOUND cannot be invoked for an assumed-rank object
+! that is associated with a scalar if DIM is present because the rank of
+! a scalar is zero and DIM must be ≥ 1.
+!
+! The idea here is that the main program passes some arrays to a test
+! subroutine with an assumed-size dummy, which in turn passes that to a
+! subroutine with an assumed-rank dummy.
+
+program test
+
+ ! Define some arrays for testing.
+ integer, target :: x1(5)
+ integer :: y1(0:9)
+ integer, pointer :: p1(:)
+ integer, allocatable :: a1(:)
+ integer, target :: x3(2,3,4)
+ integer :: y3(0:1,-3:-1,4)
+ integer, pointer :: p3(:,:,:)
+ integer, allocatable :: a3(:,:,:)
+ integer :: x
+
+ ! Test the 1-dimensional arrays.
+ call test1 (x1)
+ call testit2(x1, shape(x1))
+ call test1 (y1)
+ call testit2(y1, shape(y1))
+ p1 => x1
+ call testit2(p1, shape(p1))
+ call testit2p(p1, lbound(p1), shape(p1))
+ call test1 (p1)
+ p1(77:) => x1
+ call testit2p(p1, [77], shape(p1))
+ allocate (a1(5))
+ call testit2(a1, shape(a1))
+ call testit2a(a1, lbound(a1), shape(a1))
+ call test1 (a1)
+ deallocate(a1)
+ allocate (a1(-38:5))
+ call test1 (a1)
+ call testit2(a1, shape(a1))
+ call testit2a(a1, [-38], shape(a1))
+
+ ! Test the multi-dimensional arrays.
+ call test3 (x3, 1, 2, 1, 3)
+ call test3 (y3, 0, 1, -3, -1)
+ p3 => x3
+ call test3 (p3, 1, 2, 1, 3)
+ allocate (a3(2,3,4))
+ call test3 (a3, 1, 2, 1, 3)
+
+ ! Test some scalars.
+ call test0 (x)
+ call test0 (-1)
+ call test0 (x1(1))
+
+contains
+
+ subroutine testit (a)
+ integer :: a(..)
+ integer :: r
+ r = rank(a)
+ if (any (lbound (a) .ne. 1)) stop 101
+ if (ubound (a, r) .ne. -1) stop 102
+ end subroutine
+
+ subroutine testit2(a, shape)
+ integer :: a(..)
+ integer :: shape(:)
+ if (rank(a) /= size(shape)) stop 111
+ if (any (lbound(a) /= 1)) stop 112
+ if (any (ubound(a) /= shape)) stop 113
+ end subroutine
+
+ subroutine testit2a(a,lbound2, shape2)
+ integer, allocatable :: a(..)
+ integer :: lbound2(:), shape2(:)
+ if (rank(a) /= size(shape2)) stop 121
+ if (any (lbound(a) /= lbound2)) stop 122
+ if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 123
+ if (any (shape(a) /= shape2)) stop 124
+ if (sum (shape(a)) /= size(a)) stop 125
+ end subroutine
+
+ subroutine testit2p(a, lbound2, shape2)
+ integer, pointer :: a(..)
+ integer :: lbound2(:), shape2(:)
+ if (rank(a) /= size(shape2)) stop 131
+ if (any (lbound(a) /= lbound2)) stop 132
+ if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 133
+ if (any (shape(a) /= shape2)) stop 134
+ if (sum (shape(a)) /= size(a)) stop 135
+ end subroutine
+
+ subroutine test0 (a)
+ integer :: a(..)
+ if (rank (a) .ne. 0) stop 141
+ if (size (lbound (a)) .ne. 0) stop 142
+ if (size (ubound (a)) .ne. 0) stop 143
+ end subroutine
+
+ subroutine test1 (a)
+ integer :: a(*)
+
+ call testit (a)
+ end subroutine
+
+ subroutine test3 (a, l1, u1, l2, u2)
+ implicit none
+ integer :: l1, u1, l2, u2
+ integer :: a(l1:u1, l2:u2, *)
+
+ call testit (a)
+ end subroutine
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/class_72.f90 b/gcc/testsuite/gfortran.dg/class_72.f90
new file mode 100644
index 0000000..0fd6ec0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_72.f90
@@ -0,0 +1,83 @@
+! PR fortran/102745
+
+implicit none
+
+type t
+end type t
+
+type, extends(t) :: t2
+end type t2
+
+type t3
+end type t3
+
+type(t), allocatable :: var
+type(t2), allocatable :: v2ar
+type(t3), allocatable :: v3ar
+class(t), allocatable :: cvar
+class(t2), allocatable :: c2var
+class(t3), allocatable :: c3var
+
+call f(var)
+call f(v2ar) ! { dg-error "passed TYPE.t2. to TYPE.t." }
+call f(v2ar%t)
+call f(cvar)
+call f(c2var) ! { dg-error "passed CLASS.t2. to TYPE.t." }
+call f(c2var%t)
+
+call f2(var) ! { dg-error "passed TYPE.t. to TYPE.t2." }
+call f2(v2ar)
+call f2(cvar) ! { dg-error "passed CLASS.t. to TYPE.t2." }
+call f2(c2var)
+
+
+var = var
+var = v2ar ! { dg-error "TYPE.t2. to TYPE.t." }
+var = cvar
+var = c2var ! { dg-error "TYPE.t2. to TYPE.t." }
+
+v2ar = var ! { dg-error "Cannot convert TYPE.t. to TYPE.t2." }
+v2ar = v2ar
+v2ar = cvar ! { dg-error "Cannot convert TYPE.t. to TYPE.t2." }
+v2ar = c2var
+
+cvar = var
+cvar = v2ar
+cvar = cvar
+cvar = c2var
+
+c2var = var ! { dg-error "Cannot convert TYPE.t. to CLASS.t2." }
+c2var = v3ar ! { dg-error "Cannot convert TYPE.t3. to CLASS.t2." }
+c2var = v2ar
+c2var = cvar ! { dg-error "Cannot convert CLASS.t. to CLASS.t2." }
+c2var = c3var ! { dg-error "Cannot convert CLASS.t3. to CLASS.t2." }
+c2var = c2var
+
+allocate (var, source=var)
+allocate (var, source=v2ar) ! { dg-error "incompatible with source-expr" }
+allocate (var, source=cvar)
+allocate (var, source=c2var) ! { dg-error "incompatible with source-expr" }
+
+allocate (v2ar, source=var) ! { dg-error "incompatible with source-expr" }
+allocate (v2ar, source=v2ar)
+allocate (v2ar, source=cvar) ! { dg-error "incompatible with source-expr" }
+allocate (v2ar, source=c2var)
+
+allocate (cvar, source=var)
+allocate (cvar, source=v2ar)
+allocate (cvar, source=cvar)
+allocate (cvar, source=c2var)
+
+allocate (c2var, source=var) ! { dg-error "incompatible with source-expr" }
+allocate (c2var, source=v2ar)
+allocate (c2var, source=cvar) ! { dg-error "incompatible with source-expr" }
+allocate (c2var, source=c2var)
+
+contains
+ subroutine f(x)
+ type(t) :: x
+ end
+ subroutine f2(x)
+ type(t2) :: x
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90 b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
new file mode 100644
index 0000000..a423d1f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/coarray_allocated.f90
@@ -0,0 +1,55 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
+! PR fortran/93834 - ICE in trans_caf_is_present
+
+program p
+ type t
+ integer, allocatable :: x[:,:,:]
+ end type t
+ integer, allocatable :: a[:]
+ type(t) :: c
+ if (allocated (a)) stop 1
+ if (allocated (c%x)) stop 2
+
+ ! The coindexed scalar (!) variable is regarded as allocatable but
+ ! we can check the value on any image of the team as they are
+ ! established collectively. As tested by the dump, we do it on
+ ! this_image ().
+ !
+ ! For this reason, -fcoarray=single and -fcoarray=lib give the
+ ! same result
+ if (allocated (a[1])) stop 3
+ if (allocated (c%x[1,2,3])) stop 4
+
+ ! Allocate collectively
+ allocate(a[*])
+ allocate(c%x[4,10,*])
+
+ if (.not. allocated (a)) stop 5
+ if (.not. allocated (c%x)) stop 6
+ if (.not. allocated (a[1])) stop 7
+ if (.not. allocated (c%x[1,2,3])) stop 8
+
+ ! Dellocate collectively
+ deallocate(a)
+ deallocate(c%x)
+
+ if (allocated (a)) stop 9
+ if (allocated (c%x)) stop 10
+ if (allocated (a[1])) stop 11
+ if (allocated (c%x[1,2,3])) stop 12
+end
+
+! twice == 0 for .not. allocated' (coindexed vs. not)
+! four times != for allocated (before alloc after dealloc, coindexed and not)
+
+! There are also == 0 and != 0 for (de)allocate checks with -fcoarray=single but those
+! aren't prefixed by '(integer(kind=4) *)'
+
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data != 0B" 4 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data != 0B" 4 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) a.data == 0B" 2 "original" } }
+! { dg-final { scan-tree-dump-times "\\(integer\\(kind=4\\) \\*\\) c.x.data == 0B" 2 "original" } }
+
+! Expected: always local access and never a call to _gfortran_caf_get
+! { dg-final { scan-tree-dump-not "caf_get" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/derived_constructor_char_1.f90 b/gcc/testsuite/gfortran.dg/derived_constructor_char_1.f90
index 892a9c9..91fc4c9 100644
--- a/gcc/testsuite/gfortran.dg/derived_constructor_char_1.f90
+++ b/gcc/testsuite/gfortran.dg/derived_constructor_char_1.f90
@@ -5,7 +5,7 @@
!
!
Type :: t5
- character (len=5) :: txt(4)
+ character (len=5) :: txt(2)
End Type t5
character (len=3), parameter :: str3(2) = [ "ABC", "ZYX" ]
diff --git a/gcc/testsuite/gfortran.dg/entry_24.f90 b/gcc/testsuite/gfortran.dg/entry_24.f90
new file mode 100644
index 0000000..9773597
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/entry_24.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/87737 - improve check on function entry characteristics
+
+function f() ! { dg-error "mismatched characteristics" }
+ character(:), allocatable :: f
+ character(1) :: g
+ f = 'f'
+ return
+entry g()
+ g = 'g'
+end
+
+function f2() ! { dg-error "mismatched characteristics" }
+ character(1) :: f2
+ character(1), allocatable :: g2
+ f2 = 'f'
+ return
+entry g2()
+ g2 = 'g'
+end
diff --git a/gcc/testsuite/gfortran.dg/entry_25.f90 b/gcc/testsuite/gfortran.dg/entry_25.f90
new file mode 100644
index 0000000..518560a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/entry_25.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! PR fortran/102311 - ICE during error recovery checking entry characteristics
+
+module m
+contains
+ function f() ! { dg-error "mismatched characteristics" }
+ character(:), allocatable :: f
+ character(1) :: g
+ f = 'f'
+ entry g()
+ g = 'g'
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/privatization-1-compute.f90 b/gcc/testsuite/gfortran.dg/goacc/privatization-1-compute.f90
index ed7e9ec..31f998d 100644
--- a/gcc/testsuite/gfortran.dg/goacc/privatization-1-compute.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/privatization-1-compute.f90
@@ -39,9 +39,9 @@ contains
!$acc atomic write ! ... to force 'TREE_ADDRESSABLE'.
y = a
!$acc end parallel
- ! { dg-note {variable 'i' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO" { xfail *-*-* } l_compute$c_compute }
- ! { dg-note {variable 'j' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO" { xfail *-*-* } l_compute$c_compute }
- ! { dg-note {variable 'a' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO" { xfail *-*-* } l_compute$c_compute }
+ ! { dg-note {variable 'i' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO2" { xfail *-*-* } l_compute$c_compute }
+ ! { dg-note {variable 'j' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO3" { xfail *-*-* } l_compute$c_compute }
+ ! { dg-note {variable 'a' in 'private' clause potentially has improper OpenACC privatization level: 'parm_decl'} "TODO4" { xfail *-*-* } l_compute$c_compute }
! { dg-note {variable 'C\.[0-9]+' declared in block potentially has improper OpenACC privatization level: 'const_decl'} "TODO" { target *-*-* } l_compute$c_compute }
! { dg-note {variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} "" { target *-*-* } l_compute$c_compute }
end subroutine f
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f b/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
index 04d507f..949d571 100644
--- a/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
@@ -22,8 +22,8 @@
! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, n
call workerr (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
-! { dg-bogus "note: routine 'workerr' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
-! { dg-bogus "note: routine 'workerr_' declared here" "TODO" { xfail offloading_enabled } .-2 }
+! { dg-bogus "note: routine 'workerr' declared here" "TODO1" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'workerr_' declared here" "TODO2" { xfail offloading_enabled } .-2 }
end do
end do
!$acc end parallel loop
@@ -36,8 +36,8 @@
do j = 1, n
call gangr (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
-! { dg-bogus "note: routine 'gangr' declared here" "TODO" { xfail { ! offloading_enabled } } .-2 }
-! { dg-bogus "note: routine 'gangr_' declared here" "TODO" { xfail offloading_enabled } .-3 }
+! { dg-bogus "note: routine 'gangr' declared here" "TODO1" { xfail { ! offloading_enabled } } .-2 }
+! { dg-bogus "note: routine 'gangr_' declared here" "TODO2" { xfail offloading_enabled } .-3 }
end do
end do
!$acc end parallel loop
@@ -162,8 +162,8 @@
!$acc parallel loop ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
do i = 1, n
call vectorr (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
-! { dg-bogus "note: routine 'vectorr' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
-! { dg-bogus "note: routine 'vectorr_' declared here" "TODO" { xfail offloading_enabled } .-2 }
+! { dg-bogus "note: routine 'vectorr' declared here" "TODO1" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'vectorr_' declared here" "TODO2" { xfail offloading_enabled } .-2 }
end do
!$acc end parallel loop
@@ -214,8 +214,8 @@
! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, n
a(i) = workerf (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
-! { dg-bogus "note: routine 'workerf' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
-! { dg-bogus "note: routine 'workerf_' declared here" "TODO" { xfail offloading_enabled } .-2 }
+! { dg-bogus "note: routine 'workerf' declared here" "TODO1" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'workerf_' declared here" "TODO2" { xfail offloading_enabled } .-2 }
end do
end do
!$acc end parallel loop
@@ -228,8 +228,8 @@
do j = 1, n
a(i) = gangf (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
-! { dg-bogus "note: routine 'gangf' declared here" "TODO" { xfail { ! offloading_enabled } } .-2 }
-! { dg-bogus "note: routine 'gangf_' declared here" "TODO" { xfail offloading_enabled } .-3 }
+! { dg-bogus "note: routine 'gangf' declared here" "TODO1" { xfail { ! offloading_enabled } } .-2 }
+! { dg-bogus "note: routine 'gangf_' declared here" "TODO2" { xfail offloading_enabled } .-3 }
end do
end do
!$acc end parallel loop
@@ -354,8 +354,8 @@
!$acc parallel loop ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
do i = 1, n
a(i) = vectorf (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
-! { dg-bogus "note: routine 'vectorf' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
-! { dg-bogus "note: routine 'vectorf_' declared here" "TODO" { xfail offloading_enabled } .-2 }
+! { dg-bogus "note: routine 'vectorf' declared here" "TODO1" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'vectorf_' declared here" "TODO2" { xfail offloading_enabled } .-2 }
end do
!$acc end parallel loop
diff --git a/gcc/testsuite/gfortran.dg/goacc/unexpected-end.f90 b/gcc/testsuite/gfortran.dg/goacc/unexpected-end.f90
new file mode 100644
index 0000000..e9db47b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/unexpected-end.f90
@@ -0,0 +1,25 @@
+! PR fortran/102313
+
+!$acc end ATOMIC ! { dg-error "Unexpected !.ACC END ATOMIC" }
+
+!$acc end DATA ! { dg-error "Unexpected !.ACC END DATA" }
+
+!$acc end HOST_DATA ! { dg-error "Unexpected !.ACC END HOST_DATA" }
+
+!$acc end KERNELS ! { dg-error "Unexpected !.ACC END KERNELS" }
+
+!$acc end KERNELS LOOP ! { dg-error "Unexpected !.ACC END KERNELS LOOP" }
+
+!$acc end LOOP ! { dg-error "Unexpected !.ACC END LOOP" }
+
+!$acc end PARALLEL ! { dg-error "Unexpected !.ACC END PARALLEL" }
+
+!$acc end PARALLEL LOOP ! { dg-error "Unexpected !.ACC END PARALLEL LOOP" }
+
+!$acc end SERIAL ! { dg-error "Unexpected !.ACC END SERIAL" }
+
+!$acc end SERIAL LOOP ! { dg-error "Unexpected !.ACC END SERIAL LOOP" }
+
+!$acc end EUPHORBIA LATHYRIS ! { dg-error "Unclassifiable OpenACC directive" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90
new file mode 100644
index 0000000..de09dbf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90
@@ -0,0 +1,93 @@
+module main
+ implicit none
+
+ interface
+ integer function foo (a, b, c)
+ integer, intent(in) :: a, b
+ integer, intent(inout) :: c
+ end function
+
+ integer function bar (a, b, c)
+ integer, intent(in) :: a, b
+ integer, intent(inout) :: c
+ end function
+
+ integer function baz (a, b, c)
+ integer, intent(in) :: a, b
+ integer, intent(inout) :: c
+
+ !$omp declare variant (foo) &
+ !$omp & match (construct={parallel,do}, &
+ !$omp & device={isa(avx512f,avx512vl),kind(host,cpu)}, &
+ !$omp & implementation={vendor(score(0):gnu),unified_shared_memory}, &
+ !$omp & user={condition(score(0):0)})
+ !$omp declare variant (bar) &
+ !$omp & match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, &
+ !$omp & implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, "bar")}, &
+ !$omp & user={condition(3-3)})
+ end function
+
+ subroutine quux
+ end subroutine quux
+
+ integer function baz3 (x, y, z)
+ integer, intent(in) :: x, y
+ integer, intent(inout) :: z
+
+ !$omp declare variant (bar) match &
+ !$omp & (implementation={atomic_default_mem_order(score(3): acq_rel)})
+ end function
+ end interface
+contains
+ integer function qux ()
+ integer :: i = 3
+
+ qux = baz (1, 2, i)
+ end function
+
+ subroutine corge
+ integer :: i
+ !$omp declare variant (quux) match (construct={parallel,do})
+
+ interface
+ subroutine waldo (x)
+ integer, intent(in) :: x
+ end subroutine
+ end interface
+
+ call waldo (5)
+ !$omp parallel do
+ do i = 1, 3
+ call waldo (6)
+ end do
+ !$omp end parallel do
+
+ !$omp parallel
+ !$omp taskgroup
+ !$omp do
+ do i = 1, 3
+ call waldo (7)
+ end do
+ !$omp end do
+ !$omp end taskgroup
+ !$omp end parallel
+
+ !$omp parallel
+ !$omp master
+ call waldo (8)
+ !$omp end master
+ !$omp end parallel
+ end subroutine
+
+ integer function baz2 (x, y, z)
+ integer, intent(in) :: x, y
+ integer, intent(inout) :: z
+
+ !$omp declare variant (bar) match &
+ !$omp & (implementation={atomic_default_mem_order(relaxed), &
+ !$omp & unified_address, unified_shared_memory, &
+ !$omp & dynamic_allocators, reverse_offload})
+
+ baz2 = x + y + z
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90
new file mode 100644
index 0000000..d6d2c8c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90
@@ -0,0 +1,97 @@
+! { dg-do compile }
+! { dg-additional-options "-cpp -foffload=disable -fdump-tree-gimple" }
+! { dg-additional-options "-mavx512bw" { target { i?86-*-* x86_64-*-* } } }
+
+#undef i386
+
+program main
+ !$omp declare target to (test3)
+contains
+ subroutine f01 ()
+ end subroutine
+ subroutine f02 ()
+ !$omp declare variant (f01) match (device={isa(avx512f,avx512bw)})
+ end subroutine
+ subroutine f03 ()
+ end subroutine
+ subroutine f04 ()
+ !$omp declare variant (f03) match (device={kind("any"),arch(x86_64),isa(avx512f,avx512bw)})
+ end subroutine
+ subroutine f05 ()
+ end subroutine
+ subroutine f06 ()
+ !$omp declare variant (f05) match (device={kind(gpu)})
+ end subroutine
+ subroutine f07 ()
+ end subroutine
+ subroutine f08 ()
+ !$omp declare variant (f07) match (device={kind(cpu)})
+ end subroutine
+ subroutine f09 ()
+ end subroutine
+ subroutine f10 ()
+ !$omp declare variant (f09) match (device={isa(sm_35)})
+ end subroutine
+ subroutine f11 ()
+ end subroutine
+ subroutine f12 ()
+ !$omp declare variant (f11) match (device={arch("nvptx")})
+ end subroutine
+ subroutine f13 ()
+ end subroutine
+ subroutine f14 ()
+ !$omp declare variant (f13) match (device={arch(i386),isa("sse4")})
+ end subroutine
+ subroutine f15 ()
+ end subroutine
+ subroutine f16 ()
+ !$omp declare variant (f15) match (device={isa(sse4,ssse3),arch(i386)})
+ end subroutine
+ subroutine f17 ()
+ end subroutine
+ subroutine f18 ()
+ !$omp declare variant (f17) match (device={kind(any,fpga)})
+ end subroutine
+
+ subroutine test1 ()
+ !$omp declare target
+ integer :: i
+
+ call f02 () ! { dg-final { scan-tree-dump-times "f01 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } }
+ ! { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ call f14 () ! { dg-final { scan-tree-dump-times "f13 \\\(\\\);" 1 "gimple" { target ia32 } } }
+ ! { dg-final { scan-tree-dump-times "f14 \\\(\\\);" 1 "gimple" { target { ! ia32 } } } }
+ call f18 () ! { dg-final { scan-tree-dump-times "f18 \\\(\\\);" 1 "gimple" } } */
+ end subroutine
+
+#if defined(__i386__) || defined(__x86_64__)
+ __attribute__((target ("avx512f,avx512bw")))
+#endif
+ subroutine test2 ()
+ !$omp target
+ call f04 () ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } }
+ ! { dg-final { scan-tree-dump-times "f04 \\\(\\\);" 1 "gimple" { target { { ! lp64 } || { ! { i?86-*-* x86_64-*-* } } } } } }
+ !$omp end target
+ !$omp target
+ call f16 () ! { dg-final { scan-tree-dump-times "f15 \\\(\\\);" 1 "gimple" { target ia32 } } }
+ ! { dg-final { scan-tree-dump-times "f16 \\\(\\\);" 1 "gimple" { target { ! ia32 } } } }
+ !$omp end target
+ end subroutine
+
+ subroutine test3 ()
+ call f06 () ! { dg-final { scan-tree-dump-times "f06 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ call f08 () ! { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ end subroutine
+
+ subroutine test4 ()
+ !$omp target
+ call f10 () ! { dg-final { scan-tree-dump-times "f10 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ !$omp end target
+
+ !$omp target
+ call f12 () ! { dg-final { scan-tree-dump-times "f12 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* } } } } }
+ ! { dg-final { scan-tree-dump-times "f11 \\\(\\\);" 1 "gimple" { target { nvptx*-*-* } } } }
+ !$omp end target
+ end subroutine
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-11.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-11.f90
new file mode 100644
index 0000000..60aa0fc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-11.f90
@@ -0,0 +1,134 @@
+! { dg-do compile }
+! { dg-additional-options "-foffload=disable -fdump-tree-gimple" }
+! { dg-additional-options "-mavx512bw -mavx512vl" { target { i?86-*-* x86_64-*-* } } }
+
+program main
+ implicit none
+contains
+ subroutine f01 ()
+ end subroutine
+
+ subroutine f02 ()
+ end subroutine
+
+ subroutine f03 ()
+ !$omp declare variant (f01) match (device={isa(avx512f,"avx512vl")})
+ !$omp declare variant (f02) match (device={isa(avx512bw,avx512vl,"avx512f")})
+ end subroutine
+
+ subroutine f04 ()
+ end subroutine
+
+ subroutine f05 ()
+ end subroutine
+
+ subroutine f06 ()
+ !$omp declare variant (f04) match (device={isa(avx512f,avx512vl)})
+ !$omp declare variant (f05) match (device={isa(avx512bw,avx512vl,avx512f)})
+ end subroutine
+
+ subroutine f07 ()
+ end subroutine
+
+ subroutine f08 ()
+ end subroutine
+
+ subroutine f09 ()
+ !$omp declare variant (f07) match (device={isa(sse4,"sse4.1","sse4.2",sse3,"avx")})
+ !$omp declare variant (f08) match (device={isa("avx",sse3)})
+ end subroutine
+
+ subroutine f10 ()
+ end subroutine
+
+ subroutine f11 ()
+ end subroutine
+
+ subroutine f12 ()
+ end subroutine
+
+ subroutine f13 ()
+ !$omp declare variant (f10) match (device={isa("avx512f")})
+ !$omp declare variant (f11) match (user={condition(1)},device={isa(avx512f)},implementation={vendor(gnu)})
+ !$omp declare variant (f12) match (user={condition(2 + 1)},device={isa(avx512f)})
+ end subroutine
+
+ subroutine f14 ()
+ end subroutine
+
+ subroutine f15 ()
+ end subroutine
+
+ subroutine f16 ()
+ end subroutine
+
+ subroutine f17 ()
+ end subroutine
+
+ subroutine f18 ()
+ !$omp declare variant (f14) match (construct={teams,do})
+ !$omp declare variant (f15) match (construct={teams,parallel,do})
+ !$omp declare variant (f16) match (construct={do})
+ !$omp declare variant (f17) match (construct={parallel,do})
+ end subroutine
+
+ subroutine f19 ()
+ end subroutine
+
+ subroutine f20 ()
+ end subroutine
+
+ subroutine f21 ()
+ end subroutine
+
+ subroutine f22 ()
+ end subroutine
+
+ subroutine f23 ()
+ !$omp declare variant (f19) match (construct={teams,do})
+ !$omp declare variant (f20) match (construct={teams,parallel,do})
+ !$omp declare variant (f21) match (construct={do})
+ !$omp declare variant (f22) match (construct={parallel,do})
+ end subroutine
+
+ subroutine f24 ()
+ end subroutine
+
+ subroutine f25 ()
+ end subroutine
+
+ subroutine f26 ()
+ end subroutine
+
+ subroutine f27 ()
+ !$omp declare variant (f24) match (device={kind(cpu)})
+ !$omp declare variant (f25) match (device={kind(cpu),isa(avx512f),arch(x86_64)})
+ !$omp declare variant (f26) match (device={arch(x86_64),kind(cpu)})
+ end subroutine
+
+ subroutine test1
+ integer :: i
+ call f03 () ! { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } }
+ ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ call f09 () ! { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } }
+ ! { dg-final { scan-tree-dump-times "f09 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ call f13 () ! { dg-final { scan-tree-dump-times "f11 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } }
+ ! { dg-final { scan-tree-dump-times "f13 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ !$omp teams distribute parallel do
+ do i = 1, 2
+ call f18 () ! { dg-final { scan-tree-dump-times "f15 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end teams distribute parallel do
+
+ !$omp parallel do
+ do i = 1, 2
+ call f23 () ! { dg-final { scan-tree-dump-times "f22 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end parallel do
+
+ call f27 () ! { dg-final { scan-tree-dump-times "f25 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } }
+ ! { dg-final { scan-tree-dump-times "f24 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! lp64 } } } } }
+ ! { dg-final { scan-tree-dump-times "f24 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* i?86-*-* x86_64-*-* } } } } }
+ ! { dg-final { scan-tree-dump-times "f27 \\\(\\\);" 1 "gimple" { target { nvptx*-*-* amdgcn*-*-* } } } }
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-12.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-12.f90
new file mode 100644
index 0000000..610693e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-12.f90
@@ -0,0 +1,159 @@
+! { dg-do compile }
+! { dg-additional-options "-foffload=disable -fdump-tree-gimple" }
+! { dg-additional-options "-mavx512bw -mavx512vl" { target { i?86-*-* x86_64-*-* } } }
+
+program main
+ !$omp requires atomic_default_mem_order(seq_cst)
+contains
+ subroutine f01 ()
+ end subroutine
+
+ subroutine f02 ()
+ end subroutine
+
+ subroutine f03 ()
+ end subroutine
+
+ subroutine f04 ()
+ !$omp declare variant (f01) match (device={isa("avx512f","avx512vl")}) ! 16
+ !$omp declare variant (f02) match (implementation={vendor(score(15):gnu)})
+ !$omp declare variant (f03) match (user={condition(score(11):1)})
+ end subroutine
+
+ subroutine f05 ()
+ end subroutine
+
+ subroutine f06 ()
+ end subroutine
+
+ subroutine f07 ()
+ end subroutine
+
+ subroutine f08 ()
+ !$omp declare variant (f05) match (device={isa(avx512f,avx512vl)}) ! 16
+ !$omp declare variant (f06) match (implementation={vendor(score(15):gnu)})
+ !$omp declare variant (f07) match (user={condition(score(17):1)})
+ end subroutine
+
+ subroutine f09 ()
+ end subroutine
+
+ subroutine f10 ()
+ end subroutine
+
+ subroutine f11 ()
+ end subroutine
+
+ subroutine f12 ()
+ end subroutine
+
+ subroutine f13 ()
+ !$omp declare variant (f09) match (device={arch(x86_64)},user={condition(score(65):1)}) ! 64+65
+ !$omp declare variant (f10) match (implementation={vendor(score(127):"gnu")})
+ !$omp declare variant (f11) match (device={isa(ssse3)}) ! 128
+ !$omp declare variant (f12) match (implementation={atomic_default_mem_order(score(126):seq_cst)})
+ end subroutine
+
+ subroutine f14 ()
+ end subroutine
+
+ subroutine f15 ()
+ end subroutine
+
+ subroutine f16 ()
+ end subroutine
+
+ subroutine f17 ()
+ !$omp declare variant (f14) match (construct={teams,parallel,do}) ! 16+8+4
+ !$omp declare variant (f15) match (construct={parallel},user={condition(score(19):1)}) ! 8+19
+ !$omp declare variant (f16) match (implementation={atomic_default_mem_order(score(27):seq_cst)})
+ end subroutine
+
+ subroutine f18 ()
+ end subroutine
+
+ subroutine f19 ()
+ end subroutine
+
+ subroutine f20 ()
+ end subroutine
+
+ subroutine f21 ()
+ !$omp declare variant (f18) match (construct={teams,parallel,do}) ! 16+8+4
+ !$omp declare variant (f19) match (construct={do},user={condition(score(25):1)}) ! 4+25
+ !$omp declare variant (f20) match (implementation={atomic_default_mem_order(score(28):seq_cst)})
+ end subroutine
+
+ subroutine f22 ()
+ end subroutine
+
+ subroutine f23 ()
+ end subroutine
+
+ subroutine f24 ()
+ end subroutine
+
+ subroutine f25 ()
+ !$omp declare variant (f22) match (construct={parallel,do}) ! 2+1
+ !$omp declare variant (f23) match (construct={do}) ! 0
+ !$omp declare variant (f24) match (implementation={atomic_default_mem_order(score(2):seq_cst)})
+ end subroutine
+
+ subroutine f26 ()
+ end subroutine
+
+ subroutine f27 ()
+ end subroutine
+
+ subroutine f28 ()
+ end subroutine
+
+ subroutine f29 ()
+ !$omp declare variant (f26) match (construct={parallel,do}) ! 2+1
+ !$omp declare variant (f27) match (construct={do},user={condition(1)}) ! 4
+ !$omp declare variant (f28) match (implementation={atomic_default_mem_order(score(3):seq_cst)})
+ end subroutine
+
+ subroutine test1 ()
+ integer :: i, j
+
+ !$omp parallel do ! 2 constructs in OpenMP context, isa has score 2^4.
+ do i = 1, 2
+ call f04 () ! { dg-final { scan-tree-dump-times "f01 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } }
+ ! { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ end do
+ !$omp end parallel do
+
+ !$omp target teams ! 2 constructs in OpenMP context, isa has score 2^4.
+ call f08 () ! { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" } }
+ !$omp end target teams
+
+ !$omp teams
+ !$omp parallel do
+ do i = 1, 2
+ !$omp parallel do ! 5 constructs in OpenMP context, arch is 2^6, isa 2^7.
+ do j = 1, 2
+ call f13 () ! { dg-final { scan-tree-dump-times "f09 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } }
+ ! { dg-final { scan-tree-dump-times "f11 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! lp64 } } } } }
+ ! { dg-final { scan-tree-dump-times "f10 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } }
+ call f17 () ! { dg-final { scan-tree-dump-times "f14 \\\(\\\);" 1 "gimple" } }
+ call f21 () ! { dg-final { scan-tree-dump-times "f19 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end parallel do
+ end do
+ !$omp end parallel do
+ !$omp end teams
+
+ !$omp do
+ do i = 1, 2
+ !$omp parallel do
+ do j = 1, 2
+ call f25 (); ! { dg-final { scan-tree-dump-times "f22 \\\(\\\);" 1 "gimple" } }
+ call f29 (); ! { dg-final { scan-tree-dump-times "f27 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end parallel do
+ end do
+ !$omp end do
+ end subroutine
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-13.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-13.f90
new file mode 100644
index 0000000..91648f9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-13.f90
@@ -0,0 +1,48 @@
+! { dg-do compile { target vect_simd_clones } }
+! { dg-additional-options "-fdump-tree-gimple" }
+! { dg-additional-options "-mno-sse3" { target { i?86-*-* x86_64-*-* } } }
+
+program main
+ implicit none
+contains
+ integer function f01 (x)
+ integer, intent(in) :: x
+ f01 = x
+ end function
+
+ integer function f02 (x)
+ integer, intent(in) :: x
+ f02 = x
+ end function
+
+ integer function f03 (x)
+ integer, intent(in) :: x
+ f03 = x
+ end function
+
+ integer function f04 (x)
+ integer, intent(in) :: x
+ f04 = x
+ end function
+
+ integer function f05 (x)
+ integer, intent(in) :: x
+
+ !$omp declare variant (f01) match (device={isa("avx512f")}) ! 4 or 8
+ !$omp declare variant (f02) match (implementation={vendor(score(3):gnu)},device={kind(cpu)}) ! (1 or 2) + 3
+ !$omp declare variant (f03) match (user={condition(score(9):1)})
+ !$omp declare variant (f04) match (implementation={vendor(score(6):gnu)},device={kind(host)}) ! (1 or 2) + 6
+ f05 = x
+ end function
+
+ integer function test1 (x)
+ !$omp declare simd
+ integer, intent(in) :: x
+
+ ! 0 or 1 (the latter if in a declare simd clone) constructs in OpenMP context,
+ ! isa has score 2^2 or 2^3. We can't decide on whether avx512f will match or
+ ! not, that also depends on whether it is a declare simd clone or not and which
+ ! one, but the f03 variant has a higher score anyway. */
+ test1 = f05 (x) ! { dg-final { scan-tree-dump-times "f03 \\\(x" 1 "gimple" } }
+ end function
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-14.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-14.f90
new file mode 100644
index 0000000..06c9a5d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-14.f90
@@ -0,0 +1,49 @@
+! { dg-do compile { target vect_simd_clones } }
+! { dg-additional-options "-O0 -fdump-tree-gimple -fdump-tree-optimized" }
+! { dg-additional-options "-mno-sse3" { target { i?86-*-* x86_64-*-* } } }
+
+module main
+ implicit none
+contains
+ integer function f01 (x)
+ integer, intent (in) :: x
+ f01 = x
+ end function
+
+ integer function f02 (x)
+ integer, intent (in) :: x
+ f02 = x
+ end function
+
+ integer function f03 (x)
+ integer, intent (in) :: x
+ f03 = x
+ end function
+
+ integer function f04 (x)
+ integer, intent(in) :: x
+
+ !$omp declare variant (f01) match (device={isa("avx512f")}) ! 4 or 8
+ !$omp declare variant (f02) match (implementation={vendor(score(3):gnu)},device={kind(cpu)}) ! (1 or 2) + 3
+ !$omp declare variant (f03) match (implementation={vendor(score(5):gnu)},device={kind(host)}) ! (1 or 2) + 5
+ f04 = x
+ end function
+
+ integer function test1 (x)
+ !$omp declare simd
+ integer, intent (in) :: x
+ integer :: a, b
+
+ ! At gimplification time, we can't decide yet which function to call.
+ ! { dg-final { scan-tree-dump-times "f04 \\\(x" 2 "gimple" } }
+ ! After simd clones are created, the original non-clone test1 shall
+ ! call f03 (score 6), the sse2/avx/avx2 clones too, but avx512f clones
+ ! shall call f01 with score 8.
+ ! { dg-final { scan-tree-dump-not "f04 \\\(x" "optimized" } }
+ ! { dg-final { scan-tree-dump-times "f03 \\\(x" 14 "optimized" } }
+ ! { dg-final { scan-tree-dump-times "f01 \\\(x" 4 "optimized" } }
+ a = f04 (x)
+ b = f04 (x)
+ test1 = a + b
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90
new file mode 100644
index 0000000..b2ad96a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple" }
+
+! Test 'declare variant' directive with an explicit base procedure name.
+
+module main
+ implicit none
+
+ !$omp declare variant (base: variant) match (construct={target,parallel})
+contains
+ subroutine variant ()
+ end subroutine
+
+ subroutine base ()
+ end subroutine
+
+ subroutine test1 ()
+ !$omp target
+ !$omp parallel
+ call base () ! { dg-final { scan-tree-dump-times "variant \\\(\\\);" 1 "gimple" } }
+ !$omp end parallel
+ !$omp end target
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90
new file mode 100644
index 0000000..fc97322
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple" }
+
+! Test that 'declare variant' works when applied to an external subroutine
+
+module main
+ implicit none
+
+ interface
+ subroutine base ()
+ !$omp declare variant (variant) match (construct={parallel})
+ end subroutine
+ end interface
+
+contains
+ subroutine variant ()
+ end subroutine
+
+ subroutine test ()
+ !$omp parallel
+ call base () ! { dg-final { scan-tree-dump-times "variant \\\(\\\);" 1 "gimple" } }
+ !$omp end parallel
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90
new file mode 100644
index 0000000..df57f9c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+
+! Declare variant directives should only appear in the specification parts.
+
+program main
+ implicit none
+
+ continue
+
+ !$omp declare variant (base: variant) match (construct={parallel}) ! { dg-error "Unexpected \\\!\\\$OMP DECLARE VARIANT statement at .1." }
+contains
+ subroutine base ()
+ continue
+
+ !$omp declare variant (variant) match (construct={parallel}) ! { dg-error "Unexpected \\\!\\\$OMP DECLARE VARIANT statement at .1." }
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-18.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-18.f90
new file mode 100644
index 0000000..f97cf34
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-18.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+
+! The base procedure must have an accessible explicit interface when the
+! directive appears.
+
+program main
+ interface
+ subroutine base_proc ()
+ end subroutine
+ end interface
+
+ !$omp declare variant (base_proc: variant_proc) match (construct={parallel})
+ !$omp declare variant (base_proc2: variant_proc) match (construct={parallel}) ! { dg-error "The base procedure at .1. must have an explicit interface" }
+contains
+ subroutine variant_proc ()
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-19.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-19.f90
new file mode 100644
index 0000000..d387f5e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-19.f90
@@ -0,0 +1,49 @@
+! { dg-do compile }
+
+! Test Fortran-specific compilation failures.
+
+module main
+ implicit none
+
+ interface base_gen
+ subroutine base_gen_int (x)
+ integer :: x
+ end subroutine
+
+ subroutine base_gen_real (x)
+ real :: x
+ end subroutine
+ end interface
+
+ interface
+ subroutine base_p ()
+ end subroutine
+ end interface
+
+ procedure (base_p), pointer :: base_proc_ptr
+
+ !$omp declare variant (base_entry: variant) match (construct={parallel}) ! { dg-error "The base name at .1. must not be an entry name" }
+ !$omp declare variant (base_proc_ptr: variant) match (construct={parallel}) ! { dg-error "The base name at .1. must not be a procedure pointer" }
+ !$omp declare variant (base_gen: variant2) match (construct={parallel}) ! { dg-error "The base name at .1. must not be a generic name" }
+ !$omp declare variant (variant) match (construct={parallel}) ! { dg-error "The base name for 'declare variant' must be specified at .1." }
+
+contains
+ subroutine base ()
+ entry base_entry
+ end subroutine
+
+ subroutine base2 ()
+ !$omp declare variant (variant2) match (construct={parallel}) ! { dg-error "variant .variant2. and base .base2. at .1. have incompatible types: .variant2. has the wrong number of arguments" }
+ end subroutine
+
+ subroutine base3 ()
+ !$omp declare variant (base: variant2) match (construct={parallel}) ! { dg-error "The base name at .1. does not match the name of the current procedure" }
+ end subroutine
+
+ subroutine variant ()
+ end subroutine
+
+ subroutine variant2 (x)
+ integer :: x
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90
new file mode 100644
index 0000000..63d7778
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90
@@ -0,0 +1,197 @@
+module main
+ implicit none
+contains
+ subroutine f0 ()
+ end subroutine
+ subroutine f1 ()
+ end subroutine
+ subroutine f2 ()
+ !$omp declare variant ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f3 ()
+ !$omp declare variant ( ! { dg-error "" }
+ end subroutine
+ subroutine f4 ()
+ !$omp declare variant () ! { dg-error "" }
+ end subroutine
+ subroutine f5 ()
+ !$omp declare variant match(user={condition(0)}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f6 ()
+ !$omp declare variant (f1) ! { dg-error "expected 'match' at .1." }
+ end subroutine
+ subroutine f7 ()
+ !$omp declare variant (f1) simd ! { dg-error "expected 'match' at .1." }
+ end subroutine
+ subroutine f8 ()
+ !$omp declare variant (f1) match ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f9 ()
+ !$omp declare variant (f1) match( ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ end subroutine
+ subroutine f10 ()
+ !$omp declare variant (f1) match() ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ end subroutine
+ subroutine f11 ()
+ !$omp declare variant (f1) match(foo) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ end subroutine
+ subroutine f12 ()
+ !$omp declare variant (f1) match(something={something}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ end subroutine
+ subroutine f13 ()
+ !$omp declare variant (f1) match(user) ! { dg-error "expected '=' at .1." }
+ end subroutine
+ subroutine f14 ()
+ !$omp declare variant (f1) match(user=) ! { dg-error "expected '\\\{' at .1." }
+ end subroutine
+ subroutine f15 ()
+ !$omp declare variant (f1) match(user= ! { dg-error "expected '\\\{' at .1." }
+ end subroutine
+ subroutine f16 ()
+ !$omp declare variant (f1) match(user={) ! { dg-error "expected trait selector name at .1." }
+ end subroutine
+ subroutine f17 ()
+ !$omp declare variant (f1) match(user={}) ! { dg-error "expected trait selector name at .1." }
+ end subroutine
+ subroutine f18 ()
+ !$omp declare variant (f1) match(user={condition}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f19 ()
+ !$omp declare variant (f1) match(user={condition(}) ! { dg-error "expected expression at .1." }
+ end subroutine
+ subroutine f20 ()
+ !$omp declare variant (f1) match(user={condition()}) ! { dg-error "expected expression at .1." }
+ end subroutine
+ subroutine f21 ()
+ !$omp declare variant (f1) match(user={condition(f1)}) ! { dg-error "expected expression at .1." }
+ end subroutine
+ subroutine f22 ()
+ !$omp declare variant (f1) match(user={condition(1, 2, 3)}) ! { dg-error "expected '\\)' at .1." }
+ end subroutine
+ subroutine f23 ()
+ !$omp declare variant (f1) match(construct={master}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f24 ()
+ !$omp declare variant (f1) match(construct={teams,parallel,master,do}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f25 ()
+ !$omp declare variant (f1) match(construct={parallel(1 ! { dg-error "selector 'parallel' does not accept any properties at .1." }
+ end subroutine
+ subroutine f26 ()
+ !$omp declare variant (f1) match(construct={parallel(1)}) ! { dg-error "selector 'parallel' does not accept any properties at .1." }
+ end subroutine
+ subroutine f27 ()
+ !$omp declare variant (f0) match(construct={simd(12)}) ! { dg-error "expected simd clause at .1." }
+ end subroutine
+ subroutine f32 ()
+ !$omp declare variant (f1) match(device={kind}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f33 ()
+ !$omp declare variant (f1) match(device={isa}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f34 ()
+ !$omp declare variant (f1) match(device={arch}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f35 ()
+ !$omp declare variant (f1) match(device={kind,isa,arch}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f36 ()
+ !$omp declare variant (f1) match(device={kind(}) ! { dg-error "expected identifier or string literal at .1." }
+ end subroutine
+ subroutine f39 ()
+ !$omp declare variant (f1) match(device={isa(1)}) ! { dg-error "expected identifier or string literal at .1." }
+ end subroutine
+ subroutine f40 ()
+ !$omp declare variant (f1) match(device={arch(17)}) ! { dg-error "expected identifier or string literal at .1." }
+ end subroutine
+ subroutine f41 ()
+ !$omp declare variant (f1) match(device={foobar(3)})
+ end subroutine
+ subroutine f43 ()
+ !$omp declare variant (f1) match(implementation={foobar(3)})
+ end subroutine
+ subroutine f44 ()
+ !$omp declare variant (f1) match(implementation={vendor}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f45 ()
+ !$omp declare variant (f1) match(implementation={extension}) ! { dg-error "expected '\\(' at .1." }
+ end subroutine
+ subroutine f45a ()
+ !$omp declare variant (f1) match(implementation={vendor()}) ! { dg-error "expected identifier or string literal at .1." }
+ end subroutine
+ subroutine f46 ()
+ !$omp declare variant (f1) match(implementation={vendor(123-234)}) ! { dg-error "expected identifier or string literal at .1." }
+ end subroutine
+ subroutine f48 ()
+ !$omp declare variant (f1) match(implementation={unified_address(yes)}) ! { dg-error "selector 'unified_address' does not accept any properties at .1." }
+ end subroutine
+ subroutine f49 ()
+ !$omp declare variant (f1) match(implementation={unified_shared_memory(no)}) ! { dg-error "selector 'unified_shared_memory' does not accept any properties at .1." }
+ end subroutine
+ subroutine f50 ()
+ !$omp declare variant (f1) match(implementation={dynamic_allocators(42)}) ! { dg-error "selector 'dynamic_allocators' does not accept any properties at .1." }
+ end subroutine
+ subroutine f51 ()
+ !$omp declare variant (f1) match(implementation={reverse_offload()}) ! { dg-error "selector 'reverse_offload' does not accept any properties at .1." }
+ end subroutine
+ subroutine f52 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order}) ! { dg-error "expected '\\('" }
+ end subroutine
+ subroutine f56 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed,seq_cst)}) ! { dg-error "expected '\\)' at .1." }
+ end subroutine
+ subroutine f58 ()
+ !$omp declare variant (f1) match(user={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'user' at .1." }
+ end subroutine
+ subroutine f59 ()
+ !$omp declare variant (f1) match(construct={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f60 ()
+ !$omp declare variant (f1) match(construct={parallel},foobar={bar}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ end subroutine
+ subroutine f64 ()
+ !$omp declare variant (f1) match(construct={single}) ! { dg-error "selector 'single' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f65 ()
+ !$omp declare variant (f1) match(construct={taskgroup}) ! { dg-error "selector 'taskgroup' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f66 ()
+ !$omp declare variant (f1) match(construct={for}) ! { dg-error "selector 'for' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f67 ()
+ !$omp declare variant (f1) match(construct={threadprivate}) ! { dg-error "selector 'threadprivate' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f68 ()
+ !$omp declare variant (f1) match(construct={critical}) ! { dg-error "selector 'critical' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f69 ()
+ !$omp declare variant (f1) match(construct={task}) ! { dg-error "selector 'task' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f70 ()
+ !$omp declare variant (f1) match(construct={taskloop}) ! { dg-error "selector 'taskloop' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f71 ()
+ !$omp declare variant (f1) match(construct={sections}) ! { dg-error "selector 'sections' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f72 ()
+ !$omp declare variant (f1) match(construct={section}) ! { dg-error "selector 'section' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f73 ()
+ !$omp declare variant (f1) match(construct={workshare}) ! { dg-error "selector 'workshare' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f74 ()
+ !$omp declare variant (f1) match(construct={requires}) ! { dg-error "selector 'requires' not allowed for context selector set 'construct' at .1." }
+ end subroutine
+ subroutine f75 ()
+ !$omp declare variant (f1),match(construct={parallel}) ! { dg-error "expected 'match' at .1." }
+ end subroutine
+ subroutine f76 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) ! { dg-error "expected identifier at .1." }
+ end subroutine
+ subroutine f77 ()
+ !$omp declare variant (f1) match(user={condition(score(f76):1)}) ! { dg-error "score argument must be constant integer expression at .1." }
+ end subroutine
+ subroutine f78 ()
+ !$omp declare variant (f1) match(user={condition(score(-130):1)}) ! { dg-error "score argument must be non-negative" }
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-2a.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2a.f90
new file mode 100644
index 0000000..56de117
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2a.f90
@@ -0,0 +1,53 @@
+module main
+ implicit none
+contains
+ subroutine f1 ()
+ end subroutine
+ subroutine f28 ()
+ !$omp declare variant (f1) match(construct={parallel},construct={do}) ! { dg-error "selector set 'construct' specified more than once" }
+ end subroutine
+ subroutine f29 ()
+ !$omp declare variant (f1) match(construct={parallel},construct={parallel}) ! { dg-error "selector set 'construct' specified more than once" }
+ end subroutine
+ subroutine f30 ()
+ !$omp declare variant (f1) match(user={condition(0)},construct={target},user={condition(0)}) ! { dg-error "selector set 'user' specified more than once" }
+ end subroutine
+ subroutine f31 ()
+ !$omp declare variant (f1) match(user={condition(0)},user={condition(1)}) ! { dg-error "selector set 'user' specified more than once" }
+ end subroutine
+ subroutine f37 ()
+ !$omp declare variant (f1) match(device={kind(unknown)}) ! { dg-warning "unknown property 'unknown' of 'kind' selector" }
+ end subroutine
+ subroutine f38 ()
+ !$omp declare variant (f1) match(device={kind(unknown,foobar)}) ! { dg-warning "unknown property 'unknown' of 'kind' selector" }
+ ! { dg-warning "unknown property 'foobar' of 'kind' selector" "" { target *-*-* } 22 }
+ end subroutine
+ subroutine f42 ()
+ !$omp declare variant (f1) match(device={arch(x86_64)},device={isa(avx512vl)}) ! { dg-error "selector set 'device' specified more than once" }
+ end subroutine
+ subroutine f47 ()
+ !$omp declare variant (f1) match(implementation={vendor("foobar")}) ! { dg-warning "unknown property '.foobar.' of 'vendor' selector" }
+ end subroutine
+ subroutine f53 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order(acquire)}) ! { dg-error "incorrect property 'acquire' of 'atomic_default_mem_order' selector" }
+ end subroutine
+ subroutine f54 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order(release)}) ! { dg-error "incorrect property 'release' of 'atomic_default_mem_order' selector" }
+ end subroutine
+ subroutine f55 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order(foobar)}) ! { dg-error "incorrect property 'foobar' of 'atomic_default_mem_order' selector" }
+ end subroutine
+ subroutine f57 ()
+ !$omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed)},&
+ !$omp & implementation={atomic_default_mem_order(relaxed)}) ! { dg-error "selector set 'implementation' specified more than once" "" { target *-*-* } 41 }
+ end subroutine
+ subroutine f61 ()
+ !$omp declare variant (f1) match(construct={parallel,parallel}) ! { dg-error "selector 'parallel' specified more than once in set 'construct'" }
+ end subroutine
+ subroutine f62 ()
+ !$omp declare variant (f1) match(construct={target,parallel,do,simd,parallel}) ! { dg-error "selector 'parallel' specified more than once in set 'construct'" }
+ end subroutine
+ subroutine f63 ()
+ !$omp declare variant (f1) match(construct={target,teams,teams}) ! { dg-error "selector 'teams' specified more than once in set 'construct'" }
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90
new file mode 100644
index 0000000..c62622b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90
@@ -0,0 +1,237 @@
+module main
+contains
+ subroutine f1 ()
+ end subroutine
+ subroutine f2 ()
+ !$omp declare variant (f1) match (construct={target})
+ end subroutine
+ subroutine f3 ()
+ end subroutine
+ subroutine f4 ()
+ !$omp declare variant (f3) match (construct={teams})
+ end subroutine
+ subroutine f5 ()
+ end subroutine
+ subroutine f6 ()
+ !$omp declare variant (f5) match (construct={parallel})
+ end subroutine
+ subroutine f7 ()
+ end subroutine
+ subroutine f8 ()
+ !$omp declare variant (f7) match (construct={do})
+ end subroutine
+ subroutine f9 ()
+ end subroutine
+ subroutine f10 ()
+ !$omp declare variant (f9) match (construct={target,teams,parallel,do})
+ end subroutine
+ subroutine f11 ()
+ end subroutine
+ subroutine f12 ()
+ !$omp declare variant (f11) match (construct={teams,do,parallel})
+ end subroutine
+ subroutine f13 ()
+ end subroutine
+ subroutine f14 ()
+ !$omp declare variant (f13) match (device={kind(any)})
+ end subroutine
+ subroutine f15 ()
+ !$omp declare variant (f13) match (device={kind("host")})
+ end subroutine
+ subroutine f16 ()
+ !$omp declare variant (f13) match (device={kind(nohost)})
+ end subroutine
+ subroutine f17 ()
+ !$omp declare variant (f13) match (device={kind(cpu)})
+ end subroutine
+ subroutine f18 ()
+ !$omp declare variant (f13) match (device={kind("gpu")})
+ end subroutine
+ subroutine f19 ()
+ !$omp declare variant (f13) match (device={kind(fpga)})
+ end subroutine
+ subroutine f20 ()
+ !$omp declare variant (f13) match (device={kind(any,any)})
+ end subroutine
+ subroutine f21 ()
+ !$omp declare variant (f13) match (device={kind(host,nohost)})
+ end subroutine
+ subroutine f22 ()
+ !$omp declare variant (f13) match (device={kind("cpu","gpu","fpga")})
+ end subroutine
+ subroutine f23 ()
+ !$omp declare variant (f13) match (device={kind(any,cpu,nohost)})
+ end subroutine
+ subroutine f24 ()
+ !$omp declare variant (f13) match (device={isa(avx)})
+ end subroutine
+ subroutine f25 ()
+ !$omp declare variant (f13) match (device={isa(sse4,"avx512f",avx512vl,avx512bw)})
+ end subroutine
+ subroutine f26 ()
+ !$omp declare variant (f13) match (device={arch("x86_64")})
+ end subroutine
+ subroutine f27 ()
+ !$omp declare variant (f13) match (device={arch(riscv64)})
+ end subroutine
+ subroutine f28 ()
+ !$omp declare variant (f13) match (device={arch(nvptx)})
+ end subroutine
+ subroutine f29 ()
+ !$omp declare variant (f13) match (device={arch(x86_64),isa("avx512f","avx512vl"),kind(cpu)})
+ end subroutine
+ subroutine f30 ()
+ !$omp declare variant (f13) match (implementation={vendor(amd)})
+ end subroutine
+ subroutine f31 ()
+ !$omp declare variant (f13) match (implementation={vendor(arm)})
+ end subroutine
+ subroutine f32 ()
+ !$omp declare variant (f13) match (implementation={vendor("bsc")})
+ end subroutine
+ subroutine f33 ()
+ !$omp declare variant (f13) match (implementation={vendor(cray)})
+ end subroutine
+ subroutine f34 ()
+ !$omp declare variant (f13) match (implementation={vendor(fujitsu)})
+ end subroutine
+ subroutine f35 ()
+ !$omp declare variant (f13) match (implementation={vendor(gnu)})
+ end subroutine
+ subroutine f36 ()
+ !$omp declare variant (f13) match (implementation={vendor(ibm)})
+ end subroutine
+ subroutine f37 ()
+ !$omp declare variant (f13) match (implementation={vendor("intel")})
+ end subroutine
+ subroutine f38 ()
+ !$omp declare variant (f13) match (implementation={vendor(llvm)})
+ end subroutine
+ subroutine f39 ()
+ !$omp declare variant (f13) match (implementation={vendor(pgi)})
+ end subroutine
+ subroutine f40 ()
+ !$omp declare variant (f13) match (implementation={vendor(ti)})
+ end subroutine
+ subroutine f41 ()
+ !$omp declare variant (f13) match (implementation={vendor(unknown)})
+ end subroutine
+ subroutine f42 ()
+ !$omp declare variant (f13) match (implementation={vendor(gnu,llvm,intel,ibm)})
+ end subroutine
+ subroutine f43 ()
+ !$omp declare variant (f13) match (implementation={extension(my_cute_extension)}) ! { dg-warning "unknown property 'my_cute_extension' of 'extension' selector" }
+ end subroutine
+ subroutine f44 ()
+ !$omp declare variant (f13) match (implementation={extension(some_other_ext,another_ext)}) ! { dg-warning "unknown property 'some_other_ext' of 'extension' selector" }
+ ! { dg-warning "unknown property 'another_ext' of 'extension' selector" "" { target *-*-* } .-1 }
+ end subroutine
+ subroutine f45 ()
+ !$omp declare variant (f13) match (implementation={unified_shared_memory})
+ end subroutine
+ subroutine f46 ()
+ !$omp declare variant (f13) match (implementation={unified_address})
+ end subroutine
+ subroutine f47 ()
+ !$omp declare variant (f13) match (implementation={dynamic_allocators})
+ end subroutine
+ subroutine f48 ()
+ !$omp declare variant (f13) match (implementation={reverse_offload})
+ end subroutine
+ subroutine f49 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(seq_cst)})
+ end subroutine
+ subroutine f50 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(relaxed)})
+ end subroutine
+ subroutine f51 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(acq_rel)})
+ end subroutine
+ subroutine f52 ()
+ !$omp declare variant (f14) match (implementation={atomic_default_mem_order(acq_rel),vendor(gnu),&
+ !$omp& unified_address,extension(foobar)}) ! { dg-warning "unknown property 'foobar' of 'extension' selector" "" { target *-*-* } .-1 }
+ end subroutine
+ subroutine f53 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(3):amd)})
+ end subroutine
+ subroutine f54 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(4):"arm")})
+ end subroutine
+ subroutine f55 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(5):bsc)})
+ end subroutine
+ subroutine f56 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(6):cray)})
+ end subroutine
+ subroutine f57 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(7):fujitsu)})
+ end subroutine
+ subroutine f58 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(8):gnu)})
+ end subroutine
+ subroutine f59 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(9):ibm)})
+ end subroutine
+ subroutine f60 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(10):intel)})
+ end subroutine
+ subroutine f61 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(11):llvm)})
+ end subroutine
+ subroutine f62 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(12):pgi)})
+ end subroutine
+ subroutine f63 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(13):"ti")})
+ end subroutine
+ subroutine f64 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(14):unknown)})
+ end subroutine
+ subroutine f65 ()
+ !$omp declare variant (f13) match (implementation={vendor(score(15):gnu,llvm,intel,ibm)})
+ end subroutine
+ subroutine f66 ()
+ !$omp declare variant (f13) match (implementation={extension(score(16):my_cute_extension)}) ! { dg-warning "unknown property 'my_cute_extension' of 'extension' selector" }
+ end subroutine
+ subroutine f67 ()
+ !$omp declare variant (f13) match (implementation={extension(score(17):some_other_ext,another_ext)}) ! { dg-warning "unknown property 'some_other_ext' of 'extension' selector" }
+ end subroutine ! { dg-warning "unknown property 'another_ext' of 'extension' selector" "" { target *-*-* } .-1 }
+ subroutine f68 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(score(18):seq_cst)})
+ end subroutine
+ subroutine f69 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(score(19):relaxed)})
+ end subroutine
+ subroutine f70 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(score(20):acq_rel)})
+ end subroutine
+ subroutine f71 ()
+ !$omp declare variant (f13) match (implementation={atomic_default_mem_order(score(21):acq_rel),&
+ !$omp& vendor(score(22):gnu),unified_address,extension(score(22):foobar)}) ! { dg-warning "unknown property 'foobar' of 'extension' selector" "" { target *-*-* } .-1 }
+ end subroutine
+ subroutine f72 ()
+ !$omp declare variant (f13) match (user={condition(0)})
+ end subroutine
+ subroutine f73 ()
+ !$omp declare variant (f13) match (user={condition(272-272*1)})
+ end subroutine
+ subroutine f74 ()
+ !$omp declare variant (f13) match (user={condition(score(25):1)})
+ end subroutine
+ subroutine f75 ()
+ !$omp declare variant (f13) match (device={kind(any,"any")})
+ end subroutine
+ subroutine f76 ()
+ !$omp declare variant (f13) match (device={kind("any","any")})
+ end subroutine
+ subroutine f77 ()
+ !$omp declare variant (f13) match (device={kind("any",any)})
+ end subroutine
+ subroutine f78 ()
+ !$omp declare variant (f13) match (implementation={vendor(nvidia)})
+ end subroutine
+ subroutine f79 ()
+ !$omp declare variant (f13) match (user={condition(score(0):0)})
+ end subroutine
+
+ end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-4.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-4.f90
new file mode 100644
index 0000000..bc4f416
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-4.f90
@@ -0,0 +1,62 @@
+program main
+ implicit none
+contains
+ function f6 (x, y, z)
+ real (kind = 8) :: f6
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+
+ interface
+ function f1 (x, y, z)
+ real (kind = 8) :: f1
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+ end function
+
+ function f2 (x, y, z)
+ real (kind = 8) :: f2
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+ end function
+
+ function f3 (x, y, z)
+ real (kind = 8) :: f3
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+ end function
+
+ function f4 (x, y, z)
+ real (kind = 8) :: f4
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+ end function
+
+ function f5 (x, y, z)
+ real (kind = 8) :: f5
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real (kind = 4), intent(in) :: z
+ end function
+ end interface
+
+ !$omp declare variant (f1) match (user={condition(1)})
+ !$omp declare variant (f2) match (user={condition(score(1):1)})
+ !$omp declare variant (f3) match (user={condition(score(3):1)})
+ !$omp declare variant (f4) match (user={condition(score(2):1)})
+ !$omp declare variant (f5) match (implementation={vendor(gnu)})
+
+ f6 = z + x + y
+ end function
+
+ function test (x)
+ real (kind = 8) :: test
+ integer, intent(in) :: x
+
+ test = f6 (x, int (x, kind = 8), 3.5)
+ end function
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90
new file mode 100644
index 0000000..ad7acb9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90
@@ -0,0 +1,75 @@
+! { dg-do compile { target i?86-*-* x86_64-*-* } }
+! { dg-additional-options "-mavx2" }
+
+module main
+ implicit none
+contains
+ function f1 (x, y, z)
+ integer, dimension(4) :: f1
+ real, dimension(4), intent(in) :: x, y
+ real, intent(out) :: z
+
+ f1 = x
+ end function
+
+ function f2 (x, y, z)
+ integer, dimension(8) :: f2
+ real, dimension(8), intent(in) :: x, y
+ real, intent(out) :: z
+
+ f2 = x
+ end function
+
+ function f3 (x, y, z)
+ integer, dimension(4) :: f3
+ real, dimension(4), intent(in) :: x, z
+ integer, intent(in) :: y
+
+ f3 = x
+ end function
+
+ integer function f4 (x, y, z)
+ real, intent(in) :: x, y
+ real, intent(out) :: z
+ !$omp declare variant (f1) match (construct={parallel,do,simd(simdlen(4),notinbranch,uniform(z),aligned(z:16))})
+ !$omp declare variant (f2) match (construct={do,simd(uniform(z),simdlen(8),notinbranch)})
+ end function
+
+ integer function f5 (x, y)
+ integer, intent(in) :: x, y
+ !$omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))})
+ end function
+
+ subroutine test (x, y, z, w)
+ integer, dimension(8192), intent(inout) :: x
+ real, dimension(8192), intent(inout) :: y, z
+ real, pointer, intent(out) :: w
+ integer :: i
+
+ !$omp parallel
+ !$omp do simd aligned (w:16)
+ do i = 1, 1024
+ x(i) = f4 (y(i), z(i), w)
+ end do
+ !$omp end do simd
+ !$omp end parallel
+
+ !$omp parallel do simd aligned (w:16) simdlen(4)
+ do i = 1025, 2048
+ x(i) = f4 (y(i), z(i), w)
+ end do
+ !$omp end parallel do simd
+
+ !$omp simd aligned (w:16)
+ do i = 2049, 4096
+ x(i) = f4 (y(i), z(i), w)
+ end do
+ !$omp end simd
+
+ !$omp simd
+ do i = 4097, 8192
+ if (x(i) .gt. 10) x(i) = f5 (x(i), i)
+ end do
+ !$omp end simd
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-6.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-6.f90
new file mode 100644
index 0000000..3f33f38
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-6.f90
@@ -0,0 +1,188 @@
+module main
+ implicit none
+contains
+ function f1 (x, y, z)
+ real (kind = 8) :: f1
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+
+ f1 = 0.0
+ end function
+
+ function f2 (x, y, z)
+ real (kind = 8) :: f2
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+
+ f2 = 0.0
+ end function
+
+ function f3 (x, y, z)
+ real (kind = 8) :: f3
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f1) match (user={condition(0)},construct={parallel})
+ f3 = 0.0
+ end function
+
+ function f4 (x, y, z)
+ real (kind = 8) :: f4
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f1) match (construct={parallel},user={condition(score(1):1)})
+ f4 = 0.0
+ end function
+
+ function f5 (x, y, z)
+ real (kind = 8) :: f5
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ f5 = 0.0
+ end function
+
+ function f6 (x, y, z)
+ real (kind = 8) :: f6
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f5) match (user={condition(0)}) ! { dg-error "'f5' used as a variant with incompatible 'construct' selector sets" }
+ f6 = 0.0
+ end function
+
+ function f7 (x, y, z)
+ real (kind = 8) :: f7
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f5) match (construct={parallel},user={condition(score(1):1)})
+ f7 = 0.0
+ end function
+
+ function f8 (x, y, z)
+ real (kind = 8) :: f8
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ f8 = 0.0
+ end function
+
+ function f9 (x, y, z)
+ real (kind = 8) :: f9
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f8) match (user={condition(0)},construct={do}) ! { dg-error "'f8' used as a variant with incompatible 'construct' selector sets" }
+ f9 = 0.0
+ end function
+
+ function f10 (x, y, z)
+ real (kind = 8) :: f10
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f8) match (user={condition(1)})
+ f10 = 0.0
+ end function
+
+ function f11 (x, y, z)
+ real (kind = 8) :: f11
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ f11 = 0.0
+ end function
+
+ function f12 (x, y, z)
+ real (kind = 8) :: f12
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f11) match (construct={target,teams,parallel,do}) ! { dg-error "'f11' used as a variant with incompatible 'construct' selector sets" }
+ f12 = 0.0
+ end function
+
+ function f13 (x, y, z)
+ real (kind = 8) :: f13
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f11) match (user={condition(score(1):1)},construct={target,teams,parallel,do}) ! { dg-error "'f11' used as a variant with incompatible 'construct' selector sets" }
+ f13 = 0.0
+ end function
+
+ function f14 (x, y, z)
+ real (kind = 8) :: f14
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f11) match (implementation={vendor(gnu)},construct={target,teams,parallel}) ! { dg-error "'f11' used as a variant with incompatible 'construct' selector sets" }
+ f14 = 0.0
+ end function
+
+ function f15 (x, y, z)
+ real (kind = 8) :: f15
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f11) match (device={kind(any)},construct={teams,parallel})
+ f15 = 0.0
+ end function
+
+ function f16 (x, y, z)
+ real (kind = 8) :: f16
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ f16 = 0.0
+ end function
+
+ function f17 (x, y, z)
+ real (kind = 8) :: f17
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f16) match (construct={teams,parallel}) ! { dg-error "'f16' used as a variant with incompatible 'construct' selector sets" }
+ f17 = 0.0
+ end function
+
+ function f18 (x, y, z)
+ real (kind = 8) :: f18
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f16) match(construct={teams,parallel,do})
+ f18 = 0.0
+ end function
+
+ function f19 (x, y, z)
+ real (kind = 8) :: f19
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ f19 = 0.0
+ end function
+
+ function f20 (x, y, z)
+ real (kind = 8) :: f20
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f19) match (construct={parallel}) ! { dg-error "'f19' used as a variant with incompatible 'construct' selector sets" }
+ f20 = 0.0
+ end function
+
+ function f21 (x, y, z)
+ real (kind = 8) :: f21
+ integer, intent(in) :: x
+ integer (kind = 8), intent(in) :: y
+ real :: z
+ !$omp declare variant (f19) match (construct={do},implementation={vendor(gnu,llvm)})
+ f21 = 0.0
+ end function
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90
new file mode 100644
index 0000000..1590a2a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90
@@ -0,0 +1,93 @@
+! { dg-do compile { target i?86-*-* x86_64-*-* } }
+! { dg-additional-options "-mavx2" }
+
+module main
+ implicit none
+contains
+ function f1 (x, y, z)
+ integer, dimension(4) :: f1
+ real, dimension(4), intent(in) :: x, y
+ real, intent(out) :: z
+
+ f1 = x
+ end function
+
+ function f2 (x, y, z)
+ integer, dimension(8) :: f2
+ real, dimension(8), intent(in) :: x, y
+ real, intent(out) :: z
+
+ f2 = x
+ end function
+
+ function f3 (x, y, z)
+ integer, dimension(4) :: f3
+ real, dimension(4), intent(in) :: x, z
+ integer, intent(in) :: y
+
+ f3 = x
+ end function
+
+ integer function f4 (x, y, z)
+ real, intent(in) :: x, y
+ real, pointer, intent(out) :: z
+ !$omp declare variant (f1) match (construct={parallel,do,simd(simdlen(4),notinbranch,uniform(z),aligned(z:16))}) ! { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f5 (u, v, w)
+ real, intent(in) :: u, v
+ real, pointer, intent(out) :: w
+ !$omp declare variant (f1) match (construct={parallel,do,simd(uniform(w),simdlen(8*2-12),aligned(w:16),notinbranch)}) ! { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f6 (u, v, w)
+ real, intent(in) :: u, v
+ real, pointer, intent(out) :: w
+ !$omp declare variant (f1) match (construct={parallel,do,simd(linear(w),notinbranch,simdlen(4),aligned(w:16))}) ! { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f7 (u, v, w)
+ real, intent(in) :: u, v
+ real, pointer, intent(out) :: w
+ !$omp declare variant (f1) match (construct={parallel,do,simd(uniform(w),notinbranch,simdlen(4),aligned(w:8))}) ! { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f8 (u, v, w)
+ real, intent(in) :: u, v
+ real, pointer, intent(out) :: w
+ !$omp declare variant (f1) match (construct={parallel,do,simd(uniform(w),notinbranch,simdlen(4),aligned(w))})
+ end function
+
+ integer function f9 (x, y, z)
+ real, intent(in) :: x, y
+ real, pointer, intent(out) :: z
+ !$omp declare variant (f2) match (construct={do,simd(uniform(z),simdlen(8),notinbranch)}) ! { dg-error "'f2' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f10 (x, y, q)
+ real, intent(in) :: x, y
+ real, pointer, intent(out) :: q
+ !$omp declare variant (f2) match (construct={do,simd(notinbranch,simdlen(2+2+4),uniform (q))}) ! { dg-error "'f2' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f11 (x, y, z)
+ real, intent(in) :: x, y
+ real, pointer, intent(out) :: z
+ !$omp declare variant (f2) match (construct={do,simd(linear(z:2),simdlen(8),notinbranch)})
+ end function
+
+ integer function f12 (x, y)
+ integer, intent(in) :: x, y
+ !$omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) ! { dg-error "'f3' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f13 (x, q)
+ integer, intent(in) :: x, q
+ !$omp declare variant (f3) match (construct={simd(inbranch, simdlen (5-1), linear (q:4-3))}) ! { dg-error "'f3' used as a variant with incompatible 'construct' selector sets" }
+ end function
+
+ integer function f14 (x, q)
+ integer, intent(in) :: x, q
+ !$omp declare variant (f3) match (construct={simd(inbranch,simdlen(4),linear(q:2))})
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-8.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-8.f90
new file mode 100644
index 0000000..c751489
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-8.f90
@@ -0,0 +1,218 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple" }
+
+program main
+ !$omp requires atomic_default_mem_order(seq_cst)
+ !$omp declare target to (test3)
+contains
+ subroutine f01 ()
+ end subroutine
+
+ subroutine f02 ()
+ !$omp declare variant (f01) match (user={condition(6 == 7)},implementation={vendor(gnu)})
+ end subroutine
+
+ subroutine f03 ()
+ end subroutine
+
+ subroutine f04 ()
+ !$omp declare variant (f03) match (user={condition(6 == 6)},implementation={atomic_default_mem_order(seq_cst)})
+ end subroutine
+
+ subroutine f05 ()
+ end subroutine
+
+ subroutine f06 ()
+ !$omp declare variant (f05) match (user={condition(1)},implementation={atomic_default_mem_order(relaxed)})
+ end subroutine
+
+ subroutine f07 ()
+ end subroutine
+
+ subroutine f08 ()
+ !$omp declare variant (f07) match (construct={parallel,do},device={kind("any")})
+ end subroutine
+
+ subroutine f09 ()
+ end subroutine
+
+ subroutine f10 ()
+ !$omp declare variant (f09) match (construct={parallel,do},implementation={vendor("gnu")})
+ end subroutine
+
+ subroutine f11 ()
+ end subroutine
+
+ subroutine f12 ()
+ !$omp declare variant (f11) match (construct={parallel,do})
+ end subroutine
+
+ subroutine f13 ()
+ end subroutine
+
+ subroutine f14 ()
+ !$omp declare variant (f13) match (construct={parallel,do})
+ end subroutine
+
+ subroutine f15 ()
+ !$omp declare target to (f13, f14)
+ end subroutine
+
+ subroutine f16 ()
+ !$omp declare variant (f15) match (implementation={vendor(llvm)})
+ end subroutine
+
+ subroutine f17 ()
+ end subroutine
+
+ subroutine f18 ()
+ !$omp declare variant (f17) match (construct={target,parallel})
+ end subroutine
+
+ subroutine f19 ()
+ end subroutine
+
+ subroutine f20 ()
+ !$omp declare variant (f19) match (construct={target,parallel})
+ end subroutine
+
+ subroutine f22 ()
+ !$omp declare variant (f21) match (construct={teams,parallel})
+ end subroutine
+
+ subroutine f23 ()
+ end subroutine
+
+ subroutine f24 ()
+ !$omp declare variant (f23) match (construct={teams,parallel,do})
+ end subroutine
+
+ subroutine f25 ()
+ end subroutine
+
+ subroutine f27 ()
+ end subroutine
+
+ subroutine f28 ()
+ !$omp declare variant (f27) match (construct={teams,parallel,do})
+ end subroutine
+
+ subroutine f30 ()
+ !$omp declare variant (f29) match (implementation={vendor(gnu)})
+ end subroutine
+
+ subroutine f31 ()
+ end subroutine
+
+ subroutine f32 ()
+ !$omp declare variant (f31) match (construct={teams,parallel,do})
+ end subroutine
+
+ subroutine f33 ()
+ end subroutine
+
+ subroutine f34 ()
+ !$omp declare variant (f33) match (device={kind("any\0any")}) ! { dg-warning "unknown property '.any..0any.' of 'kind' selector" }
+ end subroutine
+
+ subroutine f35 ()
+ end subroutine
+
+ subroutine f36 ()
+ !$omp declare variant (f35) match (implementation={vendor("gnu\0")}) ! { dg-warning "unknown property '.gnu..0.' of 'vendor' selector" }
+ end subroutine
+
+ subroutine test1 ()
+ integer :: i
+
+ call f02 () ! { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" } }
+ call f04 () ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" } }
+ call f06 () ! { dg-final { scan-tree-dump-times "f06 \\\(\\\);" 1 "gimple" } }
+
+ !$omp parallel
+ !$omp do
+ do i = 1, 2
+ call f08 () ! { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end do
+ !$omp end parallel
+
+ !$omp parallel do
+ do i = 1, 2
+ call f10 () ! { dg-final { scan-tree-dump-times "f09 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end parallel do
+
+ !$omp do
+ do i = 1, 2
+ !$omp parallel
+ call f12 () ! { dg-final { scan-tree-dump-times "f12 \\\(\\\);" 1 "gimple" } }
+ !$omp end parallel
+ end do
+ !$omp end do
+
+ !$omp parallel
+ !$omp target
+ !$omp do
+ do i = 1, 2
+ call f14 () ! { dg-final { scan-tree-dump-times "f14 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end do
+ !$omp end target
+ !$omp end parallel
+
+ call f16 () ! { dg-final { scan-tree-dump-times "f16 \\\(\\\);" 1 "gimple" } }
+ call f34 () ! { dg-final { scan-tree-dump-times "f34 \\\(\\\);" 1 "gimple" } }
+ call f36 () ! { dg-final { scan-tree-dump-times "f36 \\\(\\\);" 1 "gimple" } }
+ end subroutine
+
+ subroutine test2 ()
+ ! OpenMP 5.0 specifies that the 'target' trait should be added for
+ ! functions within a declare target block, but Fortran does not have
+ ! the notion of a declare target _block_, so the variant is not used here.
+ ! This may change in later versions of OpenMP.
+
+ !$omp declare target
+ !$omp parallel
+ call f18 () ! { dg-final { scan-tree-dump-times "f18 \\\(\\\);" 1 "gimple" } }
+ !$omp end parallel
+ end subroutine
+
+ subroutine test3 ()
+ ! In the C version, this test was used to check that the
+ ! 'declare target to' form of the directive did not result in the variant
+ ! being used.
+ !$omp parallel
+ call f20 () ! { dg-final { scan-tree-dump-times "f20 \\\(\\\);" 1 "gimple" } }
+ !$omp end parallel
+ end subroutine
+
+ subroutine f21 ()
+ integer :: i
+ !$omp do
+ do i = 1, 2
+ call f24 () ! { dg-final { scan-tree-dump-times "f23 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end do
+ end subroutine
+
+ subroutine f26 ()
+ !$omp declare variant (f25) match (construct={teams,parallel})
+
+ integer :: i
+ !$omp do
+ do i = 1, 2
+ call f28 () ! { dg-final { scan-tree-dump-times "f28 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end do
+ end subroutine
+
+ subroutine f29 ()
+ integer :: i
+ !$omp do
+ do i = 1, 2
+ call f32 () ! { dg-final { scan-tree-dump-times "f32 \\\(\\\);" 1 "gimple" } }
+ end do
+ !$omp end do
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-9.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-9.f90
new file mode 100644
index 0000000..ebd0666
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-9.f90
@@ -0,0 +1,58 @@
+! { dg-do compile }
+! { dg-additional-options "-cpp -fdump-tree-gimple" }
+! { dg-additional-options "-mno-sse3" { target { i?86-*-* x86_64-*-* } } }
+
+program main
+ implicit none
+contains
+ subroutine f01 ()
+ end subroutine
+ subroutine f02 ()
+ !$omp declare variant (f01) match (device={isa("avx512f",avx512bw)})
+ end subroutine
+ subroutine f05 ()
+ end subroutine
+ subroutine f06 ()
+ !$omp declare variant (f05) match (device={kind(gpu)})
+ end subroutine
+ subroutine f07 ()
+ end subroutine
+ subroutine f08 ()
+ !$omp declare variant (f07) match (device={kind("cpu")})
+ end subroutine
+ subroutine f09 ()
+ end subroutine
+ subroutine f10 ()
+ !$omp declare variant (f09) match (device={isa(sm_35)})
+ end subroutine
+ subroutine f11 ()
+ end subroutine
+ subroutine f12 ()
+ !$omp declare variant (f11) match (device={arch(nvptx)})
+ end subroutine
+ subroutine f13 ()
+ end subroutine
+ subroutine f14 ()
+ !$omp declare variant (f13) match (device={arch("i386"),isa(sse4)})
+ end subroutine
+ subroutine f17 ()
+ end subroutine
+ subroutine f18 ()
+ !$omp declare variant (f17) match (device={kind("any","fpga")})
+ end subroutine
+
+ subroutine test1 ()
+ integer :: i;
+ call f02 () ! { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" } }
+ call f14 () ! { dg-final { scan-tree-dump-times "f14 \\\(\\\);" 1 "gimple" } }
+ call f18 () ! { dg-final { scan-tree-dump-times "f18 \\\(\\\);" 1 "gimple" } }
+ end subroutine
+
+ subroutine test3 ()
+ call f06 () ! { dg-final { scan-tree-dump-times "f06 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ call f08 () ! { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ call f10 () ! { dg-final { scan-tree-dump-times "f10 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* } } } } }
+ call f12 () ! { dg-final { scan-tree-dump-times "f12 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* } } } } }
+ ! { dg-final { scan-tree-dump-times "f11 \\\(\\\);" 1 "gimple" { target { nvptx*-*-* } } } }
+ end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/flush-1.f90 b/gcc/testsuite/gfortran.dg/gomp/flush-1.f90
index d0b7f9e..904bb1d 100644
--- a/gcc/testsuite/gfortran.dg/gomp/flush-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/flush-1.f90
@@ -1,4 +1,5 @@
! { dg-additional-options "-fdump-tree-gimple" }
+! { dg-final { scan-tree-dump "foo \\(6\\);\[\n\r]* __sync_synchronize \\(\\);\[\n\r]* foo \\(6\\);" "gimple" } }
! { dg-final { scan-tree-dump "foo \\(4\\);\[\n\r]* __atomic_thread_fence \\(4\\);\[\n\r]* foo \\(4\\);" "gimple" } }
! { dg-final { scan-tree-dump "foo \\(3\\);\[\n\r]* __atomic_thread_fence \\(3\\);\[\n\r]* foo \\(3\\);" "gimple" } }
! { dg-final { scan-tree-dump "foo \\(2\\);\[\n\r]* __atomic_thread_fence \\(2\\);\[\n\r]* foo \\(2\\);" "gimple" } }
@@ -39,3 +40,10 @@ subroutine f4
!$omp flush
call foo (5)
end
+
+subroutine f5
+ use m
+ call foo (6)
+ !$omp flush seq_cst
+ call foo (6)
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/flush-2.f90 b/gcc/testsuite/gfortran.dg/gomp/flush-2.f90
index 6857371..ba23444 100644
--- a/gcc/testsuite/gfortran.dg/gomp/flush-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/flush-2.f90
@@ -9,10 +9,11 @@ subroutine foo (void)
!$omp flush acquire
!$omp flush release
!$omp flush acq_rel
- !$omp flush relaxed ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" }
- !$omp flush seq_cst ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" }
- !$omp flush foobar ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" }
+ !$omp flush seq_cst
+ !$omp flush relaxed ! { dg-error "Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE" }
+ !$omp flush foobar ! { dg-error "Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE" }
!$omp flush acquire (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" }
!$omp flush release (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" }
!$omp flush acq_rel (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" }
-end
+ !$omp flush seq_cst (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" }
+ end
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-5.f90 b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
new file mode 100644
index 0000000..0dddb96
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/order-5.f90
@@ -0,0 +1,129 @@
+! { dg-additional-options "-fdump-tree-original" }
+
+subroutine f1 (a)
+ integer :: a(*), i
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp simd order ( reproducible : concurrent )
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order(reproducible :concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+subroutine f2 (a)
+ integer :: a(*), i
+ !$omp parallel do order(reproducible: concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp parallel do simd order (reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do simd order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams
+ !$omp distribute parallel do order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute parallel do simd order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute order(reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp end teams
+ !$omp taskloop simd order (reproducible:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+subroutine f3 (a)
+ integer :: a(*), i
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp simd order ( unconstrained : concurrent )
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order(unconstrained :concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+subroutine f4 (a)
+ integer :: a(*), i
+ !$omp parallel do order(unconstrained: concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp parallel do simd order (unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do simd order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams
+ !$omp distribute parallel do order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute parallel do simd order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute order(unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp end teams
+ !$omp taskloop simd order (unconstrained:concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(reproducible:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp distribute order\\(unconstrained:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(reproducible:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait order\\(unconstrained:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for order\\(reproducible:concurrent\\)" 2 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp for order\\(unconstrained:concurrent\\)" 2 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel" 12 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(reproducible:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) order\\(unconstrained:concurrent\\)" 6 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp taskloop" 2 "original"} }
+! { dg-final { scan-tree-dump-times "#pragma omp teams" 8 "original"} }
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-6.f90 b/gcc/testsuite/gfortran.dg/gomp/order-6.f90
new file mode 100644
index 0000000..c8aeecb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/order-6.f90
@@ -0,0 +1,436 @@
+module m
+ use iso_c_binding
+ implicit none (type, external)
+ interface
+ subroutine foo()
+ end subroutine foo
+ integer function omp_get_thread_num ()
+ end
+ integer function omp_get_num_threads ()
+ end
+ integer function omp_target_is_present (x, i)
+ import :: c_ptr
+ type(c_ptr) :: x
+ integer, value :: i
+ end
+ integer function omp_get_cancellation ()
+ end
+ end interface
+ integer :: v
+contains
+subroutine f1 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp parallel ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc (a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+
+subroutine f2 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp parallel ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc(a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+
+subroutine f3 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp parallel
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ !$omp task ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = a(i) + 1
+ !$omp end task
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp taskloop ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc (a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(reproducible:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+
+subroutine f4 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp parallel ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc (a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+
+subroutine f5 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp parallel ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc (a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do simd order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+
+subroutine f6 (a)
+ integer, target :: a(*)
+ integer :: i
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp parallel
+ call foo ()
+ !$omp end parallel
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp simd
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp critical ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end critical
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp ordered simd ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ call foo ()
+ !$omp end ordered
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = v + 1
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic read ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = v
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp atomic write ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ v = a(i)
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ !$omp task ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ a(i) = a(i) + 1
+ !$omp end task
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ block
+ integer j
+ !$omp taskloop ! { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" }
+ do j = 1, 64
+ a(64 * i + j) = i + j
+ end do
+ end block
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_thread_num () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_num_threads () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_target_is_present (c_loc (a(i)), 0) ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+ !$omp do order(unconstrained:concurrent)
+ do i = 1, 64
+ a(i) = a(i) + omp_get_cancellation () ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" }
+ end do
+end
+end module m
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-7.f90 b/gcc/testsuite/gfortran.dg/gomp/order-7.f90
new file mode 100644
index 0000000..4be8ab3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/order-7.f90
@@ -0,0 +1,59 @@
+subroutine f1 (a)
+ integer :: a(*)
+ integer i
+ !$omp do order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp simd order ( concurrent )
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+subroutine f2 (a)
+ integer :: a(*)
+ integer i
+ !$omp parallel do order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp parallel do simd order (concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute parallel do simd order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams distribute order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp teams
+ !$omp distribute parallel do order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute parallel do simd order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp distribute order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp end teams
+ !$omp taskloop simd order (concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-8.f90 b/gcc/testsuite/gfortran.dg/gomp/order-8.f90
new file mode 100644
index 0000000..c753886
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/order-8.f90
@@ -0,0 +1,61 @@
+subroutine f1 (a)
+ integer :: a(*)
+ integer i
+ !$omp do order ! { dg-error "Failed to match clause" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order : ! { dg-error "Failed to match clause" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp simd order ( foobar ) ! { dg-error "Expected ORDER\\(CONCURRENT\\) at .1. with optional 'reproducible' or 'unconstrained' modifier" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order( concurrent ! { dg-error "Expected ORDER\\(CONCURRENT\\) at .1. with optional 'reproducible' or 'unconstrained' modifier" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do simd order( concurrent : foo )! { dg-error "Expected ORDER\\(CONCURRENT\\) at .1. with optional 'reproducible' or 'unconstrained' modifier" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+end
+
+subroutine f2 (a)
+ integer :: a(*)
+ integer i
+ !$omp teams
+ !$omp distribute order(concurrent)
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp end teams
+ !$omp taskloop order (concurrent) ! { dg-error "Failed to match clause" }
+ do i = 1, 128
+ a(i) = a(i) + 1
+ end do
+ !$omp do order(concurrent) ordered ! { dg-error "ORDER clause must not be used together ORDERED" }
+ do i = 1, 128
+ !$omp ordered
+ a(i) = a(i) + 1
+ !$omp end ordered
+ end do
+ !$omp do ordered order(concurrent) ! { dg-error "ORDER clause must not be used together ORDERED" }
+ do i = 1, 128
+ !$omp ordered
+ a(i) = a(i) + 1
+ !$omp end ordered
+ end do
+ !$omp do ordered (1) order(concurrent) ! { dg-error "ORDER clause must not be used together ORDERED" }
+ do i = 1, 128
+ !$omp ordered depend (sink: i - 1)
+ !$omp ordered depend (source)
+ end do
+ !$omp do order(concurrent)ordered (1) ! { dg-error "ORDER clause must not be used together ORDERED" }
+ do i = 1, 128
+ !$omp ordered depend (sink: i - 1)
+ !$omp ordered depend (source)
+ end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-9.f90 b/gcc/testsuite/gfortran.dg/gomp/order-9.f90
new file mode 100644
index 0000000..c769511
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/order-9.f90
@@ -0,0 +1,35 @@
+subroutine foo
+ !$omp do schedule(static) order(concurrent) order(concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp do schedule(static) order(reproducible:concurrent) order(unconstrained:concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+
+ !$omp loop bind(thread) order(concurrent) order(concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp loop bind(thread) order(reproducible:concurrent) order(unconstrained:concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp simd order(concurrent) order(concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp simd order(reproducible:concurrent) order(unconstrained:concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp distribute dist_schedule(static) order(concurrent) order(concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+ !$omp loop bind(thread) order(reproducible:concurrent) order(unconstrained:concurrent) ! { dg-error "Duplicated 'order \\(' clause" }
+ do i = 1, 8
+ call f0 ()
+ end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr43711.f90 b/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
index e47e586..d790e3e 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr43711.f90
@@ -11,8 +11,8 @@ program NF03_2_5_2_1a
print *, 'FAIL'
!$omp section
print *, 'FAIL'
- !$omp end sections nowait nowait ! { dg-error "Unexpected junk" }
- !$omp end parallel
-end program NF03_2_5_2_1a
+ !$omp end sections nowait nowait ! { dg-error "Unexpected junk after NOWAIT clause" }
+ !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" }
+end program NF03_2_5_2_1a ! { dg-error "Unexpected END statement" }
-! { dg-excess-errors "Unexpected" }
+! { dg-prune-output "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-1.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-1.f90
new file mode 100644
index 0000000..20b9755
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-1.f90
@@ -0,0 +1,67 @@
+! { dg-do compile }
+
+implicit none
+
+integer :: n
+
+!$omp target device (1)
+!$omp end target
+
+!$omp target device (n)
+!$omp end target
+
+!$omp target device (n + 1)
+!$omp end target
+
+!$omp target device (device_num : 1)
+!$omp end target
+
+!$omp target device (device_num : n)
+!$omp end target
+
+!$omp target device (device_num : n + 1)
+!$omp end target
+
+!$omp target device (invalid : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device ( : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device ( , : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (ancestor, device_num : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (ancestor, device_num, ancestor : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (device_num device_num : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (ancestor device_num : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (device_num, invalid : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (ancestor, invalid : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (ancestor, , , : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (invalid, ancestor : 1) ! { dg-error "xpected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (invalid, invalid, ancestor : 1) ! { dg-error "xpected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (device_num invalid : 1) ! { dg-error "Expected integer expression or a single device-modifier 'device_num' or 'ancestor' at" }
+! !$omp end target
+
+!$omp target device (device_num : n, n) ! { dg-error "Expected integer expression" }
+! !$omp end target
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-2.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-2.f90
new file mode 100644
index 0000000..133b805
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-2.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+! Test to ensure that device-modifier 'device_num' is parsed correctly in
+! device clauses.
+
+!$omp target device (device_num : 42)
+!$omp end target
+
+end
+
+! { dg-final { scan-tree-dump "pragma omp target \[^\n\r)]*device\\(42\\)" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-1.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-1.f90
new file mode 100644
index 0000000..9a170db
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-1.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+
+! Ensure that a 'requires' directive with the 'reverse_offload' clause was
+! specified.
+
+!$omp target device (ancestor:1) ! { dg-error "'ancestor' device modifier not preceded by 'requires' directive with 'reverse_offload' clause" }
+! !$omp end target
+
+end \ No newline at end of file
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-2.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-2.f90
new file mode 100644
index 0000000..117a1d0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-2.f90
@@ -0,0 +1,92 @@
+! { dg-do compile }
+
+implicit none
+
+integer :: a, b, c
+
+!$omp requires reverse_offload ! { dg-error "Sorry, 'reverse_offload' clause at \\(1\\) on REQUIRES directive is not yet supported" }
+
+
+! The following test case is marked with 'xfail' because a previous 'sorry' from
+! 'reverse_offload' suppresses the 'sorry' for 'ancestor'.
+
+!$omp target device (ancestor: 1) ! { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } }
+!$omp end target
+
+!$omp target device (ancestor : a) ! { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } }
+!$omp end target
+
+!$omp target device (ancestor : a + 1) ! { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } }
+!$omp end target
+
+
+! Ensure that the integer expression in the 'device' clause for
+! device-modifier 'ancestor' evaluates to '1' in case of a constant.
+
+!$omp target device (ancestor: 42) ! { dg-error "the 'device' clause expression must evaluate to '1'" }
+! !$omp end target
+
+!$omp target device (device_num:42)
+!$omp end target
+
+!$omp target device (42)
+!$omp end target
+
+
+! Ensure that no OpenMP constructs appear inside target regions with 'ancestor'.
+! The following test case is marked with 'xfail' because a previous 'sorry' from
+! 'reverse_offload' suppresses the 'sorry' for 'ancestor'.
+
+!$omp target device (ancestor: 1)
+ !$omp teams ! { dg-error "" "OpenMP constructs are not allowed in target region with 'ancestor'" { xfail *-*-* } }
+ !$omp end teams
+!$omp end target
+
+!$omp target device (device_num: 1)
+ !$omp teams
+ !$omp end teams
+!$omp end target
+
+!$omp target device (1)
+ !$omp teams
+ !$omp end teams
+!$omp end target
+
+
+! Ensure that with 'ancestor' only the 'device', 'firstprivate', 'private',
+! 'defaultmap', and 'map' clauses appear on the construct.
+! The following test case is marked with 'xfail' because a previous 'sorry' from
+! 'reverse_offload' suppresses the 'sorry' for 'ancestor'.
+
+!$omp target nowait device (ancestor: 1) ! { dg-error "" "with 'ancestor', only the 'device', 'firstprivate', 'private', 'defaultmap', and 'map' clauses may appear on the construct" { xfail *-*-* } }
+!$omp end target
+
+!$omp target device (ancestor: 1) nowait ! { dg-error "" "with 'ancestor', only the 'device', 'firstprivate', 'private', 'defaultmap', and 'map' clauses may appear on the construct" { xfail *-*-* } }
+!$omp end target
+
+!$omp target nowait device (device_num: 1)
+!$omp end target
+
+!$omp target nowait device (1)
+!$omp end target
+
+!$omp target device (ancestor: 1) firstprivate (a) private (b) defaultmap (none) map (c)
+!$omp end target
+
+
+! Ensure that 'ancestor' is only used with 'target' constructs (not with
+! 'target data', 'target update' etc.).
+! The following test case is marked with 'xfail' because a previous 'sorry' from
+! 'reverse_offload' suppresses the 'sorry' for 'ancestor'.
+
+!$omp target data map (a) device (ancestor: 1) ! { dg-error "" "'device' clause with 'ancestor' is only allowed on 'target' construct" { xfail *-*-* } }
+!$omp end target data
+
+!$omp target enter data map (to: a) device (ancestor: 1) ! { dg-error "" "'device' clause with 'ancestor' is only allowed on 'target' construct" { xfail *-*-* } }
+!$omp target exit data map (from: a) device (ancestor: 1) ! { dg-error "" "'device' clause with 'ancestor' is only allowed on 'target' construct" { xfail *-*-* } }
+
+!$omp target update to (a) device (ancestor: 1) ! { dg-error "'device' clause with 'ancestor' is only allowed on 'target' construct" "" { xfail *-*-* } }
+! { dg-error "with 'ancestor', only the 'device', 'firstprivate', 'private', 'defaultmap', and 'map' clauses may appear on the construct" "" { xfail *-*-* } .-1 }
+
+
+end \ No newline at end of file
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-3.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-3.f90
new file mode 100644
index 0000000..f1145bd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-3.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+
+! This testcase ensure that no calls to OpenMP API runtime routines are allowed
+! inside the corresponding target region.
+
+module my_omp_mod
+ use iso_c_binding
+ interface
+ integer function omp_get_thread_num ()
+ end
+ end interface
+end
+
+subroutine f1 ()
+ use my_omp_mod
+ implicit none
+ integer :: n
+
+ !$omp requires reverse_offload ! { dg-error "Sorry, 'reverse_offload' clause at \\(1\\) on REQUIRES directive is not yet supported" }
+
+ !$omp target device (ancestor : 1)
+ n = omp_get_thread_num () ! { dg-error "" "OpenMP runtime API call 'omp_get_thread_num' in a region with 'device\\(ancestor\\)' clause" { xfail *-*-* } }
+ !$omp end target
+
+ !$omp target device (device_num : 1)
+ n = omp_get_thread_num ()
+ !$omp end target
+
+ !$omp target device (1)
+ n = omp_get_thread_num ()
+ !$omp end target
+
+end \ No newline at end of file
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90
new file mode 100644
index 0000000..63872fa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+! Test to ensure that device-modifier 'ancestor' is parsed correctly in
+! device clauses.
+
+!$omp requires reverse_offload ! { dg-error "Sorry, 'reverse_offload' clause at \\(1\\) on REQUIRES directive is not yet supported" }
+
+!$omp target device (ancestor : 1) ! { dg-message "" "sorry, unimplemented: 'ancestor' not yet supported" { xfail *-*-* } }
+!$omp end target
+
+end
+
+! TODO: dg-final { scan-tree-dump-times "pragma omp target \[^\n\r)]*device\\(ancestor:1\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/unexpected-end.f90 b/gcc/testsuite/gfortran.dg/gomp/unexpected-end.f90
new file mode 100644
index 0000000..d2e8daa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/unexpected-end.f90
@@ -0,0 +1,123 @@
+! PR fortran/102313
+
+!$omp end ATOMIC ! { dg-error "Unexpected !.OMP END ATOMIC" }
+
+!$omp end CRITICAL ! { dg-error "Unexpected !.OMP END CRITICAL" }
+
+!$omp end DISTRIBUTE ! { dg-error "Unexpected !.OMP END DISTRIBUTE" }
+
+!$omp end DISTRIBUTE PARALLEL DO ! { dg-error "Unexpected !.OMP END DISTRIBUTE PARALLEL DO" }
+
+!$omp end DISTRIBUTE PARALLEL DO SIMD ! { dg-error "Unexpected !.OMP END DISTRIBUTE PARALLEL DO SIMD" }
+
+!$omp end DISTRIBUTE SIMD ! { dg-error "Unexpected !.OMP END DISTRIBUTE SIMD" }
+
+!$omp end DO ! { dg-error "Unexpected !.OMP END DO" }
+
+!$omp end DO SIMD ! { dg-error "Unexpected !.OMP END DO SIMD" }
+
+!$omp end LOOP ! { dg-error "Unclassifiable OpenMP directive" }
+
+!$omp parallel loop
+do i = 1, 5
+end do
+!$omp end LOOP ! { dg-error "Unclassifiable OpenMP directive" }
+
+!$omp end MASKED ! { dg-error "Unexpected !.OMP END MASKED" }
+
+!$omp end MASKED TASKLOOP ! { dg-error "Unexpected !.OMP END MASKED TASKLOOP" }
+
+!$omp end MASKED TASKLOOP SIMD ! { dg-error "Unexpected !.OMP END MASKED TASKLOOP SIMD" }
+
+!$omp end MASTER ! { dg-error "Unexpected !.OMP END MASTER" }
+
+!$omp end MASTER TASKLOOP ! { dg-error "Unexpected !.OMP END MASTER TASKLOOP" }
+
+!$omp end MASTER TASKLOOP SIMD ! { dg-error "Unexpected !.OMP END MASTER TASKLOOP SIMD" }
+
+!$omp end ORDERED ! { dg-error "Unexpected !.OMP END ORDERED" }
+
+!$omp end PARALLEL ! { dg-error "Unexpected !.OMP END PARALLEL" }
+
+!$omp end PARALLEL DO ! { dg-error "Unexpected !.OMP END PARALLEL DO" }
+
+!$omp end PARALLEL DO SIMD ! { dg-error "Unexpected !.OMP END PARALLEL DO SIMD" }
+
+!$omp loop
+!$omp end PARALLEL LOOP ! { dg-error "Unexpected junk" }
+
+!$omp end PARALLEL MASKED ! { dg-error "Unexpected !.OMP END PARALLEL MASKED" }
+
+!$omp end PARALLEL MASKED TASKLOOP ! { dg-error "Unexpected !.OMP END PARALLEL MASKED TASKLOOP" }
+
+!$omp end PARALLEL MASKED TASKLOOP SIMD ! { dg-error "Unexpected !.OMP END PARALLEL MASKED TASKLOOP SIMD" }
+
+!$omp end PARALLEL MASTER ! { dg-error "Unexpected !.OMP END PARALLEL MASTER" }
+
+!$omp end PARALLEL MASTER TASKLOOP ! { dg-error "Unexpected !.OMP END PARALLEL MASTER TASKLOOP" }
+
+!$omp end PARALLEL MASTER TASKLOOP SIMD ! { dg-error "Unexpected !.OMP END PARALLEL MASTER TASKLOOP SIMD" }
+
+!$omp end PARALLEL SECTIONS ! { dg-error "Unexpected !.OMP END PARALLEL SECTIONS" }
+
+!$omp end PARALLEL WORKSHARE ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE" }
+
+!$omp end SCOPE ! { dg-error "Unexpected !.OMP END SCOPE" }
+
+!$omp end SECTIONS ! { dg-error "Unexpected !.OMP END SECTIONS" }
+
+!$omp end SIMD ! { dg-error "Unexpected !.OMP END SIMD" }
+
+!$omp end SINGLE ! { dg-error "Unexpected !.OMP END SINGLE" }
+
+!$omp end TARGET ! { dg-error "Unexpected !.OMP END TARGET" }
+
+!$omp end TARGET DATA ! { dg-error "Unexpected !.OMP END TARGET DATA" }
+
+!$omp end TARGET PARALLEL ! { dg-error "Unexpected !.OMP END TARGET PARALLEL" }
+
+!$omp end TARGET PARALLEL DO ! { dg-error "Unexpected !.OMP END TARGET PARALLEL DO" }
+
+!$omp end TARGET PARALLEL DO SIMD ! { dg-error "Unexpected !.OMP END TARGET PARALLEL DO SIMD" }
+
+!$omp end TARGET PARALLEL LOOP ! { dg-error "Unexpected junk" }
+
+!$omp end TARGET SIMD ! { dg-error "Unexpected !.OMP END TARGET SIMD" }
+
+!$omp end TARGET TEAMS ! { dg-error "Unexpected !.OMP END TARGET TEAMS" }
+
+!$omp end TARGET TEAMS DISTRIBUTE ! { dg-error "Unexpected !.OMP END TARGET TEAMS DISTRIBUTE" }
+
+!$omp end TARGET TEAMS DISTRIBUTE PARALLEL DO ! { dg-error "Unexpected !.OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO" }
+
+!$omp end TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ! { dg-error "Unexpected !.OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" }
+
+!$omp end TARGET TEAMS DISTRIBUTE SIMD ! { dg-error "Unexpected !.OMP END TARGET TEAMS DISTRIBUTE SIMD" }
+
+!$omp end TARGET TEAMS LOOP ! { dg-error "Unexpected junk" }
+
+!$omp end TASK ! { dg-error "Unexpected !.OMP END TASK" }
+
+!$omp end TASKGROUP ! { dg-error "Unexpected !.OMP END TASKGROUP" }
+
+!$omp end TASKLOOP ! { dg-error "Unexpected !.OMP END TASKLOOP" }
+
+!$omp end TASKLOOP SIMD ! { dg-error "Unexpected !.OMP END TASKLOOP SIMD" }
+
+!$omp end TEAMS ! { dg-error "Unexpected !.OMP END TEAMS" }
+
+!$omp end TEAMS DISTRIBUTE ! { dg-error "Unexpected !.OMP END TEAMS DISTRIBUTE" }
+
+!$omp end TEAMS DISTRIBUTE PARALLEL DO ! { dg-error "Unexpected !.OMP END TEAMS DISTRIBUTE PARALLEL DO" }
+
+!$omp end TEAMS DISTRIBUTE PARALLEL DO SIMD ! { dg-error "Unexpected !.OMP END TEAMS DISTRIBUTE PARALLEL DO SIMD" }
+
+!$omp end TEAMS DISTRIBUTE SIMD ! { dg-error "Unexpected !.OMP END TEAMS DISTRIBUTE SIMD" }
+
+!$omp end TEAMS LOOP ! { dg-error "Unexpected junk" }
+
+!$omp end WORKSHARE ! { dg-error "Unexpected !.OMP END WORKSHARE" }
+
+end ! { dg-error "Unexpected END statement" }
+
+! { dg-excess-errors "Unexpected end of file" }
diff --git a/gcc/testsuite/gfortran.dg/goto_9.f90 b/gcc/testsuite/gfortran.dg/goto_9.f90
new file mode 100644
index 0000000..e05e738
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goto_9.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! { dg-options "-std=legacy" }
+! PR fortran/102113 - parsing error in assigned goto
+
+program p
+ assign 10 to i
+ goto i,(10,20 )
+10 continue
+20 continue
+end
diff --git a/gcc/testsuite/gfortran.dg/include_14.f90 b/gcc/testsuite/gfortran.dg/include_14.f90
new file mode 100644
index 0000000..8110e49
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_14.f90
@@ -0,0 +1,6 @@
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar" }
+end
+! default: warn for -I and -J but ignore other options.
+! { dg-warning "Nonexistent include directory 'bar/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'foo/bar/'" "" { target *-*-* } 0 }
+
diff --git a/gcc/testsuite/gfortran.dg/include_15.f90 b/gcc/testsuite/gfortran.dg/include_15.f90
new file mode 100644
index 0000000..18d91f6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_15.f90
@@ -0,0 +1,9 @@
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar -Wmissing-include-dirs" }
+end
+
+! { dg-warning " /fdaf/: No such file or directory" "" { target *-*-* } 0 }
+! { dg-warning " bar: No such file or directory" "" { target *-*-* } 0 }
+! { dg-warning " foo/bar: No such file or directory" "" { target *-*-* } 0 }
+
+! Depending how the testsuite is run, it may or may not print the following warning:
+! { dg-prune-output "Warning: finclude: No such file or directory" }
diff --git a/gcc/testsuite/gfortran.dg/include_16.f90 b/gcc/testsuite/gfortran.dg/include_16.f90
new file mode 100644
index 0000000..65e4c7e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_16.f90
@@ -0,0 +1,2 @@
+! { dg-additional-options "-cpp -idirafter /fdaf/ -I bar -J foo/bar -Wno-missing-include-dirs" }
+end
diff --git a/gcc/testsuite/gfortran.dg/include_17.f90 b/gcc/testsuite/gfortran.dg/include_17.f90
new file mode 100644
index 0000000..0667759
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_17.f90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! { dg-options "-I foo-bar -J foo/bar" }
+end
+! { dg-warning "Nonexistent include directory 'foo-bar/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'foo/bar/'" "" { target *-*-* } 0 }
+
diff --git a/gcc/testsuite/gfortran.dg/include_18.f90 b/gcc/testsuite/gfortran.dg/include_18.f90
new file mode 100644
index 0000000..b74a585
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_18.f90
@@ -0,0 +1,5 @@
+! { dg-do compile }
+! { dg-options "-I nothere -J neither/here -Wmissing-include-dirs" }
+end
+! { dg-warning "Nonexistent include directory 'nothere/'" "" { target *-*-* } 0 }
+! { dg-warning "Nonexistent include directory 'neither/here/'" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/include_19.f90 b/gcc/testsuite/gfortran.dg/include_19.f90
new file mode 100644
index 0000000..7404929
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_19.f90
@@ -0,0 +1,4 @@
+! { dg-do compile }
+! { dg-options "-I nothere -J foobar/foo -Wno-missing-include-dirs" }
+program main
+end program main
diff --git a/gcc/testsuite/gfortran.dg/include_20.f90 b/gcc/testsuite/gfortran.dg/include_20.f90
new file mode 100644
index 0000000..4f8fdc6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_20.f90
@@ -0,0 +1,5 @@
+! { dg-do compile }
+! { dg-options "-J foobar/foo" }
+program main
+end program main
+! { dg-warning "Nonexistent include directory" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/include_21.f90 b/gcc/testsuite/gfortran.dg/include_21.f90
new file mode 100644
index 0000000..40bc598
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_21.f90
@@ -0,0 +1,26 @@
+# 1 "../../../trunk/libgfortran/generated/_abs_c4.F90"
+# 1 "C:\\msys\\1.0.10\\home\\FX\\ibin\\i586-pc-mingw32\\libgfortran//"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "../../../trunk/libgfortran/generated/_abs_c4.F90"
+! Comment here
+
+# 1 "./config.h" 1
+
+# 37 "../../../trunk/libgfortran/generated/_abs_c4.F90" 2
+
+# 1 "./kinds.inc" 1
+# 38 "../../../trunk/libgfortran/generated/_abs_c4.F90" 2
+
+# 1 "./c99_protos.inc" 1
+# 39 "../../../trunk/libgfortran/generated/_abs_c4.F90" 2
+
+elemental function abs_c4 (parm)
+ complex (kind=4), intent (in) :: parm
+ real (kind=4) :: abs_c4
+
+ abs_c4 = abs (parm)
+end function
+
+! { dg-do compile }
+! { dg-options "-fpreprocessed -g3 -Wno-missing-include-dirs" }
diff --git a/gcc/testsuite/gfortran.dg/include_23.f90 b/gcc/testsuite/gfortran.dg/include_23.f90
new file mode 100644
index 0000000..421ddda
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_23.f90
@@ -0,0 +1,4 @@
+implicit none
+include "nonexisting/file.f90" ! { dg-error "Cannot open included file 'nonexisting/file.f90'" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_24.f90 b/gcc/testsuite/gfortran.dg/include_24.f90
new file mode 100644
index 0000000..1fe9eb5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_24.f90
@@ -0,0 +1,4 @@
+implicit none
+include "." ! { dg-error "Included file '.' is not a regular file" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_6.f90 b/gcc/testsuite/gfortran.dg/include_6.f90
index f5bb085..3e3be1b 100644
--- a/gcc/testsuite/gfortran.dg/include_6.f90
+++ b/gcc/testsuite/gfortran.dg/include_6.f90
@@ -1,6 +1,6 @@
! { dg-do compile }
! { dg-options "-I gfortran.log" }
-! { dg-error "is not a directory" "" { target *-*-* } 0 }
+! { dg-warning "Include directory 'gfortran.log/': Not a directory" "" { target *-*-* } 0 }
! { dg-prune-output "compilation terminated." }
end
diff --git a/gcc/testsuite/gfortran.dg/include_9.f90 b/gcc/testsuite/gfortran.dg/include_9.f90
index c4ef50f..6b0648b 100644
--- a/gcc/testsuite/gfortran.dg/include_9.f90
+++ b/gcc/testsuite/gfortran.dg/include_9.f90
@@ -4,3 +4,4 @@
program main
end program
! { dg-error "is not a regular file" " " { target *-*-* } 3 }
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/intent_out_14.f90 b/gcc/testsuite/gfortran.dg/intent_out_14.f90
new file mode 100644
index 0000000..e599463
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_out_14.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! PR fortran/102287 - optional allocatable DT array arguments (intent out)
+
+module m
+ type t
+ integer, allocatable :: a
+ end type t
+contains
+ subroutine a (x, v)
+ type(t), optional, allocatable, intent(out) :: x(:)
+ type(t), optional, intent(out) :: v(:)
+ call b (x, v)
+ end subroutine a
+
+ subroutine b (y, w)
+ type(t), optional, allocatable, intent(out) :: y(:)
+ type(t), optional, intent(out) :: w(:)
+ end subroutine b
+end module m
+
+program p
+ use m
+ call a ()
+end
diff --git a/gcc/testsuite/gfortran.dg/interface_operator_3.f90 b/gcc/testsuite/gfortran.dg/interface_operator_3.f90
new file mode 100644
index 0000000..6a580b2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_operator_3.f90
@@ -0,0 +1,141 @@
+! { dg-do compile }
+! PR fortran/65454 - accept both old and new-style relational operators
+
+module m
+ implicit none
+ private :: t1
+ type t1
+ integer :: i
+ end type t1
+ interface operator (==)
+ module procedure :: my_cmp
+ end interface
+ interface operator (/=)
+ module procedure :: my_cmp
+ end interface
+ interface operator (<=)
+ module procedure :: my_cmp
+ end interface
+ interface operator (<)
+ module procedure :: my_cmp
+ end interface
+ interface operator (>=)
+ module procedure :: my_cmp
+ end interface
+ interface operator (>)
+ module procedure :: my_cmp
+ end interface
+contains
+ elemental function my_cmp (a, b) result (c)
+ type(t1), intent(in) :: a, b
+ logical :: c
+ c = a%i == b%i
+ end function my_cmp
+end module m
+
+module m_os
+ implicit none
+ private :: t2
+ type t2
+ integer :: i
+ end type t2
+ interface operator (.eq.)
+ module procedure :: my_cmp
+ end interface
+ interface operator (.ne.)
+ module procedure :: my_cmp
+ end interface
+ interface operator (.le.)
+ module procedure :: my_cmp
+ end interface
+ interface operator (.lt.)
+ module procedure :: my_cmp
+ end interface
+ interface operator (.ge.)
+ module procedure :: my_cmp
+ end interface
+ interface operator (.gt.)
+ module procedure :: my_cmp
+ end interface
+contains
+ elemental function my_cmp (a, b) result (c)
+ type(t2), intent(in) :: a, b
+ logical :: c
+ c = a%i .eq. b%i
+ end function my_cmp
+end module m_os
+
+! new style only
+module m1
+ use m, only: operator(==), operator(/=)
+ use m, only: operator(<=), operator(<)
+ use m, only: operator(>=), operator(>)
+end module m1
+
+! old -> new style
+module m2
+ use m_os, only: operator(==), operator(/=)
+ use m_os, only: operator(<=), operator(<)
+ use m_os, only: operator(>=), operator(>)
+end module m2
+
+! new -> old style
+module m3
+ use m, only: operator(.eq.), operator(.ne.)
+ use m, only: operator(.le.), operator(.lt.)
+ use m, only: operator(.ge.), operator(.gt.)
+end module m3
+
+! old style only
+module m4
+ use m_os, only: operator(.eq.), operator(.ne.)
+ use m_os, only: operator(.le.), operator(.lt.)
+ use m_os, only: operator(.ge.), operator(.gt.)
+end module m4
+
+! new -> all styles
+module m5
+ use m, only: operator(.eq.), operator(.ne.), operator(==), operator(/=)
+ use m, only: operator(.le.), operator(.lt.), operator(<=), operator(<)
+ use m, only: operator(.ge.), operator(.gt.), operator(>=), operator(>)
+end module m5
+
+! old -> all styles
+module m6
+ use m_os, only: operator(.eq.), operator(.ne.), operator(==), operator(/=)
+ use m_os, only: operator(.le.), operator(.lt.), operator(<=), operator(<)
+ use m_os, only: operator(.ge.), operator(.gt.), operator(>=), operator(>)
+end module m6
+
+! all -> all styles
+module m7
+ use m, only: operator(.eq.), operator(.ne.), operator(==), operator(/=)
+ use m, only: operator(.le.), operator(.lt.), operator(<=), operator(<)
+ use m, only: operator(.ge.), operator(.gt.), operator(>=), operator(>)
+ use m_os, only: operator(.eq.), operator(.ne.), operator(==), operator(/=)
+ use m_os, only: operator(.le.), operator(.lt.), operator(<=), operator(<)
+ use m_os, only: operator(.ge.), operator(.gt.), operator(>=), operator(>)
+end module m7
+
+module m_eq
+ implicit none
+ private :: t3
+ type t3
+ integer :: i
+ end type t3
+ interface operator (==)
+ module procedure :: my_cmp
+ end interface
+contains
+ elemental function my_cmp (a, b) result (c)
+ type(t3), intent(in) :: a, b
+ logical :: c
+ c = a%i == b%i
+ end function my_cmp
+end module m_eq
+
+module m8
+ use m_eq, only: operator(==), operator(.eq.)
+ use m_eq, only: operator(/=) ! { dg-error "operator ./=. referenced" }
+ use m_eq, only: operator(.ne.) ! { dg-error "operator .\.ne\.. referenced" }
+end module m8
diff --git a/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90 b/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
index 923cbc3..afdf9b3 100644
--- a/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
+++ b/gcc/testsuite/gfortran.dg/intrinsic_size_3.f90
@@ -22,4 +22,4 @@ program bug
stop
end program bug
-! { dg-final { scan-tree-dump-times "iszs = \\(integer\\(kind=2\\)\\) MAX_EXPR <\\(D.\[0-9\]+->dim.0..ubound - D.\[0-9\]+->dim.0..lbound\\) \\+ 1, 0>;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "iszs = \\(integer\\(kind=2\\)\\) MAX_EXPR <\\(a.dim.0..ubound - a.dim.0..lbound\\) \\+ 1, 0>;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90
index abe5cb7..2a4a618 100644
--- a/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90
@@ -4,7 +4,7 @@
!
! Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
!
-subroutine bar(c,d) BIND(C) ! { dg-error "character dummy argument 'c' at .1. with assumed length is not yet supported for procedure 'bar' with BIND\\(C\\) attribute" }
+subroutine bar(c,d) BIND(C) ! { dg-error "Character dummy argument 'd' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'bar' has the BIND\\(C\\) attribute" }
character (len=*) c
character (len=2) d
end
diff --git a/gcc/testsuite/gfortran.dg/parameter_array_init_8.f90 b/gcc/testsuite/gfortran.dg/parameter_array_init_8.f90
new file mode 100644
index 0000000..2e5f769
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/parameter_array_init_8.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+! PR fortran/99348
+! PR fortran/102521
+! Check simplifications for initialization of DT parameter arrays
+
+program p
+ type t
+ integer :: n
+ end type
+ type(t), parameter :: a(4) = t(1)
+ type(t), parameter :: d(*) = a
+ type(t), parameter :: b(2,2) = reshape(d, [2,2])
+ integer, parameter :: nn = b(2,2)% n
+ type u
+ character(3) :: c
+ end type
+ type(u), parameter :: x(2,3) = u('ab')
+ type(u), parameter :: y(*,*) = transpose (x)
+ character(*), parameter :: c = y(3,2)% c
+ integer, parameter :: lc = c% len
+ integer, parameter :: lyc = len (y(3,2)% c)
+! integer, parameter :: lxc = x(1,1)% c% len ! fails (pr101735?)
+ if (nn /= 1) stop 1
+ if (lc /= 3 .or. lyc /= 3 .or. c /= "ab ") stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/pr100950.f90 b/gcc/testsuite/gfortran.dg/pr100950.f90
index cb9d126..a19409c 100644
--- a/gcc/testsuite/gfortran.dg/pr100950.f90
+++ b/gcc/testsuite/gfortran.dg/pr100950.f90
@@ -46,6 +46,18 @@ program p
integer, parameter :: l9 = len (r(1)%u(:)(3:4))
if (l9 /= 2) stop 13
end block
+
+ call sub (42, "abcde")
+contains
+ subroutine sub (m, c)
+ integer, intent(in) :: m
+ character(len=*), intent(in) :: c
+ character(len=m) :: p, o(3)
+ integer, parameter :: l10 = len (p(6:7))
+ integer, parameter :: l11 = len (o(:)(6:7))
+ integer, parameter :: l12 = len (c(2:3))
+ if (l10 /= 2 .or. l11 /= 2 .or. l12 /= 2) stop 14
+ end subroutine sub
end
! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/pr101327.f90 b/gcc/testsuite/gfortran.dg/pr101327.f90
new file mode 100644
index 0000000..f4377aa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr101327.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! PR fortran/101327 - ICE in find_array_element, at fortran/expr.c:1355
+
+subroutine s
+ integer, parameter :: n([2]) = [1, 2] ! { dg-error "must be scalar" }
+ type t
+ integer :: a(n(1):n(2))
+ end type
+end
+
+! { dg-error "cannot be automatic or of deferred shape" " " { target *-*-* } 5 }
diff --git a/gcc/testsuite/gfortran.dg/pr102366.f90 b/gcc/testsuite/gfortran.dg/pr102366.f90
new file mode 100644
index 0000000..d002f64
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102366.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -Wall" }
+! { dg-final { scan-tree-dump-times "static real" 1 "original" } }
+! PR fortran/102366 - large arrays no longer become static
+
+program p
+ real(kind=4) :: a(16776325)
+ a=1.0
+end
diff --git a/gcc/testsuite/gfortran.dg/pr102458.f90 b/gcc/testsuite/gfortran.dg/pr102458.f90
new file mode 100644
index 0000000..555e497
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102458.f90
@@ -0,0 +1,42 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=lib" }
+! PR fortran/102458 - standard intrinsics excluded in constant expressions
+
+subroutine s1
+ integer :: a(command_argument_count()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+program p
+ block
+ integer :: a(get_team()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+ end block
+end
+
+subroutine s2
+ integer :: a(num_images()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+function f()
+ block
+ integer :: a(team_number()) = 0 ! { dg-error "Automatic array" }
+ a = 1
+ end block
+end
+
+subroutine s3
+ integer :: a(this_image()) = 1 ! { dg-error "Automatic array" }
+ print *, a
+end
+
+subroutine s4
+ integer, parameter :: n = 4
+ integer, parameter :: x(transfer(n, n)) = 1 ! legal
+ integer :: y(transfer(n, n)) = 2 ! legal
+ integer, parameter :: k = size (x) ! ok
+! integer, parameter :: m = size (y) ! fails, tracked separately
+ print *, k, x, y
+ if (k /= size (y)) stop 1
+end
diff --git a/gcc/testsuite/gfortran.dg/pr102458b.f90 b/gcc/testsuite/gfortran.dg/pr102458b.f90
new file mode 100644
index 0000000..3e1026e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102458b.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 0 "original" } }
+! PR fortran/102458
+
+subroutine s4
+ integer, parameter :: n = 4
+ integer :: w(transfer(n, n)) = 1
+ integer :: x(transfer(n, n))
+ integer :: y(2*int(n) - n)
+ type t
+ integer :: z(int(n))
+ end type t
+ type(t) :: tt, uu(3)
+ integer, parameter :: i = size (w)
+ integer, parameter :: k = size (x)
+ integer, parameter :: m = size (y)
+ integer, parameter :: j = size (tt% z)
+ integer, parameter :: l = size (uu(2)% z)
+ if (i /= n .or. k /= n .or. m /= n .or. j /= n .or. l /= n) stop 1
+end
diff --git a/gcc/testsuite/gfortran.dg/pr102520.f90 b/gcc/testsuite/gfortran.dg/pr102520.f90
new file mode 100644
index 0000000..1c98c18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102520.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! PR fortran/102520 - ICE in expand_constructor, at fortran/array.c:1802
+
+program p
+ type t
+ end type
+ type(t), parameter :: a(4) = shape(1) ! { dg-error "Incompatible" }
+ type(t), parameter :: b(2,2) = reshape(a,[2,2]) ! { dg-error "Incompatible" }
+ type(t), parameter :: c(2,2) = transpose(b) ! { dg-error "Unclassifiable" }
+end
+
+! { dg-error "Different shape for array assignment" " " { target *-*-* } 7 }
diff --git a/gcc/testsuite/gfortran.dg/pr102685.f90 b/gcc/testsuite/gfortran.dg/pr102685.f90
new file mode 100644
index 0000000..d325c27
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr102685.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+! PR fortran/102685
+
+program p
+ type t
+ integer :: a(2)
+ end type
+ type(t), parameter :: x0 = t([2]) ! { dg-error "shape of component" }
+ type(t), parameter :: x1(2) = t([2]) ! { dg-error "shape of component" }
+ type(t), parameter :: x(2) = t([integer::]) ! { dg-error "shape of component" }
+
+ type u
+ integer :: a
+ integer :: b(0)
+ end type
+ type(u), parameter :: z0(2) = u(1, [integer::]) ! valid
+ type(u), parameter :: z1 = u(1, 2 ) ! valid
+ type(u), parameter :: z2(2) = u(1, 2 ) ! valid
+ type(u), parameter :: z3 = u(1, [2]) ! { dg-error "shape of component" }
+ type(u), parameter :: z4(2) = u(1, [2]) ! { dg-error "shape of component" }
+
+ type v
+ integer :: a(2,1)
+ end type
+ type(v), parameter :: y0 = v(reshape([1,2],[2,1])) ! valid
+ type(v), parameter :: y1 = v(reshape([1,2],[1,2])) ! { dg-error "shape of component" }
+ type(v), parameter :: y(1) = v(reshape([1,2],[1,2])) ! { dg-error "shape of component" }
+
+ print *, x0,x,x1,y0,y1,y,z0,z1,z2,z3,z4
+end
diff --git a/gcc/testsuite/gfortran.dg/pr32599.f03 b/gcc/testsuite/gfortran.dg/pr32599.f03
index bf9bd8c..819a2b8 100644
--- a/gcc/testsuite/gfortran.dg/pr32599.f03
+++ b/gcc/testsuite/gfortran.dg/pr32599.f03
@@ -14,7 +14,7 @@ module pr32599
character(len=*,kind=c_char), intent(IN) :: path
end subroutine destroy
- subroutine create(path) BIND(C) ! { dg-error "Fortran 2008: Character dummy argument 'path' at .1. with length greater than 1 for procedure 'create' with BIND\\(C\\) attribute" }
+ subroutine create(path) BIND(C) ! { dg-error "Character dummy argument 'path' at .1. must be of constant length of one or assumed length, unless it has assumed shape or assumed rank, as procedure 'create' has the BIND\\(C\\) attribute" }
use iso_c_binding
implicit none
character(len=5,kind=c_char), intent(IN) :: path
diff --git a/gcc/testsuite/gfortran.dg/pr70931.f90 b/gcc/testsuite/gfortran.dg/pr70931.f90
index 08ecd68..4444b5e 100644
--- a/gcc/testsuite/gfortran.dg/pr70931.f90
+++ b/gcc/testsuite/gfortran.dg/pr70931.f90
@@ -5,6 +5,7 @@ program p
integer :: a
integer :: b(0)
end type
- type(t), parameter :: z = t(1, [2])
+! type(t), parameter :: z = t(1, [2]) ! original invalid code
+ type(t), parameter :: z = t(1, [integer::])
print *, z
end
diff --git a/gcc/testsuite/gfortran.dg/pr77498.f b/gcc/testsuite/gfortran.dg/pr77498.f
index f957b57..a0fc827 100644
--- a/gcc/testsuite/gfortran.dg/pr77498.f
+++ b/gcc/testsuite/gfortran.dg/pr77498.f
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O2 -ffast-math -fdump-tree-pre" }
+! { dg-options "-O2 -fno-tree-vectorize -ffast-math -fdump-tree-pre" }
subroutine foo(U,V,R,N,A)
integer N
diff --git a/gcc/testsuite/gfortran.dg/pr82314.f90 b/gcc/testsuite/gfortran.dg/pr82314.f90
new file mode 100644
index 0000000..3a147e2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr82314.f90
@@ -0,0 +1,11 @@
+! { dg-do run }
+! PR fortran/82314 - ICE in gfc_conv_expr_descriptor
+
+program p
+ implicit none
+ integer, parameter :: karray(merge(3,7,.true.):merge(3,7,.false.)) = 1
+ integer, parameter :: i = size (karray)
+ integer, parameter :: l = lbound (karray,1)
+ integer, parameter :: u = ubound (karray,1)
+ if (l /= 3 .or. u /= 7 .or. i /= 5) stop 1
+end
diff --git a/gcc/testsuite/gfortran.dg/pr93792.f90 b/gcc/testsuite/gfortran.dg/pr93792.f90
index 960d050..c7939af 100644
--- a/gcc/testsuite/gfortran.dg/pr93792.f90
+++ b/gcc/testsuite/gfortran.dg/pr93792.f90
@@ -14,4 +14,4 @@ end
! { dg-error "Parameterized type 't' does not have a component" " " { target *-*-* } 5 }
! { dg-error "BOZ literal constant at .1. cannot appear" " " { target *-*-* } 6 }
! { dg-error "Cannot open module file" " " { target *-*-* } 10 }
-! { dg-excess-errors "compilation terminated" }
+! { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/gfortran.dg/predict-2.f90 b/gcc/testsuite/gfortran.dg/predict-2.f90
index 11a9ec5..93e3ad6 100644
--- a/gcc/testsuite/gfortran.dg/predict-2.f90
+++ b/gcc/testsuite/gfortran.dg/predict-2.f90
@@ -2,10 +2,10 @@
! { dg-options "-O2 -fdump-tree-profile_estimate" }
subroutine test(block, array)
-integer :: i,j, block(9), array(2)
+integer :: i,j, block(9), array(4)
do i = array(1), array(2), 2
- do j = array(1), array(2), 3
+ do j = array(3), array(4), 3
block(i) = j
end do
end do
diff --git a/gcc/testsuite/gfortran.dg/reshape_shape_2.f90 b/gcc/testsuite/gfortran.dg/reshape_shape_2.f90
new file mode 100644
index 0000000..8f17576
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/reshape_shape_2.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! PR fortran/102717
+
+program p
+ integer, parameter :: a(1) = 2
+ integer, parameter :: b(2) = reshape([3,4], -[a]) ! { dg-error "negative" }
+end
diff --git a/gcc/testsuite/gfortran.dg/shape_10.f90 b/gcc/testsuite/gfortran.dg/shape_10.f90
new file mode 100644
index 0000000..4943c21
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/shape_10.f90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! PR fortran/102716
+
+program p
+ integer, parameter :: a(1) = shape([2], [1]) ! { dg-error "must be a scalar" }
+end
diff --git a/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90 b/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
index c6e8f76..cbf4aa4 100644
--- a/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
+++ b/gcc/testsuite/gfortran.dg/size_optional_dim_1.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
! PR 30865 - passing a subroutine optional argument to size(dim=...)
! used to segfault.
program main
@@ -19,3 +20,6 @@ contains
ires = size (a1, dim=opt1)
end subroutine checkv
end program main
+
+! Ensure inline code is generated, cf. PR fortran/94070
+! { dg-final { scan-tree-dump-not "_gfortran_size" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/substr_6.f90 b/gcc/testsuite/gfortran.dg/substr_6.f90
index 0d5e3d7..83e788a 100644
--- a/gcc/testsuite/gfortran.dg/substr_6.f90
+++ b/gcc/testsuite/gfortran.dg/substr_6.f90
@@ -6,6 +6,8 @@ CHARACTER(5), parameter :: c0(1) = (/ "123" // ACHAR(0) // "5" /)
CHARACTER*5 c(1)
CHARACTER(1), parameter :: c1(5) = (/ "1", "2", "3", ACHAR(0), "5" /)
+c = c0(1)(-5:-8)
+if (c(1) /= " ") STOP 1
c = (/ c0(1)(1:5) /)
do i=1,5
if (c(1)(i:i) /= c1(i)) STOP 2
diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90
index e0f3f94..b428fa6 100644
--- a/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90
+++ b/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90
@@ -145,7 +145,7 @@ contains
real(4) :: x(2)
end type mytype
- type (mytype), parameter :: dt1(2) = transfer (c1, mytype ((/1.0,2.0,3.0,4.0/)), 2)
+ type (mytype), parameter :: dt1(2) = transfer (c1, mytype ((/1.0,2.0/)), 2)
type (mytype) :: dt2(2)
dt2 = transfer (c2, dt2);
diff --git a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90 b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
index c49cd42..54271b1 100644
--- a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
+++ b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
@@ -60,5 +60,5 @@ end
!
! The check below for temporaries gave 14 and 33 for "parm" and "atmp".
!
-! { dg-final { scan-tree-dump-times "parm" 72 "original" } }
+! { dg-final { scan-tree-dump-times "parm" 76 "original" } }
! { dg-final { scan-tree-dump-times "atmp" 13 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
index afd7522..8634031 100644
--- a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
@@ -196,16 +196,25 @@ END MODULE
! Check assumed rank calls
- call foobar (u3, 0)
- call foobar (u4, 1)
+ call foobar (u3, 0, is_u3=.true.)
+ call foobar (u4, 1, is_u3=.false.)
contains
- subroutine foobar (arg, ranki)
+ subroutine foobar (arg, ranki, is_u3)
class(*) :: arg (..)
integer :: ranki
+ logical, value :: is_u3
integer i
i = rank (arg)
- if (i .ne. ranki) STOP 1
+ if (i .ne. ranki) STOP 1
+ if (is_u3) then
+ if (EXTENDS_TYPE_OF (arg, obj1) .neqv. .FALSE.) STOP 1
+ else
+ ! arg == u4
+ if (EXTENDS_TYPE_OF (arg, obj1) .neqv. .FALSE.) STOP 1
+ end if
+ ! if (.NOT. SAME_TYPE_AS (arg, u3)) STOP 1
+ ! if (.NOT. SAME_TYPE_AS (arg, u4)) STOP 1
end subroutine
END
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90
new file mode 100644
index 0000000..df57bcd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f90
@@ -0,0 +1,254 @@
+implicit none
+type t2
+ integer :: x
+end type t2
+
+type, extends(t2) :: t2e
+ integer :: y
+end type t2e
+
+type t
+ class(*), allocatable :: au, au2(:,:)
+ class(t2), allocatable :: at, at2(:,:)
+end type t
+
+type(t), target :: var, var0, var2(4), var2a(4)
+class(*), allocatable :: au, au2(:,:)
+class(t2), allocatable :: at, at2(:,:)
+
+
+if (same_type_as (var%au, var%at)) error stop 1
+if (same_type_as (var%au2, var%at)) error stop 2
+if (same_type_as (var%au, var%at)) error stop 3
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (var%au, var0%au)) error stop 4
+if (same_type_as (var%au2, var0%au2)) error stop 5
+if (same_type_as (var%au, var0%au2)) error stop 6
+call c1(var%au, var%au, var%au2)
+
+if (.not.same_type_as (var%at, var%at)) error stop 7
+if (.not.same_type_as (var%at2, var%at)) error stop 8
+if (.not.same_type_as (var%at, var%at2)) error stop 9
+if (.not.extends_type_of (var%at, var%at)) error stop 10
+if (.not.extends_type_of (var%at2, var%at)) error stop 11
+if (.not.extends_type_of (var%at, var%at2)) error stop 12
+if (same_type_as (var%at, var0%au)) error stop 13
+if (same_type_as (var%at2, var0%au2)) error stop 14
+if (same_type_as (var%at, var0%au2)) error stop 15
+call c2(var%at, var%at, var%at2)
+
+if (same_type_as (au, var%at)) error stop 16
+if (same_type_as (au2, var%at)) error stop 17
+if (same_type_as (au, var%at)) error stop 18
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (au, var0%au)) error stop 19
+if (same_type_as (au2, var0%au2)) error stop 20
+if (same_type_as (au, var0%au2)) error stop 21
+call c1(au, var%au, var%au2)
+
+if (.not.same_type_as (at, var%at)) error stop 22
+if (.not.same_type_as (at2, var%at)) error stop 23
+if (.not.same_type_as (at, var%at2)) error stop 24
+if (.not.extends_type_of (at, var%at)) error stop 25
+if (.not.extends_type_of (at2, var%at)) error stop 26
+if (.not.extends_type_of (at, var%at2)) error stop 27
+if (same_type_as (at, var0%au)) error stop 28
+if (same_type_as (at2, var0%au2)) error stop 29
+if (same_type_as (at, var0%au2)) error stop 30
+call c2(var%at, var%at, var%at2)
+
+if (same_type_as (var%au, at)) error stop 31
+if (same_type_as (var%au2, at)) error stop 32
+if (same_type_as (var%au, at)) error stop 33
+! Note: class(*) has no declared type, hence .false.
+if (same_type_as (var%au, au)) error stop 34
+if (same_type_as (var%au2, au2)) error stop 35
+if (same_type_as (var%au, au2)) error stop 36
+call c1(var%au, var%au, au2)
+
+if (.not.same_type_as (var%at, at)) error stop 37
+if (.not.same_type_as (var%at2, at)) error stop 38
+if (.not.same_type_as (var%at, at2)) error stop 39
+if (.not.extends_type_of (var%at, at)) error stop 40
+if (.not.extends_type_of (var%at2, at)) error stop 41
+if (.not.extends_type_of (var%at, at2)) error stop 42
+if (same_type_as (var%at, au)) error stop 43
+if (same_type_as (var%at2, au2)) error stop 44
+if (same_type_as (var%at, au2)) error stop 45
+call c2(var%at, var%at, at2)
+
+allocate(t2e :: var0%at, var0%at2(4,4))
+allocate(t2 :: var0%au, var0%au2(4,4))
+
+if (.not.same_type_as (var0%au, var%at)) error stop 46
+if (.not.same_type_as (var0%au2, var%at)) error stop 47
+if (.not.same_type_as (var0%au, var%at)) error stop 48
+if (.not.same_type_as (var0%au, var0%au2)) error stop 49
+if (.not.same_type_as (var0%au2, var0%au2)) error stop 50
+if (.not.same_type_as (var0%au, var0%au2)) error stop 51
+if (.not.extends_type_of (var0%au, var%at)) error stop 52
+if (.not.extends_type_of (var0%au2, var%at)) error stop 53
+if (.not.extends_type_of (var0%au, var%at)) error stop 54
+if (.not.extends_type_of (var0%au, var0%au2)) error stop 55
+if (.not.extends_type_of (var0%au2, var0%au2)) error stop 56
+if (.not.extends_type_of (var0%au, var0%au2)) error stop 57
+
+if (.not.same_type_as (var0%au, at)) error stop 58
+if (.not.same_type_as (var0%au2, at)) error stop 59
+if (.not.same_type_as (var0%au, at2)) error stop 60
+if (.not.extends_type_of (var0%au, at)) error stop 61
+if (.not.extends_type_of (var0%au2, at)) error stop 62
+if (.not.extends_type_of (var0%au, at2)) error stop 63
+
+if (same_type_as (var0%at, var%at)) error stop 64
+if (same_type_as (var0%at2, var%at)) error stop 65
+if (same_type_as (var0%at, var%at)) error stop 66
+if (same_type_as (var0%at, var0%au2)) error stop 67
+if (same_type_as (var0%at2, var0%au2)) error stop 68
+if (same_type_as (var0%at, var0%au2)) error stop 69
+if (.not.extends_type_of (var0%at, var%at)) error stop 70
+if (.not.extends_type_of (var0%at2, var%at)) error stop 71
+if (.not.extends_type_of (var0%at, var%at)) error stop 72
+if (.not.extends_type_of (var0%at, var0%au2)) error stop 73
+if (.not.extends_type_of (var0%at2, var0%au2)) error stop 74
+if (.not.extends_type_of (var0%at, var0%au2)) error stop 75
+
+if (same_type_as (var0%at, at)) error stop 76
+if (same_type_as (var0%at2, at)) error stop 77
+if (same_type_as (var0%at, at2)) error stop 78
+if (.not.extends_type_of (var0%at, at)) error stop 79
+if (.not.extends_type_of (var0%at2, at)) error stop 80
+if (.not.extends_type_of (var0%at, at2)) error stop 81
+
+call c3(var0%au, var0%au2, var0%at, var0%at2)
+call c4(var0%au, var0%au2, var0%at, var0%at2)
+
+contains
+ subroutine c1(x, y, z)
+ class(*) :: x, y(..), z(..)
+ if (same_type_as (x, var0%at)) error stop 82
+ if (same_type_as (y, var0%at)) error stop 83
+ if (same_type_as (z, var0%at)) error stop 84
+ if (same_type_as (x, var%au)) error stop 85
+ if (same_type_as (y, var%au2)) error stop 86
+ if (same_type_as (z, var%au2)) error stop 87
+
+ if (same_type_as (x, at)) error stop 88
+ if (same_type_as (y, at)) error stop 89
+ if (same_type_as (z, at)) error stop 90
+ if (same_type_as (x, au)) error stop 91
+ if (same_type_as (y, au2)) error stop 92
+ if (same_type_as (z, au2)) error stop 93
+ end
+
+ subroutine c2(x, y, z)
+ class(*) :: x, y(..), z(..)
+ if (.not.same_type_as (x, var0%at)) error stop 94
+ if (.not.same_type_as (y, var0%at)) error stop 95
+ if (.not.same_type_as (z, var0%at)) error stop 96
+ if (.not.extends_type_of (x, var0%at)) error stop 97
+ if (.not.extends_type_of (y, var0%at)) error stop 98
+ if (.not.extends_type_of (z, var0%at)) error stop 99
+ if (same_type_as (x, var%au)) error stop 100
+ if (same_type_as (y, var%au2)) error stop 101
+ if (same_type_as (z, var%au2)) error stop 102
+
+ if (.not.same_type_as (x, at)) error stop 103
+ if (.not.same_type_as (y, at)) error stop 104
+ if (.not.same_type_as (z, at)) error stop 105
+ if (.not.extends_type_of (x, at)) error stop 106
+ if (.not.extends_type_of (y, at)) error stop 107
+ if (.not.extends_type_of (z, at)) error stop 108
+ if (same_type_as (x, au)) error stop 109
+ if (same_type_as (y, au2)) error stop 110
+ if (same_type_as (z, au2)) error stop 111
+ end
+
+ subroutine c3(mau, mau2, mat, mat2)
+ class(*) :: mau, mau2(:,:), mat, mat2(:,:)
+
+ if (.not.same_type_as (mau, var%at)) error stop 112
+ if (.not.same_type_as (mau2, var%at)) error stop 113
+ if (.not.same_type_as (mau, var%at)) error stop 114
+ if (.not.same_type_as (mau, var0%au2)) error stop 115
+ if (.not.same_type_as (mau2, var0%au2)) error stop 116
+ if (.not.same_type_as (mau, var0%au2)) error stop 117
+ if (.not.extends_type_of (mau, var%at)) error stop 118
+ if (.not.extends_type_of (mau2, var%at)) error stop 119
+ if (.not.extends_type_of (mau, var%at)) error stop 120
+ if (.not.extends_type_of (mau, var0%au2)) error stop 121
+ if (.not.extends_type_of (mau2, var0%au2)) error stop 122
+ if (.not.extends_type_of (mau, var0%au2)) error stop 123
+
+ if (.not.same_type_as (mau, at)) error stop 124
+ if (.not.same_type_as (mau2, at)) error stop 125
+ if (.not.same_type_as (mau, at2)) error stop 126
+ if (.not.extends_type_of (mau, at)) error stop 127
+ if (.not.extends_type_of (mau2, at)) error stop 128
+ if (.not.extends_type_of (mau, at2)) error stop 129
+
+ if (same_type_as (mat, var%at)) error stop 130
+ if (same_type_as (mat2, var%at)) error stop 131
+ if (same_type_as (mat, var%at)) error stop 132
+ if (same_type_as (mat, var0%au2)) error stop 133
+ if (same_type_as (mat2, var0%au2)) error stop 134
+ if (same_type_as (mat, var0%au2)) error stop 135
+ if (.not.extends_type_of (mat, var%at)) error stop 136
+ if (.not.extends_type_of (mat2, var%at)) error stop 137
+ if (.not.extends_type_of (mat, var%at)) error stop 138
+ if (.not.extends_type_of (mat, var0%au2)) error stop 139
+ if (.not.extends_type_of (mat2, var0%au2)) error stop 140
+ if (.not.extends_type_of (mat, var0%au2)) error stop 141
+
+ if (same_type_as (mat, at)) error stop 142
+ if (same_type_as (mat2, at)) error stop 143
+ if (same_type_as (mat, at2)) error stop 144
+ if (.not.extends_type_of (mat, at)) error stop 145
+ if (.not.extends_type_of (mat2, at)) error stop 147
+ if (.not.extends_type_of (mat, at2)) error stop 148
+ end
+
+ subroutine c4(mau, mau2, mat, mat2)
+ class(*) :: mau(..), mau2(..), mat(..), mat2(..)
+
+ if (.not.same_type_as (mau, var%at)) error stop 149
+ if (.not.same_type_as (mau2, var%at)) error stop 150
+ if (.not.same_type_as (mau, var%at)) error stop 151
+ if (.not.same_type_as (mau, var0%au2)) error stop 152
+ if (.not.same_type_as (mau2, var0%au2)) error stop 153
+ if (.not.same_type_as (mau, var0%au2)) error stop 154
+ if (.not.extends_type_of (mau, var%at)) error stop 155
+ if (.not.extends_type_of (mau2, var%at)) error stop 156
+ if (.not.extends_type_of (mau, var%at)) error stop 157
+ if (.not.extends_type_of (mau, var0%au2)) error stop 158
+ if (.not.extends_type_of (mau2, var0%au2)) error stop 159
+ if (.not.extends_type_of (mau, var0%au2)) error stop 160
+
+ if (.not.same_type_as (mau, at)) error stop 161
+ if (.not.same_type_as (mau2, at)) error stop 162
+ if (.not.same_type_as (mau, at2)) error stop 163
+ if (.not.extends_type_of (mau, at)) error stop 164
+ if (.not.extends_type_of (mau2, at)) error stop 165
+ if (.not.extends_type_of (mau, at2)) error stop 166
+
+ if (same_type_as (mat, var%at)) error stop 167
+ if (same_type_as (mat2, var%at)) error stop 168
+ if (same_type_as (mat, var%at)) error stop 169
+ if (same_type_as (mat, var0%au2)) error stop 170
+ if (same_type_as (mat2, var0%au2)) error stop 171
+ if (same_type_as (mat, var0%au2)) error stop 172
+ if (.not.extends_type_of (mat, var%at)) error stop 173
+ if (.not.extends_type_of (mat2, var%at)) error stop 174
+ if (.not.extends_type_of (mat, var%at)) error stop 175
+ if (.not.extends_type_of (mat, var0%au2)) error stop 176
+ if (.not.extends_type_of (mat2, var0%au2)) error stop 178
+ if (.not.extends_type_of (mat, var0%au2)) error stop 179
+
+ if (same_type_as (mat, at)) error stop 180
+ if (same_type_as (mat2, at)) error stop 181
+ if (same_type_as (mat, at2)) error stop 182
+ if (.not.extends_type_of (mat, at)) error stop 183
+ if (.not.extends_type_of (mat2, at)) error stop 184
+ if (.not.extends_type_of (mat, at2)) error stop 185
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_33.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_33.f90
new file mode 100644
index 0000000..8bb8864
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_33.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! PR fortran/101349 - ICE in gfc_get_descriptor_field
+! Check constraint F2008:C628 / F2018:C932
+
+subroutine s(x)
+ class(*) :: x(:)
+ allocate (x, source=['abc']) ! { dg-error "must be ALLOCATABLE or a POINTER" }
+end
+
+subroutine t(x)
+ class(*), allocatable :: x(:)
+ allocate (x, source=['abc'])
+end
+
+subroutine u(x)
+ class(*), pointer :: x(:)
+ allocate (x, source=['abc'])
+end
diff --git a/gcc/testsuite/gnat.dg/asan1.adb b/gcc/testsuite/gnat.dg/asan1.adb
index a4bc59a..26bc1a4 100644
--- a/gcc/testsuite/gnat.dg/asan1.adb
+++ b/gcc/testsuite/gnat.dg/asan1.adb
@@ -1,7 +1,7 @@
-- { dg-do compile }
-- { dg-additional-sources asan1_pkg.ads }
-- { dg-options "-fsanitize=address" }
--- { dg-skip-if "" no_fsanitize_address }
+-- { dg-skip-if "no address sanitizer" { no_fsanitize_address } }
with Asan1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/enum_rep2.adb b/gcc/testsuite/gnat.dg/enum_rep2.adb
new file mode 100644
index 0000000..6554ad4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/enum_rep2.adb
@@ -0,0 +1,117 @@
+-- { dg-do compile }
+
+with Ada.Integer_Text_IO;
+with Ada.Text_IO;
+
+procedure Enum_Rep2 is
+
+ type T is
+ (E80, E81, E82, E83, E84, E85, E86, E87, E88, E89, E8A, E8B, E8C, E8D, E8E, E8F,
+ E90, E91, E92, E93, E94, E95, E96, E97, E98, E99, E9A, E9B, E9C, E9D, E9E, E9F,
+ EA0, EA1, EA2, EA3, EA4, EA5, EA6, EA7, EA8, EA9, EAA, EAB, EAC, EAD, EAE, EAF,
+ EB0, EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EBA, EBB, EBC, EBD, EBE, EBF,
+ EC0, EC1, EC2, EC3, EC4, EC5, EC6, EC7, EC8, EC9, ECA, ECB, ECC, ECD, ECE, ECF,
+ ED0, ED1, ED2, ED3, ED4, ED5, ED6, ED7, ED8, ED9, EDA, EDB, EDC, EDD, EDE, EDF,
+ EE0, EE1, EE2, EE3, EE4, EE5, EE6, EE7, EE8, EE9, EEA, EEB, EEC, EED, EEE, EEF,
+ EF0, EF1, EF2, EF3, EF4, EF5, EF6, EF7, EF8, EF9, EFA, EFB, EFC, EFD, EFE, EFF,
+ E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E0A, E0B, E0C, E0D, E0E, E0F,
+ E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E1A, E1B, E1C, E1D, E1E, E1F,
+ E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E2A, E2B, E2C, E2D, E2E, E2F,
+ E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E3A, E3B, E3C, E3D, E3E, E3F,
+ E40, E41, E42, E43, E44, E45, E46, E47, E48, E49, E4A, E4B, E4C, E4D, E4E, E4F,
+ E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E5A, E5B, E5C, E5D, E5E, E5F,
+ E60, E61, E62, E63, E64, E65, E66, E67, E68, E69, E6A, E6B, E6C, E6D, E6E, E6F,
+ E70, E71, E72, E73, E74, E75, E76, E77, E78, E79, E7A, E7B, E7C, E7D, E7E, E7F);
+ for T use
+ (E80 => -16#80#, E81 => -16#7F#, E82 => -16#7E#, E83 => -16#7D#,
+ E84 => -16#7C#, E85 => -16#7B#, E86 => -16#7A#, E87 => -16#79#,
+ E88 => -16#78#, E89 => -16#77#, E8A => -16#76#, E8B => -16#75#,
+ E8C => -16#74#, E8D => -16#73#, E8E => -16#72#, E8F => -16#71#,
+
+ E90 => -16#70#, E91 => -16#6F#, E92 => -16#6E#, E93 => -16#6D#,
+ E94 => -16#6C#, E95 => -16#6B#, E96 => -16#6A#, E97 => -16#69#,
+ E98 => -16#68#, E99 => -16#67#, E9A => -16#66#, E9B => -16#65#,
+ E9C => -16#64#, E9D => -16#63#, E9E => -16#62#, E9F => -16#61#,
+
+ EA0 => -16#60#, EA1 => -16#5F#, EA2 => -16#5E#, EA3 => -16#5D#,
+ EA4 => -16#5C#, EA5 => -16#5B#, EA6 => -16#5A#, EA7 => -16#59#,
+ EA8 => -16#58#, EA9 => -16#57#, EAA => -16#56#, EAB => -16#55#,
+ EAC => -16#54#, EAD => -16#53#, EAE => -16#52#, EAF => -16#51#,
+
+ EB0 => -16#50#, EB1 => -16#4F#, EB2 => -16#4E#, EB3 => -16#4D#,
+ EB4 => -16#4C#, EB5 => -16#4B#, EB6 => -16#4A#, EB7 => -16#49#,
+ EB8 => -16#48#, EB9 => -16#47#, EBA => -16#46#, EBB => -16#45#,
+ EBC => -16#44#, EBD => -16#43#, EBE => -16#42#, EBF => -16#41#,
+
+ EC0 => -16#40#, EC1 => -16#3F#, EC2 => -16#3E#, EC3 => -16#3D#,
+ EC4 => -16#3C#, EC5 => -16#3B#, EC6 => -16#3A#, EC7 => -16#39#,
+ EC8 => -16#38#, EC9 => -16#37#, ECA => -16#36#, ECB => -16#35#,
+ ECC => -16#34#, ECD => -16#33#, ECE => -16#32#, ECF => -16#31#,
+
+ ED0 => -16#30#, ED1 => -16#2F#, ED2 => -16#2E#, ED3 => -16#2D#,
+ ED4 => -16#2C#, ED5 => -16#2B#, ED6 => -16#2A#, ED7 => -16#29#,
+ ED8 => -16#28#, ED9 => -16#27#, EDA => -16#26#, EDB => -16#25#,
+ EDC => -16#24#, EDD => -16#23#, EDE => -16#22#, EDF => -16#21#,
+
+ EE0 => -16#20#, EE1 => -16#1F#, EE2 => -16#1E#, EE3 => -16#1D#,
+ EE4 => -16#1C#, EE5 => -16#1B#, EE6 => -16#1A#, EE7 => -16#19#,
+ EE8 => -16#18#, EE9 => -16#17#, EEA => -16#16#, EEB => -16#15#,
+ EEC => -16#14#, EED => -16#13#, EEE => -16#12#, EEF => -16#11#,
+
+ EF0 => -16#10#, EF1 => -16#0F#, EF2 => -16#0E#, EF3 => -16#0D#,
+ EF4 => -16#0C#, EF5 => -16#0B#, EF6 => -16#0A#, EF7 => -16#09#,
+ EF8 => -16#08#, EF9 => -16#07#, EFA => -16#06#, EFB => -16#05#,
+ EFC => -16#04#, EFD => -16#03#, EFE => -16#02#, EFF => -16#01#,
+
+ E00 => 16#00#, E01 => 16#01#, E02 => 16#02#, E03 => 16#03#,
+ E04 => 16#04#, E05 => 16#05#, E06 => 16#06#, E07 => 16#07#,
+ E08 => 16#08#, E09 => 16#09#, E0A => 16#0A#, E0B => 16#0B#,
+ E0C => 16#0C#, E0D => 16#0D#, E0E => 16#0E#, E0F => 16#0F#,
+
+ E10 => 16#10#, E11 => 16#11#, E12 => 16#12#, E13 => 16#13#,
+ E14 => 16#14#, E15 => 16#15#, E16 => 16#16#, E17 => 16#17#,
+ E18 => 16#18#, E19 => 16#19#, E1A => 16#1A#, E1B => 16#1B#,
+ E1C => 16#1C#, E1D => 16#1D#, E1E => 16#1E#, E1F => 16#1F#,
+
+ E20 => 16#20#, E21 => 16#21#, E22 => 16#22#, E23 => 16#23#,
+ E24 => 16#24#, E25 => 16#25#, E26 => 16#26#, E27 => 16#27#,
+ E28 => 16#28#, E29 => 16#29#, E2A => 16#2A#, E2B => 16#2B#,
+ E2C => 16#2C#, E2D => 16#2D#, E2E => 16#2E#, E2F => 16#2F#,
+
+ E30 => 16#30#, E31 => 16#31#, E32 => 16#32#, E33 => 16#33#,
+ E34 => 16#34#, E35 => 16#35#, E36 => 16#36#, E37 => 16#37#,
+ E38 => 16#38#, E39 => 16#39#, E3A => 16#3A#, E3B => 16#3B#,
+ E3C => 16#3C#, E3D => 16#3D#, E3E => 16#3E#, E3F => 16#3F#,
+
+ E40 => 16#40#, E41 => 16#41#, E42 => 16#42#, E43 => 16#43#,
+ E44 => 16#44#, E45 => 16#45#, E46 => 16#46#, E47 => 16#47#,
+ E48 => 16#48#, E49 => 16#49#, E4A => 16#4A#, E4B => 16#4B#,
+ E4C => 16#4C#, E4D => 16#4D#, E4E => 16#4E#, E4F => 16#4F#,
+
+ E50 => 16#50#, E51 => 16#51#, E52 => 16#52#, E53 => 16#53#,
+ E54 => 16#54#, E55 => 16#55#, E56 => 16#56#, E57 => 16#57#,
+ E58 => 16#58#, E59 => 16#59#, E5A => 16#5A#, E5B => 16#5B#,
+ E5C => 16#5C#, E5D => 16#5D#, E5E => 16#5E#, E5F => 16#5F#,
+
+ E60 => 16#60#, E61 => 16#61#, E62 => 16#62#, E63 => 16#63#,
+ E64 => 16#64#, E65 => 16#65#, E66 => 16#66#, E67 => 16#67#,
+ E68 => 16#68#, E69 => 16#69#, E6A => 16#6A#, E6B => 16#6B#,
+ E6C => 16#6C#, E6D => 16#6D#, E6E => 16#6E#, E6F => 16#6F#,
+
+ E70 => 16#70#, E71 => 16#71#, E72 => 16#72#, E73 => 16#73#,
+ E74 => 16#74#, E75 => 16#75#, E76 => 16#76#, E77 => 16#77#,
+ E78 => 16#78#, E79 => 16#79#, E7A => 16#7A#, E7B => 16#7B#,
+ E7C => 16#7C#, E7D => 16#7D#, E7E => 16#7E#, E7F => 16#7F#);
+ for T'Size use 8;
+
+ procedure Print (X : T) is
+ begin
+ Ada.Integer_Text_IO.Put (T'Pos (X));
+ Ada.Integer_Text_IO.Put (T'Enum_Rep (X));
+ Ada.Text_IO.New_Line;
+ end;
+
+begin
+ Print (T'First);
+ Print (T'Last);
+end;
diff --git a/gcc/testsuite/gnat.dg/unroll1.adb b/gcc/testsuite/gnat.dg/unroll1.adb
index 34d8a8f..8b732dd 100644
--- a/gcc/testsuite/gnat.dg/unroll1.adb
+++ b/gcc/testsuite/gnat.dg/unroll1.adb
@@ -1,5 +1,5 @@
-- { dg-do compile }
--- { dg-options "-O2 -funroll-all-loops -fdump-rtl-loop2_unroll-details -fdump-tree-cunrolli-details" }
+-- { dg-options "-O2 -funroll-all-loops -fno-tree-vectorize -fdump-rtl-loop2_unroll-details -fdump-tree-cunrolli-details" }
package body Unroll1 is
diff --git a/gcc/testsuite/gnat.dg/zcur_attr.adb b/gcc/testsuite/gnat.dg/zcur_attr.adb
new file mode 100644
index 0000000..5d15f5e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/zcur_attr.adb
@@ -0,0 +1,8 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-optimized" }
+
+package body ZCUR_Attr is
+ function F return Integer is (0);
+end ZCUR_Attr;
+
+-- { dg-final { scan-tree-dump "zero_call_used_regs \[(\]\"all\"\[)\]" "optimized" } }
diff --git a/gcc/testsuite/gnat.dg/zcur_attr.ads b/gcc/testsuite/gnat.dg/zcur_attr.ads
new file mode 100644
index 0000000..b756cc8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/zcur_attr.ads
@@ -0,0 +1,4 @@
+package ZCUR_Attr is
+ function F return Integer;
+ pragma Machine_Attribute (F, "zero_call_used_regs", "all");
+end ZCUR_Attr;
diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 005ba01..10b98bd 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -167,6 +167,9 @@ proc fixed_host_execute {args} {
if {![file exists ${executable}]} {
perror "The executable, \"$executable\" is missing" 0
return "No source file found"
+ } elseif {![file executable ${executable}]} {
+ perror "The executable, \"$executable\" is not usable" 0
+ return "Bad executable found"
}
verbose "params: $params" 2
@@ -194,84 +197,125 @@ proc fixed_host_execute {args} {
set args [concat $args ${params}]
verbose "args: $args" 2
- eval spawn -noecho $args
-
- expect_after full_buffer { error "got full_buffer" }
+ # We checked that the executable exists above, and can be executed, but
+ # that does not cover other reasons that the launch could fail (e.g.
+ # missing or malformed params); catch such cases here and report them.
+ set err [catch "spawn -noecho $args" pid]
+ set sub_proc_id $spawn_id
+ if { $pid <= 0 || $err != 0 || $sub_proc_id < 0 } {
+ warning "failed to spawn : $args : err = $err"
+ }
+
+ # Increase the buffer size, if needed to avoid spurious buffer-full
+ # events; GCC uses 10000; chose a power of two here.
+ set current_max_match [match_max -i $sub_proc_id]
+ if { $current_max_match < 8192 } {
+ match_max -i $sub_proc_id 8192
+ set used [match_max -i $sub_proc_id]
+ }
+
+ # If we get a buffer-full error, that seems to be unrecoverable so try to
+ # exit in a reasonable manner to avoid wedged processes.
+ expect_after full_buffer {
+ verbose -log "fixed_host_execute: $args FULL BUFFER"
+ # FIXME: this all assumes that closing the connection will cause the
+ # sub-process to terminate (but that is not going to be the case if,
+ # for example, there is something started with -nohup somewhere).
+ # We should explicitly kill it here.
+ # Set the process to be a nowait exit.
+ wait -nowait -i $sub_proc_id
+ catch close
+ perror "${executable} got full_buffer"
+ return "${executable} got full_buffer"
+ }
set prefix "\[^\r\n\]*"
+ # Work around a Darwin tcl or termios bug that sometimes inserts extra
+ # CR characters into the cooked tty stream
+ set endline "\r\n"
+ if { [istarget *-*-darwin*] } {
+ set endline "\r(\r)*\n"
+ }
+
+ # Note that the logic here assumes that we cannot (validly) get single
+ # carriage return or line feed characters in the stream. If those occur,
+ # it will stop any further matching. We arange for the matching to be
+ # at the start of the buffer - so that if there is any spurious output
+ # to be discarded, it must be done explicitly - not by matching part-way
+ # through the buffer.
expect {
- -re "^$prefix\[0-9\]\[0-9\]:..:..:${text}*\r\n" {
+ -re "^$prefix\[0-9\]\[0-9\]:..:..:${text}*$endline" {
regsub "\[\n\r\t\]*NOTE: $text\r\n" $expect_out(0,string) "" output
verbose "$output" 3
set timetol 0
exp_continue
}
- -re "^$prefix\tNOTE:\[^\r\n\]+\r\n" {
- regsub "\[\n\r\t\]*NOTE: $text\r\n" $expect_out(0,string) "" output
- set output [string range $output 6 end-2]
- verbose "$output" 2
+ -re "^\tNOTE: (\[^\r\n\]+)$endline" {
+ # discard notes.
+ verbose "Ignored note: $expect_out(1,string)" 2
set timetol 0
exp_continue
}
- -re "^$prefix\tPASSED:\[^\r\n\]+\r\n" {
- regsub "\[\n\r\t\]*PASSED: $text\r\n" $expect_out(0,string) "" output
- set output [string range $output 8 end-2]
- pass "$output"
+ -re "^\tPASSED: (\[^\r\n\]+)$endline" {
+ pass "$expect_out(1,string)"
set timetol 0
exp_continue
}
- -re "^$prefix\tFAILED:\[^\r\n\]+\r\n" {
- regsub "\[\n\r\t\]*FAILED: $text\r\n" $expect_out(0,string) "" output
- set output [string range $output 8 end-2]
- fail "$output"
+ -re "^\tFAILED: (\[^\r\n\]+)$endline" {
+ fail "$expect_out(1,string)"
set timetol 0
exp_continue
}
- -re "^$prefix\tUNTESTED:\[^\r\n\]+\r\n" {
- regsub "\[\n\r\t\]*TESTED: $text\r\n" $expect_out(0,string) "" output
- set output [string range $output 8 end-2]
- untested "$output"
+ -re "^\tUNTESTED: (\[^\r\n\]+)$endline" {
+ untested "$expect_out(1,string)"
set timetol 0
exp_continue
}
- -re "^$prefix\tUNRESOLVED:\[^\r\n\]+\r\n" {
- regsub "\[\n\r\t\]*UNRESOLVED: $text\r\n" $expect_out(0,string) "" output
- set output [string range $output 8 end-2]
- unresolved "$output"
+ -re "^\tUNRESOLVED: (\[^\r\n\]+)$endline" {
+ unresolved "$expect_out(1,string)"
set timetol 0
exp_continue
}
- -re "^Totals" {
- verbose "All done" 2
+ -re "^$prefix$endline" {
+ # This matches and discards any other lines (including blank ones).
+ if { [string length $expect_out(buffer)] <= 2 } {
+ set output "blank line"
+ } else {
+ set output [string range $expect_out(buffer) 0 end-2]
+ }
+ verbose -log "DISCARDED $expect_out(spawn_id) : $output"
+ exp_continue
}
eof {
- # unresolved "${executable} died prematurely"
- # catch close
- # return "${executable} died prematurely"
+ # This seems to be the only way that we can reliably know that the
+ # output is finished since there are cases where further output
+ # follows the dejagnu test harness totals.
+ verbose "saw eof" 2
}
timeout {
- warning "Timed out executing test case"
if { $timetol <= 2 } {
+ verbose -log "Timed out with retry (timeout = $timeout)"
incr timetol
exp_continue
} else {
+ warning "Timed out executing testcase (timeout = $timeout)"
catch close
return "Timed out executing test case"
}
}
- -re "^$prefix\r\n" {
- exp_continue
- }
}
- # Use "wait" before "close": valgrind might not have finished
- # writing the log out before we parse it, so we need to wait for
- # the spawnee to finish.
-
- catch wait wres
- verbose "wres: $wres" 2
- verify_exit_status $executable $wres
-
+ # Use "wait" to pick up the sub-process exit state. If the sub-process is
+ # writing to a file (perhaps under valgrind) then that also needs to be
+ # complete; only attempt this on a valid spawn.
+ if { $sub_proc_id > 0 } {
+ verbose "waiting for $sub_proc_id" 1
+ # Be explicit about what we are waiting for.
+ catch "wait -i $sub_proc_id" wres
+ verbose "wres: $wres" 2
+ verify_exit_status $executable $wres
+ }
+
if $run_under_valgrind {
upvar 2 name name
parse_valgrind_logfile $name $valgrind_logfile
@@ -377,6 +421,34 @@ proc dg-jit-set-exe-params { args } {
}
}
+# For test-debuginfo.c. Starts gdb, does cmds and checks the output against match
+proc jit-check-debug-info { obj_file cmds match } {
+ verbose "Checking debug info for $obj_file with match: $match"
+
+ if { [catch {exec gdb -v} fid] } {
+ verbose "No gdb seems to be in path. Can't check debug info. Reporting 'unsupported'."
+ unsupported "No gdb seems to be in path. Can't check debug info"
+ return
+ }
+
+ spawn gdb $obj_file
+
+ verbose "Disable color styling in GDB newer then 8.3 (errors on older)"
+ send "set style enabled off\n"
+
+ foreach cmd $cmds {
+ send $cmd
+ }
+ expect {
+ -re $match { pass OK }
+ default { fail FAIL }
+ }
+
+ # Quit gdb
+ send "set confirm off\n"
+ send "q\n"
+}
+
proc jit-dg-test { prog do_what extra_tool_flags } {
verbose "within jit-dg-test..."
verbose " prog: $prog"
diff --git a/gcc/testsuite/jit.dg/test-debuginfo.c b/gcc/testsuite/jit.dg/test-debuginfo.c
new file mode 100644
index 0000000..49e8834
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-debuginfo.c
@@ -0,0 +1,72 @@
+/* Essentially this test checks that debug info are generated for globals
+ locals and functions, including type info. The comment bellow is used
+ as fake code (does not affect the test, use for manual debugging). */
+/*
+int a_global_for_test_debuginfo;
+int main (int argc, char **argv)
+{
+ int a_local_for_test_debuginfo = 2;
+ return a_global_for_test_debuginfo + a_local_for_test_debuginfo;
+}
+*/
+#include "libgccjit.h"
+
+/* We don't want set_options() in harness.h to set -O3 so our little local
+ is optimized away. */
+#define TEST_ESCHEWS_SET_OPTIONS
+static void set_options (gcc_jit_context *ctxt, const char *argv0)
+{
+ gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
+}
+
+#define TEST_COMPILING_TO_FILE
+#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_EXECUTABLE
+#define OUTPUT_FILENAME "jit-debuginfo.o"
+#include "harness.h"
+
+#define LOC(row, col) gcc_jit_context_new_location(ctxt, "test-debuginfo.c", row, col)
+
+void
+create_code (gcc_jit_context *ctxt, void* p)
+{
+ gcc_jit_type *int_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_lvalue *bar = gcc_jit_context_new_global(ctxt,
+ LOC(5,1), GCC_JIT_GLOBAL_EXPORTED,
+ int_type, "a_global_for_test_debuginfo");
+
+ gcc_jit_param *argc_para = gcc_jit_context_new_param(ctxt, LOC(6,15),
+ int_type, "argc");
+ gcc_jit_param *argv_para = gcc_jit_context_new_param(ctxt, LOC(6,28),
+ gcc_jit_type_get_pointer(
+ gcc_jit_type_get_pointer(
+ gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_CHAR))),
+ "argc");
+
+ gcc_jit_param *params[] = {argc_para, argv_para};
+
+ gcc_jit_function *foo_fn = gcc_jit_context_new_function(ctxt, LOC(6,5),
+ GCC_JIT_FUNCTION_EXPORTED, int_type, "main", 2, params, 0);
+ gcc_jit_block *start_block = gcc_jit_function_new_block(foo_fn,
+ "start_block");
+
+ gcc_jit_lvalue *a = gcc_jit_function_new_local(foo_fn, LOC(8,5),
+ int_type, "a_local_for_test_debuginfo");
+ gcc_jit_block_add_assignment(start_block, LOC(8,36), a,
+ gcc_jit_context_new_rvalue_from_int(ctxt, int_type, 2));
+ gcc_jit_rvalue *add = gcc_jit_context_new_binary_op(ctxt, LOC(9,40),
+ GCC_JIT_BINARY_OP_PLUS, int_type,
+ gcc_jit_lvalue_as_rvalue(a), gcc_jit_lvalue_as_rvalue(bar));
+
+ gcc_jit_block_end_with_return(start_block, LOC(9,5), add);
+}
+
+#undef LOC
+
+/* jit-check-debug-info fires up gdb and checks that the variables have
+ debug info */
+
+/* { dg-final { jit-check-debug-info "jit-debuginfo.o" {"info variables\n"} "int\\s+a_global_for_test_debuginfo;" } } */
+/* { dg-final { jit-check-debug-info "jit-debuginfo.o" {"pt main\n"} "int\\s*\\(\\s*int\\s*,\\s*char\\s*\\*\\*\\s*\\)"} } */
+/* { dg-final { jit-check-debug-info "jit-debuginfo.o" {"start\n" "info locals\n"} "a_local_for_test_debuginfo"} } */
+/* { dg-final { jit-check-debug-info "jit-debuginfo.o" {"start\n" "pt a_local_for_test_debuginfo\n"} "int"} } */ \ No newline at end of file
diff --git a/gcc/testsuite/jit.dg/test-error-array-bounds.c b/gcc/testsuite/jit.dg/test-error-array-bounds.c
index cd9361f..b6c0ee5 100644
--- a/gcc/testsuite/jit.dg/test-error-array-bounds.c
+++ b/gcc/testsuite/jit.dg/test-error-array-bounds.c
@@ -70,5 +70,5 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
/* ...and that the message was captured by the API. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
"array subscript 10 is above array bounds of"
- " 'unsigned char[10]' [-Warray-bounds]");
+ " 'char[10]' [-Warray-bounds]");
}
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 91f165b..1314248 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -37,6 +37,9 @@ proc prune_gcc_output { text } {
# Handle any freeform regexps.
set text [handle-dg-regexps $text]
+ # Remove Windows .exe suffix
+ regsub -all "(as|cc1|cc1plus|collect2|f951|ld|lto-wrapper)\.exe?:" $text {\1:} text
+
regsub -all "(^|\n)(\[^\n\]*: \[iI\]|I)n ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|substitution|program|subroutine|block-data)\[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*(: )?At (top level|global scope):\[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*: (recursively )?required \[^\n\]*" $text "" text
@@ -90,6 +93,9 @@ proc prune_gcc_output { text } {
# Ignore dsymutil warning (tool bug is actually linker)
regsub -all "(^|\n)\[^\n\]*could not find object file symbol for symbol\[^\n\]*" $text "" text
+ # Ignore stabs obsoletion warnings
+ regsub -all "(^|\n)\[^\n\]*\[Ww\]arning: STABS debugging information is obsolete and not supported anymore\[^\n\]*" $text "" text
+
# If dg-enable-nn-line-numbers was provided, then obscure source-margin
# line numbers by converting them to "NN" form.
set text [maybe-handle-nn-line-numbers $text]
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 350dbdb..9ebca7a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1576,6 +1576,22 @@ proc check_effective_target_fortran_real_10 { } {
}]
}
+# Return 1 if the target supports Fortran real kind C_FLOAT128,
+# 0 otherwise. This differs from check_effective_target_fortran_real_16
+# because _Float128 has the additional requirement that it be the
+# 128-bit IEEE encoding; even if _Float128 is available in C, it may not
+# have a corresponding Fortran kind on targets (PowerPC) that use some
+# other encoding for long double/TFmode/real(16).
+proc check_effective_target_fortran_real_c_float128 { } {
+ return [check_no_compiler_messages fortran_real_c_float128 executable {
+ ! Fortran
+ use iso_c_binding
+ real(kind=c_float128) :: x
+ x = cos (x)
+ end
+ }]
+}
+
# Return 1 if the target supports Fortran's IEEE modules,
# 0 otherwise.
#
@@ -3148,7 +3164,7 @@ proc check_effective_target_has_q_floating_suffix { } {
proc check_effective_target_float16 {} {
return [check_no_compiler_messages_nocache float16 object {
- _Float16 x;
+ _Float16 foo (_Float16 x) { return x; }
} [add_options_for_float16 ""]]
}
@@ -8058,7 +8074,7 @@ proc check_effective_target_sync_int_128_runtime { } {
# Note: 32bit s390 targets require -mzarch in dg-options.
proc check_effective_target_sync_long_long { } {
- if { [istarget i?86-*-*] || [istarget x86_64-*-*])
+ if { [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget aarch64*-*-*]
|| [istarget arm*-*-*]
|| [istarget alpha*-*-*]
@@ -8861,6 +8877,17 @@ proc check_prefer_avx128 { } {
}
+# Return 1 if avx512fp16 instructions can be compiled.
+
+proc check_effective_target_avx512fp16 { } {
+ return [check_no_compiler_messages avx512fp16 object {
+ void foo (void)
+ {
+ asm volatile ("vmovw %edi, %xmm0");
+ }
+ } "-O2 -mavx512fp16" ]
+}
+
# Return 1 if avx512f instructions can be compiled.
proc check_effective_target_avx512f { } {
@@ -9601,7 +9628,14 @@ proc check_effective_target_gas { } {
set status [remote_exec host "$gcc_as" "-v /dev/null"]
set as_output [lindex $status 1]
if { [ string first "GNU" $as_output ] >= 0 } {
- set use_gas_saved 1
+ # Some Darwin versions have an assembler which is based on an old
+ # version of GAS (and reports GNU assembler in its -v output) but
+ # but doesn't support many of the modern GAS features.
+ if { [ string first "cctools" $as_output ] >= 0 } {
+ set use_gas_saved 0
+ } else {
+ set use_gas_saved 1
+ }
} else {
set use_gas_saved 0
}
@@ -11217,14 +11251,15 @@ proc check_effective_target_movdir { } {
} "-mmovdiri -mmovdir64b" ]
}
-# Return 1 if target is not support address sanitize, 1 otherwise.
+# Return 1 if the target does not support address sanitizer, 0 otherwise
proc check_effective_target_no_fsanitize_address {} {
if ![check_no_compiler_messages fsanitize_address executable {
int main (void) { return 0; }
- }] {
+ } "-fsanitize=address" ] {
return 1;
}
+
return 0;
}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-1.mm
new file mode 100644
index 0000000..e5708c2
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-1.mm
@@ -0,0 +1,34 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) method;
+- (int) method;
++ (int) unavailableClassMethod __attribute__((unavailable));
+- (int) unavailableInstanceMethod __attribute__((unavailable));
+@end
+
+/* Test that deprecation warnings are produced, but not if the
+ receiver is of type 'id'. */
+void foo (void)
+{
+ Class c;
+ id object;
+ MyClass *another_object;
+
+ [c method];
+ [object method];
+ [c unavailableClassMethod];
+ [object unavailableInstanceMethod];
+
+ [object method];
+ [another_object method];
+ [MyClass unavailableClassMethod]; /* { dg-error "is unavailable" } */
+ [another_object unavailableInstanceMethod]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-2.mm b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-2.mm
new file mode 100644
index 0000000..68ea46d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-2.mm
@@ -0,0 +1,24 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) unavailableClassMethod: (id)firstObject, ... __attribute__((sentinel)) __attribute__((unavailable));
+- (int) unavailableInstanceMethod: (id)firstobject, ... __attribute__((sentinel)) __attribute__((unavailable));
+@end
+
+/* Test that unavailability errors are produced even if the method is
+ also marked with another attribute too (this is to test the
+ processing of multiple attributes). */
+void foo (void)
+{
+ MyClass *object = nil;
+
+ [MyClass unavailableClassMethod: object, nil]; /* { dg-error "is unavailable" } */
+ [object unavailableInstanceMethod: object, nil]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-3.mm b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-3.mm
new file mode 100644
index 0000000..9e55ae1
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-unavailable-3.mm
@@ -0,0 +1,22 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+/* Test that __attribute__ ((__unavailable__)) works as well as __attribute__ ((unavailable)). */
+@interface MyClass
+{
+ Class isa;
+}
++ (int) unavailableClassMethod: (id)firstObject, ... __attribute__((__unavailable__));
+- (int) unavailableInstanceMethod: (id)firstobject, ... __attribute__((__unavailable__));
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+ [MyClass unavailableClassMethod: object, nil]; /* { dg-error "is unavailable" } */
+ [object unavailableInstanceMethod: object, nil]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-1.mm b/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-1.mm
new file mode 100644
index 0000000..6bb4755
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-1.mm
@@ -0,0 +1,38 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* Test that properties can be unavailable. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a __attribute__((unavailable));
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 40; /* { dg-error "is unavailable" } */
+ if (object.a != 40) /* { dg-error "is unavailable" } */
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-2.mm b/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-2.mm
new file mode 100644
index 0000000..5edc162
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-unavailable-2.mm
@@ -0,0 +1,26 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* Test that unavailability errors are produced when a setter/getter of
+ a @property is used directly. */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+ int variable;
+}
+@property (assign, nonatomic) int property __attribute__ ((unavailable));
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+ if ([object property] > 0) /* { dg-error "is unavailable" } */
+ {
+ [object setProperty: 43]; /* { dg-error "is unavailable" } */
+ }
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-unavailable-1.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-unavailable-1.mm
new file mode 100644
index 0000000..e2ef2a5
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-unavailable-1.mm
@@ -0,0 +1,42 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* Test the 'dot syntax' with unavailable methods. */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) classCount __attribute__ ((unavailable));
++ (void) setClassCount: (int)value __attribute__ ((unavailable));
+
+- (int) count __attribute__ ((unavailable));
+- (void) setCount: (int)value __attribute__ ((unavailable));
+
+- (int) classCount2;
+- (void) setClassCount2: (int)value;
+
+- (int) count2;
+- (void) setCount2: (int)value;
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+
+ if (object.count > 0) /* { dg-error "is unavailable" } */
+ object.count = 20; /* { dg-error "is unavailable" } */
+
+ if (MyClass.classCount < -7) /* { dg-error "is unavailable" } */
+ MyClass.classCount = 11; /* { dg-error "is unavailable" } */
+
+ if (object.classCount2 > 0)
+ object.classCount2 = 19;
+
+ if (object.count2 < -7)
+ object.count2 = 74;
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-unavailable-1.m b/gcc/testsuite/objc.dg/attributes/method-unavailable-1.m
new file mode 100644
index 0000000..7a3de6b
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/method-unavailable-1.m
@@ -0,0 +1,34 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) method;
+- (int) method;
++ (int) unavailableClassMethod __attribute__((unavailable));
+- (int) unavailableInstanceMethod __attribute__((unavailable));
+@end
+
+/* Test that unavailability errors are produced, but not if the
+ receiver is of type 'id'. */
+void foo (void)
+{
+ Class c;
+ id object;
+ MyClass *another_object;
+
+ [c method];
+ [object method];
+ [c unavailableClassMethod];
+ [object unavailableInstanceMethod];
+
+ [object method];
+ [another_object method];
+ [MyClass unavailableClassMethod]; /* { dg-error "is unavailable" } */
+ [another_object unavailableInstanceMethod]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-unavailable-2.m b/gcc/testsuite/objc.dg/attributes/method-unavailable-2.m
new file mode 100644
index 0000000..68ea46d
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/method-unavailable-2.m
@@ -0,0 +1,24 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) unavailableClassMethod: (id)firstObject, ... __attribute__((sentinel)) __attribute__((unavailable));
+- (int) unavailableInstanceMethod: (id)firstobject, ... __attribute__((sentinel)) __attribute__((unavailable));
+@end
+
+/* Test that unavailability errors are produced even if the method is
+ also marked with another attribute too (this is to test the
+ processing of multiple attributes). */
+void foo (void)
+{
+ MyClass *object = nil;
+
+ [MyClass unavailableClassMethod: object, nil]; /* { dg-error "is unavailable" } */
+ [object unavailableInstanceMethod: object, nil]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-unavailable-3.m b/gcc/testsuite/objc.dg/attributes/method-unavailable-3.m
new file mode 100644
index 0000000..9e55ae1
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/method-unavailable-3.m
@@ -0,0 +1,22 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include <objc/objc.h>
+
+/* Test that __attribute__ ((__unavailable__)) works as well as __attribute__ ((unavailable)). */
+@interface MyClass
+{
+ Class isa;
+}
++ (int) unavailableClassMethod: (id)firstObject, ... __attribute__((__unavailable__));
+- (int) unavailableInstanceMethod: (id)firstobject, ... __attribute__((__unavailable__));
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+ [MyClass unavailableClassMethod: object, nil]; /* { dg-error "is unavailable" } */
+ [object unavailableInstanceMethod: object, nil]; /* { dg-error "is unavailable" } */
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-unavailable-1.m b/gcc/testsuite/objc.dg/property/at-property-unavailable-1.m
new file mode 100644
index 0000000..c33e1b6
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-unavailable-1.m
@@ -0,0 +1,39 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
+
+/* Test that properties can be unavailable. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a __attribute__((unavailable));
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 40; /* { dg-error "is unavailable" } */
+ if (object.a != 40) /* { dg-error "is unavailable" } */
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-unavailable-2.m b/gcc/testsuite/objc.dg/property/at-property-unavailable-2.m
new file mode 100644
index 0000000..5edc162
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-unavailable-2.m
@@ -0,0 +1,26 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* Test that unavailability errors are produced when a setter/getter of
+ a @property is used directly. */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+ int variable;
+}
+@property (assign, nonatomic) int property __attribute__ ((unavailable));
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+ if ([object property] > 0) /* { dg-error "is unavailable" } */
+ {
+ [object setProperty: 43]; /* { dg-error "is unavailable" } */
+ }
+}
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-unavailable-1.m b/gcc/testsuite/objc.dg/property/dotsyntax-unavailable-1.m
new file mode 100644
index 0000000..e2ef2a5
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dotsyntax-unavailable-1.m
@@ -0,0 +1,42 @@
+/* Test __attribute__ ((unavailable)) */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* Test the 'dot syntax' with unavailable methods. */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ Class isa;
+}
++ (int) classCount __attribute__ ((unavailable));
++ (void) setClassCount: (int)value __attribute__ ((unavailable));
+
+- (int) count __attribute__ ((unavailable));
+- (void) setCount: (int)value __attribute__ ((unavailable));
+
+- (int) classCount2;
+- (void) setClassCount2: (int)value;
+
+- (int) count2;
+- (void) setCount2: (int)value;
+@end
+
+void foo (void)
+{
+ MyClass *object = nil;
+
+
+ if (object.count > 0) /* { dg-error "is unavailable" } */
+ object.count = 20; /* { dg-error "is unavailable" } */
+
+ if (MyClass.classCount < -7) /* { dg-error "is unavailable" } */
+ MyClass.classCount = 11; /* { dg-error "is unavailable" } */
+
+ if (object.classCount2 > 0)
+ object.classCount2 = 19;
+
+ if (object.count2 < -7)
+ object.count2 = 74;
+}
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 16d1657..f903833 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -158,6 +158,7 @@ DEFTIMEVAR (TV_TREE_CFG , "tree CFG construction")
DEFTIMEVAR (TV_TREE_CLEANUP_CFG , "tree CFG cleanup")
DEFTIMEVAR (TV_TREE_TAIL_MERGE , "tree tail merge")
DEFTIMEVAR (TV_TREE_VRP , "tree VRP")
+DEFTIMEVAR (TV_TREE_VRP_THREADER , "tree VRP threader")
DEFTIMEVAR (TV_TREE_EARLY_VRP , "tree Early VRP")
DEFTIMEVAR (TV_TREE_COPY_PROP , "tree copy propagation")
DEFTIMEVAR (TV_FIND_REFERENCED_VARS , "tree find ref. vars")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 14d1335..cb4f8c4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -104,8 +104,6 @@ along with GCC; see the file COPYING3. If not see
#endif
static void general_init (const char *, bool);
-static void do_compile ();
-static void process_options (void);
static void backend_init (void);
static int lang_dependent_init (const char *);
static void init_asm_output (const char *);
@@ -114,16 +112,12 @@ static void finalize (bool);
static void crash_signal (int) ATTRIBUTE_NORETURN;
static void compile_file (void);
-/* True if we don't need a backend (e.g. preprocessing only). */
-static bool no_backend;
-
/* Decoded options, and number of such options. */
struct cl_decoded_option *save_decoded_options;
unsigned int save_decoded_options_count;
-/* Used to enable -fvar-tracking, -fweb and -frename-registers according
- to optimize in process_options (). */
-#define AUTODETECT_VALUE 2
+/* Vector of saved Optimization decoded command line options. */
+vec<cl_decoded_option> *save_opt_decoded_options;
/* Debug hooks - dependent upon command line options. */
@@ -1230,7 +1224,7 @@ parse_alignment_opts (void)
/* Process the options that have been parsed. */
static void
-process_options (void)
+process_options (bool no_backend)
{
const char *language_string = lang_hooks.name;
/* Just in case lang_hooks.post_options ends up calling a debug_hook.
@@ -1239,12 +1233,6 @@ process_options (void)
maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
- /* Allow the front end to perform consistency checks and do further
- initialization based on the command line options. This hook also
- sets the original filename if appropriate (e.g. foo.i -> foo.c)
- so we can correctly initialize debug output. */
- no_backend = lang_hooks.post_options (&main_input_filename);
-
/* Some machines may reject certain combinations of options. */
location_t saved_location = input_location;
input_location = UNKNOWN_LOCATION;
@@ -1327,7 +1315,7 @@ process_options (void)
}
/* One region RA really helps to decrease the code size. */
- if (flag_ira_region == IRA_REGION_AUTODETECT)
+ if (!OPTION_SET_P (flag_ira_region))
flag_ira_region
= optimize_size || !optimize ? IRA_REGION_ONE : IRA_REGION_MIXED;
@@ -1339,13 +1327,6 @@ process_options (void)
flag_abi_version = 2;
}
- /* web and rename-registers help when run after loop unrolling. */
- if (flag_web == AUTODETECT_VALUE)
- flag_web = flag_unroll_loops;
-
- if (flag_rename_registers == AUTODETECT_VALUE)
- flag_rename_registers = flag_unroll_loops;
-
if (flag_non_call_exceptions)
flag_asynchronous_unwind_tables = 1;
if (flag_asynchronous_unwind_tables)
@@ -1416,14 +1397,16 @@ process_options (void)
debug_info_level = DINFO_LEVEL_NONE;
}
- /* CTF is supported for only C at this time.
- Compiling with -flto results in frontend language of GNU GIMPLE. */
+ /* CTF is supported for only C at this time. */
if (!lang_GNU_C ()
&& ctf_debug_info_level > CTFINFO_LEVEL_NONE)
{
- inform (UNKNOWN_LOCATION,
- "CTF debug info requested, but not supported for %qs frontend",
- language_string);
+ /* Compiling with -flto results in frontend language of GNU GIMPLE. It
+ is not useful to warn in that case. */
+ if (!startswith (lang_hooks.name, "GNU GIMPLE"))
+ inform (UNKNOWN_LOCATION,
+ "CTF debug info requested, but not supported for %qs frontend",
+ language_string);
ctf_debug_info_level = CTFINFO_LEVEL_NONE;
}
@@ -1452,6 +1435,11 @@ process_options (void)
&& ctf_debug_info_level == CTFINFO_LEVEL_NONE)
write_symbols = NO_DEBUG;
+ /* Warn if STABS debug gets enabled and is not the default. */
+ if (PREFERRED_DEBUGGING_TYPE != DBX_DEBUG && (write_symbols & DBX_DEBUG))
+ warning (0, "STABS debugging information is obsolete and not "
+ "supported anymore");
+
if (write_symbols == NO_DEBUG)
;
#if defined(DBX_DEBUGGING_INFO)
@@ -1496,8 +1484,9 @@ process_options (void)
|| !dwarf_debuginfo_p ()
|| debug_hooks->var_location == do_nothing_debug_hooks.var_location)
{
- if (flag_var_tracking == 1
- || flag_var_tracking_uninit == 1)
+ if ((OPTION_SET_P (flag_var_tracking) && flag_var_tracking == 1)
+ || (OPTION_SET_P (flag_var_tracking_uninit)
+ && flag_var_tracking_uninit == 1))
{
if (debug_info_level < DINFO_LEVEL_NORMAL)
warning_at (UNKNOWN_LOCATION, 0,
@@ -1518,19 +1507,11 @@ process_options (void)
if (flag_dump_go_spec != NULL)
debug_hooks = dump_go_spec_init (flag_dump_go_spec, debug_hooks);
- /* If the user specifically requested variable tracking with tagging
- uninitialized variables, we need to turn on variable tracking.
- (We already determined above that variable tracking is feasible.) */
- if (flag_var_tracking_uninit == 1)
- flag_var_tracking = 1;
-
- if (flag_var_tracking == AUTODETECT_VALUE)
- flag_var_tracking = optimize >= 1;
+ /* One could use EnabledBy, but it would lead to a circular dependency. */
+ if (!OPTION_SET_P (flag_var_tracking_uninit))
+ flag_var_tracking_uninit = flag_var_tracking;
- if (flag_var_tracking_uninit == AUTODETECT_VALUE)
- flag_var_tracking_uninit = flag_var_tracking;
-
- if (flag_var_tracking_assignments == AUTODETECT_VALUE)
+ if (!OPTION_SET_P (flag_var_tracking_assignments))
flag_var_tracking_assignments
= (flag_var_tracking
&& !(flag_selective_scheduling || flag_selective_scheduling2));
@@ -1546,21 +1527,19 @@ process_options (void)
warning_at (UNKNOWN_LOCATION, 0,
"var-tracking-assignments changes selective scheduling");
- if (debug_nonbind_markers_p == AUTODETECT_VALUE)
+ if (!OPTION_SET_P (debug_nonbind_markers_p))
debug_nonbind_markers_p
= (optimize
&& debug_info_level >= DINFO_LEVEL_NORMAL
&& dwarf_debuginfo_p ()
&& !(flag_selective_scheduling || flag_selective_scheduling2));
- if (dwarf2out_as_loc_support == AUTODETECT_VALUE)
- dwarf2out_as_loc_support
- = dwarf2out_default_as_loc_support ();
- if (dwarf2out_as_locview_support == AUTODETECT_VALUE)
- dwarf2out_as_locview_support
- = dwarf2out_default_as_locview_support ();
+ if (!OPTION_SET_P (dwarf2out_as_loc_support))
+ dwarf2out_as_loc_support = dwarf2out_default_as_loc_support ();
+ if (!OPTION_SET_P (dwarf2out_as_locview_support))
+ dwarf2out_as_locview_support = dwarf2out_default_as_locview_support ();
- if (debug_variable_location_views == AUTODETECT_VALUE)
+ if (!OPTION_SET_P (debug_variable_location_views))
{
debug_variable_location_views
= (flag_var_tracking
@@ -1594,7 +1573,7 @@ process_options (void)
debug_internal_reset_location_views = 0;
}
- if (debug_inline_points == AUTODETECT_VALUE)
+ if (!OPTION_SET_P (debug_inline_points))
debug_inline_points = debug_variable_location_views;
else if (debug_inline_points && !debug_nonbind_markers_p)
{
@@ -1604,7 +1583,7 @@ process_options (void)
debug_inline_points = 0;
}
- if (flag_tree_cselim == AUTODETECT_VALUE)
+ if (!OPTION_SET_P (flag_tree_cselim))
{
if (HAVE_conditional_move)
flag_tree_cselim = 1;
@@ -1695,14 +1674,6 @@ process_options (void)
flag_stack_check = NO_STACK_CHECK;
}
- /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
- if (flag_cx_limited_range)
- flag_complex_method = 0;
-
- /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
- if (flag_cx_fortran_rules)
- flag_complex_method = 1;
-
/* Targets must be able to place spill slots at lower addresses. If the
target already uses a soft frame pointer, the transition is trivial. */
if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
@@ -1767,7 +1738,7 @@ process_options (void)
/* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
have not been set. */
- if (!global_options_set.x_warnings_are_errors)
+ if (!OPTION_SET_P (warnings_are_errors))
{
if (warn_coverage_mismatch
&& (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
@@ -2150,10 +2121,8 @@ standard_type_bitsize (int bitsize)
/* Initialize the compiler, and compile the input file. */
static void
-do_compile ()
+do_compile (bool no_backend)
{
- process_options ();
-
/* Don't do any more if an error has already occurred. */
if (!seen_error ())
{
@@ -2282,11 +2251,6 @@ toplev::start_timevars ()
void
toplev::run_self_tests ()
{
- if (no_backend)
- {
- error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
- return;
- }
#if CHECKING_P
/* Reset some state. */
input_location = UNKNOWN_LOCATION;
@@ -2342,6 +2306,13 @@ toplev::main (int argc, char **argv)
&save_decoded_options,
&save_decoded_options_count);
+ /* Save Optimization decoded options. */
+ save_opt_decoded_options = new vec<cl_decoded_option> ();
+ for (unsigned i = 1; i < save_decoded_options_count; ++i)
+ if (save_decoded_options[i].opt_index < cl_options_count
+ && cl_options[save_decoded_options[i].opt_index].flags & CL_OPTIMIZATION)
+ save_opt_decoded_options->safe_push (save_decoded_options[i]);
+
/* Perform language-specific options initialization. */
lang_hooks.init_options (save_decoded_options_count, save_decoded_options);
@@ -2367,17 +2338,30 @@ toplev::main (int argc, char **argv)
/* Exit early if we can (e.g. -help). */
if (!exit_after_options)
{
+ /* Allow the front end to perform consistency checks and do further
+ initialization based on the command line options. This hook also
+ sets the original filename if appropriate (e.g. foo.i -> foo.c)
+ so we can correctly initialize debug output. */
+ bool no_backend = lang_hooks.post_options (&main_input_filename);
+
+ process_options (no_backend);
+
if (m_use_TV_TOTAL)
start_timevars ();
- do_compile ();
+ do_compile (no_backend);
+
+ if (flag_self_test)
+ {
+ if (no_backend)
+ error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
+ else
+ run_self_tests ();
+ }
}
if (warningcount || errorcount || werrorcount)
print_ignored_options ();
- if (flag_self_test)
- run_self_tests ();
-
/* Invoke registered plugin callbacks if any. Some plugins could
emit some diagnostics here. */
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
diff --git a/gcc/toplev.h b/gcc/toplev.h
index f543554..493f7eb 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
/* Decoded options, and number of such options. */
extern struct cl_decoded_option *save_decoded_options;
extern unsigned int save_decoded_options_count;
+extern vec<cl_decoded_option> *save_opt_decoded_options;
class timer;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 61b5391..4b4b0b5 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3452,11 +3452,56 @@ verify_gimple_call (gcall *stmt)
}
}
+ /* For a call to .DEFERRED_INIT,
+ LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA)
+ we should guarantee that the 1st and the 3rd arguments are consistent:
+ 1st argument: SIZE of the DECL;
+ 3rd argument: IS_VLA, 0 NO, 1 YES;
+
+ if IS_VLA is false, the 1st argument should be a constant and the same as
+ the size of the LHS. */
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+ {
+ tree size_of_arg0 = gimple_call_arg (stmt, 0);
+ tree size_of_lhs = TYPE_SIZE_UNIT (TREE_TYPE (lhs));
+ tree is_vla_node = gimple_call_arg (stmt, 2);
+ bool is_vla = (bool) TREE_INT_CST_LOW (is_vla_node);
+
+ if (TREE_CODE (lhs) == SSA_NAME)
+ lhs = SSA_NAME_VAR (lhs);
+
+ poly_uint64 size_from_arg0, size_from_lhs;
+ bool is_constant_size_arg0 = poly_int_tree_p (size_of_arg0,
+ &size_from_arg0);
+ bool is_constant_size_lhs = poly_int_tree_p (size_of_lhs,
+ &size_from_lhs);
+ if (!is_vla)
+ {
+ if (!is_constant_size_arg0)
+ {
+ error ("%<DEFFERED_INIT%> calls for non-VLA should have "
+ "constant size for the first argument");
+ return true;
+ }
+ else if (!is_constant_size_lhs)
+ {
+ error ("%<DEFFERED_INIT%> calls for non-VLA should have "
+ "constant size for the LHS");
+ return true;
+ }
+ else if (maybe_ne (size_from_arg0, size_from_lhs))
+ {
+ error ("%<DEFFERED_INIT%> calls for non-VLA should have same "
+ "constant size for the first argument and LHS");
+ return true;
+ }
+ }
+ }
+
/* ??? The C frontend passes unpromoted arguments in case it
didn't see a function declaration before the call. So for now
leave the call arguments mostly unverified. Once we gimplify
unit-at-a-time we have a chance to fix this. */
-
for (i = 0; i < gimple_call_num_args (stmt); ++i)
{
tree arg = gimple_call_arg (stmt, i);
@@ -8082,14 +8127,22 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
fprintf (file, ",%s(%" PRIu64 ")",
profile_quality_as_string (bb->count.quality ()),
bb->count.value ());
- fprintf (file, ")\n%s (", function_name (fun));
+ if (dump_flags & TDF_UID)
+ fprintf (file, ")\n%sD_%u (", function_name (fun),
+ DECL_UID (fndecl));
+ else
+ fprintf (file, ")\n%s (", function_name (fun));
}
}
else
{
print_generic_expr (file, TREE_TYPE (fntype), dump_flags);
- fprintf (file, " %s %s(", function_name (fun),
- tmclone ? "[tm-clone] " : "");
+ if (dump_flags & TDF_UID)
+ fprintf (file, " %sD.%u %s(", function_name (fun), DECL_UID (fndecl),
+ tmclone ? "[tm-clone] " : "");
+ else
+ fprintf (file, " %s %s(", function_name (fun),
+ tmclone ? "[tm-clone] " : "");
}
arg = DECL_ARGUMENTS (fndecl);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 239a3a3..d3d2a8d 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -583,8 +583,17 @@ enum omp_memory_order {
OMP_MEMORY_ORDER_ACQUIRE,
OMP_MEMORY_ORDER_RELEASE,
OMP_MEMORY_ORDER_ACQ_REL,
- OMP_MEMORY_ORDER_SEQ_CST
-};
+ OMP_MEMORY_ORDER_SEQ_CST,
+ OMP_MEMORY_ORDER_MASK = 7,
+ OMP_FAIL_MEMORY_ORDER_UNSPECIFIED = OMP_MEMORY_ORDER_UNSPECIFIED * 8,
+ OMP_FAIL_MEMORY_ORDER_RELAXED = OMP_MEMORY_ORDER_RELAXED * 8,
+ OMP_FAIL_MEMORY_ORDER_ACQUIRE = OMP_MEMORY_ORDER_ACQUIRE * 8,
+ OMP_FAIL_MEMORY_ORDER_RELEASE = OMP_MEMORY_ORDER_RELEASE * 8,
+ OMP_FAIL_MEMORY_ORDER_ACQ_REL = OMP_MEMORY_ORDER_ACQ_REL * 8,
+ OMP_FAIL_MEMORY_ORDER_SEQ_CST = OMP_MEMORY_ORDER_SEQ_CST * 8,
+ OMP_FAIL_MEMORY_ORDER_MASK = OMP_MEMORY_ORDER_MASK * 8
+};
+#define OMP_FAIL_MEMORY_ORDER_SHIFT 3
/* There is a TYPE_QUAL value for each type qualifier. They can be
combined by bitwise-or to form the complete set of qualifiers for a
@@ -1038,7 +1047,8 @@ struct GTY(()) tree_base {
unsigned user_align : 1;
unsigned nameless_flag : 1;
unsigned atomic_flag : 1;
- unsigned spare0 : 3;
+ unsigned unavailable_flag : 1;
+ unsigned spare0 : 2;
unsigned spare1 : 8;
@@ -1360,6 +1370,12 @@ struct GTY(()) tree_base {
SSA_NAME_POINTS_TO_READONLY_MEMORY in
SSA_NAME
+ unavailable_flag:
+
+ TREE_UNAVAILABLE in
+ all decls
+ all types
+
visited:
TREE_VISITED in
@@ -1407,6 +1423,7 @@ struct GTY(()) tree_base {
CALL_EXPR_BY_DESCRIPTOR in
CALL_EXPR
+
*/
struct GTY(()) tree_typed {
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index e061baa..57bac06 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -99,6 +99,7 @@ along with GCC; see the file COPYING3. If not see
#include "internal-fn.h"
#include "vr-values.h"
#include "range-op.h"
+#include "tree-ssa-loop-ivopts.h"
static struct datadep_stats
{
@@ -1300,22 +1301,18 @@ base_supports_access_fn_components_p (tree base)
DR, analyzed in LOOP and instantiated before NEST. */
static void
-dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
+dr_analyze_indices (struct indices *dri, tree ref, edge nest, loop_p loop)
{
- vec<tree> access_fns = vNULL;
- tree ref, op;
- tree base, off, access_fn;
-
/* If analyzing a basic-block there are no indices to analyze
and thus no access functions. */
if (!nest)
{
- DR_BASE_OBJECT (dr) = DR_REF (dr);
- DR_ACCESS_FNS (dr).create (0);
+ dri->base_object = ref;
+ dri->access_fns.create (0);
return;
}
- ref = DR_REF (dr);
+ vec<tree> access_fns = vNULL;
/* REALPART_EXPR and IMAGPART_EXPR can be handled like accesses
into a two element array with a constant index. The base is
@@ -1338,8 +1335,8 @@ dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
{
if (TREE_CODE (ref) == ARRAY_REF)
{
- op = TREE_OPERAND (ref, 1);
- access_fn = analyze_scalar_evolution (loop, op);
+ tree op = TREE_OPERAND (ref, 1);
+ tree access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (nest, loop, access_fn);
access_fns.safe_push (access_fn);
}
@@ -1370,16 +1367,17 @@ dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
analyzed nest, add it as an additional independent access-function. */
if (TREE_CODE (ref) == MEM_REF)
{
- op = TREE_OPERAND (ref, 0);
- access_fn = analyze_scalar_evolution (loop, op);
+ tree op = TREE_OPERAND (ref, 0);
+ tree access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (nest, loop, access_fn);
+ STRIP_NOPS (access_fn);
if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
{
- tree orig_type;
tree memoff = TREE_OPERAND (ref, 1);
- base = initial_condition (access_fn);
- orig_type = TREE_TYPE (base);
+ tree base = initial_condition (access_fn);
+ tree orig_type = TREE_TYPE (base);
STRIP_USELESS_TYPE_CONVERSION (base);
+ tree off;
split_constant_offset (base, &base, &off);
STRIP_USELESS_TYPE_CONVERSION (base);
/* Fold the MEM_REF offset into the evolutions initial
@@ -1424,7 +1422,7 @@ dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
base, memoff);
MR_DEPENDENCE_CLIQUE (ref) = MR_DEPENDENCE_CLIQUE (old);
MR_DEPENDENCE_BASE (ref) = MR_DEPENDENCE_BASE (old);
- DR_UNCONSTRAINED_BASE (dr) = true;
+ dri->unconstrained_base = true;
access_fns.safe_push (access_fn);
}
}
@@ -1436,8 +1434,8 @@ dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
build_int_cst (reference_alias_ptr_type (ref), 0));
}
- DR_BASE_OBJECT (dr) = ref;
- DR_ACCESS_FNS (dr) = access_fns;
+ dri->base_object = ref;
+ dri->access_fns = access_fns;
}
/* Extracts the alias analysis information from the memory reference DR. */
@@ -1463,6 +1461,8 @@ void
free_data_ref (data_reference_p dr)
{
DR_ACCESS_FNS (dr).release ();
+ if (dr->alt_indices.base_object)
+ dr->alt_indices.access_fns.release ();
free (dr);
}
@@ -1497,7 +1497,7 @@ create_data_ref (edge nest, loop_p loop, tree memref, gimple *stmt,
dr_analyze_innermost (&DR_INNERMOST (dr), memref,
nest != NULL ? loop : NULL, stmt);
- dr_analyze_indices (dr, nest, loop);
+ dr_analyze_indices (&dr->indices, DR_REF (dr), nest, loop);
dr_analyze_alias (dr);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3066,41 +3066,30 @@ access_fn_components_comparable_p (tree ref_a, tree ref_b)
TREE_TYPE (TREE_OPERAND (ref_b, 0)));
}
-/* Initialize a data dependence relation between data accesses A and
- B. NB_LOOPS is the number of loops surrounding the references: the
- size of the classic distance/direction vectors. */
+/* Initialize a data dependence relation RES in LOOP_NEST. USE_ALT_INDICES
+ is true when the main indices of A and B were not comparable so we try again
+ with alternate indices computed on an indirect reference. */
struct data_dependence_relation *
-initialize_data_dependence_relation (struct data_reference *a,
- struct data_reference *b,
- vec<loop_p> loop_nest)
+initialize_data_dependence_relation (struct data_dependence_relation *res,
+ vec<loop_p> loop_nest,
+ bool use_alt_indices)
{
- struct data_dependence_relation *res;
+ struct data_reference *a = DDR_A (res);
+ struct data_reference *b = DDR_B (res);
unsigned int i;
- res = XCNEW (struct data_dependence_relation);
- DDR_A (res) = a;
- DDR_B (res) = b;
- DDR_LOOP_NEST (res).create (0);
- DDR_SUBSCRIPTS (res).create (0);
- DDR_DIR_VECTS (res).create (0);
- DDR_DIST_VECTS (res).create (0);
-
- if (a == NULL || b == NULL)
+ struct indices *indices_a = &a->indices;
+ struct indices *indices_b = &b->indices;
+ if (use_alt_indices)
{
- DDR_ARE_DEPENDENT (res) = chrec_dont_know;
- return res;
+ if (TREE_CODE (DR_REF (a)) != MEM_REF)
+ indices_a = &a->alt_indices;
+ if (TREE_CODE (DR_REF (b)) != MEM_REF)
+ indices_b = &b->alt_indices;
}
-
- /* If the data references do not alias, then they are independent. */
- if (!dr_may_alias_p (a, b, loop_nest.exists () ? loop_nest[0] : NULL))
- {
- DDR_ARE_DEPENDENT (res) = chrec_known;
- return res;
- }
-
- unsigned int num_dimensions_a = DR_NUM_DIMENSIONS (a);
- unsigned int num_dimensions_b = DR_NUM_DIMENSIONS (b);
+ unsigned int num_dimensions_a = indices_a->access_fns.length ();
+ unsigned int num_dimensions_b = indices_b->access_fns.length ();
if (num_dimensions_a == 0 || num_dimensions_b == 0)
{
DDR_ARE_DEPENDENT (res) = chrec_dont_know;
@@ -3125,9 +3114,9 @@ initialize_data_dependence_relation (struct data_reference *a,
the a and b accesses have a single ARRAY_REF component reference [0]
but have two subscripts. */
- if (DR_UNCONSTRAINED_BASE (a))
+ if (indices_a->unconstrained_base)
num_dimensions_a -= 1;
- if (DR_UNCONSTRAINED_BASE (b))
+ if (indices_b->unconstrained_base)
num_dimensions_b -= 1;
/* These structures describe sequences of component references in
@@ -3210,6 +3199,10 @@ initialize_data_dependence_relation (struct data_reference *a,
B: [3, 4] (i.e. s.e) */
while (index_a < num_dimensions_a && index_b < num_dimensions_b)
{
+ /* The alternate indices form always has a single dimension
+ with unconstrained base. */
+ gcc_assert (!use_alt_indices);
+
/* REF_A and REF_B must be one of the component access types
allowed by dr_analyze_indices. */
gcc_checking_assert (access_fn_component_p (ref_a));
@@ -3280,11 +3273,12 @@ initialize_data_dependence_relation (struct data_reference *a,
/* See whether FULL_SEQ ends at the base and whether the two bases
are equal. We do not care about TBAA or alignment info so we can
use OEP_ADDRESS_OF to avoid false negatives. */
- tree base_a = DR_BASE_OBJECT (a);
- tree base_b = DR_BASE_OBJECT (b);
+ tree base_a = indices_a->base_object;
+ tree base_b = indices_b->base_object;
bool same_base_p = (full_seq.start_a + full_seq.length == num_dimensions_a
&& full_seq.start_b + full_seq.length == num_dimensions_b
- && DR_UNCONSTRAINED_BASE (a) == DR_UNCONSTRAINED_BASE (b)
+ && (indices_a->unconstrained_base
+ == indices_b->unconstrained_base)
&& operand_equal_p (base_a, base_b, OEP_ADDRESS_OF)
&& (types_compatible_p (TREE_TYPE (base_a),
TREE_TYPE (base_b))
@@ -3323,7 +3317,7 @@ initialize_data_dependence_relation (struct data_reference *a,
both lvalues are distinct from the object's declared type. */
if (same_base_p)
{
- if (DR_UNCONSTRAINED_BASE (a))
+ if (indices_a->unconstrained_base)
full_seq.length += 1;
}
else
@@ -3332,8 +3326,41 @@ initialize_data_dependence_relation (struct data_reference *a,
/* Punt if we didn't find a suitable sequence. */
if (full_seq.length == 0)
{
- DDR_ARE_DEPENDENT (res) = chrec_dont_know;
- return res;
+ if (use_alt_indices
+ || (TREE_CODE (DR_REF (a)) == MEM_REF
+ && TREE_CODE (DR_REF (b)) == MEM_REF)
+ || may_be_nonaddressable_p (DR_REF (a))
+ || may_be_nonaddressable_p (DR_REF (b)))
+ {
+ /* Fully exhausted possibilities. */
+ DDR_ARE_DEPENDENT (res) = chrec_dont_know;
+ return res;
+ }
+
+ /* Try evaluating both DRs as dereferences of pointers. */
+ if (!a->alt_indices.base_object
+ && TREE_CODE (DR_REF (a)) != MEM_REF)
+ {
+ tree alt_ref = build2 (MEM_REF, TREE_TYPE (DR_REF (a)),
+ build1 (ADDR_EXPR, ptr_type_node, DR_REF (a)),
+ build_int_cst
+ (reference_alias_ptr_type (DR_REF (a)), 0));
+ dr_analyze_indices (&a->alt_indices, alt_ref,
+ loop_preheader_edge (loop_nest[0]),
+ loop_containing_stmt (DR_STMT (a)));
+ }
+ if (!b->alt_indices.base_object
+ && TREE_CODE (DR_REF (b)) != MEM_REF)
+ {
+ tree alt_ref = build2 (MEM_REF, TREE_TYPE (DR_REF (b)),
+ build1 (ADDR_EXPR, ptr_type_node, DR_REF (b)),
+ build_int_cst
+ (reference_alias_ptr_type (DR_REF (b)), 0));
+ dr_analyze_indices (&b->alt_indices, alt_ref,
+ loop_preheader_edge (loop_nest[0]),
+ loop_containing_stmt (DR_STMT (b)));
+ }
+ return initialize_data_dependence_relation (res, loop_nest, true);
}
if (!same_base_p)
@@ -3381,8 +3408,8 @@ initialize_data_dependence_relation (struct data_reference *a,
struct subscript *subscript;
subscript = XNEW (struct subscript);
- SUB_ACCESS_FN (subscript, 0) = DR_ACCESS_FN (a, full_seq.start_a + i);
- SUB_ACCESS_FN (subscript, 1) = DR_ACCESS_FN (b, full_seq.start_b + i);
+ SUB_ACCESS_FN (subscript, 0) = indices_a->access_fns[full_seq.start_a + i];
+ SUB_ACCESS_FN (subscript, 1) = indices_b->access_fns[full_seq.start_b + i];
SUB_CONFLICTS_IN_A (subscript) = conflict_fn_not_known ();
SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known ();
SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
@@ -3393,6 +3420,40 @@ initialize_data_dependence_relation (struct data_reference *a,
return res;
}
+/* Initialize a data dependence relation between data accesses A and
+ B. NB_LOOPS is the number of loops surrounding the references: the
+ size of the classic distance/direction vectors. */
+
+struct data_dependence_relation *
+initialize_data_dependence_relation (struct data_reference *a,
+ struct data_reference *b,
+ vec<loop_p> loop_nest)
+{
+ data_dependence_relation *res = XCNEW (struct data_dependence_relation);
+ DDR_A (res) = a;
+ DDR_B (res) = b;
+ DDR_LOOP_NEST (res).create (0);
+ DDR_SUBSCRIPTS (res).create (0);
+ DDR_DIR_VECTS (res).create (0);
+ DDR_DIST_VECTS (res).create (0);
+
+ if (a == NULL || b == NULL)
+ {
+ DDR_ARE_DEPENDENT (res) = chrec_dont_know;
+ return res;
+ }
+
+ /* If the data references do not alias, then they are independent. */
+ if (!dr_may_alias_p (a, b, loop_nest.exists () ? loop_nest[0] : NULL))
+ {
+ DDR_ARE_DEPENDENT (res) = chrec_known;
+ return res;
+ }
+
+ return initialize_data_dependence_relation (res, loop_nest, false);
+}
+
+
/* Frees memory used by the conflict function F. */
static void
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 685f33d..74f579c 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -166,14 +166,19 @@ struct data_reference
and runs to completion. */
bool is_conditional_in_stmt;
+ /* Alias information for the data reference. */
+ struct dr_alias alias;
+
/* Behavior of the memory reference in the innermost loop. */
struct innermost_loop_behavior innermost;
/* Subscripts of this data reference. */
struct indices indices;
- /* Alias information for the data reference. */
- struct dr_alias alias;
+ /* Alternate subscripts initialized lazily and used by data-dependence
+ analysis only when the main indices of two DRs are not comparable.
+ Keep last to keep vec_info_shared::check_datarefs happy. */
+ struct indices alt_indices;
};
#define DR_STMT(DR) (DR)->stmt
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index d7b7b30..15dcc1e 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -132,6 +132,11 @@ along with GCC; see the file COPYING3. If not see
predicate_statements for the kinds of predication we support. */
static bool need_to_predicate;
+/* True if we have to rewrite stmts that may invoke undefined behavior
+ when a condition C was false so it doesn't if it is always executed.
+ See predicate_statements for the kinds of predication we support. */
+static bool need_to_rewrite_undefined;
+
/* Indicate if there are any complicated PHIs that need to be handled in
if-conversion. Complicated PHI has more than two arguments and can't
be degenerated to two arguments PHI. See more information in comment
@@ -1042,6 +1047,13 @@ if_convertible_gimple_assign_stmt_p (gimple *stmt,
fprintf (dump_file, "tree could trap...\n");
return false;
}
+ else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
+ && arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt)))
+ /* We have to rewrite stmts with undefined overflow. */
+ need_to_rewrite_undefined = true;
/* When if-converting stores force versioning, likewise if we
ended up generating store data races. */
@@ -2509,6 +2521,7 @@ predicate_statements (loop_p loop)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
{
gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
+ tree lhs;
if (!stmt)
;
else if (is_false_predicate (cond)
@@ -2563,6 +2576,37 @@ predicate_statements (loop_p loop)
gsi_replace (&gsi, new_stmt, true);
}
+ else if (((lhs = gimple_assign_lhs (stmt)), true)
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
+ && arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt)))
+ {
+ gsi_remove (&gsi, true);
+ gimple_seq stmts = rewrite_to_defined_overflow (stmt);
+ bool first = true;
+ for (gimple_stmt_iterator gsi2 = gsi_start (stmts);
+ !gsi_end_p (gsi2);)
+ {
+ gassign *stmt2 = as_a <gassign *> (gsi_stmt (gsi2));
+ gsi_remove (&gsi2, false);
+ /* Make sure to move invariant conversions out of the
+ loop. */
+ if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+ && expr_invariant_in_loop_p (loop,
+ gimple_assign_rhs1 (stmt2)))
+ gsi_insert_on_edge_immediate (loop_preheader_edge (loop),
+ stmt2);
+ else if (first)
+ {
+ gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT);
+ first = false;
+ }
+ else
+ gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
+ }
+ }
else if (gimple_vdef (stmt))
{
tree lhs = gimple_assign_lhs (stmt);
@@ -2580,7 +2624,7 @@ predicate_statements (loop_p loop)
gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi));
update_stmt (stmt);
}
- tree lhs = gimple_get_lhs (gsi_stmt (gsi));
+ lhs = gimple_get_lhs (gsi_stmt (gsi));
if (lhs && TREE_CODE (lhs) == SSA_NAME)
ssa_names.add (lhs);
gsi_next (&gsi);
@@ -2647,7 +2691,7 @@ combine_blocks (class loop *loop)
insert_gimplified_predicates (loop);
predicate_all_scalar_phis (loop);
- if (need_to_predicate)
+ if (need_to_predicate || need_to_rewrite_undefined)
predicate_statements (loop);
/* Merge basic blocks. */
@@ -3148,6 +3192,7 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds)
rloop = NULL;
ifc_bbs = NULL;
need_to_predicate = false;
+ need_to_rewrite_undefined = false;
any_complicated_phi = false;
/* Apply more aggressive if-conversion when loop or its outer loop were
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 5955ff1..b2c58ac 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2117,7 +2117,13 @@ copy_bb (copy_body_data *id, basic_block bb,
size_t nargs = nargs_caller;
for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
- nargs--;
+ {
+ /* Avoid crashing on invalid IL that doesn't have a
+ varargs function or that passes not enough arguments. */
+ if (nargs == 0)
+ break;
+ nargs--;
+ }
/* Create the new array of arguments. */
size_t nargs_callee = gimple_call_num_args (call_stmt);
@@ -3490,7 +3496,11 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
/* We may produce non-gimple trees by adding NOPs or introduce invalid
sharing when the value is not constant or DECL. And we need to make
sure that it cannot be modified from another path in the callee. */
- if ((is_gimple_min_invariant (value)
+ if (((is_gimple_min_invariant (value)
+ /* When the parameter is used in a context that forces it to
+ not be a GIMPLE register avoid substituting something that
+ is not a decl there. */
+ && ! DECL_NOT_GIMPLE_REG_P (p))
|| (DECL_P (value) && TREE_READONLY (value))
|| (auto_var_in_fn_p (value, id->dst_fn)
&& !TREE_ADDRESSABLE (value)))
@@ -4436,8 +4446,8 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
/* Do not special case builtins where we see the body.
This just confuse inliner. */
struct cgraph_node *node;
- if (!(node = cgraph_node::get (decl))
- || node->definition)
+ if ((node = cgraph_node::get (decl))
+ && node->definition)
;
/* For buitins that are likely expanded to nothing or
inlined do not account operand costs. */
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 2df762c..583c01a 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -116,6 +116,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "gimple-fold.h"
#include "tree-affine.h"
+#include "intl.h"
+#include "rtl.h"
+#include "memmodel.h"
+#include "optabs.h"
#define MAX_DATAREFS_NUM \
@@ -651,6 +655,10 @@ class loop_distribution
control_dependences *cd, int *nb_calls, bool *destroy_p,
bool only_patterns_p);
+ /* Transform loops which mimic the effects of builtins rawmemchr or strlen and
+ replace them accordingly. */
+ bool transform_reduction_loop (loop_p loop);
+
/* Compute topological order for basic blocks. Topological order is
needed because data dependence is computed for data references in
lexicographical order. */
@@ -1492,14 +1500,14 @@ loop_distribution::build_rdg_partition_for_vertex (struct graph *rdg, int v)
data references. */
static bool
-find_single_drs (class loop *loop, struct graph *rdg, partition *partition,
+find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_stmts,
data_reference_p *dst_dr, data_reference_p *src_dr)
{
unsigned i;
data_reference_p single_ld = NULL, single_st = NULL;
bitmap_iterator bi;
- EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (partition_stmts, 0, i, bi)
{
gimple *stmt = RDG_STMT (rdg, i);
data_reference_p dr;
@@ -1540,44 +1548,47 @@ find_single_drs (class loop *loop, struct graph *rdg, partition *partition,
}
}
- if (!single_st)
- return false;
-
- /* Bail out if this is a bitfield memory reference. */
- if (TREE_CODE (DR_REF (single_st)) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_st), 1)))
+ if (!single_ld && !single_st)
return false;
- /* Data reference must be executed exactly once per iteration of each
- loop in the loop nest. We only need to check dominance information
- against the outermost one in a perfect loop nest because a bb can't
- dominate outermost loop's latch without dominating inner loop's. */
- basic_block bb_st = gimple_bb (DR_STMT (single_st));
- if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st))
- return false;
+ basic_block bb_ld = NULL;
+ basic_block bb_st = NULL;
if (single_ld)
{
- gimple *store = DR_STMT (single_st), *load = DR_STMT (single_ld);
- /* Direct aggregate copy or via an SSA name temporary. */
- if (load != store
- && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
- return false;
-
/* Bail out if this is a bitfield memory reference. */
if (TREE_CODE (DR_REF (single_ld)) == COMPONENT_REF
&& DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_ld), 1)))
return false;
- /* Load and store must be in the same loop nest. */
- basic_block bb_ld = gimple_bb (DR_STMT (single_ld));
- if (bb_st->loop_father != bb_ld->loop_father)
+ /* Data reference must be executed exactly once per iteration of each
+ loop in the loop nest. We only need to check dominance information
+ against the outermost one in a perfect loop nest because a bb can't
+ dominate outermost loop's latch without dominating inner loop's. */
+ bb_ld = gimple_bb (DR_STMT (single_ld));
+ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld))
+ return false;
+ }
+
+ if (single_st)
+ {
+ /* Bail out if this is a bitfield memory reference. */
+ if (TREE_CODE (DR_REF (single_st)) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_st), 1)))
return false;
/* Data reference must be executed exactly once per iteration.
- Same as single_st, we only need to check against the outermost
+ Same as single_ld, we only need to check against the outermost
loop. */
- if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld))
+ bb_st = gimple_bb (DR_STMT (single_st));
+ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st))
+ return false;
+ }
+
+ if (single_ld && single_st)
+ {
+ /* Load and store must be in the same loop nest. */
+ if (bb_st->loop_father != bb_ld->loop_father)
return false;
edge e = single_exit (bb_st->loop_father);
@@ -1852,9 +1863,19 @@ loop_distribution::classify_partition (loop_p loop,
return has_reduction;
/* Find single load/store data references for builtin partition. */
- if (!find_single_drs (loop, rdg, partition, &single_st, &single_ld))
+ if (!find_single_drs (loop, rdg, partition->stmts, &single_st, &single_ld)
+ || !single_st)
return has_reduction;
+ if (single_ld && single_st)
+ {
+ gimple *store = DR_STMT (single_st), *load = DR_STMT (single_ld);
+ /* Direct aggregate copy or via an SSA name temporary. */
+ if (load != store
+ && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
+ return has_reduction;
+ }
+
partition->loc = gimple_location (DR_STMT (single_st));
/* Classify the builtin kind. */
@@ -3260,6 +3281,429 @@ find_seed_stmts_for_distribution (class loop *loop, vec<gimple *> *work_list)
return work_list->length () > 0;
}
+/* A helper function for generate_{rawmemchr,strlen}_builtin functions in order
+ to place new statements SEQ before LOOP and replace the old reduction
+ variable with the new one. */
+
+static void
+generate_reduction_builtin_1 (loop_p loop, gimple_seq &seq,
+ tree reduction_var_old, tree reduction_var_new,
+ const char *info, machine_mode load_mode)
+{
+ /* Place new statements before LOOP. */
+ gimple_stmt_iterator gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
+ gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+
+ /* Replace old reduction variable with new one. */
+ imm_use_iterator iter;
+ gimple *stmt;
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_STMT (stmt, iter, reduction_var_old)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, reduction_var_new);
+
+ update_stmt (stmt);
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, info, GET_MODE_NAME (load_mode));
+}
+
+/* Generate a call to rawmemchr and place it before LOOP. REDUCTION_VAR is
+ replaced with a fresh SSA name representing the result of the call. */
+
+static void
+generate_rawmemchr_builtin (loop_p loop, tree reduction_var,
+ data_reference_p store_dr, tree base, tree pattern,
+ location_t loc)
+{
+ gimple_seq seq = NULL;
+
+ tree mem = force_gimple_operand (base, &seq, true, NULL_TREE);
+ gimple *fn_call = gimple_build_call_internal (IFN_RAWMEMCHR, 2, mem, pattern);
+ tree reduction_var_new = copy_ssa_name (reduction_var);
+ gimple_call_set_lhs (fn_call, reduction_var_new);
+ gimple_set_location (fn_call, loc);
+ gimple_seq_add_stmt (&seq, fn_call);
+
+ if (store_dr)
+ {
+ gassign *g = gimple_build_assign (DR_REF (store_dr), reduction_var_new);
+ gimple_seq_add_stmt (&seq, g);
+ }
+
+ generate_reduction_builtin_1 (loop, seq, reduction_var, reduction_var_new,
+ "generated rawmemchr%s\n",
+ TYPE_MODE (TREE_TYPE (TREE_TYPE (base))));
+}
+
+/* Helper function for generate_strlen_builtin(,_using_rawmemchr) */
+
+static void
+generate_strlen_builtin_1 (loop_p loop, gimple_seq &seq,
+ tree reduction_var_old, tree reduction_var_new,
+ machine_mode mode, tree start_len)
+{
+ /* REDUCTION_VAR_NEW has either size type or ptrdiff type and must be
+ converted if types of old and new reduction variable are not compatible. */
+ reduction_var_new = gimple_convert (&seq, TREE_TYPE (reduction_var_old),
+ reduction_var_new);
+
+ /* Loops of the form `for (i=42; s[i]; ++i);` have an additional start
+ length. */
+ if (!integer_zerop (start_len))
+ {
+ tree lhs = make_ssa_name (TREE_TYPE (reduction_var_new));
+ gimple *g = gimple_build_assign (lhs, PLUS_EXPR, reduction_var_new,
+ start_len);
+ gimple_seq_add_stmt (&seq, g);
+ reduction_var_new = lhs;
+ }
+
+ generate_reduction_builtin_1 (loop, seq, reduction_var_old, reduction_var_new,
+ "generated strlen%s\n", mode);
+}
+
+/* Generate a call to strlen and place it before LOOP. REDUCTION_VAR is
+ replaced with a fresh SSA name representing the result of the call. */
+
+static void
+generate_strlen_builtin (loop_p loop, tree reduction_var, tree base,
+ tree start_len, location_t loc)
+{
+ gimple_seq seq = NULL;
+
+ tree reduction_var_new = make_ssa_name (size_type_node);
+
+ tree mem = force_gimple_operand (base, &seq, true, NULL_TREE);
+ tree fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_STRLEN));
+ gimple *fn_call = gimple_build_call (fn, 1, mem);
+ gimple_call_set_lhs (fn_call, reduction_var_new);
+ gimple_set_location (fn_call, loc);
+ gimple_seq_add_stmt (&seq, fn_call);
+
+ generate_strlen_builtin_1 (loop, seq, reduction_var, reduction_var_new,
+ QImode, start_len);
+}
+
+/* Generate code in order to mimic the behaviour of strlen but this time over
+ an array of elements with mode different than QI. REDUCTION_VAR is replaced
+ with a fresh SSA name representing the result, i.e., the length. */
+
+static void
+generate_strlen_builtin_using_rawmemchr (loop_p loop, tree reduction_var,
+ tree base, tree load_type,
+ tree start_len, location_t loc)
+{
+ gimple_seq seq = NULL;
+
+ tree start = force_gimple_operand (base, &seq, true, NULL_TREE);
+ tree zero = build_zero_cst (load_type);
+ gimple *fn_call = gimple_build_call_internal (IFN_RAWMEMCHR, 2, start, zero);
+ tree end = make_ssa_name (TREE_TYPE (base));
+ gimple_call_set_lhs (fn_call, end);
+ gimple_set_location (fn_call, loc);
+ gimple_seq_add_stmt (&seq, fn_call);
+
+ /* Determine the number of elements between START and END by
+ evaluating (END - START) / sizeof (*START). */
+ tree diff = make_ssa_name (ptrdiff_type_node);
+ gimple *diff_stmt = gimple_build_assign (diff, POINTER_DIFF_EXPR, end, start);
+ gimple_seq_add_stmt (&seq, diff_stmt);
+ /* Let SIZE be the size of each character. */
+ tree size = gimple_convert (&seq, ptrdiff_type_node,
+ TYPE_SIZE_UNIT (load_type));
+ tree count = make_ssa_name (ptrdiff_type_node);
+ gimple *count_stmt = gimple_build_assign (count, TRUNC_DIV_EXPR, diff, size);
+ gimple_seq_add_stmt (&seq, count_stmt);
+
+ generate_strlen_builtin_1 (loop, seq, reduction_var, count,
+ TYPE_MODE (load_type),
+ start_len);
+}
+
+/* Return true if we can count at least as many characters by taking pointer
+ difference as we can count via reduction_var without an overflow. Thus
+ compute 2^n < (2^(m-1) / s) where n = TYPE_PRECISION (reduction_var_type),
+ m = TYPE_PRECISION (ptrdiff_type_node), and s = size of each character. */
+static bool
+reduction_var_overflows_first (tree reduction_var_type, tree load_type)
+{
+ widest_int n2 = wi::lshift (1, TYPE_PRECISION (reduction_var_type));;
+ widest_int m2 = wi::lshift (1, TYPE_PRECISION (ptrdiff_type_node) - 1);
+ widest_int s = wi::to_widest (TYPE_SIZE_UNIT (load_type));
+ return wi::ltu_p (n2, wi::udiv_trunc (m2, s));
+}
+
+static gimple *
+determine_reduction_stmt_1 (const loop_p loop, const basic_block *bbs)
+{
+ gimple *reduction_stmt = NULL;
+
+ for (unsigned i = 0, ninsns = 0; i < loop->num_nodes; ++i)
+ {
+ basic_block bb = bbs[i];
+
+ for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
+ gsi_next_nondebug (&bsi))
+ {
+ gphi *phi = bsi.phi ();
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ continue;
+ if (stmt_has_scalar_dependences_outside_loop (loop, phi))
+ {
+ if (reduction_stmt)
+ return NULL;
+ reduction_stmt = phi;
+ }
+ }
+
+ for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
+ gsi_next_nondebug (&bsi), ++ninsns)
+ {
+ /* Bail out early for loops which are unlikely to match. */
+ if (ninsns > 16)
+ return NULL;
+ gimple *stmt = gsi_stmt (bsi);
+ if (gimple_clobber_p (stmt))
+ continue;
+ if (gimple_code (stmt) == GIMPLE_LABEL)
+ continue;
+ if (gimple_has_volatile_ops (stmt))
+ return NULL;
+ if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
+ {
+ if (reduction_stmt)
+ return NULL;
+ reduction_stmt = stmt;
+ }
+ }
+ }
+
+ return reduction_stmt;
+}
+
+/* If LOOP has a single non-volatile reduction statement, then return a pointer
+ to it. Otherwise return NULL. */
+static gimple *
+determine_reduction_stmt (const loop_p loop)
+{
+ basic_block *bbs = get_loop_body (loop);
+ gimple *reduction_stmt = determine_reduction_stmt_1 (loop, bbs);
+ XDELETEVEC (bbs);
+ return reduction_stmt;
+}
+
+/* Transform loops which mimic the effects of builtins rawmemchr or strlen and
+ replace them accordingly. For example, a loop of the form
+
+ for (; *p != 42; ++p);
+
+ is replaced by
+
+ p = rawmemchr<MODE> (p, 42);
+
+ under the assumption that rawmemchr is available for a particular MODE.
+ Another example is
+
+ int i;
+ for (i = 42; s[i]; ++i);
+
+ which is replaced by
+
+ i = (int)strlen (&s[42]) + 42;
+
+ for some character array S. In case array S is not of type character array
+ we end up with
+
+ i = (int)(rawmemchr<MODE> (&s[42], 0) - &s[42]) + 42;
+
+ assuming that rawmemchr is available for a particular MODE. */
+
+bool
+loop_distribution::transform_reduction_loop (loop_p loop)
+{
+ gimple *reduction_stmt;
+ data_reference_p load_dr = NULL, store_dr = NULL;
+
+ edge e = single_exit (loop);
+ gcond *cond = safe_dyn_cast <gcond *> (last_stmt (e->src));
+ if (!cond)
+ return false;
+ /* Ensure loop condition is an (in)equality test and loop is exited either if
+ the inequality test fails or the equality test succeeds. */
+ if (!(e->flags & EDGE_FALSE_VALUE && gimple_cond_code (cond) == NE_EXPR)
+ && !(e->flags & EDGE_TRUE_VALUE && gimple_cond_code (cond) == EQ_EXPR))
+ return false;
+ /* A limitation of the current implementation is that we only support
+ constant patterns in (in)equality tests. */
+ tree pattern = gimple_cond_rhs (cond);
+ if (TREE_CODE (pattern) != INTEGER_CST)
+ return false;
+
+ reduction_stmt = determine_reduction_stmt (loop);
+
+ /* A limitation of the current implementation is that we require a reduction
+ statement. Therefore, loops without a reduction statement as in the
+ following are not recognized:
+ int *p;
+ void foo (void) { for (; *p; ++p); } */
+ if (reduction_stmt == NULL)
+ return false;
+
+ /* Reduction variables are guaranteed to be SSA names. */
+ tree reduction_var;
+ switch (gimple_code (reduction_stmt))
+ {
+ case GIMPLE_ASSIGN:
+ case GIMPLE_PHI:
+ reduction_var = gimple_get_lhs (reduction_stmt);
+ break;
+ default:
+ /* Bail out e.g. for GIMPLE_CALL. */
+ return false;
+ }
+
+ struct graph *rdg = build_rdg (loop, NULL);
+ if (rdg == NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Loop %d not transformed: failed to build the RDG.\n",
+ loop->num);
+
+ return false;
+ }
+ auto_bitmap partition_stmts;
+ bitmap_set_range (partition_stmts, 0, rdg->n_vertices);
+ find_single_drs (loop, rdg, partition_stmts, &store_dr, &load_dr);
+ free_rdg (rdg);
+
+ /* Bail out if there is no single load. */
+ if (load_dr == NULL)
+ return false;
+
+ /* Reaching this point we have a loop with a single reduction variable,
+ a single load, and an optional single store. */
+
+ tree load_ref = DR_REF (load_dr);
+ tree load_type = TREE_TYPE (load_ref);
+ tree load_access_base = build_fold_addr_expr (load_ref);
+ tree load_access_size = TYPE_SIZE_UNIT (load_type);
+ affine_iv load_iv, reduction_iv;
+
+ if (!INTEGRAL_TYPE_P (load_type)
+ || !type_has_mode_precision_p (load_type))
+ return false;
+
+ /* We already ensured that the loop condition tests for (in)equality where the
+ rhs is a constant pattern. Now ensure that the lhs is the result of the
+ load. */
+ if (gimple_cond_lhs (cond) != gimple_assign_lhs (DR_STMT (load_dr)))
+ return false;
+
+ /* Bail out if no affine induction variable with constant step can be
+ determined. */
+ if (!simple_iv (loop, loop, load_access_base, &load_iv, false))
+ return false;
+
+ /* Bail out if memory accesses are not consecutive or not growing. */
+ if (!operand_equal_p (load_iv.step, load_access_size, 0))
+ return false;
+
+ if (!simple_iv (loop, loop, reduction_var, &reduction_iv, false))
+ return false;
+
+ /* Handle rawmemchr like loops. */
+ if (operand_equal_p (load_iv.base, reduction_iv.base)
+ && operand_equal_p (load_iv.step, reduction_iv.step))
+ {
+ if (store_dr)
+ {
+ /* Ensure that we store to X and load from X+I where I>0. */
+ if (TREE_CODE (load_iv.base) != POINTER_PLUS_EXPR
+ || !integer_onep (TREE_OPERAND (load_iv.base, 1)))
+ return false;
+ tree ptr_base = TREE_OPERAND (load_iv.base, 0);
+ if (TREE_CODE (ptr_base) != SSA_NAME)
+ return false;
+ gimple *def = SSA_NAME_DEF_STMT (ptr_base);
+ if (!gimple_assign_single_p (def)
+ || gimple_assign_rhs1 (def) != DR_REF (store_dr))
+ return false;
+ /* Ensure that the reduction value is stored. */
+ if (gimple_assign_rhs1 (DR_STMT (store_dr)) != reduction_var)
+ return false;
+ }
+ /* Bail out if target does not provide rawmemchr for a certain mode. */
+ machine_mode mode = TYPE_MODE (load_type);
+ if (direct_optab_handler (rawmemchr_optab, mode) == CODE_FOR_nothing)
+ return false;
+ location_t loc = gimple_location (DR_STMT (load_dr));
+ generate_rawmemchr_builtin (loop, reduction_var, store_dr, load_iv.base,
+ pattern, loc);
+ return true;
+ }
+
+ /* Handle strlen like loops. */
+ if (store_dr == NULL
+ && integer_zerop (pattern)
+ && TREE_CODE (reduction_iv.base) == INTEGER_CST
+ && TREE_CODE (reduction_iv.step) == INTEGER_CST
+ && integer_onep (reduction_iv.step))
+ {
+ location_t loc = gimple_location (DR_STMT (load_dr));
+ tree reduction_var_type = TREE_TYPE (reduction_var);
+ /* While determining the length of a string an overflow might occur.
+ If an overflow only occurs in the loop implementation and not in the
+ strlen implementation, then either the overflow is undefined or the
+ truncated result of strlen equals the one of the loop. Otherwise if
+ an overflow may also occur in the strlen implementation, then
+ replacing a loop by a call to strlen is sound whenever we ensure that
+ if an overflow occurs in the strlen implementation, then also an
+ overflow occurs in the loop implementation which is undefined. It
+ seems reasonable to relax this and assume that the strlen
+ implementation cannot overflow in case sizetype is big enough in the
+ sense that an overflow can only happen for string objects which are
+ bigger than half of the address space; at least for 32-bit targets and
+ up.
+
+ For strlen which makes use of rawmemchr the maximal length of a string
+ which can be determined without an overflow is PTRDIFF_MAX / S where
+ each character has size S. Since an overflow for ptrdiff type is
+ undefined we have to make sure that if an overflow occurs, then an
+ overflow occurs in the loop implementation, too, and this is
+ undefined, too. Similar as before we relax this and assume that no
+ string object is larger than half of the address space; at least for
+ 32-bit targets and up. */
+ if (TYPE_MODE (load_type) == TYPE_MODE (char_type_node)
+ && TYPE_PRECISION (load_type) == TYPE_PRECISION (char_type_node)
+ && ((TYPE_PRECISION (sizetype) >= TYPE_PRECISION (ptr_type_node) - 1
+ && TYPE_PRECISION (ptr_type_node) >= 32)
+ || (TYPE_OVERFLOW_UNDEFINED (reduction_var_type)
+ && TYPE_PRECISION (reduction_var_type) <= TYPE_PRECISION (sizetype)))
+ && builtin_decl_implicit (BUILT_IN_STRLEN))
+ generate_strlen_builtin (loop, reduction_var, load_iv.base,
+ reduction_iv.base, loc);
+ else if (direct_optab_handler (rawmemchr_optab, TYPE_MODE (load_type))
+ != CODE_FOR_nothing
+ && ((TYPE_PRECISION (ptrdiff_type_node) == TYPE_PRECISION (ptr_type_node)
+ && TYPE_PRECISION (ptrdiff_type_node) >= 32)
+ || (TYPE_OVERFLOW_UNDEFINED (reduction_var_type)
+ && reduction_var_overflows_first (reduction_var_type, load_type))))
+ generate_strlen_builtin_using_rawmemchr (loop, reduction_var,
+ load_iv.base,
+ load_type,
+ reduction_iv.base, loc);
+ else
+ return false;
+ return true;
+ }
+
+ return false;
+}
+
/* Given innermost LOOP, return the outermost enclosing loop that forms a
perfect loop nest. */
@@ -3324,10 +3768,27 @@ loop_distribution::execute (function *fun)
&& !optimize_loop_for_speed_p (loop)))
continue;
- /* Don't distribute loop if niters is unknown. */
+ /* If niters is unknown don't distribute loop but rather try to transform
+ it to a call to a builtin. */
tree niters = number_of_latch_executions (loop);
if (niters == NULL_TREE || niters == chrec_dont_know)
- continue;
+ {
+ datarefs_vec.create (20);
+ if (transform_reduction_loop (loop))
+ {
+ changed = true;
+ loops_to_be_destroyed.safe_push (loop);
+ if (dump_enabled_p ())
+ {
+ dump_user_location_t loc = find_loop_location (loop);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
+ loc, "Loop %d transformed into a builtin.\n",
+ loop->num);
+ }
+ }
+ free_data_refs (datarefs_vec);
+ continue;
+ }
/* Get the perfect loop nest for distribution. */
loop = prepare_perfect_loop_nest (loop);
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 744748d..6a4dc72 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -54,8 +54,7 @@ static const unsigned HOST_WIDE_INT unknown[4] = {
static tree compute_object_offset (const_tree, const_tree);
static bool addr_object_size (struct object_size_info *,
- const_tree, int, unsigned HOST_WIDE_INT *,
- tree * = NULL, tree * = NULL);
+ const_tree, int, unsigned HOST_WIDE_INT *);
static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
static tree pass_through_call (const gcall *);
static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -209,17 +208,10 @@ decl_init_size (tree decl, bool min)
static bool
addr_object_size (struct object_size_info *osi, const_tree ptr,
- int object_size_type, unsigned HOST_WIDE_INT *psize,
- tree *pdecl /* = NULL */, tree *poff /* = NULL */)
+ int object_size_type, unsigned HOST_WIDE_INT *psize)
{
tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
- tree dummy_decl, dummy_off = size_zero_node;
- if (!pdecl)
- pdecl = &dummy_decl;
- if (!poff)
- poff = &dummy_off;
-
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
/* Set to unknown and overwrite just before returning if the size
@@ -241,7 +233,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
|| TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
{
compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
- object_size_type & ~1, &sz, pdecl, poff);
+ object_size_type & ~1, &sz);
}
else
{
@@ -259,11 +251,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
offset_int mem_offset;
if (mem_ref_offset (pt_var).is_constant (&mem_offset))
{
- if (*poff)
- *poff = wide_int_to_tree (ptrdiff_type_node,
- mem_offset + wi::to_offset (*poff));
- else
- *poff = wide_int_to_tree (ptrdiff_type_node, mem_offset);
offset_int dsz = wi::sub (sz, mem_offset);
if (wi::neg_p (dsz))
sz = 0;
@@ -281,7 +268,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
}
else if (DECL_P (pt_var))
{
- *pdecl = pt_var;
pt_var_size = decl_init_size (pt_var, object_size_type & 2);
if (!pt_var_size)
return false;
@@ -418,7 +404,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
if (bytes != error_mark_node)
{
- *poff = bytes;
if (TREE_CODE (bytes) == INTEGER_CST
&& tree_int_cst_lt (var_size, bytes))
bytes = size_zero_node;
@@ -438,7 +423,6 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes2 = size_zero_node;
else
bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
- *poff = size_binop (PLUS_EXPR, *poff, bytes2);
bytes = size_binop (MIN_EXPR, bytes, bytes2);
}
}
@@ -446,11 +430,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
else if (!pt_var_size)
return false;
else
- {
- bytes = pt_var_size;
- if (!*poff)
- *poff = size_zero_node;
- }
+ bytes = pt_var_size;
if (tree_fits_uhwi_p (bytes))
{
@@ -548,17 +528,10 @@ pass_through_call (const gcall *call)
bool
compute_builtin_object_size (tree ptr, int object_size_type,
- unsigned HOST_WIDE_INT *psize,
- tree *pdecl /* = NULL */, tree *poff /* = NULL */)
+ unsigned HOST_WIDE_INT *psize)
{
gcc_assert (object_size_type >= 0 && object_size_type <= 3);
- tree dummy_decl, dummy_off = size_zero_node;
- if (!pdecl)
- pdecl = &dummy_decl;
- if (!poff)
- poff = &dummy_off;
-
/* Set to unknown and overwrite just before returning if the size
could be determined. */
*psize = unknown[object_size_type];
@@ -567,7 +540,7 @@ compute_builtin_object_size (tree ptr, int object_size_type,
init_offset_limit ();
if (TREE_CODE (ptr) == ADDR_EXPR)
- return addr_object_size (NULL, ptr, object_size_type, psize, pdecl, poff);
+ return addr_object_size (NULL, ptr, object_size_type, psize);
if (TREE_CODE (ptr) != SSA_NAME
|| !POINTER_TYPE_P (TREE_TYPE (ptr)))
@@ -592,12 +565,11 @@ compute_builtin_object_size (tree ptr, int object_size_type,
if (tree_fits_shwi_p (offset)
&& compute_builtin_object_size (ptr, object_size_type,
- psize, pdecl, poff))
+ psize))
{
/* Return zero when the offset is out of bounds. */
unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
*psize = off < *psize ? *psize - off : 0;
- *poff = offset;
return true;
}
}
diff --git a/gcc/tree-object-size.h b/gcc/tree-object-size.h
index 358b902..ef18aea 100644
--- a/gcc/tree-object-size.h
+++ b/gcc/tree-object-size.h
@@ -22,8 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern void init_object_sizes (void);
extern void fini_object_sizes (void);
-extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *,
- tree * = NULL, tree * = NULL);
+extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *);
extern tree decl_init_size (tree, bool);
#endif // GCC_TREE_OBJECT_SIZE_H
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 83941bc..d379769 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -225,6 +225,8 @@ protected:
been optimized. */
#define PROP_gimple_lomp_dev (1 << 16) /* done omp_device_lower */
#define PROP_rtl_split_insns (1 << 17) /* RTL has insns split. */
+#define PROP_loop_opts_done (1 << 18) /* SSA loop optimizations
+ have completed. */
#define PROP_gimple \
(PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
@@ -405,6 +407,7 @@ extern gimple_opt_pass *make_pass_cd_dce (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_call_cdce (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_merge_phi (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_thread_jumps (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_thread_jumps_full (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_early_thread_jumps (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_split_crit_edges (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_laddress (gcc::context *ctxt);
@@ -460,6 +463,7 @@ extern gimple_opt_pass *make_pass_copy_prop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_isolate_erroneous_paths (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_early_vrp (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_vrp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_vrp_threader (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_uncprop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_return_slot (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_reassoc (gcc::context *ctxt);
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 6b195d1..208e755 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -233,6 +233,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-affine.h"
#include "builtins.h"
+#include "opts.h"
/* The maximum number of iterations between the considered memory
references. */
@@ -3397,8 +3398,7 @@ pcom_worker::tree_predictive_commoning_loop (bool allow_unroll_p)
the phi nodes in execute_pred_commoning_cbck. A bit hacky. */
replace_phis_by_defined_names (m_chains);
- edge exit = single_dom_exit (m_loop);
- tree_transform_and_unroll_loop (m_loop, unroll_factor, exit, &desc,
+ tree_transform_and_unroll_loop (m_loop, unroll_factor, &desc,
execute_pred_commoning_cbck, &dta);
eliminate_temp_copies (m_loop, tmp_vars);
}
@@ -3492,7 +3492,7 @@ public:
only if predictive commoning isn't set explicitly, and it
doesn't allow unrolling. */
if (flag_tree_loop_vectorize
- && !global_options_set.x_flag_predictive_commoning)
+ && !OPTION_SET_P (flag_predictive_commoning))
return true;
return false;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index e103d2c..275dc7d 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -344,7 +344,16 @@ dump_function_name (pretty_printer *pp, tree node, dump_flags_t flags)
if (CONVERT_EXPR_P (node))
node = TREE_OPERAND (node, 0);
if (DECL_NAME (node) && (flags & TDF_ASMNAME) == 0)
- pp_string (pp, lang_hooks.decl_printable_name (node, 1));
+ {
+ pp_string (pp, lang_hooks.decl_printable_name (node, 1));
+ if (flags & TDF_UID)
+ {
+ char uid_sep = (flags & TDF_GIMPLE) ? '_' : '.';
+ pp_character (pp, 'D');
+ pp_character (pp, uid_sep);
+ pp_scalar (pp, "%u", DECL_UID (node));
+ }
+ }
else
dump_decl_name (pp, node, flags);
}
@@ -735,10 +744,23 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "allocate(");
if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
{
+ pp_string (pp, "allocator(");
dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause),
spc, flags, false);
- pp_colon (pp);
+ pp_right_paren (pp);
}
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ {
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ pp_comma (pp);
+ pp_string (pp, "align(");
+ dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALIGN (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ }
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause)
+ || OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ pp_colon (pp);
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
pp_right_paren (pp);
@@ -986,6 +1008,8 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case OMP_CLAUSE_DEVICE:
pp_string (pp, "device(");
+ if (OMP_CLAUSE_DEVICE_ANCESTOR (clause))
+ pp_string (pp, "ancestor:");
dump_generic_node (pp, OMP_CLAUSE_DEVICE_ID (clause),
spc, flags, false);
pp_right_paren (pp);
@@ -1147,7 +1171,12 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
break;
case OMP_CLAUSE_ORDER:
- pp_string (pp, "order(concurrent)");
+ pp_string (pp, "order(");
+ if (OMP_CLAUSE_ORDER_UNCONSTRAINED (clause))
+ pp_string (pp, "unconstrained:");
+ else if (OMP_CLAUSE_ORDER_REPRODUCIBLE (clause))
+ pp_string (pp, "reproducible:");
+ pp_string (pp, "concurrent)");
break;
case OMP_CLAUSE_BIND:
@@ -1490,7 +1519,7 @@ dump_block_node (pretty_printer *pp, tree block, int spc, dump_flags_t flags)
void
dump_omp_atomic_memory_order (pretty_printer *pp, enum omp_memory_order mo)
{
- switch (mo)
+ switch (mo & OMP_MEMORY_ORDER_MASK)
{
case OMP_MEMORY_ORDER_RELAXED:
pp_string (pp, " relaxed");
@@ -1512,6 +1541,22 @@ dump_omp_atomic_memory_order (pretty_printer *pp, enum omp_memory_order mo)
default:
gcc_unreachable ();
}
+ switch (mo & OMP_FAIL_MEMORY_ORDER_MASK)
+ {
+ case OMP_FAIL_MEMORY_ORDER_RELAXED:
+ pp_string (pp, " fail(relaxed)");
+ break;
+ case OMP_FAIL_MEMORY_ORDER_SEQ_CST:
+ pp_string (pp, " fail(seq_cst)");
+ break;
+ case OMP_FAIL_MEMORY_ORDER_ACQUIRE:
+ pp_string (pp, " fail(acquire)");
+ break;
+ case OMP_FAIL_MEMORY_ORDER_UNSPECIFIED:
+ break;
+ default:
+ gcc_unreachable ();
+ }
}
/* Helper to dump a MEM_REF node. */
@@ -2828,17 +2873,28 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
/* Unary arithmetic and logic expressions. */
+ case ADDR_EXPR:
+ if (flags & TDF_GIMPLE_VAL)
+ {
+ pp_string (pp, "_Literal (");
+ dump_generic_node (pp, TREE_TYPE (node), spc,
+ flags & ~TDF_GIMPLE_VAL, false);
+ pp_character (pp, ')');
+ }
+ /* Fallthru. */
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
- case ADDR_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case INDIRECT_REF:
- if (TREE_CODE (node) == ADDR_EXPR
+ if (!(flags & TDF_GIMPLE)
+ && TREE_CODE (node) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (node, 0)) == STRING_CST
|| TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL))
- ; /* Do not output '&' for strings and function pointers. */
+ /* Do not output '&' for strings and function pointers when not
+ dumping GIMPLE FE syntax. */
+ ;
else
pp_string (pp, op_symbol (node));
@@ -3627,6 +3683,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case OMP_ATOMIC:
pp_string (pp, "#pragma omp atomic");
+ if (OMP_ATOMIC_WEAK (node))
+ pp_string (pp, " weak");
dump_omp_atomic_memory_order (pp, OMP_ATOMIC_MEMORY_ORDER (node));
newline_and_indent (pp, spc + 2);
dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
@@ -3647,6 +3705,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case OMP_ATOMIC_CAPTURE_OLD:
case OMP_ATOMIC_CAPTURE_NEW:
pp_string (pp, "#pragma omp atomic capture");
+ if (OMP_ATOMIC_WEAK (node))
+ pp_string (pp, " weak");
dump_omp_atomic_memory_order (pp, OMP_ATOMIC_MEMORY_ORDER (node));
newline_and_indent (pp, spc + 2);
dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 3a9e14f..9b786e2 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -99,7 +99,7 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "builtins.h"
#include "tree-sra.h"
-
+#include "opts.h"
/* Enumeration of all aggregate reductions we can do. */
enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
@@ -384,6 +384,13 @@ static struct
/* Numbber of components created when splitting aggregate parameters. */
int param_reductions_created;
+
+ /* Number of deferred_init calls that are modified. */
+ int deferred_init;
+
+ /* Number of deferred_init calls that are created by
+ generate_subtree_deferred_init. */
+ int subtree_deferred_init;
} sra_stats;
static void
@@ -1388,7 +1395,14 @@ scan_function (void)
t = gimple_call_lhs (stmt);
if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
- ret |= build_access_from_expr (t, stmt, true);
+ {
+ /* If the STMT is a call to DEFERRED_INIT, avoid setting
+ cannot_scalarize_away_bitmap. */
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+ ret |= !!build_access_from_expr_1 (t, stmt, true);
+ else
+ ret |= build_access_from_expr (t, stmt, true);
+ }
break;
case GIMPLE_ASM:
@@ -3413,12 +3427,12 @@ analyze_all_variable_accesses (void)
if (optimize_speed_p)
{
- if (global_options_set.x_param_sra_max_scalarization_size_speed)
+ if (OPTION_SET_P (param_sra_max_scalarization_size_speed))
max_scalarization_size = param_sra_max_scalarization_size_speed;
}
else
{
- if (global_options_set.x_param_sra_max_scalarization_size_size)
+ if (OPTION_SET_P (param_sra_max_scalarization_size_size))
max_scalarization_size = param_sra_max_scalarization_size_size;
}
max_scalarization_size *= BITS_PER_UNIT;
@@ -4099,6 +4113,88 @@ get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
}
+
+/* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
+ of accesses within a subtree ACCESS; all its children, siblings and their
+ children are to be processed.
+ GSI is a statement iterator used to place the new statements. */
+static void
+generate_subtree_deferred_init (struct access *access,
+ tree init_type,
+ tree is_vla,
+ gimple_stmt_iterator *gsi,
+ location_t loc)
+{
+ do
+ {
+ if (access->grp_to_be_replaced)
+ {
+ tree repl = get_access_replacement (access);
+ gimple *call
+ = gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
+ TYPE_SIZE_UNIT (TREE_TYPE (repl)),
+ init_type, is_vla);
+ gimple_call_set_lhs (call, repl);
+ gsi_insert_before (gsi, call, GSI_SAME_STMT);
+ update_stmt (call);
+ gimple_set_location (call, loc);
+ sra_stats.subtree_deferred_init++;
+ }
+ if (access->first_child)
+ generate_subtree_deferred_init (access->first_child, init_type,
+ is_vla, gsi, loc);
+
+ access = access ->next_sibling;
+ }
+ while (access);
+}
+
+/* For a call to .DEFERRED_INIT:
+ var = .DEFERRED_INIT (size_of_var, init_type, is_vla);
+ examine the LHS variable VAR and replace it with a scalar replacement if
+ there is one, also replace the RHS call to a call to .DEFERRED_INIT of
+ the corresponding scalar relacement variable. Examine the subtree and
+ do the scalar replacements in the subtree too. STMT is the call, GSI is
+ the statment iterator to place newly created statement. */
+
+static enum assignment_mod_result
+sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ tree init_type = gimple_call_arg (stmt, 1);
+ tree is_vla = gimple_call_arg (stmt, 2);
+
+ struct access *lhs_access = get_access_for_expr (lhs);
+ if (!lhs_access)
+ return SRA_AM_NONE;
+
+ location_t loc = gimple_location (stmt);
+
+ if (lhs_access->grp_to_be_replaced)
+ {
+ tree lhs_repl = get_access_replacement (lhs_access);
+ gimple_call_set_lhs (stmt, lhs_repl);
+ tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl));
+ gimple_call_set_arg (stmt, 0, arg0_repl);
+ sra_stats.deferred_init++;
+ gcc_assert (!lhs_access->first_child);
+ return SRA_AM_MODIFIED;
+ }
+
+ if (lhs_access->first_child)
+ generate_subtree_deferred_init (lhs_access->first_child,
+ init_type, is_vla, gsi, loc);
+ if (lhs_access->grp_covered)
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove (gsi, true);
+ release_defs (stmt);
+ return SRA_AM_REMOVED;
+ }
+
+ return SRA_AM_MODIFIED;
+}
+
/* Examine both sides of the assignment statement pointed to by STMT, replace
them with a scalare replacement if there is one and generate copying of
replacements if scalarized aggregates have been used in the assignment. GSI
@@ -4463,17 +4559,27 @@ sra_modify_function_body (void)
break;
case GIMPLE_CALL:
- /* Operands must be processed before the lhs. */
- for (i = 0; i < gimple_call_num_args (stmt); i++)
+ /* Handle calls to .DEFERRED_INIT specially. */
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
{
- t = gimple_call_arg_ptr (stmt, i);
- modified |= sra_modify_expr (t, &gsi, false);
+ assign_result = sra_modify_deferred_init (stmt, &gsi);
+ modified |= assign_result == SRA_AM_MODIFIED;
+ deleted = assign_result == SRA_AM_REMOVED;
}
-
- if (gimple_call_lhs (stmt))
+ else
{
- t = gimple_call_lhs_ptr (stmt);
- modified |= sra_modify_expr (t, &gsi, true);
+ /* Operands must be processed before the lhs. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ t = gimple_call_arg_ptr (stmt, i);
+ modified |= sra_modify_expr (t, &gsi, false);
+ }
+
+ if (gimple_call_lhs (stmt))
+ {
+ t = gimple_call_lhs_ptr (stmt);
+ modified |= sra_modify_expr (t, &gsi, true);
+ }
}
break;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index f4a99ac..70ce6a4 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1695,7 +1695,8 @@ bit_value_binop (enum tree_code code, signop sgn, int width,
/* Logical right shift, or zero sign bit. */
widest_int arg = r1val | r1mask;
int lzcount = wi::clz (arg);
- lzcount -= wi::get_precision (arg) - width;
+ if (lzcount)
+ lzcount -= wi::get_precision (arg) - width;
widest_int tmp = wi::mask <widest_int> (width, false);
tmp = wi::lrshift (tmp, lzcount);
tmp = wi::lrshift (tmp, wi::bit_and_not (r2val, r2mask));
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 0778eb9..c4907af 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -414,7 +414,9 @@ find_obviously_necessary_stmts (bool aggressive)
if ((flags & (ECF_CONST|ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE))
return;
- /* Prevent the empty possibly infinite loops from being removed. */
+ /* Prevent the empty possibly infinite loops from being removed. This is
+ needed to make the logic in remove_dead_stmt work to identify the
+ correct edge to keep when removing a controlling condition. */
if (aggressive)
{
if (mark_irreducible_loops ())
@@ -426,17 +428,19 @@ find_obviously_necessary_stmts (bool aggressive)
&& (e->flags & EDGE_IRREDUCIBLE_LOOP))
{
if (dump_file)
- fprintf (dump_file, "Marking back edge of irreducible loop %i->%i\n",
- e->src->index, e->dest->index);
+ fprintf (dump_file, "Marking back edge of irreducible "
+ "loop %i->%i\n", e->src->index, e->dest->index);
mark_control_dependent_edges_necessary (e->dest, false);
}
}
for (auto loop : loops_list (cfun, 0))
- if (!finite_loop_p (loop))
+ /* For loops without an exit do not mark any condition. */
+ if (loop->exits->next && !finite_loop_p (loop))
{
if (dump_file)
- fprintf (dump_file, "cannot prove finiteness of loop %i\n", loop->num);
+ fprintf (dump_file, "cannot prove finiteness of loop %i\n",
+ loop->num);
mark_control_dependent_edges_necessary (loop->latch, false);
}
}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index a0df492..a8a5b34 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -585,31 +585,137 @@ record_edge_info (basic_block bb)
}
}
-class dom_jump_threader_simplifier : public jump_threader_simplifier
+class dom_jt_state : public jt_state
{
public:
- dom_jump_threader_simplifier (vr_values *v,
- avail_exprs_stack *avails)
- : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
+ dom_jt_state (const_and_copies *copies, avail_exprs_stack *avails,
+ evrp_range_analyzer *evrp)
+ : m_copies (copies), m_avails (avails), m_evrp (evrp)
+ {
+ }
+ void push (edge e) override
+ {
+ m_copies->push_marker ();
+ m_avails->push_marker ();
+ m_evrp->push_marker ();
+ jt_state::push (e);
+ }
+ void pop () override
+ {
+ m_copies->pop_to_marker ();
+ m_avails->pop_to_marker ();
+ m_evrp->pop_to_marker ();
+ jt_state::pop ();
+ }
+ void register_equivs_edge (edge e) override
+ {
+ record_temporary_equivalences (e, m_copies, m_avails);
+ }
+ void record_ranges_from_stmt (gimple *stmt, bool temporary) override
+ {
+ m_evrp->record_ranges_from_stmt (stmt, temporary);
+ }
+ void register_equiv (tree dest, tree src, bool update) override;
+private:
+ const_and_copies *m_copies;
+ avail_exprs_stack *m_avails;
+ evrp_range_analyzer *m_evrp;
+};
+
+void
+dom_jt_state::register_equiv (tree dest, tree src, bool update)
+{
+ m_copies->record_const_or_copy (dest, src);
+
+ /* If requested, update the value range associated with DST, using
+ the range from SRC. */
+ if (update)
+ {
+ /* Get new VR we can pass to push_value_range. */
+ value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv ();
+ new (new_vr) value_range_equiv ();
+
+ /* There are three cases to consider:
+
+ First if SRC is an SSA_NAME, then we can copy the value range
+ from SRC into NEW_VR.
+
+ Second if SRC is an INTEGER_CST, then we can just set NEW_VR
+ to a singleton range. Note that even if SRC is a constant we
+ need to set a suitable output range so that VR_UNDEFINED
+ ranges do not leak through.
+
+ Otherwise set NEW_VR to varying. This may be overly
+ conservative. */
+ if (TREE_CODE (src) == SSA_NAME)
+ new_vr->deep_copy (m_evrp->get_value_range (src));
+ else if (TREE_CODE (src) == INTEGER_CST)
+ new_vr->set (src);
+ else
+ new_vr->set_varying (TREE_TYPE (src));
+
+ /* This is a temporary range for DST, so push it. */
+ m_evrp->push_value_range (dest, new_vr);
+ }
+}
+
+class dom_jt_simplifier : public jt_simplifier
+{
+public:
+ dom_jt_simplifier (vr_values *v, avail_exprs_stack *avails)
+ : m_vr_values (v), m_avails (avails) { }
private:
tree simplify (gimple *, gimple *, basic_block, jt_state *) override;
- avail_exprs_stack *m_avail_exprs_stack;
+ vr_values *m_vr_values;
+ avail_exprs_stack *m_avails;
};
tree
-dom_jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block bb,
- jt_state *state)
+dom_jt_simplifier::simplify (gimple *stmt, gimple *within_stmt,
+ basic_block, jt_state *)
{
/* First see if the conditional is in the hash table. */
- tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt,
- false, true);
+ tree cached_lhs = m_avails->lookup_avail_expr (stmt, false, true);
if (cached_lhs)
return cached_lhs;
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
+ if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+ {
+ simplify_using_ranges simplifier (m_vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ gimple_cond_lhs (cond_stmt),
+ gimple_cond_rhs (cond_stmt),
+ within_stmt);
+ }
+ if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
+ {
+ tree op = gimple_switch_index (switch_stmt);
+ if (TREE_CODE (op) != SSA_NAME)
+ return NULL_TREE;
+
+ const value_range_equiv *vr = m_vr_values->get_value_range (op);
+ return find_case_label_range (switch_stmt, vr);
+ }
+ if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
+ {
+ tree lhs = gimple_assign_lhs (assign_stmt);
+ if (TREE_CODE (lhs) == SSA_NAME
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && stmt_interesting_for_vrp (stmt))
+ {
+ edge dummy_e;
+ tree dummy_tree;
+ value_range_equiv new_vr;
+ m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree,
+ &new_vr);
+ tree singleton;
+ if (new_vr.singleton_p (&singleton))
+ return singleton;
+ }
+ }
+ return NULL;
}
class dom_opt_dom_walker : public dom_walker
@@ -752,8 +858,8 @@ pass_dominator::execute (function *fun)
/* Recursively walk the dominator tree optimizing statements. */
evrp_range_analyzer analyzer (true);
- dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack);
- jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
+ dom_jt_simplifier simplifier (&analyzer, avail_exprs_stack);
+ dom_jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
jump_threader threader (&simplifier, &state);
dom_opt_dom_walker walker (CDI_DOMINATORS,
&threader,
@@ -1704,7 +1810,7 @@ record_equivalences_from_stmt (gimple *stmt, int may_optimize_p,
CONST_AND_COPIES. */
static void
-cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
+cprop_operand (gimple *stmt, use_operand_p op_p, range_query *query)
{
tree val;
tree op = USE_FROM_PTR (op_p);
@@ -1714,7 +1820,12 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
CONST_AND_COPIES. */
val = SSA_NAME_VALUE (op);
if (!val)
- val = vr_values->op_with_constant_singleton_value_range (op);
+ {
+ value_range r;
+ tree single;
+ if (query->range_of_expr (r, op, stmt) && r.singleton_p (&single))
+ val = single;
+ }
if (val && val != op)
{
@@ -1772,7 +1883,7 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
vdef_ops of STMT. */
static void
-cprop_into_stmt (gimple *stmt, vr_values *vr_values)
+cprop_into_stmt (gimple *stmt, range_query *query)
{
use_operand_p op_p;
ssa_op_iter iter;
@@ -1789,7 +1900,7 @@ cprop_into_stmt (gimple *stmt, vr_values *vr_values)
operands. */
if (old_op != last_copy_propagated_op)
{
- cprop_operand (stmt, op_p, vr_values);
+ cprop_operand (stmt, op_p, query);
tree new_op = USE_FROM_PTR (op_p);
if (new_op != old_op && TREE_CODE (new_op) == SSA_NAME)
@@ -1891,6 +2002,66 @@ dom_opt_dom_walker::test_for_singularity (gimple *stmt,
}
}
+/* If STMT is a comparison of two uniform vectors reduce it to a comparison
+ of scalar objects, otherwise leave STMT unchanged. */
+
+static void
+reduce_vector_comparison_to_scalar_comparison (gimple *stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_COND)
+ {
+ tree lhs = gimple_cond_lhs (stmt);
+ tree rhs = gimple_cond_rhs (stmt);
+
+ /* We may have a vector comparison where both arms are uniform
+ vectors. If so, we can simplify the vector comparison down
+ to a scalar comparison. */
+ if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE)
+ {
+ /* If either operand is an SSA_NAME, then look back to its
+ defining statement to try and get at a suitable source. */
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
+ if (gimple_assign_single_p (def_stmt))
+ rhs = gimple_assign_rhs1 (def_stmt);
+ }
+
+ if (TREE_CODE (lhs) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (lhs);
+ if (gimple_assign_single_p (def_stmt))
+ lhs = gimple_assign_rhs1 (def_stmt);
+ }
+
+ /* Now see if they are both uniform vectors and if so replace
+ the vector comparison with a scalar comparison. */
+ tree rhs_elem = rhs ? uniform_vector_p (rhs) : NULL_TREE;
+ tree lhs_elem = lhs ? uniform_vector_p (lhs) : NULL_TREE;
+ if (rhs_elem && lhs_elem)
+ {
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Reducing vector comparison: ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ gimple_cond_set_rhs (as_a <gcond *>(stmt), rhs_elem);
+ gimple_cond_set_lhs (as_a <gcond *>(stmt), lhs_elem);
+ gimple_set_modified (stmt, true);
+
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "To scalar equivalent: ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, "\n");
+ }
+ }
+ }
+ }
+}
+
/* Optimize the statement in block BB pointed to by iterator SI.
We try to perform some simplistic global redundancy elimination and
@@ -1930,6 +2101,11 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
+ /* STMT may be a comparison of uniform vectors that we can simplify
+ down to a comparison of scalars. Do that transformation first
+ so that all the scalar optimizations from here onward apply. */
+ reduce_vector_comparison_to_scalar_comparison (stmt);
+
update_stmt_if_modified (stmt);
opt_stats.num_stmts++;
@@ -2032,8 +2208,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
SSA_NAMES. */
update_stmt_if_modified (stmt);
edge taken_edge = NULL;
- m_evrp_range_analyzer->vrp_visit_cond_stmt
- (as_a <gcond *> (stmt), &taken_edge);
+ simplify_using_ranges simpl (m_evrp_range_analyzer);
+ simpl.vrp_visit_cond_stmt (as_a <gcond *> (stmt), &taken_edge);
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 98daa8a..27287fe 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -978,6 +978,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
fprintf (dump_file, "\n");
}
+ basic_block bb = gimple_bb (stmt);
tree lhs = gimple_call_lhs (stmt);
if (lhs)
{
@@ -985,7 +986,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
gimple *new_stmt = gimple_build_assign (lhs, ptr);
unlink_stmt_vdef (stmt);
if (gsi_replace (gsi, new_stmt, true))
- bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+ bitmap_set_bit (need_eh_cleanup, bb->index);
}
else
{
@@ -994,7 +995,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
/* Remove the dead store. */
if (gsi_remove (gsi, true))
- bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+ bitmap_set_bit (need_eh_cleanup, bb->index);
release_defs (stmt);
}
}
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index b4e09f9..ffb0aa8 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-inline.h"
-#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
#include "tree-ssa-sccvn.h"
#include "tree-phinodes.h"
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index d9f75d5..4b187c2 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -3030,19 +3030,30 @@ do_store_motion (void)
static void
fill_always_executed_in_1 (class loop *loop, sbitmap contains_call)
{
- basic_block bb = NULL, *bbs, last = NULL;
- unsigned i;
+ basic_block bb = NULL, last = NULL;
edge e;
class loop *inn_loop = loop;
if (ALWAYS_EXECUTED_IN (loop->header) == NULL)
{
- bbs = get_loop_body_in_dom_order (loop);
-
- for (i = 0; i < loop->num_nodes; i++)
+ auto_vec<basic_block, 64> worklist;
+ worklist.reserve_exact (loop->num_nodes);
+ worklist.quick_push (loop->header);
+ do
{
edge_iterator ei;
- bb = bbs[i];
+ bb = worklist.pop ();
+
+ if (!flow_bb_inside_loop_p (inn_loop, bb))
+ {
+ /* When we are leaving a possibly infinite inner loop
+ we have to stop processing. */
+ if (!finite_loop_p (inn_loop))
+ break;
+ /* If the loop was finite we can continue with processing
+ the loop we exited to. */
+ inn_loop = bb->loop_father;
+ }
if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
last = bb;
@@ -3050,17 +3061,10 @@ fill_always_executed_in_1 (class loop *loop, sbitmap contains_call)
if (bitmap_bit_p (contains_call, bb->index))
break;
+ /* If LOOP exits from this BB stop processing. */
FOR_EACH_EDGE (e, ei, bb->succs)
- {
- /* If there is an exit from this BB. */
- if (!flow_bb_inside_loop_p (loop, e->dest))
- break;
- /* Or we enter a possibly non-finite loop. */
- if (flow_loop_nested_p (bb->loop_father,
- e->dest->loop_father)
- && ! finite_loop_p (e->dest->loop_father))
- break;
- }
+ if (!flow_bb_inside_loop_p (loop, e->dest))
+ break;
if (e)
break;
@@ -3069,29 +3073,51 @@ fill_always_executed_in_1 (class loop *loop, sbitmap contains_call)
if (bb->flags & BB_IRREDUCIBLE_LOOP)
break;
- if (!flow_bb_inside_loop_p (inn_loop, bb))
- break;
-
if (bb->loop_father->header == bb)
+ /* Record that we enter into a subloop since it might not
+ be finite. */
+ /* ??? Entering into a not always executed subloop makes
+ fill_always_executed_in quadratic in loop depth since
+ we walk those loops N times. This is not a problem
+ in practice though, see PR102253 for a worst-case testcase. */
+ inn_loop = bb->loop_father;
+
+ /* Walk the body of LOOP sorted by dominance relation. Additionally,
+ if a basic block S dominates the latch, then only blocks dominated
+ by S are after it.
+ This is get_loop_body_in_dom_order using a worklist algorithm and
+ stopping once we are no longer interested in visiting further
+ blocks. */
+ unsigned old_len = worklist.length ();
+ unsigned postpone = 0;
+ for (basic_block son = first_dom_son (CDI_DOMINATORS, bb);
+ son;
+ son = next_dom_son (CDI_DOMINATORS, son))
{
- if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
- break;
-
- /* In a loop that is always entered we may proceed anyway.
- But record that we entered it and stop once we leave it. */
- inn_loop = bb->loop_father;
+ if (!flow_bb_inside_loop_p (loop, son))
+ continue;
+ if (dominated_by_p (CDI_DOMINATORS, loop->latch, son))
+ postpone = worklist.length ();
+ worklist.quick_push (son);
}
+ if (postpone)
+ /* Postponing the block that dominates the latch means
+ processing it last and thus putting it earliest in the
+ worklist. */
+ std::swap (worklist[old_len], worklist[postpone]);
}
+ while (!worklist.is_empty ());
while (1)
{
+ if (dump_enabled_p ())
+ dump_printf (MSG_NOTE, "BB %d is always executed in loop %d\n",
+ last->index, loop->num);
SET_ALWAYS_EXECUTED_IN (last, loop);
if (last == loop->header)
break;
last = get_immediate_dominator (CDI_DOMINATORS, last);
}
-
- free (bbs);
}
for (loop = loop->inner; loop; loop = loop->next)
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index c7a2f67..2d576bf 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -1182,8 +1182,9 @@ niter_for_unrolled_loop (class loop *loop, unsigned factor)
return new_est_niter;
}
-/* Unroll LOOP FACTOR times. DESC describes number of iterations of LOOP.
- EXIT is the exit of the loop to that DESC corresponds.
+/* Unroll LOOP FACTOR times. LOOP is known to have a single exit edge
+ whose source block dominates the latch. DESC describes the number of
+ iterations of LOOP.
If N is number of iterations of the loop and MAY_BE_ZERO is the condition
under that loop exits in the first iteration even if N != 0,
@@ -1241,7 +1242,7 @@ niter_for_unrolled_loop (class loop *loop, unsigned factor)
void
tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
- edge exit, class tree_niter_desc *desc,
+ class tree_niter_desc *desc,
transform_callback transform,
void *data)
{
@@ -1265,10 +1266,11 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
gcond *exit_if = nullptr;
class loop *new_loop = nullptr;
- basic_block rest;
edge new_exit;
if (!single_loop_p)
{
+ edge exit = single_dom_exit (loop);
+
/* The values for scales should keep profile consistent, and somewhat
close to correct.
@@ -1291,7 +1293,7 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
/* Prepare the cfg and update the phi nodes. Move the loop exit to the
loop latch (and make its condition dummy, for the moment). */
- rest = loop_preheader_edge (new_loop)->src;
+ basic_block rest = loop_preheader_edge (new_loop)->src;
edge precond_edge = single_pred_edge (rest);
split_edge (loop_latch_edge (loop));
basic_block exit_bb = single_pred (loop->latch);
@@ -1373,10 +1375,7 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
remove_path (exit);
}
else
- {
- new_exit = exit;
- rest = exit->dest;
- }
+ new_exit = single_dom_exit (loop);
/* Transform the loop. */
if (transform)
@@ -1401,6 +1400,7 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
}
update_ssa (TODO_update_ssa);
+ new_exit = single_dom_exit (loop);
if (!single_loop_p)
{
/* Ensure that the frequencies in the loop match the new estimated
@@ -1417,29 +1417,24 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
freq_e = freq_e.force_nonzero ();
scale_loop_frequencies (loop, freq_e.probability_in (freq_h));
}
- }
- basic_block exit_bb = single_pred (loop->latch);
- new_exit = find_edge (exit_bb, rest);
- new_exit->probability = profile_probability::always ()
- .apply_scale (1, new_est_niter + 1);
+ basic_block rest = new_exit->dest;
+ new_exit->probability = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
- if (!single_loop_p)
- rest->count += new_exit->count ();
+ rest->count += new_exit->count ();
- edge new_nonexit = single_pred_edge (loop->latch);
- profile_probability prob = new_nonexit->probability;
- new_nonexit->probability = new_exit->probability.invert ();
- prob = new_nonexit->probability / prob;
- if (prob.initialized_p ())
- scale_bbs_frequencies (&loop->latch, 1, prob);
+ edge new_nonexit = single_pred_edge (loop->latch);
+ profile_probability prob = new_nonexit->probability;
+ new_nonexit->probability = new_exit->probability.invert ();
+ prob = new_nonexit->probability / prob;
+ if (prob.initialized_p ())
+ scale_bbs_frequencies (&loop->latch, 1, prob);
- if (!single_loop_p)
- {
/* Finally create the new counter for number of iterations and add
the new exit instruction. */
tree ctr_before, ctr_after;
- gimple_stmt_iterator bsi = gsi_last_nondebug_bb (exit_bb);
+ gimple_stmt_iterator bsi = gsi_last_nondebug_bb (new_exit->src);
exit_if = as_a <gcond *> (gsi_stmt (bsi));
create_iv (exit_base, exit_step, NULL_TREE, loop,
&bsi, false, &ctr_before, &ctr_after);
@@ -1448,6 +1443,67 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
gimple_cond_set_rhs (exit_if, exit_bound);
update_stmt (exit_if);
}
+ else
+ {
+ /* gimple_duplicate_loop_to_header_edge has adjusted the loop body's
+ original profile counts in line with the unroll factor. However,
+ the old counts might not have been consistent with the old
+ iteration count.
+
+ Therefore, if the iteration count is known exactly, make sure that the
+ profile counts of the loop header (and any other blocks that might be
+ executed in the final iteration) are consistent with the combination
+ of (a) the incoming profile count and (b) the new iteration count. */
+ profile_count in_count = loop_preheader_edge (loop)->count ();
+ profile_count old_header_count = loop->header->count;
+ if (in_count.nonzero_p ()
+ && old_header_count.nonzero_p ()
+ && TREE_CODE (desc->niter) == INTEGER_CST)
+ {
+ /* The + 1 converts latch counts to iteration counts. */
+ profile_count new_header_count
+ = (in_count.apply_scale (new_est_niter + 1, 1));
+ basic_block *body = get_loop_body (loop);
+ scale_bbs_frequencies_profile_count (body, loop->num_nodes,
+ new_header_count,
+ old_header_count);
+ free (body);
+ }
+
+ /* gimple_duplicate_loop_to_header_edge discarded FACTOR - 1
+ exit edges and adjusted the loop body's profile counts for the
+ new probabilities of the remaining non-exit edges. However,
+ the remaining exit edge still has the same probability as it
+ did before, even though it is now more likely.
+
+ Therefore, all blocks executed after a failed exit test now have
+ a profile count that is too high, and the sum of the profile counts
+ for the header's incoming edges is greater than the profile count
+ of the header itself.
+
+ Adjust the profile counts of all code in the loop body after
+ the exit test so that the sum of the counts on entry to the
+ header agree. */
+ profile_count old_latch_count = loop_latch_edge (loop)->count ();
+ profile_count new_latch_count = loop->header->count - in_count;
+ if (old_latch_count.nonzero_p () && new_latch_count.nonzero_p ())
+ scale_dominated_blocks_in_loop (loop, new_exit->src, new_latch_count,
+ old_latch_count);
+
+ /* Set the probability of the exit edge based on NEW_EST_NITER
+ (which estimates latch counts rather than iteration counts).
+ Update the probabilities of other edges to match.
+
+ If the profile counts are large enough to give the required
+ precision, the updates above will have made
+
+ e->dest->count / e->src->count ~= new e->probability
+
+ for every outgoing edge e of NEW_EXIT->src. */
+ profile_probability new_exit_prob = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
+ change_edge_frequency (new_exit, new_exit_prob);
+ }
checking_verify_flow_info ();
checking_verify_loop_structure ();
@@ -1461,10 +1517,9 @@ tree_transform_and_unroll_loop (class loop *loop, unsigned factor,
void
tree_unroll_loop (class loop *loop, unsigned factor,
- edge exit, class tree_niter_desc *desc)
+ class tree_niter_desc *desc)
{
- tree_transform_and_unroll_loop (loop, factor, exit, desc,
- NULL, NULL);
+ tree_transform_and_unroll_loop (loop, factor, desc, NULL, NULL);
}
/* Rewrite the phi node at position PSI in function of the main
diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h
index 86fc118..5e2d7fa 100644
--- a/gcc/tree-ssa-loop-manip.h
+++ b/gcc/tree-ssa-loop-manip.h
@@ -50,10 +50,9 @@ extern bool can_unroll_loop_p (class loop *loop, unsigned factor,
class tree_niter_desc *niter);
extern gcov_type niter_for_unrolled_loop (class loop *, unsigned);
extern void tree_transform_and_unroll_loop (class loop *, unsigned,
- edge, class tree_niter_desc *,
+ tree_niter_desc *,
transform_callback, void *);
-extern void tree_unroll_loop (class loop *, unsigned,
- edge, class tree_niter_desc *);
+extern void tree_unroll_loop (class loop *, unsigned, tree_niter_desc *);
extern tree canonicalize_loop_ivs (class loop *, tree *, bool);
extern unsigned int loop_invariant_motion_in_fun (function *, bool);
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7af92d1..7510940 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1482,7 +1482,7 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
affine_iv *iv1, class tree_niter_desc *niter)
{
tree niter_type = unsigned_type_for (type);
- tree step, num, assumptions, may_be_zero;
+ tree step, num, assumptions, may_be_zero, span;
wide_int high, low, max, min;
may_be_zero = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, iv0->base);
@@ -1557,6 +1557,20 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0,
niter->control.no_overflow = false;
+ /* Update bound and exit condition as:
+ bound = niter * STEP + (IVbase - STEP).
+ { IVbase - STEP, +, STEP } != bound
+ Here, biasing IVbase by 1 step makes 'bound' be the value before wrap.
+ */
+ niter->control.base = fold_build2 (MINUS_EXPR, niter_type,
+ niter->control.base, niter->control.step);
+ span = fold_build2 (MULT_EXPR, niter_type, niter->niter,
+ fold_convert (niter_type, niter->control.step));
+ niter->bound = fold_build2 (PLUS_EXPR, niter_type, span,
+ fold_convert (niter_type, niter->control.base));
+ niter->bound = fold_convert (type, niter->bound);
+ niter->cmp = NE_EXPR;
+
return true;
}
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index 85977e2..04b2b33 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -1962,8 +1962,7 @@ loop_prefetch_arrays (class loop *loop)
iterations so that we do not issue superfluous prefetches. */
if (unroll_factor != 1)
{
- tree_unroll_loop (loop, unroll_factor,
- single_dom_exit (loop), &desc);
+ tree_unroll_loop (loop, unroll_factor, &desc);
unrolled = true;
}
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 0cc4b3b..1bbf2f1 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -540,7 +540,7 @@ const pass_data pass_data_tree_loop_done =
OPTGROUP_LOOP, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
- 0, /* properties_provided */
+ PROP_loop_opts_done, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_cleanup_cfg, /* todo_flags_finish */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index ebe95cc..1cc1aae 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1237,21 +1237,18 @@ fully_constant_expression (pre_expr e)
return e;
}
-/* Translate the VUSE backwards through phi nodes in PHIBLOCK, so that
- it has the value it would have in BLOCK. Set *SAME_VALID to true
+/* Translate the VUSE backwards through phi nodes in E->dest, so that
+ it has the value it would have in E->src. Set *SAME_VALID to true
in case the new vuse doesn't change the value id of the OPERANDS. */
static tree
translate_vuse_through_block (vec<vn_reference_op_s> operands,
alias_set_type set, alias_set_type base_set,
- tree type, tree vuse,
- basic_block phiblock,
- basic_block block, bool *same_valid)
+ tree type, tree vuse, edge e, bool *same_valid)
{
+ basic_block phiblock = e->dest;
gimple *phi = SSA_NAME_DEF_STMT (vuse);
ao_ref ref;
- edge e = NULL;
- bool use_oracle;
if (same_valid)
*same_valid = true;
@@ -1259,59 +1256,40 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands,
if (gimple_bb (phi) != phiblock)
return vuse;
- unsigned int cnt = param_sccvn_max_alias_queries_per_access;
- use_oracle = ao_ref_init_from_vn_reference (&ref, set, base_set,
- type, operands);
-
- /* Use the alias-oracle to find either the PHI node in this block,
- the first VUSE used in this block that is equivalent to vuse or
- the first VUSE which definition in this block kills the value. */
- if (gimple_code (phi) == GIMPLE_PHI)
- e = find_edge (block, phiblock);
- else if (use_oracle)
- while (cnt > 0
- && !stmt_may_clobber_ref_p_1 (phi, &ref))
- {
- --cnt;
- vuse = gimple_vuse (phi);
- phi = SSA_NAME_DEF_STMT (vuse);
- if (gimple_bb (phi) != phiblock)
- return vuse;
- if (gimple_code (phi) == GIMPLE_PHI)
- {
- e = find_edge (block, phiblock);
- break;
- }
- }
- else
- return NULL_TREE;
-
- if (e)
+ /* We have pruned expressions that are killed in PHIBLOCK via
+ prune_clobbered_mems but we have not rewritten the VUSE to the one
+ live at the start of the block. If there is no virtual PHI to translate
+ through return the VUSE live at entry. Otherwise the VUSE to translate
+ is the def of the virtual PHI node. */
+ phi = get_virtual_phi (phiblock);
+ if (!phi)
+ return BB_LIVE_VOP_ON_EXIT
+ (get_immediate_dominator (CDI_DOMINATORS, phiblock));
+
+ if (same_valid
+ && ao_ref_init_from_vn_reference (&ref, set, base_set, type, operands))
{
- if (use_oracle && same_valid)
- {
- bitmap visited = NULL;
- /* Try to find a vuse that dominates this phi node by skipping
- non-clobbering statements. */
- vuse = get_continuation_for_phi (phi, &ref, true,
- cnt, &visited, false, NULL, NULL);
- if (visited)
- BITMAP_FREE (visited);
- }
- else
- vuse = NULL_TREE;
- /* If we didn't find any, the value ID can't stay the same. */
- if (!vuse && same_valid)
- *same_valid = false;
- /* ??? We would like to return vuse here as this is the canonical
- upmost vdef that this reference is associated with. But during
- insertion of the references into the hash tables we only ever
- directly insert with their direct gimple_vuse, hence returning
- something else would make us not find the other expression. */
- return PHI_ARG_DEF (phi, e->dest_idx);
+ bitmap visited = NULL;
+ /* Try to find a vuse that dominates this phi node by skipping
+ non-clobbering statements. */
+ unsigned int cnt = param_sccvn_max_alias_queries_per_access;
+ vuse = get_continuation_for_phi (phi, &ref, true,
+ cnt, &visited, false, NULL, NULL);
+ if (visited)
+ BITMAP_FREE (visited);
}
-
- return NULL_TREE;
+ else
+ vuse = NULL_TREE;
+ /* If we didn't find any, the value ID can't stay the same. */
+ if (!vuse && same_valid)
+ *same_valid = false;
+
+ /* ??? We would like to return vuse here as this is the canonical
+ upmost vdef that this reference is associated with. But during
+ insertion of the references into the hash tables we only ever
+ directly insert with their direct gimple_vuse, hence returning
+ something else would make us not find the other expression. */
+ return PHI_ARG_DEF (phi, e->dest_idx);
}
/* Like bitmap_find_leader, but checks for the value existing in SET1 *or*
@@ -1630,8 +1608,7 @@ phi_translate_1 (bitmap_set_t dest,
newvuse = translate_vuse_through_block (newoperands.exists ()
? newoperands : operands,
ref->set, ref->base_set,
- ref->type,
- vuse, phiblock, pred,
+ ref->type, vuse, e,
changed
? NULL : &same_valid);
if (newvuse == NULL_TREE)
@@ -2878,9 +2855,13 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
unsigned int operand = 1;
vn_reference_op_t currop = &ref->operands[0];
tree sc = NULL_TREE;
- tree fn = find_or_generate_expression (block, currop->op0, stmts);
- if (!fn)
- return NULL_TREE;
+ tree fn = NULL_TREE;
+ if (currop->op0)
+ {
+ fn = find_or_generate_expression (block, currop->op0, stmts);
+ if (!fn)
+ return NULL_TREE;
+ }
if (currop->op1)
{
sc = find_or_generate_expression (block, currop->op1, stmts);
@@ -2896,12 +2877,19 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
return NULL_TREE;
args.quick_push (arg);
}
- gcall *call = gimple_build_call_vec (fn, args);
+ gcall *call;
+ if (currop->op0)
+ {
+ call = gimple_build_call_vec (fn, args);
+ gimple_call_set_fntype (call, currop->type);
+ }
+ else
+ call = gimple_build_call_internal_vec ((internal_fn)currop->clique,
+ args);
gimple_set_location (call, expr->loc);
- gimple_call_set_fntype (call, currop->type);
if (sc)
gimple_call_set_chain (call, sc);
- tree forcedname = make_ssa_name (TREE_TYPE (currop->type));
+ tree forcedname = make_ssa_name (ref->type);
gimple_call_set_lhs (call, forcedname);
/* There's no CCP pass after PRE which would re-compute alignment
information so make sure we re-materialize this here. */
@@ -3957,6 +3945,7 @@ compute_avail (function *fun)
/* Now compute value numbers and populate value sets with all
the expressions computed in BLOCK. */
+ bool set_bb_may_notreturn = false;
for (gimple_stmt_iterator gsi = gsi_start_bb (block); !gsi_end_p (gsi);
gsi_next (&gsi))
{
@@ -3965,6 +3954,12 @@ compute_avail (function *fun)
stmt = gsi_stmt (gsi);
+ if (set_bb_may_notreturn)
+ {
+ BB_MAY_NOTRETURN (block) = 1;
+ set_bb_may_notreturn = false;
+ }
+
/* Cache whether the basic-block has any non-visible side-effect
or control flow.
If this isn't a call or it is the last stmt in the
@@ -3976,10 +3971,12 @@ compute_avail (function *fun)
that forbids hoisting possibly trapping expressions
before it. */
int flags = gimple_call_flags (stmt);
- if (!(flags & ECF_CONST)
+ if (!(flags & (ECF_CONST|ECF_PURE))
|| (flags & ECF_LOOPING_CONST_OR_PURE)
|| stmt_can_throw_external (fun, stmt))
- BB_MAY_NOTRETURN (block) = 1;
+ /* Defer setting of BB_MAY_NOTRETURN to avoid it
+ influencing the processing of the call itself. */
+ set_bb_may_notreturn = true;
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
@@ -4018,10 +4015,6 @@ compute_avail (function *fun)
vn_reference_s ref1;
pre_expr result = NULL;
- /* We can value number only calls to real functions. */
- if (gimple_call_internal_p (stmt))
- continue;
-
vn_reference_lookup_call (as_a <gcall *> (stmt), &ref, &ref1);
/* There is no point to PRE a call without a value. */
if (!ref || !ref->result)
@@ -4030,11 +4023,16 @@ compute_avail (function *fun)
/* If the value of the call is not invalidated in
this block until it is computed, add the expression
to EXP_GEN. */
- if (!gimple_vuse (stmt)
- || gimple_code
- (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI
- || gimple_bb (SSA_NAME_DEF_STMT
- (gimple_vuse (stmt))) != block)
+ if ((!gimple_vuse (stmt)
+ || gimple_code
+ (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI
+ || gimple_bb (SSA_NAME_DEF_STMT
+ (gimple_vuse (stmt))) != block)
+ /* If the REFERENCE traps and there was a preceding
+ point in the block that might not return avoid
+ adding the reference to EXP_GEN. */
+ && (!BB_MAY_NOTRETURN (block)
+ || !vn_reference_may_trap (ref)))
{
result = get_or_alloc_expr_for_reference
(ref, gimple_location (stmt));
@@ -4220,6 +4218,11 @@ compute_avail (function *fun)
break;
}
}
+ if (set_bb_may_notreturn)
+ {
+ BB_MAY_NOTRETURN (block) = 1;
+ set_bb_may_notreturn = false;
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 8498cfc..db9fb4e 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -180,6 +180,10 @@ along with GCC; see the file COPYING3. If not see
point 3a in the pass header comment. */
static bool reassoc_insert_powi_p;
+/* Enable biasing ranks of loop accumulators. We don't want this before
+ vectorization, since it interferes with reduction chains. */
+static bool reassoc_bias_loop_carried_phi_ranks_p;
+
/* Statistics */
static struct
{
@@ -207,6 +211,10 @@ static int64_t *bb_rank;
/* Operand->rank hashtable. */
static hash_map<tree, int64_t> *operand_rank;
+/* SSA_NAMEs that are forms of loop accumulators and whose ranks need to be
+ biased. */
+static auto_bitmap biased_names;
+
/* Vector of SSA_NAMEs on which after reassociate_bb is done with
all basic blocks the CFG should be adjusted - basic blocks
split right after that SSA_NAME's definition statement and before
@@ -252,6 +260,53 @@ reassoc_remove_stmt (gimple_stmt_iterator *gsi)
the rank difference between two blocks. */
#define PHI_LOOP_BIAS (1 << 15)
+/* Return TRUE iff PHI_LOOP_BIAS should be propagated from one of the STMT's
+ operands to the STMT's left-hand side. The goal is to preserve bias in code
+ like this:
+
+ x_1 = phi(x_0, x_2)
+ a = x_1 | 1
+ b = a ^ 2
+ .MEM = b
+ c = b + d
+ x_2 = c + e
+
+ That is, we need to preserve bias along single-use chains originating from
+ loop-carried phis. Only GIMPLE_ASSIGNs to SSA_NAMEs are considered to be
+ uses, because only they participate in rank propagation. */
+static bool
+propagate_bias_p (gimple *stmt)
+{
+ use_operand_p use;
+ imm_use_iterator use_iter;
+ gimple *single_use_stmt = NULL;
+
+ if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_reference)
+ return false;
+
+ FOR_EACH_IMM_USE_FAST (use, use_iter, gimple_assign_lhs (stmt))
+ {
+ gimple *current_use_stmt = USE_STMT (use);
+
+ if (is_gimple_assign (current_use_stmt)
+ && TREE_CODE (gimple_assign_lhs (current_use_stmt)) == SSA_NAME)
+ {
+ if (single_use_stmt != NULL && single_use_stmt != current_use_stmt)
+ return false;
+ single_use_stmt = current_use_stmt;
+ }
+ }
+
+ if (single_use_stmt == NULL)
+ return false;
+
+ if (gimple_bb (stmt)->loop_father
+ != gimple_bb (single_use_stmt)->loop_father)
+ return false;
+
+ return true;
+}
+
/* Rank assigned to a phi statement. If STMT is a loop-carried phi of
an innermost loop, and the phi has only a single use which is inside
the loop, then the rank is the block rank of the loop latch plus an
@@ -269,6 +324,9 @@ phi_rank (gimple *stmt)
use_operand_p use;
gimple *use_stmt;
+ if (!reassoc_bias_loop_carried_phi_ranks_p)
+ return bb_rank[bb->index];
+
/* We only care about real loops (those with a latch). */
if (!father->latch)
return bb_rank[bb->index];
@@ -306,49 +364,27 @@ phi_rank (gimple *stmt)
return bb_rank[bb->index];
}
-/* If EXP is an SSA_NAME defined by a PHI statement that represents a
- loop-carried dependence of an innermost loop, return TRUE; else
- return FALSE. */
-static bool
-loop_carried_phi (tree exp)
-{
- gimple *phi_stmt;
- int64_t block_rank;
-
- if (TREE_CODE (exp) != SSA_NAME
- || SSA_NAME_IS_DEFAULT_DEF (exp))
- return false;
-
- phi_stmt = SSA_NAME_DEF_STMT (exp);
-
- if (gimple_code (SSA_NAME_DEF_STMT (exp)) != GIMPLE_PHI)
- return false;
-
- /* Non-loop-carried phis have block rank. Loop-carried phis have
- an additional bias added in. If this phi doesn't have block rank,
- it's biased and should not be propagated. */
- block_rank = bb_rank[gimple_bb (phi_stmt)->index];
-
- if (phi_rank (phi_stmt) != block_rank)
- return true;
-
- return false;
-}
-
/* Return the maximum of RANK and the rank that should be propagated
from expression OP. For most operands, this is just the rank of OP.
For loop-carried phis, the value is zero to avoid undoing the bias
in favor of the phi. */
static int64_t
-propagate_rank (int64_t rank, tree op)
+propagate_rank (int64_t rank, tree op, bool *maybe_biased_p)
{
int64_t op_rank;
- if (loop_carried_phi (op))
- return rank;
-
op_rank = get_rank (op);
+ /* Check whether op is biased after the get_rank () call, since it might have
+ updated biased_names. */
+ if (TREE_CODE (op) == SSA_NAME
+ && bitmap_bit_p (biased_names, SSA_NAME_VERSION (op)))
+ {
+ if (maybe_biased_p == NULL)
+ return rank;
+ *maybe_biased_p = true;
+ }
+
return MAX (rank, op_rank);
}
@@ -426,13 +462,20 @@ get_rank (tree e)
stmt = SSA_NAME_DEF_STMT (e);
if (gimple_code (stmt) == GIMPLE_PHI)
- rank = phi_rank (stmt);
+ {
+ rank = phi_rank (stmt);
+ if (rank != bb_rank[gimple_bb (stmt)->index])
+ bitmap_set_bit (biased_names, SSA_NAME_VERSION (e));
+ }
else if (!is_gimple_assign (stmt))
rank = bb_rank[gimple_bb (stmt)->index];
else
{
+ bool biased_p = false;
+ bool *maybe_biased_p = propagate_bias_p (stmt) ? &biased_p : NULL;
+
/* 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. */
@@ -441,9 +484,11 @@ get_rank (tree e)
thus have rank 0. */
rank = 0;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
- rank = propagate_rank (rank, op);
+ rank = propagate_rank (rank, op, maybe_biased_p);
rank += 1;
+ if (biased_p)
+ bitmap_set_bit (biased_names, SSA_NAME_VERSION (e));
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -6926,6 +6971,7 @@ fini_reassoc (void)
reassociate_stats.pows_created);
delete operand_rank;
+ bitmap_clear (biased_names);
operand_entry_pool.release ();
free (bb_rank);
plus_negates.release ();
@@ -6940,9 +6986,10 @@ fini_reassoc (void)
optimization of a gimple conditional. Otherwise returns zero. */
static unsigned int
-execute_reassoc (bool insert_powi_p)
+execute_reassoc (bool insert_powi_p, bool bias_loop_carried_phi_ranks_p)
{
reassoc_insert_powi_p = insert_powi_p;
+ reassoc_bias_loop_carried_phi_ranks_p = bias_loop_carried_phi_ranks_p;
init_reassoc ();
@@ -6983,15 +7030,19 @@ public:
{
gcc_assert (n == 0);
insert_powi_p = param;
+ bias_loop_carried_phi_ranks_p = !param;
}
virtual bool gate (function *) { return flag_tree_reassoc != 0; }
virtual unsigned int execute (function *)
- { return execute_reassoc (insert_powi_p); }
+ {
+ return execute_reassoc (insert_powi_p, bias_loop_carried_phi_ranks_p);
+ }
private:
/* Enable insertion of __builtin_powi calls during execute_reassoc. See
point 3a in the pass header comment. */
bool insert_powi_p;
+ bool bias_loop_carried_phi_ranks_p;
}; // class pass_reassoc
} // anon namespace
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index bf87cee..ae0172a 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-ssa-loop-niter.h"
#include "builtins.h"
+#include "fold-const-call.h"
#include "tree-ssa-sccvn.h"
/* This algorithm is based on the SCC algorithm presented by Keith
@@ -212,7 +213,8 @@ vn_reference_op_eq (const void *p1, const void *p2)
TYPE_MAIN_VARIANT (vro2->type))))
&& expressions_equal_p (vro1->op0, vro2->op0)
&& expressions_equal_p (vro1->op1, vro2->op1)
- && expressions_equal_p (vro1->op2, vro2->op2));
+ && expressions_equal_p (vro1->op2, vro2->op2)
+ && (vro1->opcode != CALL_EXPR || vro1->clique == vro2->clique));
}
/* Free a reference operation structure VP. */
@@ -264,15 +266,18 @@ print_vn_reference_ops (FILE *outfile, const vec<vn_reference_op_s> ops)
&& TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
{
fprintf (outfile, "%s", get_tree_code_name (vro->opcode));
- if (vro->op0)
+ if (vro->op0 || vro->opcode == CALL_EXPR)
{
fprintf (outfile, "<");
closebrace = true;
}
}
- if (vro->op0)
+ if (vro->op0 || vro->opcode == CALL_EXPR)
{
- print_generic_expr (outfile, vro->op0);
+ if (!vro->op0)
+ fprintf (outfile, internal_fn_name ((internal_fn)vro->clique));
+ else
+ print_generic_expr (outfile, vro->op0);
if (vro->op1)
{
fprintf (outfile, ",");
@@ -684,6 +689,8 @@ static void
vn_reference_op_compute_hash (const vn_reference_op_t vro1, inchash::hash &hstate)
{
hstate.add_int (vro1->opcode);
+ if (vro1->opcode == CALL_EXPR && !vro1->op0)
+ hstate.add_int (vro1->clique);
if (vro1->op0)
inchash::add_expr (vro1->op0, hstate);
if (vro1->op1)
@@ -769,11 +776,16 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
if (vr1->type != vr2->type)
return false;
}
+ else if (vr1->type == vr2->type)
+ ;
else 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;
+ else if (vr1->operands[0].opcode == CALL_EXPR
+ && !types_compatible_p (vr1->type, vr2->type))
+ return false;
else if (INTEGRAL_TYPE_P (vr1->type)
&& INTEGRAL_TYPE_P (vr2->type))
{
@@ -1270,6 +1282,8 @@ copy_reference_ops_from_call (gcall *call,
temp.type = gimple_call_fntype (call);
temp.opcode = CALL_EXPR;
temp.op0 = gimple_call_fn (call);
+ if (gimple_call_internal_p (call))
+ temp.clique = gimple_call_internal_fn (call);
temp.op1 = gimple_call_chain (call);
if (stmt_could_throw_p (cfun, call) && (lr = lookup_stmt_eh_lp (call)) > 0)
temp.op2 = size_int (lr);
@@ -1459,9 +1473,11 @@ fully_constant_vn_reference_p (vn_reference_t ref)
a call to a builtin function with at most two arguments. */
op = &operands[0];
if (op->opcode == CALL_EXPR
- && TREE_CODE (op->op0) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
- && fndecl_built_in_p (TREE_OPERAND (op->op0, 0))
+ && (!op->op0
+ || (TREE_CODE (op->op0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
+ && fndecl_built_in_p (TREE_OPERAND (op->op0, 0),
+ BUILT_IN_NORMAL)))
&& operands.length () >= 2
&& operands.length () <= 3)
{
@@ -1481,13 +1497,17 @@ fully_constant_vn_reference_p (vn_reference_t ref)
anyconst = true;
if (anyconst)
{
- tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
- arg1 ? 2 : 1,
- arg0->op0,
- arg1 ? arg1->op0 : NULL);
- if (folded
- && TREE_CODE (folded) == NOP_EXPR)
- folded = TREE_OPERAND (folded, 0);
+ combined_fn fn;
+ if (op->op0)
+ fn = as_combined_fn (DECL_FUNCTION_CODE
+ (TREE_OPERAND (op->op0, 0)));
+ else
+ fn = as_combined_fn ((internal_fn) op->clique);
+ tree folded;
+ if (arg1)
+ folded = fold_const_call (fn, ref->type, arg0->op0, arg1->op0);
+ else
+ folded = fold_const_call (fn, ref->type, arg0->op0);
if (folded
&& is_gimple_min_invariant (folded))
return folded;
@@ -2321,11 +2341,13 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
}
/* Return a value-number for RCODE OPS... either by looking up an existing
- value-number for the simplified result or by inserting the operation if
- INSERT is true. */
+ value-number for the possibly simplified result or by inserting the
+ operation if INSERT is true. If SIMPLIFY is false, return a value
+ number for the unsimplified expression. */
static tree
-vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
+vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert,
+ bool simplify)
{
tree result = NULL_TREE;
/* We will be creating a value number for
@@ -2333,15 +2355,16 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
So first simplify and lookup this expression to see if it
is already available. */
/* For simplification valueize. */
- unsigned i;
- for (i = 0; i < res_op->num_ops; ++i)
- if (TREE_CODE (res_op->ops[i]) == SSA_NAME)
- {
- tree tem = vn_valueize (res_op->ops[i]);
- if (!tem)
- break;
- res_op->ops[i] = tem;
- }
+ unsigned i = 0;
+ if (simplify)
+ for (i = 0; i < res_op->num_ops; ++i)
+ if (TREE_CODE (res_op->ops[i]) == SSA_NAME)
+ {
+ tree tem = vn_valueize (res_op->ops[i]);
+ if (!tem)
+ break;
+ res_op->ops[i] = tem;
+ }
/* If valueization of an operand fails (it is not available), skip
simplification. */
bool res = false;
@@ -2440,7 +2463,7 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
static tree
vn_nary_build_or_lookup (gimple_match_op *res_op)
{
- return vn_nary_build_or_lookup_1 (res_op, true);
+ return vn_nary_build_or_lookup_1 (res_op, true, true);
}
/* Try to simplify the expression RCODE OPS... of type TYPE and return
@@ -2454,7 +2477,7 @@ vn_nary_simplify (vn_nary_op_t nary)
gimple_match_op op (gimple_match_cond::UNCOND, nary->opcode,
nary->type, nary->length);
memcpy (op.ops, nary->op, sizeof (tree) * nary->length);
- return vn_nary_build_or_lookup_1 (&op, false);
+ return vn_nary_build_or_lookup_1 (&op, false, true);
}
/* Elimination engine. */
@@ -3808,6 +3831,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
if (result && TREE_CODE (result) == SSA_NAME)
result = SSA_VAL (result);
vr1->result = result;
+ vr1->result_vdef = NULL_TREE;
slot = valid_info->references->find_slot_with_hash (vr1, vr1->hashcode,
INSERT);
@@ -4105,7 +4129,7 @@ vn_nary_op_insert_into (vn_nary_op_t vno, vn_nary_op_table_type *table,
bool found = false;
for (vn_pval *val = (*slot)->u.values; val; val = val->next)
{
- if (expressions_equal_p (val->result, vno->u.values->result))
+ if (expressions_equal_p (val->result, nval->result))
{
found = true;
for (unsigned i = 0; i < val->n; ++i)
@@ -5006,7 +5030,7 @@ visit_nary_op (tree lhs, gassign *stmt)
tree ops[2];
gimple_match_op match_op (gimple_match_cond::UNCOND,
NEGATE_EXPR, type, rhs[i]);
- ops[i] = vn_nary_build_or_lookup_1 (&match_op, false);
+ ops[i] = vn_nary_build_or_lookup_1 (&match_op, false, true);
ops[j] = rhs[j];
if (ops[i]
&& (ops[0] = vn_nary_op_lookup_pieces (2, code,
@@ -5014,7 +5038,7 @@ visit_nary_op (tree lhs, gassign *stmt)
{
gimple_match_op match_op (gimple_match_cond::UNCOND,
NEGATE_EXPR, type, ops[0]);
- result = vn_nary_build_or_lookup (&match_op);
+ result = vn_nary_build_or_lookup_1 (&match_op, true, false);
if (result)
{
bool changed = set_ssa_val_to (lhs, result);
@@ -5121,13 +5145,12 @@ static bool
visit_reference_op_load (tree lhs, tree op, gimple *stmt)
{
bool changed = false;
- tree last_vuse;
tree result;
vn_reference_t res;
- last_vuse = gimple_vuse (stmt);
- result = vn_reference_lookup (op, gimple_vuse (stmt),
- default_vn_walk_kind, &res, true, &last_vuse);
+ tree vuse = gimple_vuse (stmt);
+ tree last_vuse = vuse;
+ result = vn_reference_lookup (op, vuse, default_vn_walk_kind, &res, true, &last_vuse);
/* We handle type-punning through unions by value-numbering based
on offset and size of the access. Be prepared to handle a
@@ -5170,6 +5193,16 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
{
changed = set_ssa_val_to (lhs, lhs);
vn_reference_insert (op, lhs, last_vuse, NULL_TREE);
+ if (vuse && SSA_VAL (last_vuse) != SSA_VAL (vuse))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Using extra use virtual operand ");
+ print_generic_expr (dump_file, last_vuse);
+ fprintf (dump_file, "\n");
+ }
+ vn_reference_insert (op, lhs, vuse, NULL_TREE);
+ }
}
return changed;
@@ -5635,28 +5668,30 @@ visit_stmt (gimple *stmt, bool backedges_varying_p = false)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
}
- if (!gimple_call_internal_p (call_stmt)
- && (/* Calls to the same function with the same vuse
- and the same operands do not necessarily return the same
- value, unless they're pure or const. */
- ((gimple_call_flags (call_stmt) | extra_fnflags)
- & (ECF_PURE | ECF_CONST))
- /* If calls have a vdef, subsequent calls won't have
- the same incoming vuse. So, if 2 calls with vdef have the
- same vuse, we know they're not subsequent.
- We can value number 2 calls to the same function with the
- same vuse and the same operands which are not subsequent
- the same, because there is no code in the program that can
- compare the 2 values... */
- || (gimple_vdef (call_stmt)
- /* ... unless the call returns a pointer which does
- not alias with anything else. In which case the
- information that the values are distinct are encoded
- in the IL. */
- && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
- /* Only perform the following when being called from PRE
- which embeds tail merging. */
- && default_vn_walk_kind == VN_WALK)))
+ if ((/* Calls to the same function with the same vuse
+ and the same operands do not necessarily return the same
+ value, unless they're pure or const. */
+ ((gimple_call_flags (call_stmt) | extra_fnflags)
+ & (ECF_PURE | ECF_CONST))
+ /* If calls have a vdef, subsequent calls won't have
+ the same incoming vuse. So, if 2 calls with vdef have the
+ same vuse, we know they're not subsequent.
+ We can value number 2 calls to the same function with the
+ same vuse and the same operands which are not subsequent
+ the same, because there is no code in the program that can
+ compare the 2 values... */
+ || (gimple_vdef (call_stmt)
+ /* ... unless the call returns a pointer which does
+ not alias with anything else. In which case the
+ information that the values are distinct are encoded
+ in the IL. */
+ && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
+ /* Only perform the following when being called from PRE
+ which embeds tail merging. */
+ && default_vn_walk_kind == VN_WALK))
+ /* Do not process .DEFERRED_INIT since that confuses uninit
+ analysis. */
+ && !gimple_call_internal_p (call_stmt, IFN_DEFERRED_INIT))
changed = visit_reference_op_call (lhs, call_stmt);
else
changed = defs_to_varying (call_stmt);
@@ -5851,6 +5886,7 @@ vn_reference_may_trap (vn_reference_t ref)
case MODIFY_EXPR:
case CALL_EXPR:
/* We do not handle calls. */
+ return true;
case ADDR_EXPR:
/* And toplevel address computations never trap. */
return false;
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 9610059..8a1b649 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -106,7 +106,8 @@ typedef const struct vn_phi_s *const_vn_phi_t;
typedef struct vn_reference_op_struct
{
ENUM_BITFIELD(tree_code) opcode : 16;
- /* Dependence info, used for [TARGET_]MEM_REF only. */
+ /* Dependence info, used for [TARGET_]MEM_REF only. For internal
+ function calls clique is also used for the internal function code. */
unsigned short clique;
unsigned short base;
unsigned reverse : 1;
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 15391da..8c39869 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -193,71 +193,124 @@ struct laststmt_struct
} laststmt;
static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
-static void handle_builtin_stxncpy_strncat (bool, gimple_stmt_iterator *);
-static bool handle_assign (gimple_stmt_iterator *, tree, bool *,
- pointer_query &);
/* Sets MINMAX to either the constant value or the range VAL is in
and returns either the constant value or VAL on success or null
- when the range couldn't be determined. Uses RVALS when nonnull
- to determine the range, otherwise uses global range info. */
+ when the range couldn't be determined. Uses RVALS or CFUN for
+ range info, whichever is nonnull. */
tree
get_range (tree val, gimple *stmt, wide_int minmax[2],
range_query *rvals /* = NULL */)
{
- if (TREE_CODE (val) == INTEGER_CST)
+ if (!rvals)
{
- minmax[0] = minmax[1] = wi::to_wide (val);
- return val;
- }
-
- if (TREE_CODE (val) != SSA_NAME)
- return NULL_TREE;
-
- value_range vr;
- if (rvals && stmt)
- {
- if (!rvals->range_of_expr (vr, val, stmt))
- return NULL_TREE;
- value_range_kind rng = vr.kind ();
- if (rng != VR_RANGE)
+ if (!cfun)
+ /* When called from front ends for global initializers CFUN
+ may be null. */
return NULL_TREE;
- minmax[0] = wi::to_wide (vr.min ());
- minmax[1] = wi::to_wide (vr.max ());
- return val;
+ rvals = get_range_query (cfun);
}
- // ?? This entire function should use get_range_query or get_global_range_query (),
- // instead of doing something different for RVALS and global ranges.
-
- if (!get_global_range_query ()->range_of_expr (vr, val) || vr.undefined_p ())
+ value_range vr;
+ if (!rvals->range_of_expr (vr, val, stmt))
return NULL_TREE;
- minmax[0] = wi::to_wide (vr.min ());
- minmax[1] = wi::to_wide (vr.max ());
value_range_kind rng = vr.kind ();
if (rng == VR_RANGE)
- /* This may be an inverted range whose MINMAX[1] < MINMAX[0]. */
- return val;
-
- if (rng == VR_ANTI_RANGE)
{
- /* An anti-range is the same as an ordinary range with inverted
- bounds (where MINMAX[1] < MINMAX[0] is true) that may result
- from the conversion of a signed anti-range to unsigned. */
- wide_int tmp = minmax[0];
- minmax[0] = minmax[1] + 1;
- minmax[1] = wi::sub (tmp, 1);
+ /* Only handle straight ranges. */
+ minmax[0] = wi::to_wide (vr.min ());
+ minmax[1] = wi::to_wide (vr.max ());
return val;
}
- /* Do not handle anti-ranges and instead make use of the on-demand
- VRP if/when it becomes available (hopefully in GCC 11). */
return NULL_TREE;
}
+class strlen_pass : public dom_walker
+{
+public:
+ strlen_pass (cdi_direction direction)
+ : dom_walker (direction),
+ evrp (false),
+ ptr_qry (&evrp, &var_cache),
+ var_cache (),
+ m_cleanup_cfg (false)
+ {
+ }
+
+ ~strlen_pass ();
+
+ virtual edge before_dom_children (basic_block);
+ virtual void after_dom_children (basic_block);
+
+ bool check_and_optimize_stmt (bool *cleanup_eh);
+ bool check_and_optimize_call (bool *zero_write);
+ bool handle_assign (tree lhs, bool *zero_write);
+ bool handle_store (bool *zero_write);
+ void handle_pointer_plus ();
+ void handle_builtin_strlen ();
+ void handle_builtin_strchr ();
+ void handle_builtin_strcpy (built_in_function);
+ void handle_integral_assign (bool *cleanup_eh);
+ void handle_builtin_stxncpy_strncat (bool append_p);
+ void handle_builtin_memcpy (built_in_function bcode);
+ void handle_builtin_strcat (built_in_function bcode);
+ void handle_builtin_strncat (built_in_function);
+ bool handle_builtin_memset (bool *zero_write);
+ bool handle_builtin_memcmp ();
+ bool handle_builtin_string_cmp ();
+ void handle_alloc_call (built_in_function);
+ void maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
+ strinfo *si = NULL, bool plus_one = false,
+ bool rawmem = false);
+ void maybe_warn_overflow (gimple *stmt, bool call_lhs,
+ unsigned HOST_WIDE_INT len,
+ strinfo *si = NULL,
+ bool plus_one = false, bool rawmem = false);
+ void adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat);
+ tree strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1,
+ tree arg2, int idx2,
+ unsigned HOST_WIDE_INT bound,
+ unsigned HOST_WIDE_INT len[2],
+ unsigned HOST_WIDE_INT *psize);
+ bool count_nonzero_bytes (tree expr_or_type,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul);
+ bool count_nonzero_bytes (tree exp,
+ unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT nbytes,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul,
+ ssa_name_limit_t &snlim);
+ bool count_nonzero_bytes_addr (tree exp,
+ unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT nbytes,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul,
+ ssa_name_limit_t &snlim);
+ bool get_len_or_size (gimple *stmt, tree arg, int idx,
+ unsigned HOST_WIDE_INT lenrng[2],
+ unsigned HOST_WIDE_INT *size, bool *nulterm);
+
+ /* EVRP analyzer used for printf argument range processing, and 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;
+
+ gimple_stmt_iterator m_gsi;
+
+ /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
+ execute function. */
+ bool m_cleanup_cfg;
+};
+
/* Return:
* +1 if SI is known to start with more than OFF nonzero characters.
@@ -268,7 +321,7 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
or the relationship between the number of leading nonzero
characters in SI and OFF is unknown. */
-static inline int
+static int
compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
{
if (si->nonzero_chars
@@ -943,8 +996,8 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
else
{
value_range vr;
- get_global_range_query ()->range_of_expr (vr,
- si->nonzero_chars);
+ get_range_query (cfun)
+ ->range_of_expr (vr, si->nonzero_chars);
rng = vr.kind ();
if (!vr.undefined_p ())
{
@@ -1690,9 +1743,8 @@ valid_builtin_call (gimple *stmt)
just memcpy (x, y, strlen (y)). SI must be the zero length
strinfo. */
-static void
-adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat,
- pointer_query &ptr_qry)
+void
+strlen_pass::adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
{
tree vuse, callee, len;
struct laststmt_struct last = laststmt;
@@ -1939,11 +1991,9 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
RAWMEM may be set by memcpy and other raw memory functions
to allow accesses across subobject boundaries. */
-static void
-maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
- pointer_query &ptr_qry,
- strinfo *si = NULL, bool plus_one = false,
- bool rawmem = false)
+void
+strlen_pass::maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
+ strinfo *si, bool plus_one, bool rawmem)
{
if (!len || warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
return;
@@ -2123,23 +2173,23 @@ maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
/* Convenience wrapper for the above. */
-static inline void
-maybe_warn_overflow (gimple *stmt, bool call_lhs, unsigned HOST_WIDE_INT len,
- pointer_query &ptr_qry, strinfo *si = NULL,
- bool plus_one = false, bool rawmem = false)
+void
+strlen_pass::maybe_warn_overflow (gimple *stmt, bool call_lhs,
+ unsigned HOST_WIDE_INT len,
+ strinfo *si, bool plus_one, bool rawmem)
{
tree tlen = build_int_cst (size_type_node, len);
- maybe_warn_overflow (stmt, call_lhs, tlen, ptr_qry, si, plus_one, rawmem);
+ maybe_warn_overflow (stmt, call_lhs, tlen, si, plus_one, rawmem);
}
/* Handle a strlen call. If strlen of the argument is known, replace
the strlen call with the known value, otherwise remember that strlen
of the argument is stored in the lhs SSA_NAME. */
-static void
-handle_builtin_strlen (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strlen ()
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
@@ -2193,8 +2243,8 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
if (bound)
rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
- gimplify_and_update_call_from_tree (gsi, rhs);
- stmt = gsi_stmt (*gsi);
+ gimplify_and_update_call_from_tree (&m_gsi, rhs);
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -2292,8 +2342,8 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
}
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
- gimplify_and_update_call_from_tree (gsi, ret);
- stmt = gsi_stmt (*gsi);
+ gimplify_and_update_call_from_tree (&m_gsi, ret);
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -2311,10 +2361,10 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
that lhs of the call is endptr and strlen of the argument is endptr - x. */
-static void
-handle_builtin_strchr (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strchr ()
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
@@ -2370,8 +2420,8 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
TREE_TYPE (rhs)))
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
}
- gimplify_and_update_call_from_tree (gsi, rhs);
- stmt = gsi_stmt (*gsi);
+ gimplify_and_update_call_from_tree (&m_gsi, rhs);
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -2423,14 +2473,13 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
is the same after this call. Furthermore, attempt to convert it to
memcpy. Uses RVALS to determine range information. */
-static void
-handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
- pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_strcpy (built_in_function bcode)
{
int idx, didx;
tree src, dst, srclen, len, lhs, type, fn, oldlen;
bool success;
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
strinfo *si, *dsi, *olddsi, *zsi;
location_t loc;
@@ -2451,7 +2500,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
return;
if (olddsi != NULL)
- adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+ adjust_last_stmt (olddsi, stmt, false);
srclen = NULL_TREE;
if (si != NULL)
@@ -2459,10 +2508,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, false, srclen, ptr_qry, olddsi, true);
+ maybe_warn_overflow (stmt, false, srclen, olddsi, true);
if (olddsi != NULL)
- adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+ adjust_last_stmt (olddsi, stmt, false);
loc = gimple_location (stmt);
if (srclen == NULL_TREE)
@@ -2653,7 +2702,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
if (fn == NULL_TREE)
return;
- len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
+ len = force_gimple_operand_gsi (&m_gsi, len, true, NULL_TREE, true,
GSI_SAME_STMT);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -2661,13 +2710,13 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
if (gimple_call_num_args (stmt) == 2)
- success = update_gimple_call (gsi, fn, 3, dst, src, len);
+ success = update_gimple_call (&m_gsi, fn, 3, dst, src, len);
else
- success = update_gimple_call (gsi, fn, 4, dst, src, len,
+ success = update_gimple_call (&m_gsi, fn, 4, dst, src, len,
gimple_call_arg (stmt, 2));
if (success)
{
- stmt = gsi_stmt (*gsi);
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -2691,11 +2740,11 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
size argument is derived from a call to strlen() on the source argument,
and if so, issue an appropriate warning. */
-static void
-handle_builtin_strncat (built_in_function, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strncat (built_in_function)
{
/* Same as stxncpy(). */
- handle_builtin_stxncpy_strncat (true, gsi);
+ handle_builtin_stxncpy_strncat (true);
}
/* Return true if LEN depends on a call to strlen(SRC) in an interesting
@@ -3100,13 +3149,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
and if so, issue the appropriate warning.
APPEND_P is true for strncat. */
-static void
-handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_stxncpy_strncat (bool append_p)
{
if (!strlen_to_stridx)
return;
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree dst = gimple_call_arg (stmt, 0);
tree src = gimple_call_arg (stmt, 1);
@@ -3184,7 +3233,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
stridx_strlenloc *pss = strlen_to_stridx->get (len);
if (!pss || pss->first <= 0)
{
- if (maybe_diag_stxncpy_trunc (*gsi, src, len))
+ if (maybe_diag_stxncpy_trunc (m_gsi, src, len))
suppress_warning (stmt, OPT_Wstringop_truncation);
return;
@@ -3242,12 +3291,11 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
is that plus one, strlen of the first argument is the same after this
call. Uses RVALS to determine range information. */
-static void
-handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
- pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_memcpy (built_in_function bcode)
{
tree lhs, oldlen, newlen;
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
strinfo *si, *dsi;
tree len = gimple_call_arg (stmt, 2);
@@ -3264,8 +3312,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
if (olddsi != NULL
&& !integer_zerop (len))
{
- maybe_warn_overflow (stmt, false, len, ptr_qry, olddsi, false, true);
- adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+ maybe_warn_overflow (stmt, false, len, olddsi, false, true);
+ adjust_last_stmt (olddsi, stmt, false);
}
int idx = get_stridx (src);
@@ -3342,7 +3390,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, ptr_qry);
+ adjust_last_stmt (olddsi, stmt, false);
if (didx == 0)
{
@@ -3423,14 +3471,13 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
to convert it to memcpy/strcpy if the length of the first argument
is known. */
-static void
-handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
- pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_strcat (built_in_function bcode)
{
int idx, didx;
tree srclen, args, type, fn, objsz, endptr;
bool success;
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
strinfo *si, *dsi;
location_t loc = gimple_location (stmt);
@@ -3607,7 +3654,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
len = fold_convert_loc (loc, type, unshare_expr (srclen));
len = fold_build2_loc (loc, PLUS_EXPR, type, len,
build_int_cst (type, 1));
- len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
+ len = force_gimple_operand_gsi (&m_gsi, len, true, NULL_TREE, true,
GSI_SAME_STMT);
}
if (endptr)
@@ -3616,14 +3663,14 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
dst = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dst), dst,
fold_convert_loc (loc, sizetype,
unshare_expr (dstlen)));
- dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
+ dst = force_gimple_operand_gsi (&m_gsi, dst, true, NULL_TREE, true,
GSI_SAME_STMT);
if (objsz)
{
objsz = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (objsz), objsz,
fold_convert_loc (loc, TREE_TYPE (objsz),
unshare_expr (dstlen)));
- objsz = force_gimple_operand_gsi (gsi, objsz, true, NULL_TREE, true,
+ objsz = force_gimple_operand_gsi (&m_gsi, objsz, true, NULL_TREE, true,
GSI_SAME_STMT);
}
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -3632,14 +3679,14 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
if (srclen != NULL_TREE)
- success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
+ success = update_gimple_call (&m_gsi, fn, 3 + (objsz != NULL_TREE),
dst, src, len, objsz);
else
- success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
+ success = update_gimple_call (&m_gsi, fn, 2 + (objsz != NULL_TREE),
dst, src, objsz);
if (success)
{
- stmt = gsi_stmt (*gsi);
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -3650,7 +3697,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, ptr_qry);
+ adjust_last_stmt (dsi, stmt, true);
if (srclen != NULL_TREE)
{
laststmt.stmt = stmt;
@@ -3668,10 +3715,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
/* Handle a call to an allocation function like alloca, malloc or calloc,
or an ordinary allocation function declared with attribute alloc_size. */
-static void
-handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_alloc_call (built_in_function bcode)
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
return;
@@ -3705,11 +3752,10 @@ handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
return true when the call is transformed, false otherwise.
When nonnull uses RVALS to determine range information. */
-static bool
-handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
- pointer_query &ptr_qry)
+bool
+strlen_pass::handle_builtin_memset (bool *zero_write)
{
- gimple *memset_stmt = gsi_stmt (*gsi);
+ gimple *memset_stmt = gsi_stmt (m_gsi);
tree ptr = gimple_call_arg (memset_stmt, 0);
/* Set to the non-constant offset added to PTR. */
wide_int offrng[2];
@@ -3729,8 +3775,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, false, memset_size, ptr_qry, NULL,
- false, true);
+ maybe_warn_overflow (memset_stmt, false, memset_size, NULL, false, true);
/* Bail when there is no statement associated with the destination
(the statement may be null even when SI1->ALLOC is not). */
@@ -3770,11 +3815,11 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
if (lhs)
{
gimple *assign = gimple_build_assign (lhs, ptr);
- gsi_replace (gsi, assign, false);
+ gsi_replace (&m_gsi, assign, false);
}
else
{
- gsi_remove (gsi, true);
+ gsi_remove (&m_gsi, true);
release_defs (memset_stmt);
}
@@ -3858,10 +3903,10 @@ use_in_zero_equality (tree res, bool exclusive = true)
with a __builtin_memcmp_eq call where possible.
return true when call is transformed, return false otherwise. */
-static bool
-handle_builtin_memcmp (gimple_stmt_iterator *gsi)
+bool
+strlen_pass::handle_builtin_memcmp ()
{
- gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+ gcall *stmt = as_a <gcall *> (gsi_stmt (m_gsi));
tree res = gimple_call_lhs (stmt);
if (!res || !use_in_zero_equality (res))
@@ -3903,7 +3948,7 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
fold_build2_loc (loc, NE_EXPR,
boolean_type_node,
arg1, arg2));
- gimplify_and_update_call_from_tree (gsi, res);
+ gimplify_and_update_call_from_tree (&m_gsi, res);
return true;
}
}
@@ -3920,11 +3965,10 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
*NULTERM to true, otherwise to false. When nonnull uses RVALS to
determine range information. Returns true on success. */
-static bool
-get_len_or_size (gimple *stmt, tree arg, int idx,
- unsigned HOST_WIDE_INT lenrng[2],
- unsigned HOST_WIDE_INT *size, bool *nulterm,
- range_query *rvals)
+bool
+strlen_pass::get_len_or_size (gimple *stmt, tree arg, int idx,
+ unsigned HOST_WIDE_INT lenrng[2],
+ unsigned HOST_WIDE_INT *size, bool *nulterm)
{
/* Invalidate. */
*size = HOST_WIDE_INT_M1U;
@@ -3977,7 +4021,7 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
/* Set MAXBOUND to an arbitrary non-null non-integer node as a request
to have it set to the length of the longest string in a PHI. */
lendata.maxbound = arg;
- get_range_strlen_dynamic (arg, stmt, &lendata, rvals);
+ get_range_strlen_dynamic (arg, stmt, &lendata, ptr_qry.rvals);
unsigned HOST_WIDE_INT maxbound = HOST_WIDE_INT_M1U;
if (tree_fits_uhwi_p (lendata.maxbound)
@@ -4034,18 +4078,20 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
to be at least as long and need not be nul-terminated) and size.
Otherwise return null. */
-static tree
-strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1, tree arg2, int idx2,
- unsigned HOST_WIDE_INT bound, unsigned HOST_WIDE_INT len[2],
- unsigned HOST_WIDE_INT *psize, range_query *rvals)
+tree
+strlen_pass::strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1,
+ tree arg2, int idx2,
+ unsigned HOST_WIDE_INT bound,
+ unsigned HOST_WIDE_INT len[2],
+ unsigned HOST_WIDE_INT *psize)
{
/* Determine the range the length of each string is in and whether it's
known to be nul-terminated, or the size of the array it's stored in. */
bool nul1, nul2;
unsigned HOST_WIDE_INT siz1, siz2;
unsigned HOST_WIDE_INT len1rng[2], len2rng[2];
- if (!get_len_or_size (stmt, arg1, idx1, len1rng, &siz1, &nul1, rvals)
- || !get_len_or_size (stmt, arg2, idx2, len2rng, &siz2, &nul2, rvals))
+ if (!get_len_or_size (stmt, arg1, idx1, len1rng, &siz1, &nul1)
+ || !get_len_or_size (stmt, arg2, idx2, len2rng, &siz2, &nul2))
return NULL_TREE;
/* BOUND is set to HWI_M1U for strcmp and less to strncmp, and LENiRNG
@@ -4193,10 +4239,10 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
is not known. Return true when the call has been transformed into
another and false otherwise. */
-static bool
-handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
+bool
+strlen_pass::handle_builtin_string_cmp ()
{
- gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+ gcall *stmt = as_a <gcall *> (gsi_stmt (m_gsi));
tree lhs = gimple_call_lhs (stmt);
if (!lhs)
@@ -4240,7 +4286,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
or definitely unequal and if so, either fold the result to zero
(when equal) or set the range of the result to ~[0, 0] otherwise. */
if (tree eqz = strxcmp_eqz_result (stmt, arg1, idx1, arg2, idx2, bound,
- len, &siz, rvals))
+ len, &siz))
{
if (integer_zerop (eqz))
{
@@ -4256,7 +4302,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
}
/* When the two strings are definitely equal (such as when they
are both empty) fold the call to the constant result. */
- replace_call_with_value (gsi, integer_zero_node);
+ replace_call_with_value (&m_gsi, integer_zero_node);
return true;
}
}
@@ -4276,9 +4322,8 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
unsigned HOST_WIDE_INT arsz1, arsz2;
bool nulterm[2];
- if (!get_len_or_size (stmt, arg1, idx1, len1rng, &arsz1, nulterm, rvals)
- || !get_len_or_size (stmt, arg2, idx2, len2rng, &arsz2, nulterm + 1,
- rvals))
+ if (!get_len_or_size (stmt, arg1, idx1, len1rng, &arsz1, nulterm)
+ || !get_len_or_size (stmt, arg2, idx2, len2rng, &arsz2, nulterm + 1))
return false;
if (len1rng[0] == len1rng[1] && len1rng[0] < HOST_WIDE_INT_MAX)
@@ -4326,7 +4371,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
: BUILT_IN_STRNCMP_EQ))
{
tree n = build_int_cst (size_type_node, cmpsiz);
- update_gimple_call (gsi, fn, 3, arg1, arg2, n);
+ update_gimple_call (&m_gsi, fn, 3, arg1, arg2, n);
return true;
}
}
@@ -4339,10 +4384,10 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
p = q + off is pointing to a '\0' character of a string, call
zero_length_string on it. */
-static void
-handle_pointer_plus (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_pointer_plus ()
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree lhs = gimple_assign_lhs (stmt), off;
int idx = get_stridx (gimple_assign_rhs1 (stmt));
strinfo *si, *zsi;
@@ -4385,8 +4430,8 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
enum tree_code rhs_code
= useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
? SSA_NAME : NOP_EXPR;
- gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
- gcc_assert (gsi_stmt (*gsi) == stmt);
+ gimple_assign_set_rhs_with_ops (&m_gsi, rhs_code, si->endptr);
+ gcc_assert (gsi_stmt (m_gsi) == stmt);
update_stmt (stmt);
}
}
@@ -4421,11 +4466,6 @@ nonzero_bytes_for_type (tree type, unsigned lenrange[3],
return true;
}
-static bool
-count_nonzero_bytes_addr (tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
- unsigned [3], bool *, bool *, bool *,
- range_query *, ssa_name_limit_t &);
-
/* Recursively determine the minimum and maximum number of leading nonzero
bytes in the representation of EXP and set LENRANGE[0] and LENRANGE[1]
to each.
@@ -4441,12 +4481,13 @@ count_nonzero_bytes_addr (tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
Avoids recursing deeper than the limits in SNLIM allow.
Returns true on success and false otherwise. */
-static bool
-count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
- unsigned HOST_WIDE_INT nbytes,
- unsigned lenrange[3], bool *nulterm,
- bool *allnul, bool *allnonnul, range_query *rvals,
- ssa_name_limit_t &snlim)
+bool
+strlen_pass::count_nonzero_bytes (tree exp,
+ unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT nbytes,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul,
+ ssa_name_limit_t &snlim)
{
if (TREE_CODE (exp) == SSA_NAME)
{
@@ -4462,7 +4503,7 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
for an arbitrary constant. */
exp = build_int_cst (type, 1);
return count_nonzero_bytes (exp, offset, 1, lenrange,
- nulterm, allnul, allnonnul, rvals, snlim);
+ nulterm, allnul, allnonnul, snlim);
}
gimple *stmt = SSA_NAME_DEF_STMT (exp);
@@ -4489,7 +4530,7 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
{
tree def = gimple_phi_arg_def (stmt, i);
if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm,
- allnul, allnonnul, rvals, snlim))
+ allnul, allnonnul, snlim))
return false;
}
@@ -4546,7 +4587,7 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
/* Handle MEM_REF = SSA_NAME types of assignments. */
return count_nonzero_bytes_addr (arg, offset, nbytes, lenrange, nulterm,
- allnul, allnonnul, rvals, snlim);
+ allnul, allnonnul, snlim);
}
if (VAR_P (exp) || TREE_CODE (exp) == CONST_DECL)
@@ -4656,12 +4697,13 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
/* Like count_nonzero_bytes, but instead of counting bytes in EXP, count
bytes that are pointed to by EXP, which should be a pointer. */
-static bool
-count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
- unsigned HOST_WIDE_INT nbytes,
- unsigned lenrange[3], bool *nulterm,
- bool *allnul, bool *allnonnul,
- range_query *rvals, ssa_name_limit_t &snlim)
+bool
+strlen_pass::count_nonzero_bytes_addr (tree exp,
+ unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT nbytes,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul,
+ ssa_name_limit_t &snlim)
{
int idx = get_stridx (exp);
if (idx > 0)
@@ -4679,7 +4721,7 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
&& TREE_CODE (si->nonzero_chars) == SSA_NAME)
{
value_range vr;
- rvals->range_of_expr (vr, si->nonzero_chars, si->stmt);
+ ptr_qry.rvals->range_of_expr (vr, si->nonzero_chars, si->stmt);
if (vr.kind () != VR_RANGE)
return false;
@@ -4726,8 +4768,7 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
if (TREE_CODE (exp) == ADDR_EXPR)
return count_nonzero_bytes (TREE_OPERAND (exp, 0), offset, nbytes,
- lenrange, nulterm, allnul, allnonnul, rvals,
- snlim);
+ lenrange, nulterm, allnul, allnonnul, snlim);
if (TREE_CODE (exp) == SSA_NAME)
{
@@ -4746,7 +4787,7 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
{
tree def = gimple_phi_arg_def (stmt, i);
if (!count_nonzero_bytes_addr (def, offset, nbytes, lenrange,
- nulterm, allnul, allnonnul, rvals,
+ nulterm, allnul, allnonnul,
snlim))
return false;
}
@@ -4772,9 +4813,10 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
RVALS is used to determine ranges of dynamically computed string lengths
(the results of strlen). */
-static bool
-count_nonzero_bytes (tree expr_or_type, unsigned lenrange[3], bool *nulterm,
- bool *allnul, bool *allnonnul, range_query *rvals)
+bool
+strlen_pass::count_nonzero_bytes (tree expr_or_type,
+ unsigned lenrange[3], bool *nulterm,
+ bool *allnul, bool *allnonnul)
{
if (TYPE_P (expr_or_type))
return nonzero_bytes_for_type (expr_or_type, lenrange,
@@ -4792,7 +4834,7 @@ count_nonzero_bytes (tree expr_or_type, unsigned lenrange[3], bool *nulterm,
ssa_name_limit_t snlim;
tree expr = expr_or_type;
return count_nonzero_bytes (expr, 0, 0, lenrange, nulterm, allnul, allnonnul,
- rvals, snlim);
+ snlim);
}
/* Handle a single or multibyte store other than by a built-in function,
@@ -4801,11 +4843,10 @@ count_nonzero_bytes (tree expr_or_type, unsigned lenrange[3], bool *nulterm,
'*(int*)a = 12345'). Return true to let the caller advance *GSI to
the next statement in the basic block and false otherwise. */
-static bool
-handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
- pointer_query &ptr_qry)
+bool
+strlen_pass::handle_store (bool *zero_write)
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
/* The LHS and RHS of the store. The RHS is null if STMT is a function
call. STORETYPE is the type of the store (determined from either
the RHS of the assignment statement or the LHS of a function call. */
@@ -4856,8 +4897,8 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
bool dummy;
unsigned lenrange[] = { UINT_MAX, 0, 0 };
if (count_nonzero_bytes (rhs ? rhs : storetype, lenrange,
- &dummy, &dummy, &dummy, rvals))
- maybe_warn_overflow (stmt, true, lenrange[2], ptr_qry);
+ &dummy, &dummy, &dummy))
+ maybe_warn_overflow (stmt, true, lenrange[2]);
return true;
}
@@ -4889,8 +4930,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
const bool ranges_valid
= count_nonzero_bytes (rhs ? rhs : storetype, lenrange, &full_string_p,
- &storing_all_zeros_p, &storing_all_nonzero_p,
- rvals);
+ &storing_all_zeros_p, &storing_all_nonzero_p);
if (ranges_valid)
{
@@ -4898,7 +4938,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, true, lenrange[2], ptr_qry);
+ maybe_warn_overflow (stmt, true, lenrange[2]);
}
else
{
@@ -4945,13 +4985,13 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
{
unlink_stmt_vdef (stmt);
release_defs (stmt);
- gsi_remove (gsi, true);
+ gsi_remove (&m_gsi, true);
return false;
}
else
{
si->writable = true;
- gsi_next (gsi);
+ gsi_next (&m_gsi);
return false;
}
}
@@ -4985,7 +5025,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
size_t len4 = strlen (q); // can be folded to len2
bar (len, len2, len3, len4);
} */
- gsi_next (gsi);
+ gsi_next (&m_gsi);
return false;
}
@@ -5016,7 +5056,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, ptr_qry);
+ adjust_last_stmt (si, stmt, false);
si = unshare_strinfo (si);
if (storing_nonzero_p)
{
@@ -5232,11 +5272,10 @@ is_char_type (tree type)
Return true to let the caller advance *GSI to the next statement
in the basic block and false otherwise. */
-static bool
-strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
- pointer_query &ptr_qry)
+bool
+strlen_pass::check_and_optimize_call (bool *zero_write)
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
{
@@ -5246,12 +5285,12 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
if (lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (fntype)))
{
- handle_alloc_call (BUILT_IN_NONE, gsi);
+ handle_alloc_call (BUILT_IN_NONE);
return true;
}
if (tree lhs = gimple_call_lhs (stmt))
- handle_assign (gsi, lhs, zero_write, ptr_qry);
+ handle_assign (lhs, zero_write);
/* Proceed to handle user-defined formatting functions. */
}
@@ -5262,68 +5301,68 @@ 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, ptr_qry);
+ return !handle_printf_call (&m_gsi, ptr_qry);
tree callee = gimple_call_fndecl (stmt);
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_STRLEN:
case BUILT_IN_STRNLEN:
- handle_builtin_strlen (gsi);
+ handle_builtin_strlen ();
break;
case BUILT_IN_STRCHR:
- handle_builtin_strchr (gsi);
+ handle_builtin_strchr ();
break;
case BUILT_IN_STRCPY:
case BUILT_IN_STRCPY_CHK:
case BUILT_IN_STPCPY:
case BUILT_IN_STPCPY_CHK:
- handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+ handle_builtin_strcpy (DECL_FUNCTION_CODE (callee));
break;
case BUILT_IN_STRNCAT:
case BUILT_IN_STRNCAT_CHK:
- handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
+ handle_builtin_strncat (DECL_FUNCTION_CODE (callee));
break;
case BUILT_IN_STPNCPY:
case BUILT_IN_STPNCPY_CHK:
case BUILT_IN_STRNCPY:
case BUILT_IN_STRNCPY_CHK:
- handle_builtin_stxncpy_strncat (false, gsi);
+ handle_builtin_stxncpy_strncat (false);
break;
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMCPY_CHK:
case BUILT_IN_MEMPCPY:
case BUILT_IN_MEMPCPY_CHK:
- handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+ handle_builtin_memcpy (DECL_FUNCTION_CODE (callee));
break;
case BUILT_IN_STRCAT:
case BUILT_IN_STRCAT_CHK:
- handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+ handle_builtin_strcat (DECL_FUNCTION_CODE (callee));
break;
case BUILT_IN_ALLOCA:
case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_MALLOC:
case BUILT_IN_CALLOC:
- handle_alloc_call (DECL_FUNCTION_CODE (callee), gsi);
+ handle_alloc_call (DECL_FUNCTION_CODE (callee));
break;
case BUILT_IN_MEMSET:
- if (handle_builtin_memset (gsi, zero_write, ptr_qry))
+ if (handle_builtin_memset (zero_write))
return false;
break;
case BUILT_IN_MEMCMP:
- if (handle_builtin_memcmp (gsi))
+ if (handle_builtin_memcmp ())
return false;
break;
case BUILT_IN_STRCMP:
case BUILT_IN_STRNCMP:
- if (handle_builtin_string_cmp (gsi, ptr_qry.rvals))
+ if (handle_builtin_string_cmp ())
return false;
break;
default:
- if (handle_printf_call (gsi, ptr_qry))
+ if (handle_printf_call (&m_gsi, ptr_qry))
return false;
break;
}
@@ -5334,11 +5373,10 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
/* Handle an assignment statement at *GSI to a LHS of integral type.
If GSI's basic block needs clean-up of EH, set *CLEANUP_EH to true. */
-static void
-handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
- range_query *rvals)
+void
+strlen_pass::handle_integral_assign (bool *cleanup_eh)
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
tree lhs = gimple_assign_lhs (stmt);
tree lhs_type = TREE_TYPE (lhs);
@@ -5407,11 +5445,11 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
/* Reading the final '\0' character. */
tree zero = build_int_cst (lhs_type, 0);
gimple_set_vuse (stmt, NULL_TREE);
- gimple_assign_set_rhs_from_tree (gsi, zero);
+ gimple_assign_set_rhs_from_tree (&m_gsi, zero);
*cleanup_eh
|= maybe_clean_or_replace_eh_stmt (stmt,
- gsi_stmt (*gsi));
- stmt = gsi_stmt (*gsi);
+ gsi_stmt (m_gsi));
+ stmt = gsi_stmt (m_gsi);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -5448,8 +5486,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
tree rhs = gimple_assign_rhs1 (stmt);
const bool ranges_valid
= count_nonzero_bytes (rhs, lenrange, &full_string_p,
- &storing_all_zeros_p, &storing_all_nonzero_p,
- rvals);
+ &storing_all_zeros_p,
+ &storing_all_nonzero_p);
if (ranges_valid)
{
tree length = build_int_cst (sizetype, lenrange[0]);
@@ -5472,9 +5510,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
/* Handle assignment statement at *GSI to LHS. Set *ZERO_WRITE if
the assignent stores all zero bytes.. */
-static bool
-handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
- pointer_query &ptr_qry)
+bool
+strlen_pass::handle_assign (tree lhs, bool *zero_write)
{
tree type = TREE_TYPE (lhs);
if (TREE_CODE (type) == ARRAY_TYPE)
@@ -5504,7 +5541,7 @@ handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
}
/* Handle a single or multibyte assignment. */
- if (is_char_store && !handle_store (gsi, zero_write, ptr_qry))
+ if (is_char_store && !handle_store (zero_write))
return false;
return true;
@@ -5517,11 +5554,10 @@ handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
true. Return true to let the caller advance *GSI to the next statement
in the basic block and false otherwise. */
-static bool
-check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
- pointer_query &ptr_qry)
+bool
+strlen_pass::check_and_optimize_stmt (bool *cleanup_eh)
{
- gimple *stmt = gsi_stmt (*gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
/* For statements that modify a string, set to true if the write
is only zeros. */
@@ -5529,7 +5565,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, ptr_qry))
+ if (!check_and_optimize_call (&zero_write))
return false;
}
else if (!flag_optimize_strlen || !strlen_optimize)
@@ -5550,13 +5586,13 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
}
else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
- handle_pointer_plus (gsi);
+ handle_pointer_plus ();
}
else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (lhs_type))
/* Handle assignment to a character. */
- handle_integral_assign (gsi, cleanup_eh, ptr_qry.rvals);
+ handle_integral_assign (cleanup_eh);
else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
- if (!handle_assign (gsi, lhs, &zero_write, ptr_qry))
+ if (!handle_assign (lhs, &zero_write))
return false;
}
else if (gcond *cond = dyn_cast<gcond *> (stmt))
@@ -5623,39 +5659,9 @@ do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
}
}
-class strlen_dom_walker : public dom_walker
-{
-public:
- strlen_dom_walker (cdi_direction direction)
- : dom_walker (direction),
- evrp (false),
- ptr_qry (&evrp, &var_cache),
- var_cache (),
- m_cleanup_cfg (false)
- { }
-
- ~strlen_dom_walker ();
-
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-
- /* EVRP analyzer used for printf argument range processing, and
- 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;
-};
-
/* Release pointer_query cache. */
-strlen_dom_walker::~strlen_dom_walker ()
+strlen_pass::~strlen_pass ()
{
ptr_qry.flush_cache ();
}
@@ -5664,7 +5670,7 @@ strlen_dom_walker::~strlen_dom_walker ()
string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
edge
-strlen_dom_walker::before_dom_children (basic_block bb)
+strlen_pass::before_dom_children (basic_block bb)
{
evrp.enter (bb);
@@ -5740,9 +5746,9 @@ strlen_dom_walker::before_dom_children (basic_block bb)
bool cleanup_eh = false;
/* Attempt to optimize individual statements. */
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+ for (m_gsi = gsi_start_bb (bb); !gsi_end_p (m_gsi); )
{
- gimple *stmt = gsi_stmt (gsi);
+ gimple *stmt = gsi_stmt (m_gsi);
/* First record ranges generated by this statement so they
can be used by printf argument processing. */
@@ -5751,8 +5757,8 @@ strlen_dom_walker::before_dom_children (basic_block bb)
/* Reset search depth preformance counter. */
ptr_qry.depth = 0;
- if (check_and_optimize_stmt (&gsi, &cleanup_eh, ptr_qry))
- gsi_next (&gsi);
+ if (check_and_optimize_stmt (&cleanup_eh))
+ gsi_next (&m_gsi);
}
if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
@@ -5768,7 +5774,7 @@ strlen_dom_walker::before_dom_children (basic_block bb)
owned by the current bb, clear bb->aux. */
void
-strlen_dom_walker::after_dom_children (basic_block bb)
+strlen_pass::after_dom_children (basic_block bb)
{
evrp.leave (bb);
@@ -5816,31 +5822,11 @@ printf_strlen_execute (function *fun, bool warn_only)
/* String length optimization is implemented as a walk of the dominator
tree and a forward walk of statements within each block. */
- strlen_dom_walker walker (CDI_DOMINATORS);
+ strlen_pass 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);
- }
+ walker.ptr_qry.dump (dump_file);
ssa_ver_to_stridx.release ();
strinfo_pool.release ();
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index c430855..2e6513b 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -44,6 +44,9 @@
#include "tree-ssa.h"
#include "tree-cfg.h"
#include "gimple-range.h"
+#include "ipa-modref-tree.h"
+#include "ipa-modref.h"
+#include "attr-fnspec.h"
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -4048,98 +4051,203 @@ get_function_part_constraint (varinfo_t fi, unsigned part)
return c;
}
-/* For non-IPA mode, generate constraints necessary for a call on the
- RHS. */
+/* Produce constraints for argument ARG of call STMT with eaf flags
+ FLAGS. RESULTS is array holding constraints for return value.
+ CALLESCAPE_ID is variable where call loocal escapes are added.
+ WRITES_GLOVEL_MEMORY is true if callee may write global memory. */
static void
-handle_rhs_call (gcall *stmt, vec<ce_s> *results)
-{
- struct constraint_expr rhsc;
- unsigned i;
- bool returns_uses = false;
+handle_call_arg (gcall *stmt, tree arg, vec<ce_s> *results, int flags,
+ int callescape_id, bool writes_global_memory)
+{
+ /* If the argument is not used we can ignore it.
+ Similarly argument is invisile for us if it not clobbered, does not
+ escape, is not read and can not be returned. */
+ if ((flags & EAF_UNUSED)
+ || ((flags & (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
+ | EAF_NOT_RETURNED))
+ == (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
+ | EAF_NOT_RETURNED)))
+ return;
+
+ varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
+ tem->is_reg_var = true;
+ make_constraint_to (tem->id, arg);
+ make_any_offset_constraints (tem);
+
+ if (!(flags & EAF_DIRECT))
+ make_transitive_closure_constraints (tem);
- for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ if (!(flags & EAF_NOT_RETURNED))
{
- tree arg = gimple_call_arg (stmt, i);
- int flags = gimple_call_arg_flags (stmt, i);
+ struct constraint_expr cexpr;
+ cexpr.var = tem->id;
+ cexpr.type = SCALAR;
+ cexpr.offset = 0;
+ results->safe_push (cexpr);
+ }
- /* If the argument is not used we can ignore it.
- Similarly argument is invisile for us if it not clobbered, does not
- escape, is not read and can not be returned. */
- if ((flags & EAF_UNUSED)
- || ((flags & (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
- | EAF_NOT_RETURNED))
- == (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
- | EAF_NOT_RETURNED)))
- continue;
+ if (!(flags & EAF_NOREAD))
+ {
+ varinfo_t uses = get_call_use_vi (stmt);
+ make_copy_constraint (uses, tem->id);
+ }
- /* As we compute ESCAPED context-insensitive we do not gain
- any precision with just EAF_NOCLOBBER but not EAF_NOESCAPE
- set. The argument would still get clobbered through the
- escape solution. */
- if ((flags & EAF_NOCLOBBER)
- && (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE)))
- {
- varinfo_t uses = get_call_use_vi (stmt);
- varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
- tem->is_reg_var = true;
- make_constraint_to (tem->id, arg);
- make_any_offset_constraints (tem);
- if (!(flags & EAF_DIRECT))
- make_transitive_closure_constraints (tem);
- make_copy_constraint (uses, tem->id);
- /* TODO: This is overly conservative when some parameters are
- returned while others are not. */
- if (!(flags & EAF_NOT_RETURNED))
- returns_uses = true;
- if (!(flags & (EAF_NOESCAPE | EAF_DIRECT)))
- make_indirect_escape_constraint (tem);
- }
- else if (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE))
+ if (!(flags & EAF_NOCLOBBER))
+ {
+ struct constraint_expr lhs, rhs;
+
+ /* *arg = callescape. */
+ lhs.type = DEREF;
+ lhs.var = tem->id;
+ lhs.offset = 0;
+
+ rhs.type = SCALAR;
+ rhs.var = callescape_id;
+ rhs.offset = 0;
+ process_constraint (new_constraint (lhs, rhs));
+
+ /* callclobbered = arg. */
+ make_copy_constraint (get_call_clobber_vi (stmt), tem->id);
+ }
+
+ if (!(flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE)))
+ {
+ struct constraint_expr lhs, rhs;
+
+ /* callescape = arg; */
+ lhs.var = callescape_id;
+ lhs.offset = 0;
+ lhs.type = SCALAR;
+
+ rhs.var = tem->id;
+ rhs.offset = 0;
+ rhs.type = SCALAR;
+ process_constraint (new_constraint (lhs, rhs));
+
+ if (writes_global_memory)
+ make_escape_constraint (arg);
+ }
+ else if (!(flags & EAF_NOESCAPE))
+ {
+ struct constraint_expr lhs, rhs;
+
+ /* callescape = *(arg + UNKNOWN); */
+ lhs.var = callescape_id;
+ lhs.offset = 0;
+ lhs.type = SCALAR;
+
+ rhs.var = tem->id;
+ rhs.offset = UNKNOWN_OFFSET;
+ rhs.type = DEREF;
+ process_constraint (new_constraint (lhs, rhs));
+
+ if (writes_global_memory)
+ make_indirect_escape_constraint (tem);
+ }
+}
+
+/* Determine global memory access of call STMT and update
+ WRITES_GLOBAL_MEMORY, READS_GLOBAL_MEMORY and USES_GLOBAL_MEMORY. */
+
+static void
+determine_global_memory_access (gcall *stmt,
+ bool *writes_global_memory,
+ bool *reads_global_memory,
+ bool *uses_global_memory)
+{
+ tree callee;
+ cgraph_node *node;
+ modref_summary *summary;
+
+ /* We need to detrmine reads to set uses. */
+ gcc_assert (!uses_global_memory || reads_global_memory);
+
+ if ((callee = gimple_call_fndecl (stmt)) != NULL_TREE
+ && (node = cgraph_node::get (callee)) != NULL
+ && (summary = get_modref_function_summary (node)))
+ {
+ if (writes_global_memory && *writes_global_memory)
+ *writes_global_memory = summary->global_memory_written_p ();
+ if (reads_global_memory && *reads_global_memory)
+ *reads_global_memory = summary->global_memory_read_p ();
+ if (reads_global_memory && uses_global_memory
+ && !*reads_global_memory && node->binds_to_current_def_p ())
+ *uses_global_memory = false;
+ }
+ if ((writes_global_memory && *writes_global_memory)
+ || (uses_global_memory && *uses_global_memory)
+ || (reads_global_memory && *reads_global_memory))
+ {
+ attr_fnspec fnspec = gimple_call_fnspec (stmt);
+ if (fnspec.known_p ())
{
- struct constraint_expr lhs, rhs;
- varinfo_t uses = get_call_use_vi (stmt);
- varinfo_t clobbers = get_call_clobber_vi (stmt);
- varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
- tem->is_reg_var = true;
- make_constraint_to (tem->id, arg);
- make_any_offset_constraints (tem);
- if (!(flags & EAF_DIRECT))
- make_transitive_closure_constraints (tem);
- make_copy_constraint (uses, tem->id);
- if (!(flags & EAF_NOT_RETURNED))
- returns_uses = true;
- make_copy_constraint (clobbers, tem->id);
- /* Add *tem = nonlocal, do not add *tem = callused as
- EAF_NOESCAPE parameters do not escape to other parameters
- and all other uses appear in NONLOCAL as well. */
- lhs.type = DEREF;
- lhs.var = tem->id;
- lhs.offset = 0;
- rhs.type = SCALAR;
- rhs.var = nonlocal_id;
- rhs.offset = 0;
- process_constraint (new_constraint (lhs, rhs));
- if (!(flags & (EAF_NOESCAPE | EAF_DIRECT)))
- make_indirect_escape_constraint (tem);
+ if (writes_global_memory
+ && !fnspec.global_memory_written_p ())
+ *writes_global_memory = false;
+ if (reads_global_memory && !fnspec.global_memory_read_p ())
+ {
+ *reads_global_memory = false;
+ if (uses_global_memory)
+ *uses_global_memory = false;
+ }
}
- else
- make_escape_constraint (arg);
}
+}
+
+/* For non-IPA mode, generate constraints necessary for a call on the
+ RHS and collect return value constraint to RESULTS to be used later in
+ handle_lhs_call.
+
+ IMPLICIT_EAF_FLAGS are added to each function argument. If
+ WRITES_GLOBAL_MEMORY is true function is assumed to possibly write to global
+ memory. Similar for READS_GLOBAL_MEMORY. */
+
+static void
+handle_rhs_call (gcall *stmt, vec<ce_s> *results,
+ int implicit_eaf_flags,
+ bool writes_global_memory,
+ bool reads_global_memory)
+{
+ determine_global_memory_access (stmt, &writes_global_memory,
+ &reads_global_memory,
+ NULL);
- /* If we added to the calls uses solution make sure we account for
- pointers to it to be returned. */
- if (returns_uses)
+ varinfo_t callescape = new_var_info (NULL_TREE, "callescape", true);
+
+ /* If function can use global memory, add it to callescape
+ and to possible return values. If not we can still use/return addresses
+ of global symbols. */
+ struct constraint_expr lhs, rhs;
+
+ lhs.type = SCALAR;
+ lhs.var = callescape->id;
+ lhs.offset = 0;
+
+ rhs.type = reads_global_memory ? SCALAR : ADDRESSOF;
+ rhs.var = nonlocal_id;
+ rhs.offset = 0;
+
+ process_constraint (new_constraint (lhs, rhs));
+ results->safe_push (rhs);
+
+ varinfo_t uses = get_call_use_vi (stmt);
+ make_copy_constraint (uses, callescape->id);
+
+ for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
{
- rhsc.var = get_call_use_vi (stmt)->id;
- rhsc.offset = UNKNOWN_OFFSET;
- rhsc.type = SCALAR;
- results->safe_push (rhsc);
+ tree arg = gimple_call_arg (stmt, i);
+ int flags = gimple_call_arg_flags (stmt, i);
+ handle_call_arg (stmt, arg, results,
+ flags | implicit_eaf_flags,
+ callescape->id, writes_global_memory);
}
/* The static chain escapes as well. */
if (gimple_call_chain (stmt))
- make_escape_constraint (gimple_call_chain (stmt));
+ handle_call_arg (stmt, gimple_call_chain (stmt), results,
+ implicit_eaf_flags,
+ callescape->id, writes_global_memory);
/* And if we applied NRV the address of the return slot escapes as well. */
if (gimple_call_return_slot_opt_p (stmt)
@@ -4147,20 +4255,17 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
&& TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
{
auto_vec<ce_s> tmpc;
- struct constraint_expr lhsc, *c;
+ struct constraint_expr *c;
+ unsigned i;
+
get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
- lhsc.var = escaped_id;
- lhsc.offset = 0;
- lhsc.type = SCALAR;
+
+ make_constraints_to (callescape->id, tmpc);
+ if (writes_global_memory)
+ make_constraints_to (escaped_id, tmpc);
FOR_EACH_VEC_ELT (tmpc, i, c)
- process_constraint (new_constraint (lhsc, *c));
+ results->safe_push (*c);
}
-
- /* Regular functions return nonlocal memory. */
- rhsc.var = nonlocal_id;
- rhsc.offset = 0;
- rhsc.type = SCALAR;
- results->safe_push (rhsc);
}
/* For non-IPA mode, generate constraints necessary for a call
@@ -4227,160 +4332,6 @@ handle_lhs_call (gcall *stmt, tree lhs, int flags, vec<ce_s> &rhsc,
process_all_all_constraints (lhsc, rhsc);
}
-/* For non-IPA mode, generate constraints necessary for a call of a
- const function that returns a pointer in the statement STMT. */
-
-static void
-handle_const_call (gcall *stmt, vec<ce_s> *results)
-{
- struct constraint_expr rhsc;
- unsigned int k;
- bool need_uses = false;
-
- /* Treat nested const functions the same as pure functions as far
- as the static chain is concerned. */
- if (gimple_call_chain (stmt))
- {
- varinfo_t uses = get_call_use_vi (stmt);
- make_constraint_to (uses->id, gimple_call_chain (stmt));
- need_uses = true;
- }
-
- /* And if we applied NRV the address of the return slot escapes as well. */
- if (gimple_call_return_slot_opt_p (stmt)
- && gimple_call_lhs (stmt) != NULL_TREE
- && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
- {
- varinfo_t uses = get_call_use_vi (stmt);
- auto_vec<ce_s> tmpc;
- get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
- make_constraints_to (uses->id, tmpc);
- need_uses = true;
- }
-
- if (need_uses)
- {
- varinfo_t uses = get_call_use_vi (stmt);
- make_any_offset_constraints (uses);
- make_transitive_closure_constraints (uses);
- rhsc.var = uses->id;
- rhsc.offset = 0;
- rhsc.type = SCALAR;
- results->safe_push (rhsc);
- }
-
- /* May return offsetted arguments. */
- varinfo_t tem = NULL;
- for (k = 0; k < gimple_call_num_args (stmt); ++k)
- {
- int flags = gimple_call_arg_flags (stmt, k);
-
- /* If the argument is not used or not returned we can ignore it. */
- if (flags & (EAF_UNUSED | EAF_NOT_RETURNED))
- continue;
- if (!tem)
- {
- tem = new_var_info (NULL_TREE, "callarg", true);
- tem->is_reg_var = true;
- }
- tree arg = gimple_call_arg (stmt, k);
- auto_vec<ce_s> argc;
- get_constraint_for_rhs (arg, &argc);
- make_constraints_to (tem->id, argc);
- }
- if (tem)
- {
- ce_s ce;
- ce.type = SCALAR;
- ce.var = tem->id;
- ce.offset = UNKNOWN_OFFSET;
- results->safe_push (ce);
- }
-
- /* May return addresses of globals. */
- rhsc.var = nonlocal_id;
- rhsc.offset = 0;
- rhsc.type = ADDRESSOF;
- results->safe_push (rhsc);
-}
-
-/* For non-IPA mode, generate constraints necessary for a call to a
- pure function in statement STMT. */
-
-static void
-handle_pure_call (gcall *stmt, vec<ce_s> *results)
-{
- struct constraint_expr rhsc;
- unsigned i;
- varinfo_t uses = NULL;
- bool record_uses = false;
-
- /* Memory reached from pointer arguments is call-used. */
- 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)
- || (flags & (EAF_NOT_RETURNED | EAF_NOREAD))
- == (EAF_NOT_RETURNED | EAF_NOREAD))
- continue;
- if (!uses)
- {
- uses = get_call_use_vi (stmt);
- make_any_offset_constraints (uses);
- make_transitive_closure_constraints (uses);
- }
- make_constraint_to (uses->id, arg);
- if (!(flags & EAF_NOT_RETURNED))
- record_uses = true;
- }
-
- /* The static chain is used as well. */
- if (gimple_call_chain (stmt))
- {
- if (!uses)
- {
- uses = get_call_use_vi (stmt);
- make_any_offset_constraints (uses);
- make_transitive_closure_constraints (uses);
- }
- make_constraint_to (uses->id, gimple_call_chain (stmt));
- record_uses = true;
- }
-
- /* And if we applied NRV the address of the return slot. */
- if (gimple_call_return_slot_opt_p (stmt)
- && gimple_call_lhs (stmt) != NULL_TREE
- && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
- {
- if (!uses)
- {
- uses = get_call_use_vi (stmt);
- make_any_offset_constraints (uses);
- make_transitive_closure_constraints (uses);
- }
- auto_vec<ce_s> tmpc;
- get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
- make_constraints_to (uses->id, tmpc);
- record_uses = true;
- }
-
- /* Pure functions may return call-used and nonlocal memory. */
- if (record_uses)
- {
- rhsc.var = uses->id;
- rhsc.offset = 0;
- rhsc.type = SCALAR;
- results->safe_push (rhsc);
- }
- rhsc.var = nonlocal_id;
- rhsc.offset = 0;
- rhsc.type = SCALAR;
- results->safe_push (rhsc);
-}
-
/* Return the varinfo for the callee of CALL. */
@@ -4916,6 +4867,9 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
&& find_func_aliases_for_builtin_call (fn, t))
return;
+ if (gimple_call_internal_p (t, IFN_DEFERRED_INIT))
+ return;
+
fi = get_fi_for_callee (t);
if (!in_ipa_mode
|| (fi->decl && fndecl && !fi->is_fn_info))
@@ -4928,13 +4882,13 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
if (flags & (ECF_CONST|ECF_NOVOPS))
{
if (gimple_call_lhs (t))
- handle_const_call (t, &rhsc);
+ handle_rhs_call (t, &rhsc, implicit_const_eaf_flags, false, false);
}
/* Pure functions can return addresses in and of memory
reachable from their arguments, but they are not an escape
point for reachable memory of their arguments. */
else if (flags & (ECF_PURE|ECF_LOOPING_CONST_OR_PURE))
- handle_pure_call (t, &rhsc);
+ handle_rhs_call (t, &rhsc, implicit_pure_eaf_flags, true, false);
/* 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 the effects for PTA (in particular
@@ -4944,7 +4898,7 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
&& gimple_call_from_new_or_delete (t))
;
else
- handle_rhs_call (t, &rhsc);
+ handle_rhs_call (t, &rhsc, 0, true, true);
if (gimple_call_lhs (t))
handle_lhs_call (t, gimple_call_lhs (t),
gimple_call_return_flags (t), rhsc, fndecl);
@@ -7579,43 +7533,66 @@ compute_points_to_sets (void)
pt = gimple_call_use_set (stmt);
if (gimple_call_flags (stmt) & ECF_CONST)
memset (pt, 0, sizeof (struct pt_solution));
- else if ((vi = lookup_call_use_vi (stmt)) != NULL)
- {
- *pt = find_what_var_points_to (cfun->decl, vi);
- /* Escaped (and thus nonlocal) variables are always
- implicitly used by calls. */
- /* ??? ESCAPED can be empty even though NONLOCAL
- always escaped. */
- pt->nonlocal = 1;
- pt->escaped = 1;
- }
else
{
- /* If there is nothing special about this call then
- we have made everything that is used also escape. */
- *pt = cfun->gimple_df->escaped;
- pt->nonlocal = 1;
+ bool uses_global_memory = true;
+ bool reads_global_memory = true;
+
+ determine_global_memory_access (stmt, NULL,
+ &reads_global_memory,
+ &uses_global_memory);
+ if ((vi = lookup_call_use_vi (stmt)) != NULL)
+ {
+ *pt = find_what_var_points_to (cfun->decl, vi);
+ /* Escaped (and thus nonlocal) variables are always
+ implicitly used by calls. */
+ /* ??? ESCAPED can be empty even though NONLOCAL
+ always escaped. */
+ if (uses_global_memory)
+ {
+ pt->nonlocal = uses_global_memory;
+ pt->escaped = uses_global_memory;
+ }
+ }
+ else if (uses_global_memory)
+ {
+ /* If there is nothing special about this call then
+ we have made everything that is used also escape. */
+ *pt = cfun->gimple_df->escaped;
+ pt->nonlocal = 1;
+ }
}
pt = gimple_call_clobber_set (stmt);
if (gimple_call_flags (stmt) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
memset (pt, 0, sizeof (struct pt_solution));
- else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
- {
- *pt = find_what_var_points_to (cfun->decl, vi);
- /* Escaped (and thus nonlocal) variables are always
- implicitly clobbered by calls. */
- /* ??? ESCAPED can be empty even though NONLOCAL
- always escaped. */
- pt->nonlocal = 1;
- pt->escaped = 1;
- }
else
{
- /* If there is nothing special about this call then
- we have made everything that is used also escape. */
- *pt = cfun->gimple_df->escaped;
- pt->nonlocal = 1;
+ bool writes_global_memory = true;
+
+ determine_global_memory_access (stmt, &writes_global_memory,
+ NULL, NULL);
+
+ if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
+ {
+ *pt = find_what_var_points_to (cfun->decl, vi);
+ /* Escaped (and thus nonlocal) variables are always
+ implicitly clobbered by calls. */
+ /* ??? ESCAPED can be empty even though NONLOCAL
+ always escaped. */
+ if (writes_global_memory)
+ {
+ pt->nonlocal = writes_global_memory;
+ pt->escaped = writes_global_memory;
+ }
+ }
+ else if (writes_global_memory)
+ {
+ /* If there is nothing special about this call then
+ we have made everything that is used also escape. */
+ *pt = cfun->gimple_df->escaped;
+ pt->nonlocal = 1;
+ }
}
}
}
diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c
index 9eb8a11..3a057c2 100644
--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -658,11 +658,15 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
substitution list, or the def and use span a call such that
we'll expand lifetimes across a call. We also don't want to
replace across these expressions that may call libcalls that
- clobber the register involved. See PR 70184. */
+ clobber the register involved. See PR 70184. Neither
+ do we want to move possibly trapping expressions across
+ a call. See PRs 102129 and 33593. */
if (gimple_has_volatile_ops (stmt) || same_root_var
|| (tab->call_cnt[ver] != cur_call_cnt
- && SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use), SSA_OP_USE)
- == NULL_USE_OPERAND_P)
+ && (SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use),
+ SSA_OP_USE)
+ == NULL_USE_OPERAND_P
+ || gimple_could_trap_p (SSA_NAME_DEF_STMT (use))))
|| tab->reg_vars_cnt[ver] != cur_reg_vars_cnt)
finished_with_expr (tab, ver, true);
else
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 3aad1493..62f936a 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-range-path.h"
#include "ssa.h"
#include "tree-cfgcleanup.h"
+#include "tree-pretty-print.h"
+#include "cfghooks.h"
// Path registry for the backwards threader. After all paths have been
// registered with register_path(), thread_through_all_blocks() is called
@@ -50,12 +52,11 @@ along with GCC; see the file COPYING3. If not see
class back_threader_registry
{
public:
- back_threader_registry (int max_allowable_paths);
+ back_threader_registry ();
bool register_path (const vec<basic_block> &, edge taken);
- bool thread_through_all_blocks ();
+ bool thread_through_all_blocks (bool may_peel_loop_headers);
private:
- jump_thread_path_registry m_lowlevel_registry;
- const int m_max_allowable_paths;
+ back_jt_path_registry m_lowlevel_registry;
int m_threaded_paths;
};
@@ -76,19 +77,21 @@ private:
class back_threader
{
public:
- back_threader (bool speed_p);
+ back_threader (bool speed_p, bool resolve);
~back_threader ();
void maybe_thread_block (basic_block bb);
- bool thread_through_all_blocks ();
+ bool thread_through_all_blocks (bool may_peel_loop_headers);
private:
void find_paths (basic_block bb, tree name);
- void maybe_register_path (edge taken_edge);
+ edge maybe_register_path ();
bool find_paths_to_names (basic_block bb, bitmap imports);
bool resolve_def (tree name, bitmap interesting, vec<tree> &worklist);
bool resolve_phi (gphi *phi, bitmap imports);
edge find_taken_edge (const vec<basic_block> &path);
edge find_taken_edge_cond (const vec<basic_block> &path, gcond *);
edge find_taken_edge_switch (const vec<basic_block> &path, gswitch *);
+ virtual void debug ();
+ virtual void dump (FILE *out);
back_threader_registry m_registry;
back_threader_profitability m_profit;
@@ -101,7 +104,7 @@ private:
hash_set<basic_block> m_visited_bbs;
// The set of SSA names, any of which could potentially change the
// value of the final conditional in a path.
- bitmap m_imports;
+ auto_bitmap m_imports;
// The last statement in the path.
gimple *m_last_stmt;
// This is a bit of a wart. It's used to pass the LHS SSA name to
@@ -109,44 +112,54 @@ private:
tree m_name;
// Marker to differentiate unreachable edges.
static const edge UNREACHABLE_EDGE;
+ // Set to TRUE if unknown SSA names along a path should be resolved
+ // with the ranger. Otherwise, unknown SSA names are assumed to be
+ // VARYING. Setting to true is more precise but slower.
+ bool m_resolve;
};
// Used to differentiate unreachable edges, so we may stop the search
// in a the given direction.
const edge back_threader::UNREACHABLE_EDGE = (edge) -1;
-back_threader::back_threader (bool speed_p)
- : m_registry (param_max_fsm_thread_paths),
- m_profit (speed_p),
- m_solver (m_ranger)
+back_threader::back_threader (bool speed_p, bool resolve)
+ : m_profit (speed_p),
+ m_solver (m_ranger, resolve)
{
m_last_stmt = NULL;
- m_imports = BITMAP_ALLOC (NULL);
+ m_resolve = resolve;
}
back_threader::~back_threader ()
{
- m_path.release ();
- BITMAP_FREE (m_imports);
}
// Register the current path for jump threading if it's profitable to
-// do so. TAKEN_EDGE is the known edge out of the path.
+// do so.
+//
+// Return the known taken edge out of the path, even if the path was
+// not registered, or NULL if the taken edge could not be determined.
-void
-back_threader::maybe_register_path (edge taken_edge)
+edge
+back_threader::maybe_register_path ()
{
- bool irreducible = false;
- bool profitable
- = m_profit.profitable_path_p (m_path, m_name, taken_edge, &irreducible);
+ edge taken_edge = find_taken_edge (m_path);
- if (profitable)
+ if (taken_edge && taken_edge != UNREACHABLE_EDGE)
{
- m_registry.register_path (m_path, taken_edge);
+ bool irreducible = false;
+ bool profitable
+ = m_profit.profitable_path_p (m_path, m_name, taken_edge, &irreducible);
- if (irreducible)
- vect_free_loop_info_assumptions (m_path[0]->loop_father);
+ if (profitable)
+ {
+ m_registry.register_path (m_path, taken_edge);
+
+ if (irreducible)
+ vect_free_loop_info_assumptions (m_path[0]->loop_father);
+ }
}
+ return taken_edge;
}
// Return the known taken edge out of a path. If the path can be
@@ -179,7 +192,7 @@ back_threader::find_taken_edge_switch (const vec<basic_block> &path,
tree name = gimple_switch_index (sw);
int_range_max r;
- m_solver.precompute_ranges (path, m_imports);
+ m_solver.compute_ranges (path, m_imports);
m_solver.range_of_expr (r, name, sw);
if (r.undefined_p ())
@@ -201,20 +214,14 @@ edge
back_threader::find_taken_edge_cond (const vec<basic_block> &path,
gcond *cond)
{
- m_solver.precompute_ranges (path, m_imports);
-
- // Check if either operand is unreachable since this knowledge could
- // help the caller cut down the search space.
int_range_max r;
- m_solver.range_of_expr (r, gimple_cond_lhs (cond));
- if (r.undefined_p ())
- return UNREACHABLE_EDGE;
- m_solver.range_of_expr (r, gimple_cond_rhs (cond));
- if (r.undefined_p ())
- return UNREACHABLE_EDGE;
+ m_solver.compute_ranges (path, m_imports);
m_solver.range_of_stmt (r, cond);
+ if (m_solver.unreachable_path_p ())
+ return UNREACHABLE_EDGE;
+
int_range<2> true_range (boolean_true_node, boolean_true_node);
int_range<2> false_range (boolean_false_node, boolean_false_node);
@@ -275,6 +282,13 @@ back_threader::resolve_phi (gphi *phi, bitmap interesting)
continue;
}
+ // FIXME: We currently stop looking if we find a threadable path
+ // through a PHI. This is pessimistic, as there can be multiple
+ // paths that can resolve the path. For example:
+ //
+ // x_5 = PHI <10(4), 20(5), ...>
+ // if (x_5 > 5)
+
tree arg = gimple_phi_arg_def (phi, i);
if (TREE_CODE (arg) == SSA_NAME)
{
@@ -286,18 +300,31 @@ back_threader::resolve_phi (gphi *phi, bitmap interesting)
bitmap_set_bit (interesting, v);
bitmap_set_bit (m_imports, v);
- done |= find_paths_to_names (e->src, interesting);
+
+ // When resolving unknowns, see if the incoming SSA can be
+ // resolved on entry without having to keep looking back.
+ bool keep_looking = true;
+ if (m_resolve)
+ {
+ m_path.safe_push (e->src);
+ if (maybe_register_path ())
+ {
+ keep_looking = false;
+ m_visited_bbs.add (e->src);
+ }
+ m_path.pop ();
+ }
+ if (keep_looking)
+ done |= find_paths_to_names (e->src, interesting);
+
bitmap_clear_bit (interesting, v);
}
else if (TREE_CODE (arg) == INTEGER_CST)
{
m_path.safe_push (e->src);
- edge taken_edge = find_taken_edge (m_path);
+ edge taken_edge = maybe_register_path ();
if (taken_edge && taken_edge != UNREACHABLE_EDGE)
- {
- maybe_register_path (taken_edge);
- done = true;
- }
+ done = true;
m_path.pop ();
}
}
@@ -354,6 +381,14 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting)
return false;
}
+ // Try to resolve the path with nothing but ranger knowledge.
+ if (m_resolve && m_path.length () > 1 && maybe_register_path ())
+ {
+ m_path.pop ();
+ m_visited_bbs.remove (bb);
+ return true;
+ }
+
auto_bitmap processed;
unsigned i;
bool done = false;
@@ -385,12 +420,8 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting)
|| bitmap_bit_p (m_ranger.gori ().exports (bb), i))
&& m_path.length () > 1)
{
- edge taken_edge = find_taken_edge (m_path);
- if (taken_edge)
+ if (maybe_register_path ())
{
- if (taken_edge != UNREACHABLE_EDGE)
- maybe_register_path (taken_edge);
-
done = true;
goto leave_bb;
}
@@ -494,9 +525,9 @@ back_threader::maybe_thread_block (basic_block bb)
// Perform the actual jump threading for the all queued paths.
bool
-back_threader::thread_through_all_blocks ()
+back_threader::thread_through_all_blocks (bool may_peel_loop_headers)
{
- return m_registry.thread_through_all_blocks ();
+ return m_registry.thread_through_all_blocks (may_peel_loop_headers);
}
// Dump a sequence of BBs through the CFG.
@@ -519,16 +550,39 @@ debug (const vec <basic_block> &path)
dump_path (stderr, path);
}
-back_threader_registry::back_threader_registry (int max_allowable_paths)
- : m_max_allowable_paths (max_allowable_paths)
+void
+back_threader::dump (FILE *out)
+{
+ m_solver.dump (out);
+ fprintf (out, "\nCandidates for pre-computation:\n");
+ fprintf (out, "===================================\n");
+
+ bitmap_iterator bi;
+ unsigned i;
+
+ EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
+ {
+ tree name = ssa_name (i);
+ print_generic_expr (out, name, TDF_NONE);
+ fprintf (out, "\n");
+ }
+}
+
+void
+back_threader::debug ()
+{
+ dump (stderr);
+}
+
+back_threader_registry::back_threader_registry ()
{
m_threaded_paths = 0;
}
bool
-back_threader_registry::thread_through_all_blocks ()
+back_threader_registry::thread_through_all_blocks (bool may_peel_loop_headers)
{
- return m_lowlevel_registry.thread_through_all_blocks (true);
+ return m_lowlevel_registry.thread_through_all_blocks (may_peel_loop_headers);
}
/* Examine jump threading path PATH and return TRUE if it is profitable to
@@ -541,7 +595,10 @@ back_threader_registry::thread_through_all_blocks ()
TAKEN_EDGE, otherwise it is NULL.
CREATES_IRREDUCIBLE_LOOP, if non-null is set to TRUE if threading this path
- would create an irreducible loop. */
+ would create an irreducible loop.
+
+ ?? It seems we should be able to loosen some of the restrictions in
+ this function after loop optimizations have run. */
bool
back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
@@ -563,15 +620,6 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
if (m_path.length () <= 1)
return false;
- if (m_path.length () > (unsigned) param_max_fsm_thread_length)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " FAIL: FSM jump-thread path not considered: "
- "the number of basic blocks on the path "
- "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n");
- return false;
- }
-
int n_insns = 0;
gimple_stmt_iterator gsi;
loop_p loop = m_path[0]->loop_father;
@@ -607,6 +655,14 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
if (bb->loop_father != loop)
{
path_crosses_loops = true;
+
+ // Dump rest of blocks.
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ for (j++; j < m_path.length (); j++)
+ {
+ bb = m_path[j];
+ fprintf (dump_file, " bb:%i", bb->index);
+ }
break;
}
@@ -694,7 +750,11 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
the last entry in the array when determining if we thread
through the loop latch. */
if (loop->latch == bb)
- threaded_through_latch = true;
+ {
+ threaded_through_latch = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " (latch)");
+ }
}
gimple *stmt = get_gimple_control_stmt (m_path[0]);
@@ -729,7 +789,7 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
if (path_crosses_loops)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " FAIL: FSM jump-thread path not considered: "
+ fprintf (dump_file, " FAIL: Jump-thread path not considered: "
"the path crosses loops.\n");
return false;
}
@@ -745,7 +805,7 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
if (n_insns >= param_max_fsm_thread_path_insns)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " FAIL: FSM jump-thread path not considered: "
+ fprintf (dump_file, " FAIL: Jump-thread path not considered: "
"the number of instructions on the path "
"exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
return false;
@@ -754,7 +814,7 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
else if (!m_speed_p && n_insns > 1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " FAIL: FSM jump-thread path not considered: "
+ fprintf (dump_file, " FAIL: Jump-thread path not considered: "
"duplication of %i insns is needed and optimizing for size.\n",
n_insns);
return false;
@@ -779,25 +839,22 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- " FAIL: FSM would create irreducible loop without threading "
+ " FAIL: Would create irreducible loop without threading "
"multiway branch.\n");
return false;
}
- /* If this path does not thread through the loop latch, then we are
- using the FSM threader to find old style jump threads. This
- is good, except the FSM threader does not re-use an existing
- threading path to reduce code duplication.
-
- So for that case, drastically reduce the number of statements
- we are allowed to copy. */
+ /* The generic copier used by the backthreader does not re-use an
+ existing threading path to reduce code duplication. So for that
+ case, drastically reduce the number of statements we are allowed
+ to copy. */
if (!(threaded_through_latch && threaded_multiway_branch)
&& (n_insns * param_fsm_scale_path_stmts
>= param_max_jump_thread_duplication_stmts))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- " FAIL: FSM did not thread around loop and would copy too "
+ " FAIL: Did not thread around loop and would copy too "
"many statements.\n");
return false;
}
@@ -810,10 +867,26 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- " FAIL: FSM Thread through multiway branch without threading "
+ " FAIL: Thread through multiway branch without threading "
"a multiway branch.\n");
return false;
}
+
+ /* Threading through an empty latch would cause code to be added to
+ the latch. This could alter the loop form sufficiently to cause
+ loop optimizations to fail. Disable these threads until after
+ loop optimizations have run. */
+ if ((threaded_through_latch
+ || (taken_edge && taken_edge->dest == loop->latch))
+ && !(cfun->curr_properties & PROP_loop_opts_done)
+ && empty_block_p (loop->latch))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " FAIL: Thread through latch before loop opts would create non-empty latch\n");
+ return false;
+
+ }
return true;
}
@@ -829,19 +902,11 @@ bool
back_threader_registry::register_path (const vec<basic_block> &m_path,
edge taken_edge)
{
- if (m_threaded_paths > m_max_allowable_paths)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " FAIL: FSM jump-thread path not considered: "
- "the number of previously recorded FSM paths to "
- "thread exceeds PARAM_MAX_FSM_THREAD_PATHS.\n");
- return false;
- }
-
vec<jump_thread_edge *> *jump_thread_path
= m_lowlevel_registry.allocate_thread_path ();
- /* Record the edges between the blocks in PATH. */
+ // The generic copier ignores the edge type. We can build the
+ // thread edges with any type.
for (unsigned int j = 0; j + 1 < m_path.length (); j++)
{
basic_block bb1 = m_path[m_path.length () - j - 1];
@@ -849,90 +914,56 @@ back_threader_registry::register_path (const vec<basic_block> &m_path,
edge e = find_edge (bb1, bb2);
gcc_assert (e);
- jump_thread_edge *x
- = m_lowlevel_registry.allocate_thread_edge (e, EDGE_FSM_THREAD);
- jump_thread_path->safe_push (x);
+ m_lowlevel_registry.push_edge (jump_thread_path, e, EDGE_COPY_SRC_BLOCK);
}
- /* Add the edge taken when the control variable has value ARG. */
- jump_thread_edge *x
- = m_lowlevel_registry.allocate_thread_edge (taken_edge,
- EDGE_NO_COPY_SRC_BLOCK);
- jump_thread_path->safe_push (x);
+ m_lowlevel_registry.push_edge (jump_thread_path,
+ taken_edge, EDGE_NO_COPY_SRC_BLOCK);
if (m_lowlevel_registry.register_jump_thread (jump_thread_path))
++m_threaded_paths;
return true;
}
-namespace {
-
-const pass_data pass_data_thread_jumps =
-{
- GIMPLE_PASS,
- "thread",
- OPTGROUP_NONE,
- TV_TREE_SSA_THREAD_JUMPS,
- ( PROP_cfg | PROP_ssa ),
- 0,
- 0,
- 0,
- TODO_update_ssa,
-};
-
-class pass_thread_jumps : public gimple_opt_pass
-{
-public:
- pass_thread_jumps (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_thread_jumps, ctxt)
- {}
-
- opt_pass * clone (void) { return new pass_thread_jumps (m_ctxt); }
- virtual bool gate (function *);
- virtual unsigned int execute (function *);
-};
-
-bool
-pass_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
-{
- return flag_expensive_optimizations;
-}
-
-// Try to thread blocks in FUN. Return TRUE if any jump thread paths were
-// registered.
+// Try to thread blocks in FUN. RESOLVE is TRUE when fully resolving
+// unknown SSAs. SPEED is TRUE when optimizing for speed.
+//
+// Return TRUE if any jump thread paths were registered.
static bool
-try_thread_blocks (function *fun)
+try_thread_blocks (function *fun, bool resolve, bool speed)
{
- /* Try to thread each block with more than one successor. */
- back_threader threader (/*speed_p=*/true);
+ back_threader threader (speed, resolve);
basic_block bb;
FOR_EACH_BB_FN (bb, fun)
{
if (EDGE_COUNT (bb->succs) > 1)
threader.maybe_thread_block (bb);
}
- return threader.thread_through_all_blocks ();
+ return threader.thread_through_all_blocks (/*peel_loop_headers=*/true);
}
-unsigned int
-pass_thread_jumps::execute (function *fun)
+static unsigned int
+do_early_thread_jumps (function *fun, bool resolve)
{
- loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
- bool changed = try_thread_blocks (fun);
+ try_thread_blocks (fun, resolve, /*speed=*/false);
loop_optimizer_finalize ();
-
- return changed ? TODO_cleanup_cfg : 0;
-}
-
+ return 0;
}
-gimple_opt_pass *
-make_pass_thread_jumps (gcc::context *ctxt)
+static unsigned int
+do_thread_jumps (function *fun, bool resolve)
{
- return new pass_thread_jumps (ctxt);
+ loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
+
+ bool changed = try_thread_blocks (fun, resolve, /*speed=*/true);
+
+ loop_optimizer_finalize ();
+
+ return changed ? TODO_cleanup_cfg : 0;
}
namespace {
@@ -950,6 +981,33 @@ const pass_data pass_data_early_thread_jumps =
( TODO_cleanup_cfg | TODO_update_ssa ),
};
+const pass_data pass_data_thread_jumps =
+{
+ GIMPLE_PASS,
+ "thread",
+ OPTGROUP_NONE,
+ TV_TREE_SSA_THREAD_JUMPS,
+ ( PROP_cfg | PROP_ssa ),
+ 0,
+ 0,
+ 0,
+ TODO_update_ssa,
+};
+
+const pass_data pass_data_thread_jumps_full =
+{
+ GIMPLE_PASS,
+ "thread-full",
+ OPTGROUP_NONE,
+ TV_TREE_SSA_THREAD_JUMPS,
+ ( PROP_cfg | PROP_ssa ),
+ 0,
+ 0,
+ 0,
+ TODO_update_ssa,
+};
+
+// Early jump threading pass optimizing for size.
class pass_early_thread_jumps : public gimple_opt_pass
{
public:
@@ -957,36 +1015,74 @@ public:
: gimple_opt_pass (pass_data_early_thread_jumps, ctxt)
{}
- opt_pass * clone (void) { return new pass_early_thread_jumps (m_ctxt); }
- virtual bool gate (function *);
- virtual unsigned int execute (function *);
+ opt_pass * clone () override
+ {
+ return new pass_early_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_early_thread_jumps (fun, /*resolve=*/false);
+ }
};
-bool
-pass_early_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
+// Jump threading pass without resolving of unknown SSAs.
+class pass_thread_jumps : public gimple_opt_pass
{
- return true;
-}
+public:
+ pass_thread_jumps (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_thread_jumps, ctxt)
+ {}
+ opt_pass * clone (void) override
+ {
+ return new pass_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_thread_jumps (fun, /*resolve=*/false);
+ }
+};
-unsigned int
-pass_early_thread_jumps::execute (function *fun)
+// Jump threading pass that fully resolves unknown SSAs.
+class pass_thread_jumps_full : public gimple_opt_pass
{
- loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+public:
+ pass_thread_jumps_full (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_thread_jumps_full, ctxt)
+ {}
+ opt_pass * clone (void) override
+ {
+ return new pass_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_thread_jumps (fun, /*resolve=*/true);
+ }
+};
- /* Try to thread each block with more than one successor. */
- back_threader threader (/*speed_p=*/false);
- basic_block bb;
- FOR_EACH_BB_FN (bb, fun)
- {
- if (EDGE_COUNT (bb->succs) > 1)
- threader.maybe_thread_block (bb);
- }
- threader.thread_through_all_blocks ();
+} // namespace {
- loop_optimizer_finalize ();
- return 0;
+gimple_opt_pass *
+make_pass_thread_jumps (gcc::context *ctxt)
+{
+ return new pass_thread_jumps (ctxt);
}
+gimple_opt_pass *
+make_pass_thread_jumps_full (gcc::context *ctxt)
+{
+ return new pass_thread_jumps_full (ctxt);
}
gimple_opt_pass *
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 37ee5c1..a63a976 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -33,12 +33,13 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-threadupdate.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
-#include "tree-ssa-dom.h"
#include "gimple-fold.h"
#include "cfganal.h"
#include "alloc-pool.h"
#include "vr-values.h"
#include "gimple-ssa-evrp-analyze.h"
+#include "gimple-range.h"
+#include "gimple-range-path.h"
/* To avoid code explosion due to jump threading, we limit the
number of statements we are going to copy. This variable
@@ -61,8 +62,7 @@ set_ssa_name_value (tree name, tree value)
ssa_name_values[SSA_NAME_VERSION (name)] = value;
}
-jump_threader::jump_threader (jump_threader_simplifier *simplifier,
- jt_state *state)
+jump_threader::jump_threader (jt_simplifier *simplifier, jt_state *state)
{
/* Initialize the per SSA_NAME value-handles array. */
gcc_assert (!ssa_name_values.exists ());
@@ -71,7 +71,7 @@ jump_threader::jump_threader (jump_threader_simplifier *simplifier,
dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node,
integer_zero_node, NULL, NULL);
- m_registry = new jump_thread_path_registry ();
+ m_registry = new fwd_jt_path_registry ();
m_simplifier = simplifier;
m_state = state;
}
@@ -95,6 +95,20 @@ jump_threader::thread_through_all_blocks (bool may_peel_loop_headers)
return m_registry->thread_through_all_blocks (may_peel_loop_headers);
}
+static inline bool
+has_phis_p (basic_block bb)
+{
+ return !gsi_end_p (gsi_start_phis (bb));
+}
+
+/* Return TRUE for a block with PHIs but no statements. */
+
+static bool
+empty_block_with_phis_p (basic_block bb)
+{
+ return gsi_end_p (gsi_start_nondebug_bb (bb)) && has_phis_p (bb);
+}
+
/* Return TRUE if we may be able to thread an incoming edge into
BB to an outgoing edge from BB. Return FALSE otherwise. */
@@ -107,9 +121,8 @@ potentially_threadable_block (basic_block bb)
not optimized away because they forward from outside a loop
to the loop header. We want to thread through them as we can
sometimes thread to the loop exit, which is obviously profitable.
- the interesting case here is when the block has PHIs. */
- if (gsi_end_p (gsi_start_nondebug_bb (bb))
- && !gsi_end_p (gsi_start_phis (bb)))
+ The interesting case here is when the block has PHIs. */
+ if (empty_block_with_phis_p (bb))
return true;
/* If BB has a single successor or a single predecessor, then
@@ -215,8 +228,6 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
when we're finished processing E. */
for (gsi = gsi_start_bb (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
- tree cached_lhs = NULL;
-
stmt = gsi_stmt (gsi);
/* Ignore empty statements and labels. */
@@ -313,75 +324,7 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
continue;
}
- /* At this point we have a statement which assigns an RHS to an
- SSA_VAR on the LHS. We want to try and simplify this statement
- to expose more context sensitive equivalences which in turn may
- allow us to simplify the condition at the end of the loop.
-
- Handle simple copy operations as well as implied copies from
- ASSERT_EXPRs. */
- if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
- cached_lhs = gimple_assign_rhs1 (stmt);
- else if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
- cached_lhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
- else
- {
- /* A statement that is not a trivial copy or ASSERT_EXPR.
- Try to fold the new expression. Inserting the
- expression into the hash table is unlikely to help. */
- /* ??? The DOM callback below can be changed to setting
- the mprts_hook around the call to thread_across_edge,
- avoiding the use substitution. The VRP hook should be
- changed to properly valueize operands itself using
- SSA_NAME_VALUE in addition to its own lattice. */
- cached_lhs = gimple_fold_stmt_to_constant_1 (stmt,
- threadedge_valueize);
- if (NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES) != 0
- && (!cached_lhs
- || (TREE_CODE (cached_lhs) != SSA_NAME
- && !is_gimple_min_invariant (cached_lhs))))
- {
- /* We're going to temporarily copy propagate the operands
- and see if that allows us to simplify this statement. */
- tree *copy;
- ssa_op_iter iter;
- use_operand_p use_p;
- unsigned int num, i = 0;
-
- num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES);
- copy = XALLOCAVEC (tree, num);
-
- /* Make a copy of the uses & vuses into USES_COPY, then cprop into
- the operands. */
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- {
- tree tmp = NULL;
- tree use = USE_FROM_PTR (use_p);
-
- copy[i++] = use;
- if (TREE_CODE (use) == SSA_NAME)
- tmp = SSA_NAME_VALUE (use);
- if (tmp)
- SET_USE (use_p, tmp);
- }
-
- cached_lhs = m_simplifier->simplify (stmt, stmt, e->src, m_state);
-
- /* Restore the statement's original uses/defs. */
- i = 0;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- SET_USE (use_p, copy[i++]);
- }
- }
-
- /* Record the context sensitive equivalence if we were able
- to simplify this statement. */
- if (cached_lhs
- && (TREE_CODE (cached_lhs) == SSA_NAME
- || is_gimple_min_invariant (cached_lhs)))
- m_state->register_equiv (gimple_get_lhs (stmt), cached_lhs);
+ m_state->register_equivs_stmt (stmt, e->src, m_simplifier);
}
return stmt;
}
@@ -443,17 +386,17 @@ jump_threader::simplify_control_stmt_condition (edge e, gimple *stmt)
= simplify_control_stmt_condition_1 (e, stmt, op0, cond_code, op1,
recursion_limit);
- /* If we were testing an integer/pointer against a constant, then
- we can use the FSM code to trace the value of the SSA_NAME. If
- a value is found, then the condition will collapse to a constant.
+ /* If we were testing an integer/pointer against a constant,
+ then we can trace the value of the SSA_NAME. If a value is
+ found, then the condition will collapse to a constant.
Return the SSA_NAME we want to trace back rather than the full
- expression and give the FSM threader a chance to find its value. */
+ expression and give the threader a chance to find its value. */
if (cached_lhs == NULL)
{
/* Recover the original operands. They may have been simplified
using context sensitive equivalences. Those context sensitive
- equivalences may not be valid on paths found by the FSM optimizer. */
+ equivalences may not be valid on paths. */
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -854,7 +797,7 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
/* The key property of these blocks is that they need not be duplicated
when threading. Thus they cannot have visible side effects such
as PHI nodes. */
- if (!gsi_end_p (gsi_start_phis (bb)))
+ if (has_phis_p (bb))
return false;
/* Skip over DEBUG statements at the start of the block. */
@@ -885,10 +828,8 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
if (!bitmap_bit_p (visited, taken_edge->dest->index))
{
- jump_thread_edge *x
- = m_registry->allocate_thread_edge (taken_edge,
- EDGE_NO_COPY_SRC_BLOCK);
- path->safe_push (x);
+ m_registry->push_edge (path, taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
bitmap_set_bit (visited, taken_edge->dest->index);
return thread_around_empty_blocks (path, taken_edge, visited);
}
@@ -929,10 +870,8 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
return false;
bitmap_set_bit (visited, taken_edge->dest->index);
- jump_thread_edge *x
- = m_registry->allocate_thread_edge (taken_edge,
- EDGE_NO_COPY_SRC_BLOCK);
- path->safe_push (x);
+ m_registry->push_edge (path, taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
thread_around_empty_blocks (path, taken_edge, visited);
return true;
@@ -963,7 +902,7 @@ int
jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
edge e, bitmap visited)
{
- m_state->register_equivs_on_edge (e);
+ m_state->register_equivs_edge (e);
/* PHIs create temporary equivalences.
Note that if we found a PHI that made the block non-threadable, then
@@ -994,8 +933,7 @@ jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
{
/* First case. The statement simply doesn't have any instructions, but
does have PHIs. */
- if (gsi_end_p (gsi_start_nondebug_bb (e->dest))
- && !gsi_end_p (gsi_start_phis (e->dest)))
+ if (empty_block_with_phis_p (e->dest))
return 0;
/* Second case. */
@@ -1039,16 +977,10 @@ jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
/* Only push the EDGE_START_JUMP_THREAD marker if this is
first edge on the path. */
if (path->length () == 0)
- {
- jump_thread_edge *x
- = m_registry->allocate_thread_edge (e, EDGE_START_JUMP_THREAD);
- path->safe_push (x);
- }
+ m_registry->push_edge (path, e, EDGE_START_JUMP_THREAD);
- jump_thread_edge *x
- = m_registry->allocate_thread_edge (taken_edge,
- EDGE_COPY_SRC_BLOCK);
- path->safe_push (x);
+ m_registry->push_edge (path, taken_edge, EDGE_COPY_SRC_BLOCK);
+ m_state->append_path (taken_edge->dest);
/* See if we can thread through DEST as well, this helps capture
secondary effects of threading without having to re-run DOM or
@@ -1134,53 +1066,43 @@ edge_forwards_cmp_to_conditional_jump_through_empty_bb_p (edge e)
void
jump_threader::thread_across_edge (edge e)
{
- bitmap visited = BITMAP_ALLOC (NULL);
+ auto_bitmap visited;
m_state->push (e);
stmt_count = 0;
vec<jump_thread_edge *> *path = m_registry->allocate_thread_path ();
- bitmap_clear (visited);
bitmap_set_bit (visited, e->src->index);
bitmap_set_bit (visited, e->dest->index);
- int threaded;
+ int threaded = 0;
if ((e->flags & EDGE_DFS_BACK) == 0)
threaded = thread_through_normal_block (path, e, visited);
- else
- threaded = 0;
if (threaded > 0)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
e->dest);
- m_state->pop ();
- BITMAP_FREE (visited);
m_registry->register_jump_thread (path);
+ m_state->pop ();
return;
}
- else
- {
- /* Negative and zero return values indicate no threading was possible,
- thus there should be no edges on the thread path and no need to walk
- through the vector entries. */
- gcc_assert (path->length () == 0);
- path->release ();
- /* A negative status indicates the target block was deemed too big to
- duplicate. Just quit now rather than trying to use the block as
- a joiner in a jump threading path.
+ gcc_checking_assert (path->length () == 0);
+ path->release ();
+
+ if (threaded < 0)
+ {
+ /* The target block was deemed too big to duplicate. Just quit
+ now rather than trying to use the block as a joiner in a jump
+ threading path.
This prevents unnecessary code growth, but more importantly if we
do not look at all the statements in the block, then we may have
missed some invalidations if we had traversed a backedge! */
- if (threaded < 0)
- {
- BITMAP_FREE (visited);
- m_state->pop ();
- return;
- }
+ m_state->pop ();
+ return;
}
/* We were unable to determine what out edge from E->dest is taken. However,
@@ -1205,7 +1127,6 @@ jump_threader::thread_across_edge (edge e)
if (taken_edge->flags & EDGE_COMPLEX)
{
m_state->pop ();
- BITMAP_FREE (visited);
return;
}
@@ -1223,17 +1144,11 @@ jump_threader::thread_across_edge (edge e)
bitmap_set_bit (visited, e->src->index);
bitmap_set_bit (visited, e->dest->index);
bitmap_set_bit (visited, taken_edge->dest->index);
- vec<jump_thread_edge *> *path = m_registry->allocate_thread_path ();
- /* Record whether or not we were able to thread through a successor
- of E->dest. */
- jump_thread_edge *x
- = m_registry->allocate_thread_edge (e, EDGE_START_JUMP_THREAD);
- path->safe_push (x);
+ vec<jump_thread_edge *> *path = m_registry->allocate_thread_path ();
+ m_registry->push_edge (path, e, EDGE_START_JUMP_THREAD);
+ m_registry->push_edge (path, taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
- x = m_registry->allocate_thread_edge (taken_edge,
- EDGE_COPY_SRC_JOINER_BLOCK);
- path->safe_push (x);
found = thread_around_empty_blocks (path, taken_edge, visited);
if (!found)
@@ -1255,7 +1170,6 @@ jump_threader::thread_across_edge (edge e)
m_state->pop ();
}
- BITMAP_FREE (visited);
}
m_state->pop ();
@@ -1282,6 +1196,9 @@ jump_threader::thread_outgoing_edges (basic_block bb)
int flags = (EDGE_IGNORE | EDGE_COMPLEX | EDGE_ABNORMAL);
gimple *last;
+ if (!flag_thread_jumps)
+ return;
+
/* If we have an outgoing edge to a block with multiple incoming and
outgoing edges, then we may be able to thread the edge, i.e., we
may be able to statically determine which of the outgoing edges
@@ -1309,24 +1226,18 @@ jump_threader::thread_outgoing_edges (basic_block bb)
}
}
-jt_state::jt_state (const_and_copies *copies,
- avail_exprs_stack *exprs,
- evrp_range_analyzer *evrp)
-{
- m_copies = copies;
- m_exprs = exprs;
- m_evrp = evrp;
-}
+// Marker to keep track of the start of the current path.
+const basic_block jt_state::BB_MARKER = (basic_block) -1;
// Record that E is being crossed.
void
-jt_state::push (edge)
+jt_state::push (edge e)
{
- m_copies->push_marker ();
- m_exprs->push_marker ();
- if (m_evrp)
- m_evrp->push_marker ();
+ m_blocks.safe_push (BB_MARKER);
+ if (m_blocks.length () == 1)
+ m_blocks.safe_push (e->src);
+ m_blocks.safe_push (e->dest);
}
// Pop to the last pushed state.
@@ -1334,123 +1245,223 @@ jt_state::push (edge)
void
jt_state::pop ()
{
- m_copies->pop_to_marker ();
- m_exprs->pop_to_marker ();
- if (m_evrp)
- m_evrp->pop_to_marker ();
+ if (!m_blocks.is_empty ())
+ {
+ while (m_blocks.last () != BB_MARKER)
+ m_blocks.pop ();
+ // Pop marker.
+ m_blocks.pop ();
+ }
}
-// Record an equivalence from DST to SRC. If UPDATE_RANGE is TRUE,
-// update the value range associated with DST.
+// Add BB to the list of blocks seen.
+
+void
+jt_state::append_path (basic_block bb)
+{
+ gcc_checking_assert (!m_blocks.is_empty ());
+ m_blocks.safe_push (bb);
+}
+
+void
+jt_state::dump (FILE *out)
+{
+ if (!m_blocks.is_empty ())
+ {
+ auto_vec<basic_block> path;
+ get_path (path);
+ dump_ranger (out, path);
+ }
+}
+
+void
+jt_state::debug ()
+{
+ push_dump_file save (stderr, TDF_DETAILS);
+ dump (stderr);
+}
+
+// Convert the current path in jt_state into a path suitable for the
+// path solver. Return the resulting path in PATH.
void
-jt_state::register_equiv (tree dst, tree src, bool update_range)
+jt_state::get_path (vec<basic_block> &path)
{
- m_copies->record_const_or_copy (dst, src);
+ path.truncate (0);
- /* If requested, update the value range associated with DST, using
- the range from SRC. */
- if (m_evrp && update_range)
+ for (int i = (int) m_blocks.length () - 1; i >= 0; --i)
{
- /* Get new VR we can pass to push_value_range. */
- value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv ();
- new (new_vr) value_range_equiv ();
-
- /* There are three cases to consider:
-
- First if SRC is an SSA_NAME, then we can copy the value range
- from SRC into NEW_VR.
-
- Second if SRC is an INTEGER_CST, then we can just set NEW_VR
- to a singleton range. Note that even if SRC is a constant we
- need to set a suitable output range so that VR_UNDEFINED
- ranges do not leak through.
-
- Otherwise set NEW_VR to varying. This may be overly
- conservative. */
- if (TREE_CODE (src) == SSA_NAME)
- new_vr->deep_copy (m_evrp->get_value_range (src));
- else if (TREE_CODE (src) == INTEGER_CST)
- new_vr->set (src);
- else
- new_vr->set_varying (TREE_TYPE (src));
+ basic_block bb = m_blocks[i];
- /* This is a temporary range for DST, so push it. */
- m_evrp->push_value_range (dst, new_vr);
+ if (bb != BB_MARKER)
+ path.safe_push (bb);
}
}
+// Record an equivalence from DST to SRC. If UPDATE_RANGE is TRUE,
+// update the value range associated with DST.
+
+void
+jt_state::register_equiv (tree dest ATTRIBUTE_UNUSED,
+ tree src ATTRIBUTE_UNUSED,
+ bool update_range ATTRIBUTE_UNUSED)
+{
+}
+
// Record any ranges calculated in STMT. If TEMPORARY is TRUE, then
// this is a temporary equivalence and should be recorded into the
// unwind table, instead of the global table.
void
-jt_state::record_ranges_from_stmt (gimple *stmt, bool temporary)
+jt_state::record_ranges_from_stmt (gimple *,
+ bool temporary ATTRIBUTE_UNUSED)
{
- if (m_evrp)
- m_evrp->record_ranges_from_stmt (stmt, temporary);
}
// Record any equivalences created by traversing E.
void
-jt_state::register_equivs_on_edge (edge e)
+jt_state::register_equivs_edge (edge)
{
- record_temporary_equivalences (e, m_copies, m_exprs);
}
-jump_threader_simplifier::jump_threader_simplifier (vr_values *v)
+void
+jt_state::register_equivs_stmt (gimple *stmt, basic_block bb,
+ jt_simplifier *simplifier)
{
- m_vr_values = v;
+ /* At this point we have a statement which assigns an RHS to an
+ SSA_VAR on the LHS. We want to try and simplify this statement
+ to expose more context sensitive equivalences which in turn may
+ allow us to simplify the condition at the end of the loop.
+
+ Handle simple copy operations as well as implied copies from
+ ASSERT_EXPRs. */
+ tree cached_lhs = NULL;
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ cached_lhs = gimple_assign_rhs1 (stmt);
+ else if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
+ cached_lhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+ else
+ {
+ /* A statement that is not a trivial copy or ASSERT_EXPR.
+ Try to fold the new expression. Inserting the
+ expression into the hash table is unlikely to help. */
+ /* ??? The DOM callback below can be changed to setting
+ the mprts_hook around the call to thread_across_edge,
+ avoiding the use substitution. The VRP hook should be
+ changed to properly valueize operands itself using
+ SSA_NAME_VALUE in addition to its own lattice. */
+ cached_lhs = gimple_fold_stmt_to_constant_1 (stmt,
+ threadedge_valueize);
+ if (NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES) != 0
+ && (!cached_lhs
+ || (TREE_CODE (cached_lhs) != SSA_NAME
+ && !is_gimple_min_invariant (cached_lhs))))
+ {
+ /* We're going to temporarily copy propagate the operands
+ and see if that allows us to simplify this statement. */
+ tree *copy;
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ unsigned int num, i = 0;
+
+ num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES);
+ copy = XALLOCAVEC (tree, num);
+
+ /* Make a copy of the uses & vuses into USES_COPY, then cprop into
+ the operands. */
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+ {
+ tree tmp = NULL;
+ tree use = USE_FROM_PTR (use_p);
+
+ copy[i++] = use;
+ if (TREE_CODE (use) == SSA_NAME)
+ tmp = SSA_NAME_VALUE (use);
+ if (tmp)
+ SET_USE (use_p, tmp);
+ }
+
+ cached_lhs = simplifier->simplify (stmt, stmt, bb, this);
+
+ /* Restore the statement's original uses/defs. */
+ i = 0;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+ SET_USE (use_p, copy[i++]);
+ }
+ }
+
+ /* Record the context sensitive equivalence if we were able
+ to simplify this statement. */
+ if (cached_lhs
+ && (TREE_CODE (cached_lhs) == SSA_NAME
+ || is_gimple_min_invariant (cached_lhs)))
+ register_equiv (gimple_get_lhs (stmt), cached_lhs,
+ /*update_range=*/false);
}
-// Return the singleton that resolves STMT, if it is possible to
-// simplify it.
-//
-// STMT may be a dummy statement, not necessarily in the CFG, in which
-// case WITHIN_STMT can be used to determine the position in the CFG
-// where STMT should be evaluated as being in.
+// Hybrid threader implementation.
+
+
+hybrid_jt_simplifier::hybrid_jt_simplifier (gimple_ranger *r,
+ path_range_query *q)
+{
+ m_ranger = r;
+ m_query = q;
+}
tree
-jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block,
- jt_state *)
+hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block,
+ jt_state *state)
{
- if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+ int_range_max r;
+
+ compute_ranges_from_state (stmt, state);
+
+ if (gimple_code (stmt) == GIMPLE_COND
+ || gimple_code (stmt) == GIMPLE_ASSIGN)
{
- simplify_using_ranges simplifier (m_vr_values);
- return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- within_stmt);
+ tree ret;
+ if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret))
+ return ret;
}
- if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
+ else if (gimple_code (stmt) == GIMPLE_SWITCH)
{
- tree op = gimple_switch_index (switch_stmt);
- if (TREE_CODE (op) != SSA_NAME)
- return NULL_TREE;
-
- const value_range_equiv *vr = m_vr_values->get_value_range (op);
- return find_case_label_range (switch_stmt, vr);
+ gswitch *switch_stmt = dyn_cast <gswitch *> (stmt);
+ tree index = gimple_switch_index (switch_stmt);
+ if (m_query->range_of_expr (r, index, stmt))
+ return find_case_label_range (switch_stmt, &r);
}
- if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
+ return NULL;
+}
+
+// Use STATE to generate the list of imports needed for the solver,
+// and calculate the ranges along the path.
+
+void
+hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state)
+{
+ auto_bitmap imports;
+ gori_compute &gori = m_ranger->gori ();
+
+ state->get_path (m_path);
+
+ // Start with the imports to the final conditional.
+ bitmap_copy (imports, gori.imports (m_path[0]));
+
+ // Add any other interesting operands we may have missed.
+ if (gimple_bb (stmt) != m_path[0])
{
- tree lhs = gimple_assign_lhs (assign_stmt);
- if (TREE_CODE (lhs) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && stmt_interesting_for_vrp (stmt))
+ for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
{
- edge dummy_e;
- tree dummy_tree;
- value_range_equiv new_vr;
- m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree,
- &new_vr);
- tree singleton;
- if (new_vr.singleton_p (&singleton))
- return singleton;
+ tree op = gimple_op (stmt, i);
+ if (op
+ && TREE_CODE (op) == SSA_NAME
+ && irange::supports_type_p (TREE_TYPE (op)))
+ bitmap_set_bit (imports, SSA_NAME_VERSION (op));
}
}
- return NULL;
+ m_query->compute_ranges (m_path, imports);
}
diff --git a/gcc/tree-ssa-threadedge.h b/gcc/tree-ssa-threadedge.h
index 0002b20..c46a5c6 100644
--- a/gcc/tree-ssa-threadedge.h
+++ b/gcc/tree-ssa-threadedge.h
@@ -26,19 +26,54 @@ along with GCC; see the file COPYING3. If not see
class jt_state
{
public:
- jt_state (class const_and_copies *,
- class avail_exprs_stack *,
- class evrp_range_analyzer *);
- void push (edge);
- void pop ();
- void register_equiv (tree dest, tree src, bool update_range = false);
- void register_equivs_on_edge (edge e);
- void record_ranges_from_stmt (gimple *stmt, bool temporary);
+ virtual ~jt_state () { }
+ virtual void push (edge);
+ virtual void pop ();
+ virtual void register_equiv (tree dest, tree src, bool update_range);
+ virtual void register_equivs_edge (edge e);
+ virtual void register_equivs_stmt (gimple *, basic_block,
+ class jt_simplifier *);
+ virtual void record_ranges_from_stmt (gimple *stmt, bool temporary);
+ void get_path (vec<basic_block> &);
+ void append_path (basic_block);
+ void dump (FILE *);
+ void debug ();
private:
- const_and_copies *m_copies;
- avail_exprs_stack *m_exprs;
- evrp_range_analyzer *m_evrp;
+ auto_vec<basic_block> m_blocks;
+ static const basic_block BB_MARKER;
+};
+
+// Statement simplifier callback for the jump threader.
+
+class jt_simplifier
+{
+public:
+ virtual ~jt_simplifier () { }
+ virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) = 0;
+};
+
+class hybrid_jt_state : public jt_state
+{
+private:
+ void register_equivs_stmt (gimple *, basic_block, jt_simplifier *) override
+ {
+ // Ranger has no need to simplify anything.
+ }
+};
+
+class hybrid_jt_simplifier : public jt_simplifier
+{
+public:
+ hybrid_jt_simplifier (class gimple_ranger *r, class path_range_query *q);
+ tree simplify (gimple *stmt, gimple *, basic_block, jt_state *) override;
+
+private:
+ void compute_ranges_from_state (gimple *stmt, jt_state *);
+
+ gimple_ranger *m_ranger;
+ path_range_query *m_query;
+ auto_vec<basic_block> m_path;
};
// This is the high level threader. The entry point is
@@ -49,7 +84,7 @@ private:
class jump_threader
{
public:
- jump_threader (class jump_threader_simplifier *, class jt_state *);
+ jump_threader (jt_simplifier *, class jt_state *);
~jump_threader ();
void thread_outgoing_edges (basic_block);
void remove_jump_threads_including (edge_def *);
@@ -75,24 +110,11 @@ private:
// Dummy condition to avoid creating lots of throw away statements.
gcond *dummy_cond;
- class jump_thread_path_registry *m_registry;
- jump_threader_simplifier *m_simplifier;
+ class fwd_jt_path_registry *m_registry;
+ jt_simplifier *m_simplifier;
jt_state *m_state;
};
-// Statement simplifier callback for the jump threader.
-
-class jump_threader_simplifier
-{
-public:
- jump_threader_simplifier (class vr_values *v);
- virtual ~jump_threader_simplifier () { }
- virtual tree simplify (gimple *, gimple *, basic_block, jt_state *);
-
-protected:
- vr_values *m_vr_values;
-};
-
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
extern bool single_succ_to_potentially_threadable_block (basic_block);
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index d08e7d3..32ce1e3 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -167,29 +167,45 @@ jump_thread_path_allocator::allocate_thread_path ()
return new (r) vec<jump_thread_edge *> ();
}
-jump_thread_path_registry::jump_thread_path_registry ()
+jt_path_registry::jt_path_registry (bool backedge_threads)
{
m_paths.create (5);
- m_removed_edges = new hash_table<struct removed_edges> (17);
m_num_threaded_edges = 0;
- m_redirection_data = NULL;
+ m_backedge_threads = backedge_threads;
}
-jump_thread_path_registry::~jump_thread_path_registry ()
+jt_path_registry::~jt_path_registry ()
{
m_paths.release ();
+}
+
+fwd_jt_path_registry::fwd_jt_path_registry ()
+ : jt_path_registry (/*backedge_threads=*/false)
+{
+ m_removed_edges = new hash_table<struct removed_edges> (17);
+ m_redirection_data = NULL;
+}
+
+fwd_jt_path_registry::~fwd_jt_path_registry ()
+{
delete m_removed_edges;
}
-jump_thread_edge *
-jump_thread_path_registry::allocate_thread_edge (edge e,
- jump_thread_edge_type t)
+back_jt_path_registry::back_jt_path_registry ()
+ : jt_path_registry (/*backedge_threads=*/true)
{
- return m_allocator.allocate_thread_edge (e, t);
+}
+
+void
+jt_path_registry::push_edge (vec<jump_thread_edge *> *path,
+ edge e, jump_thread_edge_type type)
+{
+ jump_thread_edge *x = m_allocator.allocate_thread_edge (e, type);
+ path->safe_push (x);
}
vec<jump_thread_edge *> *
-jump_thread_path_registry::allocate_thread_path ()
+jt_path_registry::allocate_thread_path ()
{
return m_allocator.allocate_thread_path ();
}
@@ -197,16 +213,20 @@ jump_thread_path_registry::allocate_thread_path ()
/* Dump a jump threading path, including annotations about each
edge in the path. */
-void
+static void
dump_jump_thread_path (FILE *dump_file,
- const vec<jump_thread_edge *> path,
+ const vec<jump_thread_edge *> &path,
bool registering)
{
- fprintf (dump_file,
- " %s%s jump thread: (%d, %d) incoming edge; ",
- (registering ? "Registering" : "Cancelling"),
- (path[0]->type == EDGE_FSM_THREAD ? " FSM": ""),
- path[0]->e->src->index, path[0]->e->dest->index);
+ if (registering)
+ fprintf (dump_file,
+ " [%u] Registering jump thread: (%d, %d) incoming edge; ",
+ dbg_cnt_counter (registered_jump_thread),
+ path[0]->e->src->index, path[0]->e->dest->index);
+ else
+ fprintf (dump_file,
+ " Cancelling jump thread: (%d, %d) incoming edge; ",
+ path[0]->e->src->index, path[0]->e->dest->index);
for (unsigned int i = 1; i < path.length (); i++)
{
@@ -217,20 +237,24 @@ dump_jump_thread_path (FILE *dump_file,
if (path[i]->e == NULL)
continue;
- if (path[i]->type == EDGE_COPY_SRC_JOINER_BLOCK)
- fprintf (dump_file, " (%d, %d) joiner; ",
- path[i]->e->src->index, path[i]->e->dest->index);
- if (path[i]->type == EDGE_COPY_SRC_BLOCK)
- fprintf (dump_file, " (%d, %d) normal;",
- path[i]->e->src->index, path[i]->e->dest->index);
- if (path[i]->type == EDGE_NO_COPY_SRC_BLOCK)
- fprintf (dump_file, " (%d, %d) nocopy;",
- path[i]->e->src->index, path[i]->e->dest->index);
- if (path[0]->type == EDGE_FSM_THREAD)
- fprintf (dump_file, " (%d, %d) ",
- path[i]->e->src->index, path[i]->e->dest->index);
+ fprintf (dump_file, " (%d, %d) ",
+ path[i]->e->src->index, path[i]->e->dest->index);
+ switch (path[i]->type)
+ {
+ case EDGE_COPY_SRC_JOINER_BLOCK:
+ fprintf (dump_file, "joiner");
+ break;
+ case EDGE_COPY_SRC_BLOCK:
+ fprintf (dump_file, "normal");
+ break;
+ case EDGE_NO_COPY_SRC_BLOCK:
+ fprintf (dump_file, "nocopy");
+ break;
+ default:
+ gcc_unreachable ();
+ }
}
- fputc ('\n', dump_file);
+ fprintf (dump_file, "; \n");
}
DEBUG_FUNCTION void
@@ -239,6 +263,29 @@ debug (const vec<jump_thread_edge *> &path)
dump_jump_thread_path (stderr, path, true);
}
+DEBUG_FUNCTION void
+debug (const vec<jump_thread_edge *> *path)
+{
+ debug (*path);
+}
+
+/* Release the memory associated with PATH, and if dumping is enabled,
+ dump out the reason why the thread was canceled. */
+
+static void
+cancel_thread (vec<jump_thread_edge *> *path, const char *reason = NULL)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ if (reason)
+ fprintf (dump_file, "%s:\n", reason);
+
+ dump_jump_thread_path (dump_file, *path, false);
+ fprintf (dump_file, "\n");
+ }
+ path->release ();
+}
+
/* Simple hashing function. For any given incoming edge E, we're going
to be most concerned with the final destination of its jump thread
path. So hash on the block index of the final edge in the path. */
@@ -403,8 +450,7 @@ create_block_for_threading (basic_block bb,
edges associated with E in the hash table. */
redirection_data *
-jump_thread_path_registry::lookup_redirection_data (edge e,
- enum insert_option insert)
+fwd_jt_path_registry::lookup_redirection_data (edge e, insert_option insert)
{
struct redirection_data **slot;
struct redirection_data *elt;
@@ -1390,9 +1436,9 @@ redirection_block_p (basic_block bb)
If JOINERS is true, then thread through joiner blocks as well. */
bool
-jump_thread_path_registry::thread_block_1 (basic_block bb,
- bool noloop_only,
- bool joiners)
+fwd_jt_path_registry::thread_block_1 (basic_block bb,
+ bool noloop_only,
+ bool joiners)
{
/* E is an incoming edge into BB that we may or may not want to
redirect to a duplicate of BB. */
@@ -1443,7 +1489,7 @@ jump_thread_path_registry::thread_block_1 (basic_block bb,
/* Since this case is not handled by our special code
to thread through a loop header, we must explicitly
cancel the threading request here. */
- path->release ();
+ cancel_thread (path, "Threading through unhandled loop header");
e->aux = NULL;
continue;
}
@@ -1482,7 +1528,7 @@ jump_thread_path_registry::thread_block_1 (basic_block bb,
if (i != path->length ())
{
- path->release ();
+ cancel_thread (path, "Threading through loop exit");
e->aux = NULL;
continue;
}
@@ -1571,7 +1617,7 @@ jump_thread_path_registry::thread_block_1 (basic_block bb,
opportunity. */
bool
-jump_thread_path_registry::thread_block (basic_block bb, bool noloop_only)
+fwd_jt_path_registry::thread_block (basic_block bb, bool noloop_only)
{
bool retval;
retval = thread_block_1 (bb, noloop_only, false);
@@ -1652,9 +1698,8 @@ determine_bb_domination_status (class loop *loop, basic_block bb)
to the inside of the loop. */
bool
-jump_thread_path_registry::thread_through_loop_header
- (class loop *loop,
- bool may_peel_loop_headers)
+fwd_jt_path_registry::thread_through_loop_header (class loop *loop,
+ bool may_peel_loop_headers)
{
basic_block header = loop->header;
edge e, tgt_edge, latch = loop_latch_edge (loop);
@@ -1841,7 +1886,7 @@ fail:
if (path)
{
- path->release ();
+ cancel_thread (path, "Failure in thread_through_loop_header");
e->aux = NULL;
}
}
@@ -1909,7 +1954,7 @@ count_stmts_and_phis_in_block (basic_block bb)
hash table lookups to map from threaded edge to new target. */
void
-jump_thread_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
+fwd_jt_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
{
unsigned int i;
bitmap_iterator bi;
@@ -1969,9 +2014,7 @@ jump_thread_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
else
{
m_paths.unordered_remove (i);
- if (dump_file && (dump_flags & TDF_DETAILS))
- dump_jump_thread_path (dump_file, *path, false);
- path->release ();
+ cancel_thread (path);
}
}
else
@@ -2006,9 +2049,7 @@ jump_thread_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
{
e->aux = NULL;
m_paths.unordered_remove (i);
- if (dump_file && (dump_flags & TDF_DETAILS))
- dump_jump_thread_path (dump_file, *path, false);
- path->release ();
+ cancel_thread (path);
}
}
else
@@ -2054,9 +2095,7 @@ jump_thread_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
if (j != path->length ())
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- dump_jump_thread_path (dump_file, *path, false);
- path->release ();
+ cancel_thread (path);
e->aux = NULL;
}
else
@@ -2103,7 +2142,7 @@ jump_thread_path_registry::mark_threaded_blocks (bitmap threaded_blocks)
if (e2 && !phi_args_equal_on_edges (e2, final_edge))
{
- path->release ();
+ cancel_thread (path);
e->aux = NULL;
}
}
@@ -2180,7 +2219,7 @@ bb_in_bbs (basic_block bb, basic_block *bbs, int n)
}
void
-jump_thread_path_registry::debug_path (FILE *dump_file, int pathno)
+jt_path_registry::debug_path (FILE *dump_file, int pathno)
{
vec<jump_thread_edge *> *p = m_paths[pathno];
fprintf (dump_file, "path: ");
@@ -2191,7 +2230,7 @@ jump_thread_path_registry::debug_path (FILE *dump_file, int pathno)
}
void
-jump_thread_path_registry::dump ()
+jt_path_registry::debug ()
{
for (unsigned i = 0; i < m_paths.length (); ++i)
debug_path (stderr, i);
@@ -2206,8 +2245,8 @@ jump_thread_path_registry::dump ()
Returns TRUE if we were able to successfully rewire the edge. */
bool
-jump_thread_path_registry::rewire_first_differing_edge (unsigned path_num,
- unsigned edge_num)
+back_jt_path_registry::rewire_first_differing_edge (unsigned path_num,
+ unsigned edge_num)
{
vec<jump_thread_edge *> *path = m_paths[path_num];
edge &e = (*path)[edge_num]->e;
@@ -2234,8 +2273,8 @@ jump_thread_path_registry::rewire_first_differing_edge (unsigned path_num,
return true;
}
-/* After an FSM path has been jump threaded, adjust the remaining FSM
- paths that are subsets of this path, so these paths can be safely
+/* After a path has been jump threaded, adjust the remaining paths
+ that are subsets of this path, so these paths can be safely
threaded within the context of the new threaded path.
For example, suppose we have just threaded:
@@ -2252,11 +2291,9 @@ jump_thread_path_registry::rewire_first_differing_edge (unsigned path_num,
specifies the path that was just threaded. */
void
-jump_thread_path_registry::adjust_paths_after_duplication
- (unsigned curr_path_num)
+back_jt_path_registry::adjust_paths_after_duplication (unsigned curr_path_num)
{
vec<jump_thread_edge *> *curr_path = m_paths[curr_path_num];
- gcc_assert ((*curr_path)[0]->type == EDGE_FSM_THREAD);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2273,10 +2310,9 @@ jump_thread_path_registry::adjust_paths_after_duplication
continue;
}
/* Make sure the candidate to adjust starts with the same path
- as the recently threaded path and is an FSM thread. */
+ as the recently threaded path. */
vec<jump_thread_edge *> *cand_path = m_paths[cand_path_num];
- if ((*cand_path)[0]->type != EDGE_FSM_THREAD
- || (*cand_path)[0]->e != (*curr_path)[0]->e)
+ if ((*cand_path)[0]->e != (*curr_path)[0]->e)
{
++cand_path_num;
continue;
@@ -2326,14 +2362,15 @@ jump_thread_path_registry::adjust_paths_after_duplication
if (j == cand_path->length ())
{
remove_candidate_from_list:
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "adjusted candidate: [EMPTY]\n");
- cand_path->release ();
+ cancel_thread (cand_path, "Adjusted candidate is EMPTY");
m_paths.unordered_remove (cand_path_num);
continue;
}
/* Otherwise, just remove the redundant sub-path. */
- cand_path->block_remove (0, j);
+ if (cand_path->length () - j > 1)
+ cand_path->block_remove (0, j);
+ else if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Dropping illformed candidate.\n");
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2357,11 +2394,11 @@ jump_thread_path_registry::adjust_paths_after_duplication
Returns false if it is unable to copy the region, true otherwise. */
bool
-jump_thread_path_registry::duplicate_thread_path (edge entry,
- edge exit,
- basic_block *region,
- unsigned n_region,
- unsigned current_path_no)
+back_jt_path_registry::duplicate_thread_path (edge entry,
+ edge exit,
+ basic_block *region,
+ unsigned n_region,
+ unsigned current_path_no)
{
unsigned i;
class loop *loop = entry->dest->loop_father;
@@ -2536,79 +2573,60 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
DOM/VRP rather than for every case where DOM optimizes away a COND_EXPR. */
void
-jump_thread_path_registry::remove_jump_threads_including (edge_def *e)
+fwd_jt_path_registry::remove_jump_threads_including (edge_def *e)
{
- if (!m_paths.exists ())
+ if (!m_paths.exists () || !flag_thread_jumps)
return;
edge *slot = m_removed_edges->find_slot (e, INSERT);
*slot = e;
}
-/* Walk through all blocks and thread incoming edges to the appropriate
- outgoing edge for each edge pair recorded in THREADED_EDGES.
+/* Thread all paths that have been queued for jump threading, and
+ update the CFG accordingly.
It is the caller's responsibility to fix the dominance information
and rewrite duplicated SSA_NAMEs back into SSA form.
- If MAY_PEEL_LOOP_HEADERS is false, we avoid threading edges through
- loop headers if it does not simplify the loop.
+ If PEEL_LOOP_HEADERS is false, avoid threading edges through loop
+ headers if it does not simplify the loop.
- Returns true if one or more edges were threaded, false otherwise. */
+ Returns true if one or more edges were threaded. */
bool
-jump_thread_path_registry::thread_through_all_blocks
- (bool may_peel_loop_headers)
+jt_path_registry::thread_through_all_blocks (bool peel_loop_headers)
{
- bool retval = false;
- unsigned int i;
- auto_bitmap threaded_blocks;
- hash_set<edge> visited_starting_edges;
-
- if (!m_paths.exists ())
- {
- retval = false;
- goto out;
- }
+ if (m_paths.length () == 0)
+ return false;
m_num_threaded_edges = 0;
- /* Remove any paths that referenced removed edges. */
- if (m_removed_edges)
- for (i = 0; i < m_paths.length (); )
- {
- unsigned int j;
- vec<jump_thread_edge *> *path = m_paths[i];
+ bool retval = update_cfg (peel_loop_headers);
- for (j = 0; j < path->length (); j++)
- {
- edge e = (*path)[j]->e;
- if (m_removed_edges->find_slot (e, NO_INSERT))
- break;
- }
+ statistics_counter_event (cfun, "Jumps threaded", m_num_threaded_edges);
- if (j != path->length ())
- {
- path->release ();
- m_paths.unordered_remove (i);
- continue;
- }
- i++;
- }
+ if (retval)
+ {
+ loops_state_set (LOOPS_NEED_FIXUP);
+ return true;
+ }
+ return false;
+}
- /* Jump-thread all FSM threads before other jump-threads. */
- for (i = 0; i < m_paths.length ();)
+/* This is the backward threader version of thread_through_all_blocks
+ using a generic BB copier. */
+
+bool
+back_jt_path_registry::update_cfg (bool /*peel_loop_headers*/)
+{
+ bool retval = false;
+ hash_set<edge> visited_starting_edges;
+
+ while (m_paths.length ())
{
- vec<jump_thread_edge *> *path = m_paths[i];
+ vec<jump_thread_edge *> *path = m_paths[0];
edge entry = (*path)[0]->e;
- /* Only code-generate FSM jump-threads in this loop. */
- if ((*path)[0]->type != EDGE_FSM_THREAD)
- {
- i++;
- continue;
- }
-
/* Do not jump-thread twice from the same starting edge.
Previously we only checked that we weren't threading twice
@@ -2622,9 +2640,9 @@ jump_thread_path_registry::thread_through_all_blocks
various reasons. So check it first. */
|| !valid_jump_thread_path (path))
{
- /* Remove invalid FSM jump-thread paths. */
- path->release ();
- m_paths.unordered_remove (i);
+ /* Remove invalid jump-thread paths. */
+ cancel_thread (path, "Avoiding threading twice from same edge");
+ m_paths.unordered_remove (0);
continue;
}
@@ -2635,7 +2653,7 @@ jump_thread_path_registry::thread_through_all_blocks
for (unsigned int j = 0; j < len - 1; j++)
region[j] = (*path)[j]->e->dest;
- if (duplicate_thread_path (entry, exit, region, len - 1, i))
+ if (duplicate_thread_path (entry, exit, region, len - 1, 0))
{
/* We do not update dominance info. */
free_dominance_info (CDI_DOMINATORS);
@@ -2645,27 +2663,44 @@ jump_thread_path_registry::thread_through_all_blocks
}
path->release ();
- m_paths.unordered_remove (i);
+ m_paths.unordered_remove (0);
free (region);
}
+ return retval;
+}
- /* Remove from PATHS all the jump-threads starting with an edge already
- jump-threaded. */
- for (i = 0; i < m_paths.length ();)
- {
- vec<jump_thread_edge *> *path = m_paths[i];
- edge entry = (*path)[0]->e;
+/* This is the forward threader version of thread_through_all_blocks,
+ using a custom BB copier. */
- /* Do not jump-thread twice from the same block. */
- if (visited_starting_edges.contains (entry))
- {
- path->release ();
- m_paths.unordered_remove (i);
- }
- else
+bool
+fwd_jt_path_registry::update_cfg (bool may_peel_loop_headers)
+{
+ bool retval = false;
+
+ /* Remove any paths that referenced removed edges. */
+ if (m_removed_edges)
+ for (unsigned i = 0; i < m_paths.length (); )
+ {
+ unsigned int j;
+ vec<jump_thread_edge *> *path = m_paths[i];
+
+ for (j = 0; j < path->length (); j++)
+ {
+ edge e = (*path)[j]->e;
+ if (m_removed_edges->find_slot (e, NO_INSERT))
+ break;
+ }
+
+ if (j != path->length ())
+ {
+ cancel_thread (path, "Thread references removed edge");
+ m_paths.unordered_remove (i);
+ continue;
+ }
i++;
- }
+ }
+ auto_bitmap threaded_blocks;
mark_threaded_blocks (threaded_blocks);
initialize_original_copy_tables ();
@@ -2722,17 +2757,79 @@ jump_thread_path_registry::thread_through_all_blocks
gcc_assert (e->aux == NULL);
}
- statistics_counter_event (cfun, "Jumps threaded", m_num_threaded_edges);
-
free_original_copy_tables ();
- m_paths.release ();
+ return retval;
+}
- if (retval)
- loops_state_set (LOOPS_NEED_FIXUP);
+bool
+jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path)
+{
+ gcc_checking_assert (!path.is_empty ());
+ edge entry = path[0]->e;
+ edge exit = path[path.length () - 1]->e;
+ bool seen_latch = false;
+ int loops_crossed = 0;
+ bool crossed_latch = false;
+ // Use ->dest here instead of ->src to ignore the first block. The
+ // first block is allowed to be in a different loop, since it'll be
+ // redirected. See similar comment in profitable_path_p: "we don't
+ // care about that block...".
+ loop_p loop = entry->dest->loop_father;
+ loop_p curr_loop = loop;
+
+ for (unsigned int i = 0; i < path.length (); i++)
+ {
+ edge e = path[i]->e;
- out:
- return retval;
+ if (e == NULL)
+ {
+ // NULL outgoing edges on a path can happen for jumping to a
+ // constant address.
+ cancel_thread (&path, "Found NULL edge in jump threading path");
+ return true;
+ }
+
+ if (loop->latch == e->src || loop->latch == e->dest)
+ {
+ seen_latch = true;
+ // Like seen_latch, but excludes the first block.
+ if (e->src != entry->src)
+ crossed_latch = true;
+ }
+
+ if (e->dest->loop_father != curr_loop)
+ {
+ curr_loop = e->dest->loop_father;
+ ++loops_crossed;
+ }
+
+ if (flag_checking && !m_backedge_threads)
+ gcc_assert ((path[i]->e->flags & EDGE_DFS_BACK) == 0);
+ }
+
+ // If we crossed a loop into an outer loop without crossing the
+ // latch, this is just an early exit from the loop.
+ if (loops_crossed == 1
+ && !crossed_latch
+ && flow_loop_nested_p (exit->dest->loop_father, exit->src->loop_father))
+ return false;
+
+ if (cfun->curr_properties & PROP_loop_opts_done)
+ return false;
+
+ if (seen_latch && empty_block_p (loop->latch))
+ {
+ cancel_thread (&path, "Threading through latch before loop opts "
+ "would create non-empty latch");
+ return true;
+ }
+ if (loops_crossed)
+ {
+ cancel_thread (&path, "Path crosses loops");
+ return true;
+ }
+ return false;
}
/* Register a jump threading opportunity. We queue up all the jump
@@ -2746,37 +2843,18 @@ jump_thread_path_registry::thread_through_all_blocks
Return TRUE if PATH was successfully threaded. */
bool
-jump_thread_path_registry::register_jump_thread (vec<jump_thread_edge *> *path)
+jt_path_registry::register_jump_thread (vec<jump_thread_edge *> *path)
{
+ gcc_checking_assert (flag_thread_jumps);
+
if (!dbg_cnt (registered_jump_thread))
{
path->release ();
return false;
}
- /* First make sure there are no NULL outgoing edges on the jump threading
- path. That can happen for jumping to a constant address. */
- for (unsigned int i = 0; i < path->length (); i++)
- {
- if ((*path)[i]->e == NULL)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file,
- "Found NULL edge in jump threading path. Cancelling jump thread:\n");
- dump_jump_thread_path (dump_file, *path, false);
- }
-
- path->release ();
- return false;
- }
-
- /* Only the FSM threader is allowed to thread across
- backedges in the CFG. */
- if (flag_checking
- && (*path)[0]->type != EDGE_FSM_THREAD)
- gcc_assert (((*path)[i]->e->flags & EDGE_DFS_BACK) == 0);
- }
+ if (cancel_invalid_paths (*path))
+ return false;
if (dump_file && (dump_flags & TDF_DETAILS))
dump_jump_thread_path (dump_file, *path, true);
diff --git a/gcc/tree-ssa-threadupdate.h b/gcc/tree-ssa-threadupdate.h
index 2030bda..d68795c 100644
--- a/gcc/tree-ssa-threadupdate.h
+++ b/gcc/tree-ssa-threadupdate.h
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see
enum jump_thread_edge_type
{
EDGE_START_JUMP_THREAD,
- EDGE_FSM_THREAD,
EDGE_COPY_SRC_BLOCK,
EDGE_COPY_SRC_JOINER_BLOCK,
EDGE_NO_COPY_SRC_BLOCK
@@ -54,49 +53,71 @@ private:
obstack m_obstack;
};
-// This is the underlying jump thread registry. When all candidates
-// have been registered with register_jump_thread(),
-// thread_through_all_blocks() is called to actually change the CFG.
+// Abstract class for the jump thread registry.
+//
+// When all candidates have been registered with
+// register_jump_thread(), thread_through_all_blocks() is called to
+// update the CFG.
-class jump_thread_path_registry
+class jt_path_registry
{
public:
- jump_thread_path_registry ();
- ~jump_thread_path_registry ();
+ jt_path_registry (bool backedge_threads);
+ virtual ~jt_path_registry ();
bool register_jump_thread (vec<jump_thread_edge *> *);
- void remove_jump_threads_including (edge);
- bool thread_through_all_blocks (bool);
- jump_thread_edge *allocate_thread_edge (edge e, jump_thread_edge_type t);
+ bool thread_through_all_blocks (bool peel_loop_headers);
+ void push_edge (vec<jump_thread_edge *> *path, edge, jump_thread_edge_type);
vec<jump_thread_edge *> *allocate_thread_path ();
- void dump ();
+ void debug ();
+protected:
+ void debug_path (FILE *, int pathno);
+ vec<vec<jump_thread_edge *> *> m_paths;
+ unsigned long m_num_threaded_edges;
+private:
+ virtual bool update_cfg (bool peel_loop_headers) = 0;
+ bool cancel_invalid_paths (vec<jump_thread_edge *> &path);
+ jump_thread_path_allocator m_allocator;
+ // True if threading through back edges is allowed. This is only
+ // allowed in the generic copier in the backward threader.
+ bool m_backedge_threads;
+ DISABLE_COPY_AND_ASSIGN (jt_path_registry);
+};
+
+// Forward threader path registry using a custom BB copier.
+class fwd_jt_path_registry : public jt_path_registry
+{
+public:
+ fwd_jt_path_registry ();
+ ~fwd_jt_path_registry ();
+ void remove_jump_threads_including (edge);
private:
- void debug_path (FILE *, int pathno);
+ bool update_cfg (bool peel_loop_headers) override;
void mark_threaded_blocks (bitmap threaded_blocks);
- bool rewire_first_differing_edge (unsigned path_num, unsigned edge_num);
- void adjust_paths_after_duplication (unsigned curr_path_num);
- bool duplicate_thread_path (edge entry,
- edge exit,
- basic_block *region,
- unsigned n_region,
- unsigned current_path_no);
bool thread_block_1 (basic_block, bool noloop_only, bool joiners);
bool thread_block (basic_block, bool noloop_only);
bool thread_through_loop_header (class loop *loop,
bool may_peel_loop_headers);
class redirection_data *lookup_redirection_data (edge e, enum insert_option);
- vec<vec<jump_thread_edge *> *> m_paths;
-
hash_table<struct removed_edges> *m_removed_edges;
// Main data structure to hold information for duplicates of BB.
hash_table<redirection_data> *m_redirection_data;
+};
- // Jump threading statistics.
- unsigned long m_num_threaded_edges;
+// Backward threader path registry using a generic BB copier.
- jump_thread_path_allocator m_allocator;
+class back_jt_path_registry : public jt_path_registry
+{
+public:
+ back_jt_path_registry ();
+private:
+ bool update_cfg (bool peel_loop_headers) override;
+ void adjust_paths_after_duplication (unsigned curr_path_num);
+ bool duplicate_thread_path (edge entry, edge exit, basic_block *region,
+ unsigned n_region, unsigned current_path_no);
+ bool rewire_first_differing_edge (unsigned path_num, unsigned edge_num);
};
// Rather than search all the edges in jump thread paths each time DOM
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 394dbf4..d67534f 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -39,6 +39,8 @@ along with GCC; see the file COPYING3. If not see
#include "calls.h"
#include "gimple-range.h"
+#include "gimple-predicate-analysis.h"
+
/* This implements the pass that does predicate aware warning on uses of
possibly uninitialized variables. The pass first collects the set of
possibly uninitialized SSA names. For each such name, it walks through
@@ -49,19 +51,11 @@ along with GCC; see the file COPYING3. If not see
default definitions or by checking if the predicate set that guards the
defining paths is a superset of the use predicate. */
-/* Max PHI args we can handle in pass. */
-const unsigned max_phi_args = 32;
-
/* Pointer set of potentially undefined ssa names, i.e.,
ssa names that are defined by phi with operands that
are not defined or potentially undefined. */
static hash_set<tree> *possibly_undefined_names = 0;
-/* Bit mask handling macros. */
-#define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
-#define MASK_TEST_BIT(mask, pos) (mask & (1 << pos))
-#define MASK_EMPTY(mask) (mask == 0)
-
/* Returns the first bit position (starting from LSB)
in mask that is non zero. Returns -1 if the mask is empty. */
static int
@@ -151,6 +145,42 @@ warn_uninit (opt_code opt, tree t, tree var, const char *gmsgid,
if (is_gimple_assign (context)
&& gimple_assign_rhs_code (context) == COMPLEX_EXPR)
return;
+
+ /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is a call to
+ .DEFERRED_INIT. This is for handling the following case correctly:
+
+ 1 typedef _Complex float C;
+ 2 C foo (int cond)
+ 3 {
+ 4 C f;
+ 5 __imag__ f = 0;
+ 6 if (cond)
+ 7 {
+ 8 __real__ f = 1;
+ 9 return f;
+ 10 }
+ 11 return f;
+ 12 }
+
+ with -ftrivial-auto-var-init, compiler will insert the following
+ artificial initialization at line 4:
+ f = .DEFERRED_INIT (f, 2);
+ _1 = REALPART_EXPR <f>;
+
+ without the following special handling, _1 = REALPART_EXPR <f> will
+ be treated as the uninitialized use point, which is incorrect. (the
+ real uninitialized use point is at line 11). */
+ if (is_gimple_assign (context)
+ && (gimple_assign_rhs_code (context) == REALPART_EXPR
+ || gimple_assign_rhs_code (context) == IMAGPART_EXPR))
+ {
+ tree v = gimple_assign_rhs1 (context);
+ if (TREE_CODE (TREE_OPERAND (v, 0)) == SSA_NAME
+ && gimple_call_internal_p (SSA_NAME_DEF_STMT (TREE_OPERAND (v, 0)),
+ IFN_DEFERRED_INIT))
+ return;
+ }
+
/* Anonymous SSA_NAMEs shouldn't be uninitialized, but ssa_undefined_value_p
can return true if the def stmt of an anonymous SSA_NAME is COMPLEX_EXPR
created for conversion from scalar to complex. Use the underlying var of
@@ -206,14 +236,7 @@ warn_uninit (opt_code opt, tree t, tree var, const char *gmsgid,
if (location == var_loc)
return;
- location_t cfun_loc = DECL_SOURCE_LOCATION (cfun->decl);
- expanded_location xloc = expand_location (location);
- expanded_location floc = expand_location (cfun_loc);
- if (xloc.file != floc.file
- || linemap_location_before_p (line_table, location, cfun_loc)
- || linemap_location_before_p (line_table, cfun->function_end_locus,
- location))
- inform (var_loc, "%qD was declared here", var);
+ inform (var_loc, "%qD was declared here", var);
}
struct check_defs_data
@@ -352,26 +375,32 @@ check_defs (ao_ref *ref, tree vdef, void *data_)
check_defs_data *data = (check_defs_data *)data_;
gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
+ /* Ignore the vdef if the definition statement is a call
+ to .DEFERRED_INIT function. */
+ if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+ return false;
+
/* The ASAN_MARK intrinsic doesn't modify the variable. */
if (is_gimple_call (def_stmt))
{
+ /* The ASAN_MARK intrinsic doesn't modify the variable. */
if (gimple_call_internal_p (def_stmt)
&& gimple_call_internal_fn (def_stmt) == IFN_ASAN_MARK)
- return false;
+ return false;
if (tree fndecl = gimple_call_fndecl (def_stmt))
- {
- /* Some sanitizer calls pass integer arguments to built-ins
- that expect pointers. Avoid using gimple_call_builtin_p()
- which fails for such calls. */
- if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
- {
- built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
- if (fncode > BEGIN_SANITIZER_BUILTINS
- && fncode < END_SANITIZER_BUILTINS)
- return false;
- }
- }
+ {
+ /* Some sanitizer calls pass integer arguments to built-ins
+ that expect pointets. Avoid using gimple_call_builtin_p()
+ which fails for such calls. */
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ {
+ built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
+ if (fncode > BEGIN_SANITIZER_BUILTINS
+ && fncode < END_SANITIZER_BUILTINS)
+ return false;
+ }
+ }
}
/* End of VLA scope is not a kill. */
@@ -875,6 +904,13 @@ warn_uninitialized_vars (bool wmaybe_uninit)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
+
+ /* The call is an artificial use, will not provide meaningful
+ error message. If the result of the call is used somewhere
+ else, we warn there instead. */
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+ continue;
+
if (is_gimple_debug (stmt))
continue;
@@ -957,8 +993,8 @@ can_skip_redundant_opnd (tree opnd, gimple *phi)
return true;
}
-/* Returns a bit mask holding the positions of arguments in PHI
- that have empty (or possibly empty) definitions. */
+/* Return a bitset holding the positions of arguments in PHI with empty
+ (or possibly empty) definitions. */
static unsigned
compute_uninit_opnds_pos (gphi *phi)
@@ -967,7 +1003,7 @@ compute_uninit_opnds_pos (gphi *phi)
unsigned n = gimple_phi_num_args (phi);
/* Bail out for phi with too many args. */
- if (n > max_phi_args)
+ if (n > predicate::func_t::max_phi_args)
return 0;
for (unsigned i = 0; i < n; ++i)
@@ -990,2111 +1026,32 @@ compute_uninit_opnds_pos (gphi *phi)
return uninit_opnds;
}
-/* Find the immediate postdominator of the specified basic block BLOCK. */
-
-static inline basic_block
-find_pdom (basic_block block)
-{
- if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
- return EXIT_BLOCK_PTR_FOR_FN (cfun);
- else
- {
- basic_block bb = get_immediate_dominator (CDI_POST_DOMINATORS, block);
- if (!bb)
- return EXIT_BLOCK_PTR_FOR_FN (cfun);
- return bb;
- }
-}
-
-/* Find the immediate dominator of the specified basic block BLOCK. */
-
-static inline basic_block
-find_dom (basic_block block)
-{
- if (block == ENTRY_BLOCK_PTR_FOR_FN (cfun))
- return ENTRY_BLOCK_PTR_FOR_FN (cfun);
- else
- {
- basic_block bb = get_immediate_dominator (CDI_DOMINATORS, block);
- if (!bb)
- return ENTRY_BLOCK_PTR_FOR_FN (cfun);
- return bb;
- }
-}
-
-/* Returns true if BB1 is postdominating BB2 and BB1 is
- not a loop exit bb. The loop exit bb check is simple and does
- not cover all cases. */
-
-static bool
-is_non_loop_exit_postdominating (basic_block bb1, basic_block bb2)
-{
- if (!dominated_by_p (CDI_POST_DOMINATORS, bb2, bb1))
- return false;
-
- if (single_pred_p (bb1) && !single_succ_p (bb2))
- return false;
-
- return true;
-}
-
-/* Find the closest postdominator of a specified BB, which is control
- equivalent to BB. */
-
-static inline basic_block
-find_control_equiv_block (basic_block bb)
-{
- basic_block pdom = find_pdom (bb);
-
- /* Skip the postdominating bb that is also loop exit. */
- if (!is_non_loop_exit_postdominating (pdom, bb))
- return NULL;
-
- if (dominated_by_p (CDI_DOMINATORS, pdom, bb))
- return pdom;
-
- return NULL;
-}
-
-#define MAX_NUM_CHAINS 8
-#define MAX_CHAIN_LEN 5
-#define MAX_POSTDOM_CHECK 8
-#define MAX_SWITCH_CASES 40
-
-/* Computes the control dependence chains (paths of edges)
- for DEP_BB up to the dominating basic block BB (the head node of a
- chain should be dominated by it). CD_CHAINS is pointer to an
- array holding the result chains. CUR_CD_CHAIN is the current
- chain being computed. *NUM_CHAINS is total number of chains. The
- function returns true if the information is successfully computed,
- return false if there is no control dependence or not computed. */
-
-static bool
-compute_control_dep_chain (basic_block bb, basic_block dep_bb,
- vec<edge> *cd_chains,
- size_t *num_chains,
- vec<edge> *cur_cd_chain,
- int *num_calls)
-{
- edge_iterator ei;
- edge e;
- size_t i;
- bool found_cd_chain = false;
- size_t cur_chain_len = 0;
-
- if (*num_calls > param_uninit_control_dep_attempts)
- return false;
- ++*num_calls;
-
- /* Could use a set instead. */
- cur_chain_len = cur_cd_chain->length ();
- if (cur_chain_len > MAX_CHAIN_LEN)
- return false;
-
- for (i = 0; i < cur_chain_len; i++)
- {
- edge e = (*cur_cd_chain)[i];
- /* Cycle detected. */
- if (e->src == bb)
- return false;
- }
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- basic_block cd_bb;
- int post_dom_check = 0;
- if (e->flags & (EDGE_FAKE | EDGE_ABNORMAL))
- continue;
-
- cd_bb = e->dest;
- cur_cd_chain->safe_push (e);
- while (!is_non_loop_exit_postdominating (cd_bb, bb))
- {
- if (cd_bb == dep_bb)
- {
- /* Found a direct control dependence. */
- if (*num_chains < MAX_NUM_CHAINS)
- {
- cd_chains[*num_chains] = cur_cd_chain->copy ();
- (*num_chains)++;
- }
- found_cd_chain = true;
- /* Check path from next edge. */
- break;
- }
-
- /* Now check if DEP_BB is indirectly control dependent on BB. */
- if (compute_control_dep_chain (cd_bb, dep_bb, cd_chains, num_chains,
- cur_cd_chain, num_calls))
- {
- found_cd_chain = true;
- break;
- }
-
- cd_bb = find_pdom (cd_bb);
- post_dom_check++;
- if (cd_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
- || post_dom_check > MAX_POSTDOM_CHECK)
- break;
- }
- cur_cd_chain->pop ();
- gcc_assert (cur_cd_chain->length () == cur_chain_len);
- }
- gcc_assert (cur_cd_chain->length () == cur_chain_len);
-
- return found_cd_chain;
-}
-
-/* The type to represent a simple predicate. */
+/* Function object type used to determine whether an expression
+ is of interest to the predicate analyzer. */
-struct pred_info
+struct uninit_undef_val_t: public predicate::func_t
{
- tree pred_lhs;
- tree pred_rhs;
- enum tree_code cond_code;
- bool invert;
+ virtual bool operator()(tree) override;
+ virtual unsigned phi_arg_set (gphi *) override;
};
-/* The type to represent a sequence of predicates grouped
- with .AND. operation. */
-
-typedef vec<pred_info, va_heap, vl_ptr> pred_chain;
-
-/* The type to represent a sequence of pred_chains grouped
- with .OR. operation. */
-
-typedef vec<pred_chain, va_heap, vl_ptr> pred_chain_union;
-
-/* Converts the chains of control dependence edges into a set of
- predicates. A control dependence chain is represented by a vector
- edges. DEP_CHAINS points to an array of dependence chains.
- NUM_CHAINS is the size of the chain array. One edge in a dependence
- chain is mapped to predicate expression represented by pred_info
- type. One dependence chain is converted to a composite predicate that
- is the result of AND operation of pred_info mapped to each edge.
- A composite predicate is presented by a vector of pred_info. On
- return, *PREDS points to the resulting array of composite predicates.
- *NUM_PREDS is the number of composite predictes. */
-
-static bool
-convert_control_dep_chain_into_preds (vec<edge> *dep_chains,
- size_t num_chains,
- pred_chain_union *preds)
-{
- bool has_valid_pred = false;
- size_t i, j;
- if (num_chains == 0 || num_chains >= MAX_NUM_CHAINS)
- return false;
-
- /* Now convert the control dep chain into a set
- of predicates. */
- preds->reserve (num_chains);
-
- for (i = 0; i < num_chains; i++)
- {
- vec<edge> one_cd_chain = dep_chains[i];
-
- has_valid_pred = false;
- pred_chain t_chain = vNULL;
- for (j = 0; j < one_cd_chain.length (); j++)
- {
- gimple *cond_stmt;
- gimple_stmt_iterator gsi;
- basic_block guard_bb;
- pred_info one_pred;
- edge e;
-
- e = one_cd_chain[j];
- guard_bb = e->src;
- gsi = gsi_last_bb (guard_bb);
- /* Ignore empty forwarder blocks. */
- if (empty_block_p (guard_bb) && single_succ_p (guard_bb))
- continue;
- /* An empty basic block here is likely a PHI, and is not one
- of the cases we handle below. */
- if (gsi_end_p (gsi))
- {
- has_valid_pred = false;
- break;
- }
- cond_stmt = gsi_stmt (gsi);
- if (is_gimple_call (cond_stmt) && EDGE_COUNT (e->src->succs) >= 2)
- /* Ignore EH edge. Can add assertion on the other edge's flag. */
- continue;
- /* Skip if there is essentially one succesor. */
- if (EDGE_COUNT (e->src->succs) == 2)
- {
- edge e1;
- edge_iterator ei1;
- bool skip = false;
-
- FOR_EACH_EDGE (e1, ei1, e->src->succs)
- {
- if (EDGE_COUNT (e1->dest->succs) == 0)
- {
- skip = true;
- break;
- }
- }
- if (skip)
- continue;
- }
- if (gimple_code (cond_stmt) == GIMPLE_COND)
- {
- one_pred.pred_lhs = gimple_cond_lhs (cond_stmt);
- one_pred.pred_rhs = gimple_cond_rhs (cond_stmt);
- one_pred.cond_code = gimple_cond_code (cond_stmt);
- one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE);
- t_chain.safe_push (one_pred);
- has_valid_pred = true;
- }
- else if (gswitch *gs = dyn_cast<gswitch *> (cond_stmt))
- {
- /* Avoid quadratic behavior. */
- if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES)
- {
- has_valid_pred = false;
- break;
- }
- /* Find the case label. */
- tree l = NULL_TREE;
- unsigned idx;
- for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
- {
- tree tl = gimple_switch_label (gs, idx);
- if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
- {
- if (!l)
- l = tl;
- else
- {
- l = NULL_TREE;
- break;
- }
- }
- }
- /* If more than one label reaches this block or the case
- label doesn't have a single value (like the default one)
- fail. */
- if (!l
- || !CASE_LOW (l)
- || (CASE_HIGH (l)
- && !operand_equal_p (CASE_LOW (l), CASE_HIGH (l), 0)))
- {
- has_valid_pred = false;
- break;
- }
- one_pred.pred_lhs = gimple_switch_index (gs);
- one_pred.pred_rhs = CASE_LOW (l);
- one_pred.cond_code = EQ_EXPR;
- one_pred.invert = false;
- t_chain.safe_push (one_pred);
- has_valid_pred = true;
- }
- else
- {
- has_valid_pred = false;
- break;
- }
- }
-
- if (!has_valid_pred)
- break;
- else
- preds->safe_push (t_chain);
- }
- return has_valid_pred;
-}
-
-/* Computes all control dependence chains for USE_BB. The control
- dependence chains are then converted to an array of composite
- predicates pointed to by PREDS. PHI_BB is the basic block of
- the phi whose result is used in USE_BB. */
-
-static bool
-find_predicates (pred_chain_union *preds,
- basic_block phi_bb,
- basic_block use_bb)
-{
- size_t num_chains = 0, i;
- int num_calls = 0;
- vec<edge> dep_chains[MAX_NUM_CHAINS];
- auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
- bool has_valid_pred = false;
- basic_block cd_root = 0;
-
- /* First find the closest bb that is control equivalent to PHI_BB
- that also dominates USE_BB. */
- cd_root = phi_bb;
- while (dominated_by_p (CDI_DOMINATORS, use_bb, cd_root))
- {
- basic_block ctrl_eq_bb = find_control_equiv_block (cd_root);
- if (ctrl_eq_bb && dominated_by_p (CDI_DOMINATORS, use_bb, ctrl_eq_bb))
- cd_root = ctrl_eq_bb;
- else
- break;
- }
-
- compute_control_dep_chain (cd_root, use_bb, dep_chains, &num_chains,
- &cur_chain, &num_calls);
-
- has_valid_pred
- = convert_control_dep_chain_into_preds (dep_chains, num_chains, preds);
- for (i = 0; i < num_chains; i++)
- dep_chains[i].release ();
- return has_valid_pred;
-}
-
-/* Computes the set of incoming edges of PHI that have non empty
- definitions of a phi chain. The collection will be done
- recursively on operands that are defined by phis. CD_ROOT
- is the control dependence root. *EDGES holds the result, and
- VISITED_PHIS is a pointer set for detecting cycles. */
-
-static void
-collect_phi_def_edges (gphi *phi, basic_block cd_root,
- auto_vec<edge> *edges,
- hash_set<gimple *> *visited_phis)
-{
- size_t i, n;
- edge opnd_edge;
- tree opnd;
-
- if (visited_phis->add (phi))
- return;
-
- n = gimple_phi_num_args (phi);
- for (i = 0; i < n; i++)
- {
- opnd_edge = gimple_phi_arg_edge (phi, i);
- opnd = gimple_phi_arg_def (phi, i);
-
- if (TREE_CODE (opnd) != SSA_NAME)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int) i);
- print_gimple_stmt (dump_file, phi, 0);
- }
- edges->safe_push (opnd_edge);
- }
- else
- {
- gimple *def = SSA_NAME_DEF_STMT (opnd);
-
- if (gimple_code (def) == GIMPLE_PHI
- && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root))
- collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges,
- visited_phis);
- else if (!uninit_undefined_value_p (opnd))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\n[CHECK] Found def edge %d in ",
- (int) i);
- print_gimple_stmt (dump_file, phi, 0);
- }
- edges->safe_push (opnd_edge);
- }
- }
- }
-}
-
-/* For each use edge of PHI, computes all control dependence chains.
- The control dependence chains are then converted to an array of
- composite predicates pointed to by PREDS. */
-
-static bool
-find_def_preds (pred_chain_union *preds, gphi *phi)
-{
- size_t num_chains = 0, i, n;
- vec<edge> dep_chains[MAX_NUM_CHAINS];
- auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
- auto_vec<edge> def_edges;
- bool has_valid_pred = false;
- basic_block phi_bb, cd_root = 0;
-
- phi_bb = gimple_bb (phi);
- /* First find the closest dominating bb to be
- the control dependence root. */
- cd_root = find_dom (phi_bb);
- if (!cd_root)
- return false;
-
- hash_set<gimple *> visited_phis;
- collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
-
- n = def_edges.length ();
- if (n == 0)
- return false;
-
- for (i = 0; i < n; i++)
- {
- size_t prev_nc, j;
- int num_calls = 0;
- edge opnd_edge;
-
- opnd_edge = def_edges[i];
- prev_nc = num_chains;
- compute_control_dep_chain (cd_root, opnd_edge->src, dep_chains,
- &num_chains, &cur_chain, &num_calls);
-
- /* Now update the newly added chains with
- the phi operand edge: */
- if (EDGE_COUNT (opnd_edge->src->succs) > 1)
- {
- if (prev_nc == num_chains && num_chains < MAX_NUM_CHAINS)
- dep_chains[num_chains++] = vNULL;
- for (j = prev_nc; j < num_chains; j++)
- dep_chains[j].safe_push (opnd_edge);
- }
- }
-
- has_valid_pred
- = convert_control_dep_chain_into_preds (dep_chains, num_chains, preds);
- for (i = 0; i < num_chains; i++)
- dep_chains[i].release ();
- return has_valid_pred;
-}
-
-/* Dump a pred_info. */
-
-static void
-dump_pred_info (pred_info one_pred)
-{
- if (one_pred.invert)
- fprintf (dump_file, " (.NOT.) ");
- print_generic_expr (dump_file, one_pred.pred_lhs);
- fprintf (dump_file, " %s ", op_symbol_code (one_pred.cond_code));
- print_generic_expr (dump_file, one_pred.pred_rhs);
-}
-
-/* Dump a pred_chain. */
-
-static void
-dump_pred_chain (pred_chain one_pred_chain)
-{
- size_t np = one_pred_chain.length ();
- for (size_t j = 0; j < np; j++)
- {
- dump_pred_info (one_pred_chain[j]);
- if (j < np - 1)
- fprintf (dump_file, " (.AND.) ");
- else
- fprintf (dump_file, "\n");
- }
-}
-
-/* Dumps the predicates (PREDS) for USESTMT. */
-
-static void
-dump_predicates (gimple *usestmt, pred_chain_union preds, const char *msg)
-{
- fprintf (dump_file, "%s", msg);
- if (usestmt)
- {
- print_gimple_stmt (dump_file, usestmt, 0);
- fprintf (dump_file, "is guarded by :\n\n");
- }
- size_t num_preds = preds.length ();
- for (size_t i = 0; i < num_preds; i++)
- {
- dump_pred_chain (preds[i]);
- if (i < num_preds - 1)
- fprintf (dump_file, "(.OR.)\n");
- else
- fprintf (dump_file, "\n\n");
- }
-}
-
-/* Destroys the predicate set *PREDS. */
+/* Return true if the argument is an expression of interest. */
-static void
-destroy_predicate_vecs (pred_chain_union *preds)
+bool
+uninit_undef_val_t::operator()(tree val)
{
- size_t i;
-
- size_t n = preds->length ();
- for (i = 0; i < n; i++)
- (*preds)[i].release ();
- preds->release ();
-}
-
-/* Computes the 'normalized' conditional code with operand
- swapping and condition inversion. */
-
-static enum tree_code
-get_cmp_code (enum tree_code orig_cmp_code, bool swap_cond, bool invert)
-{
- enum tree_code tc = orig_cmp_code;
-
- if (swap_cond)
- tc = swap_tree_comparison (orig_cmp_code);
- if (invert)
- tc = invert_tree_comparison (tc, false);
-
- switch (tc)
- {
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- break;
- default:
- return ERROR_MARK;
- }
- return tc;
-}
-
-/* Returns whether VAL CMPC BOUNDARY is true. */
-
-static bool
-is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
-{
- bool inverted = false;
- bool result;
-
- /* Only handle integer constant here. */
- if (TREE_CODE (val) != INTEGER_CST || TREE_CODE (boundary) != INTEGER_CST)
- return true;
-
- if (cmpc == GE_EXPR || cmpc == GT_EXPR || cmpc == NE_EXPR)
- {
- cmpc = invert_tree_comparison (cmpc, false);
- inverted = true;
- }
-
- if (cmpc == EQ_EXPR)
- result = tree_int_cst_equal (val, boundary);
- else if (cmpc == LT_EXPR)
- result = tree_int_cst_lt (val, boundary);
- else
- {
- gcc_assert (cmpc == LE_EXPR);
- result = tree_int_cst_le (val, boundary);
- }
-
- if (inverted)
- result ^= 1;
-
- return result;
-}
-
-/* Returns whether VAL satisfies (x CMPC BOUNDARY) predicate. CMPC can be
- either one of the range comparison codes ({GE,LT,EQ,NE}_EXPR and the like),
- or BIT_AND_EXPR. EXACT_P is only meaningful for the latter. It modifies the
- question from whether VAL & BOUNDARY != 0 to whether VAL & BOUNDARY == VAL.
- For other values of CMPC, EXACT_P is ignored. */
-
-static bool
-value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
- bool exact_p = false)
-{
- if (cmpc != BIT_AND_EXPR)
- return is_value_included_in (val, boundary, cmpc);
-
- wide_int andw = wi::to_wide (val) & wi::to_wide (boundary);
- if (exact_p)
- return andw == wi::to_wide (val);
- else
- return andw.to_uhwi ();
-}
-
-/* Returns true if PRED is common among all the predicate
- 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 i, j, n;
-
- /* Trival case. */
- if (preds.length () == 1)
- return true;
-
- for (i = 1; i < preds.length (); i++)
- {
- bool found = false;
- pred_chain one_chain = preds[i];
- n = one_chain.length ();
- for (j = 0; j < n; j++)
- {
- pred_info pred2 = one_chain[j];
- /* Can relax the condition comparison to not
- use address comparison. However, the most common
- case is that multiple control dependent paths share
- a common path prefix, so address comparison should
- be ok. */
-
- if (operand_equal_p (pred2.pred_lhs, pred.pred_lhs, 0)
- && operand_equal_p (pred2.pred_rhs, pred.pred_rhs, 0)
- && pred2.invert == pred.invert)
- {
- found = true;
- break;
- }
- }
- if (!found)
- return false;
- }
- return true;
-}
-
-/* Forward declaration. */
-static bool is_use_properly_guarded (gimple *use_stmt,
- basic_block use_bb,
- gphi *phi,
- unsigned uninit_opnds,
- pred_chain_union *def_preds,
- hash_set<gphi *> *visited_phis);
-
-/* Returns true if all uninitialized opnds are pruned. Returns false
- otherwise. PHI is the phi node with uninitialized operands,
- UNINIT_OPNDS is the bitmap of the uninitialize operand positions,
- FLAG_DEF is the statement defining the flag guarding the use of the
- PHI output, BOUNDARY_CST is the const value used in the predicate
- associated with the flag, CMP_CODE is the comparison code used in
- the predicate, VISITED_PHIS is the pointer set of phis visited, and
- VISITED_FLAG_PHIS is the pointer to the pointer set of flag definitions
- that are also phis.
-
- Example scenario:
-
- BB1:
- flag_1 = phi <0, 1> // (1)
- var_1 = phi <undef, some_val>
-
-
- BB2:
- flag_2 = phi <0, flag_1, flag_1> // (2)
- var_2 = phi <undef, var_1, var_1>
- if (flag_2 == 1)
- goto BB3;
-
- BB3:
- use of var_2 // (3)
-
- Because some flag arg in (1) is not constant, if we do not look into the
- flag phis recursively, it is conservatively treated as unknown and var_1
- is thought to be flowed into use at (3). Since var_1 is potentially
- uninitialized a false warning will be emitted.
- Checking recursively into (1), the compiler can find out that only some_val
- (which is defined) can flow into (3) which is OK. */
-
-static bool
-prune_uninit_phi_opnds (gphi *phi, unsigned uninit_opnds, gphi *flag_def,
- tree boundary_cst, enum tree_code cmp_code,
- hash_set<gphi *> *visited_phis,
- bitmap *visited_flag_phis)
-{
- unsigned i;
-
- for (i = 0; i < MIN (max_phi_args, gimple_phi_num_args (flag_def)); i++)
- {
- tree flag_arg;
-
- if (!MASK_TEST_BIT (uninit_opnds, i))
- continue;
-
- flag_arg = gimple_phi_arg_def (flag_def, i);
- if (!is_gimple_constant (flag_arg))
- {
- gphi *flag_arg_def, *phi_arg_def;
- tree phi_arg;
- unsigned uninit_opnds_arg_phi;
-
- if (TREE_CODE (flag_arg) != SSA_NAME)
- return false;
- flag_arg_def = dyn_cast<gphi *> (SSA_NAME_DEF_STMT (flag_arg));
- if (!flag_arg_def)
- return false;
-
- phi_arg = gimple_phi_arg_def (phi, i);
- if (TREE_CODE (phi_arg) != SSA_NAME)
- return false;
-
- phi_arg_def = dyn_cast<gphi *> (SSA_NAME_DEF_STMT (phi_arg));
- if (!phi_arg_def)
- return false;
-
- if (gimple_bb (phi_arg_def) != gimple_bb (flag_arg_def))
- return false;
-
- if (!*visited_flag_phis)
- *visited_flag_phis = BITMAP_ALLOC (NULL);
-
- tree phi_result = gimple_phi_result (flag_arg_def);
- if (bitmap_bit_p (*visited_flag_phis, SSA_NAME_VERSION (phi_result)))
- return false;
-
- bitmap_set_bit (*visited_flag_phis,
- SSA_NAME_VERSION (gimple_phi_result (flag_arg_def)));
-
- /* Now recursively prune the uninitialized phi args. */
- uninit_opnds_arg_phi = compute_uninit_opnds_pos (phi_arg_def);
- if (!prune_uninit_phi_opnds
- (phi_arg_def, uninit_opnds_arg_phi, flag_arg_def, boundary_cst,
- cmp_code, visited_phis, visited_flag_phis))
- return false;
-
- phi_result = gimple_phi_result (flag_arg_def);
- bitmap_clear_bit (*visited_flag_phis, SSA_NAME_VERSION (phi_result));
- continue;
- }
-
- /* Now check if the constant is in the guarded range. */
- if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
- {
- tree opnd;
- gimple *opnd_def;
-
- /* Now that we know that this undefined edge is not
- pruned. If the operand is defined by another phi,
- we can further prune the incoming edges of that
- phi by checking the predicates of this operands. */
-
- opnd = gimple_phi_arg_def (phi, i);
- opnd_def = SSA_NAME_DEF_STMT (opnd);
- if (gphi *opnd_def_phi = dyn_cast <gphi *> (opnd_def))
- {
- edge opnd_edge;
- unsigned uninit_opnds2 = compute_uninit_opnds_pos (opnd_def_phi);
- if (!MASK_EMPTY (uninit_opnds2))
- {
- pred_chain_union def_preds = vNULL;
- bool ok;
- opnd_edge = gimple_phi_arg_edge (phi, i);
- ok = is_use_properly_guarded (phi,
- opnd_edge->src,
- opnd_def_phi,
- uninit_opnds2,
- &def_preds,
- visited_phis);
- destroy_predicate_vecs (&def_preds);
- if (!ok)
- return false;
- }
- }
- else
- return false;
- }
- }
-
- 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. */
- tree type = TREE_TYPE (cond_lhs);
- value_range r;
- if (!INTEGRAL_TYPE_P (type)
- || !get_range_query (cfun)->range_of_expr (r, cond_rhs)
- || r.kind () != VR_RANGE)
- continue;
- wide_int min = r.lower_bound ();
- wide_int max = r.upper_bound ();
- 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:
- Example 1:
- if (some_cond)
- {
- x = ...;
- flag = true;
- }
-
- ... some code ...
-
- if (flag)
- use (x);
-
- The real world examples are usually more complicated, but similar
- and usually result from inlining:
-
- bool init_func (int * x)
- {
- if (some_cond)
- return false;
- *x = ..
- return true;
- }
-
- void foo (..)
- {
- int x;
-
- if (!init_func (&x))
- return;
-
- .. some_code ...
- use (x);
- }
-
- Another possible use scenario is in the following trivial example:
-
- Example 2:
- if (n > 0)
- x = 1;
- ...
- if (n > 0)
- {
- if (m < 2)
- .. = x;
- }
-
- Predicate analysis needs to compute the composite predicate:
-
- 1) 'x' use predicate: (n > 0) .AND. (m < 2)
- 2) 'x' default value (non-def) predicate: .NOT. (n > 0)
- (the predicate chain for phi operand defs can be computed
- starting from a bb that is control equivalent to the phi's
- bb and is dominating the operand def.)
-
- and check overlapping:
- (n > 0) .AND. (m < 2) .AND. (.NOT. (n > 0))
- <==> false
-
- This implementation provides framework that can handle
- scenarios. (Note that many simple cases are handled properly
- without the predicate analysis -- this is due to jump threading
- transformation which eliminates the merge point thus makes
- path sensitive analysis unnecessary.)
-
- PHI is the phi node whose incoming (undefined) paths need to be
- pruned, and UNINIT_OPNDS is the bitmap holding uninit operand
- positions. VISITED_PHIS is the pointer set of phi stmts being
- checked. */
-
-static bool
-use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
- gphi *phi, unsigned uninit_opnds,
- hash_set<gphi *> *visited_phis)
-{
- gimple *flag_def = 0;
- tree boundary_cst = 0;
- enum tree_code cmp_code;
- bitmap visited_flag_phis = NULL;
- bool all_pruned = false;
-
- /* Find within the common prefix of multiple predicate chains
- a predicate that is a comparison of a flag variable against
- a constant. */
- 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. */
- all_pruned = prune_uninit_phi_opnds
- (phi, uninit_opnds, as_a<gphi *> (flag_def), boundary_cst, cmp_code,
- visited_phis, &visited_flag_phis);
-
- if (visited_flag_phis)
- BITMAP_FREE (visited_flag_phis);
-
- return all_pruned;
-}
-
-/* The helper function returns true if two predicates X1 and X2
- are equivalent. It assumes the expressions have already
- properly re-associated. */
-
-static inline bool
-pred_equal_p (pred_info x1, pred_info x2)
-{
- enum tree_code c1, c2;
- if (!operand_equal_p (x1.pred_lhs, x2.pred_lhs, 0)
- || !operand_equal_p (x1.pred_rhs, x2.pred_rhs, 0))
- return false;
-
- c1 = x1.cond_code;
- if (x1.invert != x2.invert
- && TREE_CODE_CLASS (x2.cond_code) == tcc_comparison)
- c2 = invert_tree_comparison (x2.cond_code, false);
- else
- c2 = x2.cond_code;
-
- return c1 == c2;
-}
-
-/* Returns true if the predication is testing !=. */
-
-static inline bool
-is_neq_relop_p (pred_info pred)
-{
-
- return ((pred.cond_code == NE_EXPR && !pred.invert)
- || (pred.cond_code == EQ_EXPR && pred.invert));
-}
-
-/* Returns true if pred is of the form X != 0. */
-
-static inline bool
-is_neq_zero_form_p (pred_info pred)
-{
- if (!is_neq_relop_p (pred) || !integer_zerop (pred.pred_rhs)
- || TREE_CODE (pred.pred_lhs) != SSA_NAME)
- return false;
- return true;
-}
-
-/* The helper function returns true if two predicates X1
- is equivalent to X2 != 0. */
-
-static inline bool
-pred_expr_equal_p (pred_info x1, tree x2)
-{
- if (!is_neq_zero_form_p (x1))
- return false;
-
- return operand_equal_p (x1.pred_lhs, x2, 0);
-}
-
-/* Returns true of the domain of single predicate expression
- EXPR1 is a subset of that of EXPR2. Returns false if it
- cannot be proved. */
-
-static bool
-is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
-{
- enum tree_code code1, code2;
-
- if (pred_equal_p (expr1, expr2))
- return true;
-
- if ((TREE_CODE (expr1.pred_rhs) != INTEGER_CST)
- || (TREE_CODE (expr2.pred_rhs) != INTEGER_CST))
- return false;
-
- if (!operand_equal_p (expr1.pred_lhs, expr2.pred_lhs, 0))
- return false;
-
- code1 = expr1.cond_code;
- if (expr1.invert)
- code1 = invert_tree_comparison (code1, false);
- code2 = expr2.cond_code;
- if (expr2.invert)
- code2 = invert_tree_comparison (code2, false);
-
- if (code2 == NE_EXPR && code1 == NE_EXPR)
- return false;
-
- if (code2 == NE_EXPR)
- return !value_sat_pred_p (expr2.pred_rhs, expr1.pred_rhs, code1);
-
- if (code1 == EQ_EXPR)
- return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2);
-
- if (code1 == code2)
- return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2,
- code1 == BIT_AND_EXPR);
+ if (TREE_CODE (val) == SSA_NAME)
+ return uninit_undefined_value_p (val);
return false;
}
-/* Returns true if the domain of PRED1 is a subset
- of that of PRED2. Returns false if it cannot be proved so. */
+/* Return a bitset of PHI arguments of interest. */
-static bool
-is_pred_chain_subset_of (pred_chain pred1, pred_chain pred2)
+unsigned
+uninit_undef_val_t::phi_arg_set (gphi *phi)
{
- size_t np1, np2, i1, i2;
-
- np1 = pred1.length ();
- np2 = pred2.length ();
-
- for (i2 = 0; i2 < np2; i2++)
- {
- bool found = false;
- pred_info info2 = pred2[i2];
- for (i1 = 0; i1 < np1; i1++)
- {
- pred_info info1 = pred1[i1];
- if (is_pred_expr_subset_of (info1, info2))
- {
- found = true;
- break;
- }
- }
- if (!found)
- return false;
- }
- return true;
-}
-
-/* Returns true if the domain defined by
- one pred chain ONE_PRED is a subset of the domain
- of *PREDS. It returns false if ONE_PRED's domain is
- not a subset of any of the sub-domains of PREDS
- (corresponding to each individual chains in it), even
- though it may be still be a subset of whole domain
- of PREDS which is the union (ORed) of all its subdomains.
- In other words, the result is conservative. */
-
-static bool
-is_included_in (pred_chain one_pred, pred_chain_union preds)
-{
- size_t i;
- size_t n = preds.length ();
-
- for (i = 0; i < n; i++)
- {
- if (is_pred_chain_subset_of (one_pred, preds[i]))
- return true;
- }
-
- return false;
-}
-
-/* Compares two predicate sets PREDS1 and PREDS2 and returns
- true if the domain defined by PREDS1 is a superset
- of PREDS2's domain. N1 and N2 are array sizes of PREDS1 and
- PREDS2 respectively. The implementation chooses not to build
- generic trees (and relying on the folding capability of the
- compiler), but instead performs brute force comparison of
- individual predicate chains (won't be a compile time problem
- as the chains are pretty short). When the function returns
- false, it does not necessarily mean *PREDS1 is not a superset
- of *PREDS2, but mean it may not be so since the analysis cannot
- prove it. In such cases, false warnings may still be
- emitted. */
-
-static bool
-is_superset_of (pred_chain_union preds1, pred_chain_union preds2)
-{
- size_t i, n2;
- pred_chain one_pred_chain = vNULL;
-
- n2 = preds2.length ();
-
- for (i = 0; i < n2; i++)
- {
- one_pred_chain = preds2[i];
- if (!is_included_in (one_pred_chain, preds1))
- return false;
- }
-
- return true;
-}
-
-/* Returns true if X1 is the negate of X2. */
-
-static inline bool
-pred_neg_p (pred_info x1, pred_info x2)
-{
- enum tree_code c1, c2;
- if (!operand_equal_p (x1.pred_lhs, x2.pred_lhs, 0)
- || !operand_equal_p (x1.pred_rhs, x2.pred_rhs, 0))
- return false;
-
- c1 = x1.cond_code;
- if (x1.invert == x2.invert)
- c2 = invert_tree_comparison (x2.cond_code, false);
- else
- c2 = x2.cond_code;
-
- return c1 == c2;
-}
-
-/* 1) ((x IOR y) != 0) AND (x != 0) is equivalent to (x != 0);
- 2) (X AND Y) OR (!X AND Y) is equivalent to Y;
- 3) X OR (!X AND Y) is equivalent to (X OR Y);
- 4) ((x IAND y) != 0) || (x != 0 AND y != 0)) is equivalent to
- (x != 0 AND y != 0)
- 5) (X AND Y) OR (!X AND Z) OR (!Y AND Z) is equivalent to
- (X AND Y) OR Z
-
- PREDS is the predicate chains, and N is the number of chains. */
-
-/* Helper function to implement rule 1 above. ONE_CHAIN is
- the AND predication to be simplified. */
-
-static void
-simplify_pred (pred_chain *one_chain)
-{
- size_t i, j, n;
- bool simplified = false;
- pred_chain s_chain = vNULL;
-
- n = one_chain->length ();
-
- for (i = 0; i < n; i++)
- {
- pred_info *a_pred = &(*one_chain)[i];
-
- if (!a_pred->pred_lhs)
- continue;
- if (!is_neq_zero_form_p (*a_pred))
- continue;
-
- gimple *def_stmt = SSA_NAME_DEF_STMT (a_pred->pred_lhs);
- if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
- continue;
- if (gimple_assign_rhs_code (def_stmt) == BIT_IOR_EXPR)
- {
- for (j = 0; j < n; j++)
- {
- pred_info *b_pred = &(*one_chain)[j];
-
- if (!b_pred->pred_lhs)
- continue;
- if (!is_neq_zero_form_p (*b_pred))
- continue;
-
- if (pred_expr_equal_p (*b_pred, gimple_assign_rhs1 (def_stmt))
- || pred_expr_equal_p (*b_pred, gimple_assign_rhs2 (def_stmt)))
- {
- /* Mark a_pred for removal. */
- a_pred->pred_lhs = NULL;
- a_pred->pred_rhs = NULL;
- simplified = true;
- break;
- }
- }
- }
- }
-
- if (!simplified)
- return;
-
- for (i = 0; i < n; i++)
- {
- pred_info *a_pred = &(*one_chain)[i];
- if (!a_pred->pred_lhs)
- continue;
- s_chain.safe_push (*a_pred);
- }
-
- one_chain->release ();
- *one_chain = s_chain;
-}
-
-/* The helper function implements the rule 2 for the
- OR predicate PREDS.
-
- 2) (X AND Y) OR (!X AND Y) is equivalent to Y. */
-
-static bool
-simplify_preds_2 (pred_chain_union *preds)
-{
- size_t i, j, n;
- bool simplified = false;
- pred_chain_union s_preds = vNULL;
-
- /* (X AND Y) OR (!X AND Y) is equivalent to Y.
- (X AND Y) OR (X AND !Y) is equivalent to X. */
-
- n = preds->length ();
- for (i = 0; i < n; i++)
- {
- pred_info x, y;
- pred_chain *a_chain = &(*preds)[i];
-
- if (a_chain->length () != 2)
- continue;
-
- x = (*a_chain)[0];
- y = (*a_chain)[1];
-
- for (j = 0; j < n; j++)
- {
- pred_chain *b_chain;
- pred_info x2, y2;
-
- if (j == i)
- continue;
-
- b_chain = &(*preds)[j];
- if (b_chain->length () != 2)
- continue;
-
- x2 = (*b_chain)[0];
- y2 = (*b_chain)[1];
-
- if (pred_equal_p (x, x2) && pred_neg_p (y, y2))
- {
- /* Kill a_chain. */
- a_chain->release ();
- b_chain->release ();
- b_chain->safe_push (x);
- simplified = true;
- break;
- }
- if (pred_neg_p (x, x2) && pred_equal_p (y, y2))
- {
- /* Kill a_chain. */
- a_chain->release ();
- b_chain->release ();
- b_chain->safe_push (y);
- simplified = true;
- break;
- }
- }
- }
- /* Now clean up the chain. */
- if (simplified)
- {
- for (i = 0; i < n; i++)
- {
- if ((*preds)[i].is_empty ())
- continue;
- s_preds.safe_push ((*preds)[i]);
- }
- preds->release ();
- (*preds) = s_preds;
- s_preds = vNULL;
- }
-
- return simplified;
-}
-
-/* The helper function implements the rule 2 for the
- OR predicate PREDS.
-
- 3) x OR (!x AND y) is equivalent to x OR y. */
-
-static bool
-simplify_preds_3 (pred_chain_union *preds)
-{
- size_t i, j, n;
- bool simplified = false;
-
- /* Now iteratively simplify X OR (!X AND Z ..)
- into X OR (Z ...). */
-
- n = preds->length ();
- if (n < 2)
- return false;
-
- for (i = 0; i < n; i++)
- {
- pred_info x;
- pred_chain *a_chain = &(*preds)[i];
-
- if (a_chain->length () != 1)
- continue;
-
- x = (*a_chain)[0];
-
- for (j = 0; j < n; j++)
- {
- pred_chain *b_chain;
- pred_info x2;
- size_t k;
-
- if (j == i)
- continue;
-
- b_chain = &(*preds)[j];
- if (b_chain->length () < 2)
- continue;
-
- for (k = 0; k < b_chain->length (); k++)
- {
- x2 = (*b_chain)[k];
- if (pred_neg_p (x, x2))
- {
- b_chain->unordered_remove (k);
- simplified = true;
- break;
- }
- }
- }
- }
- return simplified;
-}
-
-/* The helper function implements the rule 4 for the
- OR predicate PREDS.
-
- 2) ((x AND y) != 0) OR (x != 0 AND y != 0) is equivalent to
- (x != 0 ANd y != 0). */
-
-static bool
-simplify_preds_4 (pred_chain_union *preds)
-{
- size_t i, j, n;
- bool simplified = false;
- pred_chain_union s_preds = vNULL;
- gimple *def_stmt;
-
- n = preds->length ();
- for (i = 0; i < n; i++)
- {
- pred_info z;
- pred_chain *a_chain = &(*preds)[i];
-
- if (a_chain->length () != 1)
- continue;
-
- z = (*a_chain)[0];
-
- if (!is_neq_zero_form_p (z))
- continue;
-
- def_stmt = SSA_NAME_DEF_STMT (z.pred_lhs);
- if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
- continue;
-
- if (gimple_assign_rhs_code (def_stmt) != BIT_AND_EXPR)
- continue;
-
- for (j = 0; j < n; j++)
- {
- pred_chain *b_chain;
- pred_info x2, y2;
-
- if (j == i)
- continue;
-
- b_chain = &(*preds)[j];
- if (b_chain->length () != 2)
- continue;
-
- x2 = (*b_chain)[0];
- y2 = (*b_chain)[1];
- if (!is_neq_zero_form_p (x2) || !is_neq_zero_form_p (y2))
- continue;
-
- if ((pred_expr_equal_p (x2, gimple_assign_rhs1 (def_stmt))
- && pred_expr_equal_p (y2, gimple_assign_rhs2 (def_stmt)))
- || (pred_expr_equal_p (x2, gimple_assign_rhs2 (def_stmt))
- && pred_expr_equal_p (y2, gimple_assign_rhs1 (def_stmt))))
- {
- /* Kill a_chain. */
- a_chain->release ();
- simplified = true;
- break;
- }
- }
- }
- /* Now clean up the chain. */
- if (simplified)
- {
- for (i = 0; i < n; i++)
- {
- if ((*preds)[i].is_empty ())
- continue;
- s_preds.safe_push ((*preds)[i]);
- }
-
- preds->release ();
- (*preds) = s_preds;
- s_preds = vNULL;
- }
-
- return simplified;
-}
-
-/* This function simplifies predicates in PREDS. */
-
-static void
-simplify_preds (pred_chain_union *preds, gimple *use_or_def, bool is_use)
-{
- size_t i, n;
- bool changed = false;
-
- if (dump_file && dump_flags & TDF_DETAILS)
- {
- fprintf (dump_file, "[BEFORE SIMPLICATION -- ");
- dump_predicates (use_or_def, *preds, is_use ? "[USE]:\n" : "[DEF]:\n");
- }
-
- for (i = 0; i < preds->length (); i++)
- simplify_pred (&(*preds)[i]);
-
- n = preds->length ();
- if (n < 2)
- return;
-
- do
- {
- changed = false;
- if (simplify_preds_2 (preds))
- changed = true;
-
- /* Now iteratively simplify X OR (!X AND Z ..)
- into X OR (Z ...). */
- if (simplify_preds_3 (preds))
- changed = true;
-
- if (simplify_preds_4 (preds))
- changed = true;
- }
- while (changed);
-
- return;
-}
-
-/* This is a helper function which attempts to normalize predicate chains
- by following UD chains. It basically builds up a big tree of either IOR
- operations or AND operations, and convert the IOR tree into a
- pred_chain_union or BIT_AND tree into a pred_chain.
- Example:
-
- _3 = _2 RELOP1 _1;
- _6 = _5 RELOP2 _4;
- _9 = _8 RELOP3 _7;
- _10 = _3 | _6;
- _12 = _9 | _0;
- _t = _10 | _12;
-
- then _t != 0 will be normalized into a pred_chain_union
-
- (_2 RELOP1 _1) OR (_5 RELOP2 _4) OR (_8 RELOP3 _7) OR (_0 != 0)
-
- Similarly given,
-
- _3 = _2 RELOP1 _1;
- _6 = _5 RELOP2 _4;
- _9 = _8 RELOP3 _7;
- _10 = _3 & _6;
- _12 = _9 & _0;
-
- then _t != 0 will be normalized into a pred_chain:
- (_2 RELOP1 _1) AND (_5 RELOP2 _4) AND (_8 RELOP3 _7) AND (_0 != 0)
-
- */
-
-/* This is a helper function that stores a PRED into NORM_PREDS. */
-
-inline static void
-push_pred (pred_chain_union *norm_preds, pred_info pred)
-{
- pred_chain pred_chain = vNULL;
- pred_chain.safe_push (pred);
- norm_preds->safe_push (pred_chain);
-}
-
-/* A helper function that creates a predicate of the form
- OP != 0 and push it WORK_LIST. */
-
-inline static void
-push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
- hash_set<tree> *mark_set)
-{
- if (mark_set->contains (op))
- return;
- mark_set->add (op);
-
- pred_info arg_pred;
- arg_pred.pred_lhs = op;
- arg_pred.pred_rhs = integer_zero_node;
- arg_pred.cond_code = NE_EXPR;
- arg_pred.invert = false;
- work_list->safe_push (arg_pred);
-}
-
-/* A helper that generates a pred_info from a gimple assignment
- CMP_ASSIGN with comparison rhs. */
-
-static pred_info
-get_pred_info_from_cmp (gimple *cmp_assign)
-{
- pred_info n_pred;
- n_pred.pred_lhs = gimple_assign_rhs1 (cmp_assign);
- n_pred.pred_rhs = gimple_assign_rhs2 (cmp_assign);
- n_pred.cond_code = gimple_assign_rhs_code (cmp_assign);
- n_pred.invert = false;
- return n_pred;
-}
-
-/* Returns true if the PHI is a degenerated phi with
- all args with the same value (relop). In that case, *PRED
- will be updated to that value. */
-
-static bool
-is_degenerated_phi (gimple *phi, pred_info *pred_p)
-{
- int i, n;
- tree op0;
- gimple *def0;
- pred_info pred0;
-
- n = gimple_phi_num_args (phi);
- op0 = gimple_phi_arg_def (phi, 0);
-
- if (TREE_CODE (op0) != SSA_NAME)
- return false;
-
- def0 = SSA_NAME_DEF_STMT (op0);
- if (gimple_code (def0) != GIMPLE_ASSIGN)
- return false;
- if (TREE_CODE_CLASS (gimple_assign_rhs_code (def0)) != tcc_comparison)
- return false;
- pred0 = get_pred_info_from_cmp (def0);
-
- for (i = 1; i < n; ++i)
- {
- gimple *def;
- pred_info pred;
- tree op = gimple_phi_arg_def (phi, i);
-
- if (TREE_CODE (op) != SSA_NAME)
- return false;
-
- def = SSA_NAME_DEF_STMT (op);
- if (gimple_code (def) != GIMPLE_ASSIGN)
- return false;
- if (TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison)
- return false;
- pred = get_pred_info_from_cmp (def);
- if (!pred_equal_p (pred, pred0))
- return false;
- }
-
- *pred_p = pred0;
- return true;
-}
-
-/* Normalize one predicate PRED
- 1) if PRED can no longer be normlized, put it into NORM_PREDS.
- 2) otherwise if PRED is of the form x != 0, follow x's definition
- and put normalized predicates into WORK_LIST. */
-
-static void
-normalize_one_pred_1 (pred_chain_union *norm_preds,
- pred_chain *norm_chain,
- pred_info pred,
- enum tree_code and_or_code,
- vec<pred_info, va_heap, vl_ptr> *work_list,
- hash_set<tree> *mark_set)
-{
- if (!is_neq_zero_form_p (pred))
- {
- if (and_or_code == BIT_IOR_EXPR)
- push_pred (norm_preds, pred);
- else
- norm_chain->safe_push (pred);
- return;
- }
-
- gimple *def_stmt = SSA_NAME_DEF_STMT (pred.pred_lhs);
-
- if (gimple_code (def_stmt) == GIMPLE_PHI
- && is_degenerated_phi (def_stmt, &pred))
- work_list->safe_push (pred);
- else if (gimple_code (def_stmt) == GIMPLE_PHI && and_or_code == BIT_IOR_EXPR)
- {
- int i, n;
- n = gimple_phi_num_args (def_stmt);
-
- /* If we see non zero constant, we should punt. The predicate
- * should be one guarding the phi edge. */
- for (i = 0; i < n; ++i)
- {
- tree op = gimple_phi_arg_def (def_stmt, i);
- if (TREE_CODE (op) == INTEGER_CST && !integer_zerop (op))
- {
- push_pred (norm_preds, pred);
- return;
- }
- }
-
- for (i = 0; i < n; ++i)
- {
- tree op = gimple_phi_arg_def (def_stmt, i);
- if (integer_zerop (op))
- continue;
-
- push_to_worklist (op, work_list, mark_set);
- }
- }
- else if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
- {
- if (and_or_code == BIT_IOR_EXPR)
- push_pred (norm_preds, pred);
- else
- norm_chain->safe_push (pred);
- }
- else if (gimple_assign_rhs_code (def_stmt) == and_or_code)
- {
- /* Avoid splitting up bit manipulations like x & 3 or y | 1. */
- if (is_gimple_min_invariant (gimple_assign_rhs2 (def_stmt)))
- {
- /* But treat x & 3 as condition. */
- if (and_or_code == BIT_AND_EXPR)
- {
- pred_info n_pred;
- n_pred.pred_lhs = gimple_assign_rhs1 (def_stmt);
- n_pred.pred_rhs = gimple_assign_rhs2 (def_stmt);
- n_pred.cond_code = and_or_code;
- n_pred.invert = false;
- norm_chain->safe_push (n_pred);
- }
- }
- else
- {
- push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set);
- push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set);
- }
- }
- else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
- == tcc_comparison)
- {
- pred_info n_pred = get_pred_info_from_cmp (def_stmt);
- if (and_or_code == BIT_IOR_EXPR)
- push_pred (norm_preds, n_pred);
- else
- norm_chain->safe_push (n_pred);
- }
- else
- {
- if (and_or_code == BIT_IOR_EXPR)
- push_pred (norm_preds, pred);
- else
- norm_chain->safe_push (pred);
- }
-}
-
-/* Normalize PRED and store the normalized predicates into NORM_PREDS. */
-
-static void
-normalize_one_pred (pred_chain_union *norm_preds, pred_info pred)
-{
- vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
- enum tree_code and_or_code = ERROR_MARK;
- pred_chain norm_chain = vNULL;
-
- if (!is_neq_zero_form_p (pred))
- {
- push_pred (norm_preds, pred);
- return;
- }
-
- gimple *def_stmt = SSA_NAME_DEF_STMT (pred.pred_lhs);
- if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
- and_or_code = gimple_assign_rhs_code (def_stmt);
- if (and_or_code != BIT_IOR_EXPR && and_or_code != BIT_AND_EXPR)
- {
- if (TREE_CODE_CLASS (and_or_code) == tcc_comparison)
- {
- pred_info n_pred = get_pred_info_from_cmp (def_stmt);
- push_pred (norm_preds, n_pred);
- }
- else
- push_pred (norm_preds, pred);
- return;
- }
-
- work_list.safe_push (pred);
- hash_set<tree> mark_set;
-
- while (!work_list.is_empty ())
- {
- pred_info a_pred = work_list.pop ();
- normalize_one_pred_1 (norm_preds, &norm_chain, a_pred, and_or_code,
- &work_list, &mark_set);
- }
- if (and_or_code == BIT_AND_EXPR)
- norm_preds->safe_push (norm_chain);
-
- work_list.release ();
-}
-
-static void
-normalize_one_pred_chain (pred_chain_union *norm_preds, pred_chain one_chain)
-{
- vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
- hash_set<tree> mark_set;
- pred_chain norm_chain = vNULL;
- size_t i;
-
- for (i = 0; i < one_chain.length (); i++)
- {
- work_list.safe_push (one_chain[i]);
- mark_set.add (one_chain[i].pred_lhs);
- }
-
- while (!work_list.is_empty ())
- {
- pred_info a_pred = work_list.pop ();
- normalize_one_pred_1 (0, &norm_chain, a_pred, BIT_AND_EXPR, &work_list,
- &mark_set);
- }
-
- norm_preds->safe_push (norm_chain);
- work_list.release ();
-}
-
-/* Normalize predicate chains PREDS and returns the normalized one. */
-
-static pred_chain_union
-normalize_preds (pred_chain_union preds, gimple *use_or_def, bool is_use)
-{
- pred_chain_union norm_preds = vNULL;
- size_t n = preds.length ();
- size_t i;
-
- if (dump_file && dump_flags & TDF_DETAILS)
- {
- fprintf (dump_file, "[BEFORE NORMALIZATION --");
- dump_predicates (use_or_def, preds, is_use ? "[USE]:\n" : "[DEF]:\n");
- }
-
- for (i = 0; i < n; i++)
- {
- if (preds[i].length () != 1)
- normalize_one_pred_chain (&norm_preds, preds[i]);
- else
- {
- normalize_one_pred (&norm_preds, preds[i][0]);
- preds[i].release ();
- }
- }
-
- if (dump_file)
- {
- fprintf (dump_file, "[AFTER NORMALIZATION -- ");
- dump_predicates (use_or_def, norm_preds,
- is_use ? "[USE]:\n" : "[DEF]:\n");
- }
-
- destroy_predicate_vecs (&preds);
- return norm_preds;
-}
-
-/* Return TRUE if PREDICATE can be invalidated by any individual
- predicate in USE_GUARD. */
-
-static bool
-can_one_predicate_be_invalidated_p (pred_info predicate,
- pred_chain use_guard)
-{
- if (dump_file && dump_flags & TDF_DETAILS)
- {
- fprintf (dump_file, "Testing if this predicate: ");
- dump_pred_info (predicate);
- fprintf (dump_file, "\n...can be invalidated by a USE guard of: ");
- dump_pred_chain (use_guard);
- }
- for (size_t i = 0; i < use_guard.length (); ++i)
- {
- /* NOTE: This is a very simple check, and only understands an
- exact opposite. So, [i == 0] is currently only invalidated
- by [.NOT. i == 0] or [i != 0]. Ideally we should also
- invalidate with say [i > 5] or [i == 8]. There is certainly
- room for improvement here. */
- if (pred_neg_p (predicate, use_guard[i]))
- {
- if (dump_file && dump_flags & TDF_DETAILS)
- {
- fprintf (dump_file, " Predicate was invalidated by: ");
- dump_pred_info (use_guard[i]);
- fputc ('\n', dump_file);
- }
- return true;
- }
- }
- return false;
-}
-
-/* Return TRUE if all predicates in UNINIT_PRED are invalidated by
- USE_GUARD being true. */
-
-static bool
-can_chain_union_be_invalidated_p (pred_chain_union uninit_pred,
- pred_chain use_guard)
-{
- if (uninit_pred.is_empty ())
- return false;
- if (dump_file && dump_flags & TDF_DETAILS)
- dump_predicates (NULL, uninit_pred,
- "Testing if anything here can be invalidated: ");
- for (size_t i = 0; i < uninit_pred.length (); ++i)
- {
- pred_chain c = uninit_pred[i];
- size_t j;
- for (j = 0; j < c.length (); ++j)
- if (can_one_predicate_be_invalidated_p (c[j], use_guard))
- break;
-
- /* If we were unable to invalidate any predicate in C, then there
- is a viable path from entry to the PHI where the PHI takes
- an uninitialized value and continues to a use of the PHI. */
- if (j == c.length ())
- return false;
- }
- return true;
-}
-
-/* Return TRUE if none of the uninitialized operands in UNINT_OPNDS
- can actually happen if we arrived at a use for PHI.
-
- PHI_USE_GUARDS are the guard conditions for the use of the PHI. */
-
-static bool
-uninit_uses_cannot_happen (gphi *phi, unsigned uninit_opnds,
- pred_chain_union phi_use_guards)
-{
- unsigned phi_args = gimple_phi_num_args (phi);
- if (phi_args > max_phi_args)
- return false;
-
- /* PHI_USE_GUARDS are OR'ed together. If we have more than one
- possible guard, there's no way of knowing which guard was true.
- Since we need to be absolutely sure that the uninitialized
- operands will be invalidated, bail. */
- if (phi_use_guards.length () != 1)
- return false;
-
- /* Look for the control dependencies of all the uninitialized
- operands and build guard predicates describing them. */
- pred_chain_union uninit_preds;
- bool ret = true;
- for (unsigned i = 0; i < phi_args; ++i)
- {
- if (!MASK_TEST_BIT (uninit_opnds, i))
- continue;
-
- edge e = gimple_phi_arg_edge (phi, i);
- vec<edge> dep_chains[MAX_NUM_CHAINS];
- auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
- size_t num_chains = 0;
- int num_calls = 0;
-
- /* Build the control dependency chain for uninit operand `i'... */
- uninit_preds = vNULL;
- if (!compute_control_dep_chain (ENTRY_BLOCK_PTR_FOR_FN (cfun),
- e->src, dep_chains, &num_chains,
- &cur_chain, &num_calls))
- {
- ret = false;
- break;
- }
- /* ...and convert it into a set of predicates. */
- bool has_valid_preds
- = convert_control_dep_chain_into_preds (dep_chains, num_chains,
- &uninit_preds);
- for (size_t j = 0; j < num_chains; ++j)
- dep_chains[j].release ();
- if (!has_valid_preds)
- {
- ret = false;
- break;
- }
- simplify_preds (&uninit_preds, NULL, false);
- uninit_preds = normalize_preds (uninit_preds, NULL, false);
-
- /* Can the guard for this uninitialized operand be invalidated
- by the PHI use? */
- if (!can_chain_union_be_invalidated_p (uninit_preds, phi_use_guards[0]))
- {
- ret = false;
- break;
- }
- }
- destroy_predicate_vecs (&uninit_preds);
- return ret;
-}
-
-/* Computes the predicates that guard the use and checks
- if the incoming paths that have empty (or possibly
- empty) definition can be pruned/filtered. The function returns
- true if it can be determined that the use of PHI's def in
- USE_STMT is guarded with a predicate set not overlapping with
- predicate sets of all runtime paths that do not have a definition.
-
- Returns false if it is not or it cannot be determined. USE_BB is
- the bb of the use (for phi operand use, the bb is not the bb of
- the phi stmt, but the src bb of the operand edge).
-
- UNINIT_OPNDS is a bit vector. If an operand of PHI is uninitialized, the
- corresponding bit in the vector is 1. VISITED_PHIS is a pointer
- set of phis being visited.
-
- *DEF_PREDS contains the (memoized) defining predicate chains of PHI.
- If *DEF_PREDS is the empty vector, the defining predicate chains of
- PHI will be computed and stored into *DEF_PREDS as needed.
-
- VISITED_PHIS is a pointer set of phis being visited. */
-
-static bool
-is_use_properly_guarded (gimple *use_stmt,
- basic_block use_bb,
- gphi *phi,
- unsigned uninit_opnds,
- pred_chain_union *def_preds,
- hash_set<gphi *> *visited_phis)
-{
- basic_block phi_bb;
- pred_chain_union preds = vNULL;
- bool has_valid_preds = false;
- bool is_properly_guarded = false;
-
- if (visited_phis->add (phi))
- return false;
-
- phi_bb = gimple_bb (phi);
-
- if (is_non_loop_exit_postdominating (use_bb, phi_bb))
- return false;
-
- has_valid_preds = find_predicates (&preds, phi_bb, use_bb);
-
- if (!has_valid_preds)
- {
- destroy_predicate_vecs (&preds);
- return false;
- }
-
- /* Try to prune the dead incoming phi edges. */
- is_properly_guarded
- = use_pred_not_overlap_with_undef_path_pred (preds, phi, uninit_opnds,
- visited_phis);
-
- /* We might be able to prove that if the control dependencies
- for UNINIT_OPNDS are true, that the control dependencies for
- USE_STMT can never be true. */
- if (!is_properly_guarded)
- is_properly_guarded |= uninit_uses_cannot_happen (phi, uninit_opnds,
- preds);
-
- if (is_properly_guarded)
- {
- destroy_predicate_vecs (&preds);
- return true;
- }
-
- if (def_preds->is_empty ())
- {
- has_valid_preds = find_def_preds (def_preds, phi);
-
- if (!has_valid_preds)
- {
- destroy_predicate_vecs (&preds);
- return false;
- }
-
- simplify_preds (def_preds, phi, false);
- *def_preds = normalize_preds (*def_preds, phi, false);
- }
-
- simplify_preds (&preds, use_stmt, true);
- preds = normalize_preds (preds, use_stmt, true);
-
- is_properly_guarded = is_superset_of (*def_preds, preds);
-
- destroy_predicate_vecs (&preds);
- return is_properly_guarded;
+ return compute_uninit_opnds_pos (phi);
}
/* Searches through all uses of a potentially
@@ -3108,48 +1065,42 @@ is_use_properly_guarded (gimple *use_stmt,
static gimple *
find_uninit_use (gphi *phi, unsigned uninit_opnds,
- vec<gphi *> *worklist,
- hash_set<gphi *> *added_to_worklist)
+ vec<gphi *> *worklist, hash_set<gphi *> *added_to_worklist)
{
- tree phi_result;
+ /* The Boolean predicate guarding the PHI definition. Initialized
+ lazily from PHI in the first call to is_use_guarded() and cached
+ for subsequent iterations. */
+ uninit_undef_val_t eval;
+ predicate def_preds (eval);
+
use_operand_p use_p;
- gimple *use_stmt;
imm_use_iterator iter;
- pred_chain_union def_preds = vNULL;
- gimple *ret = NULL;
-
- phi_result = gimple_phi_result (phi);
-
+ tree phi_result = gimple_phi_result (phi);
FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
{
- basic_block use_bb;
-
- use_stmt = USE_STMT (use_p);
+ gimple *use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt))
continue;
+ basic_block use_bb;
if (gphi *use_phi = dyn_cast<gphi *> (use_stmt))
use_bb = gimple_phi_arg_edge (use_phi,
PHI_ARG_INDEX_FROM_USE (use_p))->src;
else
use_bb = gimple_bb (use_stmt);
- hash_set<gphi *> visited_phis;
- if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
- &def_preds, &visited_phis))
+ if (def_preds.is_use_guarded (use_stmt, use_bb, phi, uninit_opnds))
continue;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "[CHECK]: Found unguarded use: ");
+ fprintf (dump_file, "Found unguarded use in bb %u: ",
+ use_bb->index);
print_gimple_stmt (dump_file, use_stmt, 0);
}
/* Found one real use, return. */
if (gimple_code (use_stmt) != GIMPLE_PHI)
- {
- ret = use_stmt;
- break;
- }
+ return use_stmt;
/* Found a phi use that is not guarded,
add the phi to the worklist. */
@@ -3166,8 +1117,7 @@ find_uninit_use (gphi *phi, unsigned uninit_opnds,
}
}
- destroy_predicate_vecs (&def_preds);
- return ret;
+ return NULL;
}
/* Look for inputs to PHI that are SSA_NAMEs that have empty definitions
@@ -3192,28 +1142,47 @@ warn_uninitialized_phi (gphi *phi, vec<gphi *> *worklist,
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "[CHECK]: examining phi: ");
+ fprintf (dump_file, "Examining phi: ");
print_gimple_stmt (dump_file, phi, 0);
}
- /* Now check if we have any use of the value without proper guard. */
gimple *uninit_use_stmt = find_uninit_use (phi, uninit_opnds,
worklist, added_to_worklist);
- /* All uses are properly guarded. */
+ /* All uses are properly guarded but a new PHI may have been added
+ to WORKLIST. */
if (!uninit_use_stmt)
return;
- int phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds);
+ unsigned phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds);
tree uninit_op = gimple_phi_arg_def (phi, phiarg_index);
if (SSA_NAME_VAR (uninit_op) == NULL_TREE)
return;
- location_t phi_arg_loc = gimple_phi_arg_location (phi, phiarg_index);
+ location_t loc = UNKNOWN_LOCATION;
+ if (gimple_phi_arg_has_location (phi, phiarg_index))
+ loc = gimple_phi_arg_location (phi, phiarg_index);
+ else
+ {
+ tree arg_def = gimple_phi_arg_def (phi, phiarg_index);
+ if (TREE_CODE (arg_def) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (arg_def);
+ if (gphi *arg_phi = dyn_cast<gphi *> (def_stmt))
+ {
+ unsigned uop = compute_uninit_opnds_pos (arg_phi);
+ unsigned idx = MASK_FIRST_SET_BIT (uop);
+ if (idx < gimple_phi_num_args (arg_phi)
+ && gimple_phi_arg_has_location (arg_phi, idx))
+ loc = gimple_phi_arg_location (arg_phi, idx);
+ }
+ }
+ }
+
warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
SSA_NAME_VAR (uninit_op),
"%qD may be used uninitialized in this function",
- uninit_use_stmt, phi_arg_loc);
+ uninit_use_stmt, loc);
}
static bool
@@ -3251,8 +1220,8 @@ public:
}; // class pass_late_warn_uninitialized
-unsigned int
-pass_late_warn_uninitialized::execute (function *fun)
+static void
+execute_late_warn_uninitialized (function *fun)
{
basic_block bb;
gphi_iterator gsi;
@@ -3275,15 +1244,13 @@ pass_late_warn_uninitialized::execute (function *fun)
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gphi *phi = gsi.phi ();
- size_t n, i;
-
- n = gimple_phi_num_args (phi);
/* Don't look at virtual operands. */
if (virtual_operand_p (gimple_phi_result (phi)))
continue;
- for (i = 0; i < n; ++i)
+ unsigned n = gimple_phi_num_args (phi);
+ for (unsigned i = 0; i < n; ++i)
{
tree op = gimple_phi_arg_def (phi, i);
if (TREE_CODE (op) == SSA_NAME && uninit_undefined_value_p (op))
@@ -3292,7 +1259,8 @@ pass_late_warn_uninitialized::execute (function *fun)
added_to_worklist.add (phi);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "[WORKLIST]: add to initial list: ");
+ fprintf (dump_file, "[WORKLIST]: add to initial list "
+ "for operand %u of: ", i);
print_gimple_stmt (dump_file, phi, 0);
}
break;
@@ -3312,6 +1280,12 @@ pass_late_warn_uninitialized::execute (function *fun)
possibly_undefined_names = NULL;
free_dominance_info (CDI_POST_DOMINATORS);
timevar_pop (TV_TREE_UNINIT);
+}
+
+unsigned int
+pass_late_warn_uninitialized::execute (function *fun)
+{
+ execute_late_warn_uninitialized (fun);
return 0;
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4cc400d..fde13de 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1325,6 +1325,46 @@ ssa_undefined_value_p (tree t, bool partial)
if (gimple_nop_p (def_stmt))
return true;
+ /* The value is undefined if the definition statement is a call
+ to .DEFERRED_INIT function. */
+ if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+ return true;
+
+ /* The value is partially undefined if the definition statement is
+ a REALPART_EXPR or IMAGPART_EXPR and its operand is defined by
+ the call to .DEFERRED_INIT function. This is for handling the
+ following case:
+
+ 1 typedef _Complex float C;
+ 2 C foo (int cond)
+ 3 {
+ 4 C f;
+ 5 __imag__ f = 0;
+ 6 if (cond)
+ 7 {
+ 8 __real__ f = 1;
+ 9 return f;
+ 10 }
+ 11 return f;
+ 12 }
+
+ with -ftrivial-auto-var-init, compiler will insert the following
+ artificial initialization:
+ f = .DEFERRED_INIT (f, 2);
+ _1 = REALPART_EXPR <f>;
+
+ we should treat the definition _1 = REALPART_EXPR <f> as undefined. */
+ if (partial && is_gimple_assign (def_stmt)
+ && (gimple_assign_rhs_code (def_stmt) == REALPART_EXPR
+ || gimple_assign_rhs_code (def_stmt) == IMAGPART_EXPR))
+ {
+ tree real_imag_part = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
+ if (TREE_CODE (real_imag_part) == SSA_NAME
+ && gimple_call_internal_p (SSA_NAME_DEF_STMT (real_imag_part),
+ IFN_DEFERRED_INIT))
+ return true;
+ }
+
/* Check if the complex was not only partially defined. */
if (partial && is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
@@ -2039,7 +2079,7 @@ execute_update_addresses_taken (void)
gcall *call
= gimple_build_call_internal (IFN_ASAN_POISON, 0);
gimple_call_set_lhs (call, var);
- gsi_replace (&gsi, call, GSI_SAME_STMT);
+ gsi_replace (&gsi, call, true);
}
else
{
@@ -2048,7 +2088,7 @@ execute_update_addresses_taken (void)
previous out of scope value. */
tree clobber = build_clobber (TREE_TYPE (var));
gimple *g = gimple_build_assign (var, clobber);
- gsi_replace (&gsi, g, GSI_SAME_STMT);
+ gsi_replace (&gsi, g, true);
}
continue;
}
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 2165ad7..f427c5a 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
+#include "value-query.h"
/* Rewriting a function into SSA form can create a huge number of SSA_NAMEs,
many of which may be thrown away shortly after their creation if jumps
@@ -484,7 +485,7 @@ get_nonzero_bits (const_tree name)
This can be because it is a boolean type, any unsigned integral
type with a single bit of precision, or has known range of [0..1]
- via VRP analysis. */
+ via range analysis. */
bool
ssa_name_has_boolean_range (tree op)
@@ -502,12 +503,20 @@ ssa_name_has_boolean_range (tree op)
return true;
/* An integral type with more precision, but the object
- only takes on values [0..1] as determined by VRP
+ only takes on values [0..1] as determined by range
analysis. */
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
- && (TYPE_PRECISION (TREE_TYPE (op)) > 1)
- && wi::eq_p (get_nonzero_bits (op), 1))
- return true;
+ && (TYPE_PRECISION (TREE_TYPE (op)) > 1))
+ {
+ int_range<2> onezero (build_zero_cst (TREE_TYPE (op)),
+ build_one_cst (TREE_TYPE (op)));
+ int_range<2> r;
+ if (get_range_query (cfun)->range_of_expr (r, op) && r == onezero)
+ return true;
+
+ if (wi::eq_p (get_nonzero_bits (op), 1))
+ return true;
+ }
return false;
}
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index e0522bf..848981a 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -256,7 +256,11 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_PADDING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
- DECL_FIELD_ABI_IGNORED (expr) = (unsigned) bp_unpack_value (bp, 1);
+ unsigned val = (unsigned) bp_unpack_value (bp, 1);
+ if (DECL_BIT_FIELD (expr))
+ SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (expr, val);
+ else
+ SET_DECL_FIELD_ABI_IGNORED (expr, val);
expr->decl_common.off_align = bp_unpack_value (bp, 8);
}
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 855d1cd..1f9ce52 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -219,7 +219,10 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, DECL_PACKED (expr), 1);
bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
bp_pack_value (bp, DECL_PADDING_P (expr), 1);
- bp_pack_value (bp, DECL_FIELD_ABI_IGNORED (expr), 1);
+ if (DECL_BIT_FIELD (expr))
+ bp_pack_value (bp, DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (expr), 1);
+ else
+ bp_pack_value (bp, DECL_FIELD_ABI_IGNORED (expr), 1);
bp_pack_value (bp, expr->decl_common.off_align, 8);
}
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 37f46d1..a19045f 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -887,6 +887,55 @@ vect_slp_analyze_instance_dependence (vec_info *vinfo, slp_instance instance)
return res;
}
+/* Return the misalignment of DR_INFO accessed in VECTYPE. */
+
+int
+dr_misalignment (dr_vec_info *dr_info, tree vectype)
+{
+ HOST_WIDE_INT diff = 0;
+ /* Alignment is only analyzed for the first element of a DR group,
+ use that but adjust misalignment by the offset of the access. */
+ if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt))
+ {
+ dr_vec_info *first_dr
+ = STMT_VINFO_DR_INFO (DR_GROUP_FIRST_ELEMENT (dr_info->stmt));
+ /* vect_analyze_data_ref_accesses guarantees that DR_INIT are
+ INTEGER_CSTs and the first element in the group has the lowest
+ address. */
+ diff = (TREE_INT_CST_LOW (DR_INIT (dr_info->dr))
+ - TREE_INT_CST_LOW (DR_INIT (first_dr->dr)));
+ gcc_assert (diff >= 0);
+ dr_info = first_dr;
+ }
+
+ int misalign = dr_info->misalignment;
+ gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
+ if (misalign == DR_MISALIGNMENT_UNKNOWN)
+ return misalign;
+
+ /* If the access is only aligned for a vector type with smaller alignment
+ requirement the access has unknown misalignment. */
+ if (maybe_lt (dr_info->target_alignment * BITS_PER_UNIT,
+ targetm.vectorize.preferred_vector_alignment (vectype)))
+ return DR_MISALIGNMENT_UNKNOWN;
+
+ /* If this is a backward running DR then first access in the larger
+ vectype actually is N-1 elements before the address in the DR.
+ Adjust misalign accordingly. */
+ poly_int64 misalignment = misalign + diff;
+ if (tree_int_cst_sgn (DR_STEP (dr_info->dr)) < 0)
+ misalignment += ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
+ * -TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
+
+ /* vect_compute_data_ref_alignment will have ensured that target_alignment
+ is constant and otherwise set misalign to DR_MISALIGNMENT_UNKNOWN. */
+ unsigned HOST_WIDE_INT target_alignment_c
+ = dr_info->target_alignment.to_constant ();
+ if (!known_misalignment (misalignment, target_alignment_c, &misalign))
+ return DR_MISALIGNMENT_UNKNOWN;
+ return misalign;
+}
+
/* Record the base alignment guarantee given by DRB, which occurs
in STMT_INFO. */
@@ -895,11 +944,11 @@ vect_record_base_alignment (vec_info *vinfo, stmt_vec_info stmt_info,
innermost_loop_behavior *drb)
{
bool existed;
- innermost_loop_behavior *&entry
+ std::pair<stmt_vec_info, innermost_loop_behavior *> &entry
= vinfo->base_alignments.get_or_insert (drb->base_address, &existed);
- if (!existed || entry->base_alignment < drb->base_alignment)
+ if (!existed || entry.second->base_alignment < drb->base_alignment)
{
- entry = drb;
+ entry = std::make_pair (stmt_info, drb);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"recording new base alignment for %T\n"
@@ -945,34 +994,26 @@ vect_record_base_alignments (vec_info *vinfo)
}
}
-/* Return the target alignment for the vectorized form of DR_INFO. */
-
-static poly_uint64
-vect_calculate_target_alignment (dr_vec_info *dr_info)
-{
- tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
- return targetm.vectorize.preferred_vector_alignment (vectype);
-}
-
/* Function vect_compute_data_ref_alignment
- Compute the misalignment of the data reference DR_INFO.
+ Compute the misalignment of the data reference DR_INFO when vectorizing
+ with VECTYPE.
Output:
- 1. DR_MISALIGNMENT (DR_INFO) is defined.
+ 1. initialized misalignment info for DR_INFO
FOR NOW: No analysis is actually performed. Misalignment is calculated
only for trivial cases. TODO. */
static void
-vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
+vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
+ tree vectype)
{
stmt_vec_info stmt_info = dr_info->stmt;
vec_base_alignments *base_alignments = &vinfo->base_alignments;
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
class loop *loop = NULL;
tree ref = DR_REF (dr_info->dr);
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -991,8 +1032,9 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
bool step_preserves_misalignment_p;
poly_uint64 vector_alignment
- = exact_div (vect_calculate_target_alignment (dr_info), BITS_PER_UNIT);
- DR_TARGET_ALIGNMENT (dr_info) = vector_alignment;
+ = exact_div (targetm.vectorize.preferred_vector_alignment (vectype),
+ BITS_PER_UNIT);
+ SET_DR_TARGET_ALIGNMENT (dr_info, vector_alignment);
/* If the main loop has peeled for alignment we have no way of knowing
whether the data accesses in the epilogues are aligned. We can't at
@@ -1060,11 +1102,18 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
/* Calculate the maximum of the pooled base address alignment and the
alignment that we can compute for DR itself. */
- innermost_loop_behavior **entry = base_alignments->get (drb->base_address);
- if (entry && base_alignment < (*entry)->base_alignment)
+ std::pair<stmt_vec_info, innermost_loop_behavior *> *entry
+ = base_alignments->get (drb->base_address);
+ if (entry
+ && base_alignment < (*entry).second->base_alignment
+ && (loop_vinfo
+ || (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt_info->stmt),
+ gimple_bb (entry->first->stmt))
+ && (gimple_bb (stmt_info->stmt) != gimple_bb (entry->first->stmt)
+ || (entry->first->dr_aux.group <= dr_info->group)))))
{
- base_alignment = (*entry)->base_alignment;
- base_misalignment = (*entry)->base_misalignment;
+ base_alignment = entry->second->base_alignment;
+ base_misalignment = entry->second->base_misalignment;
}
if (drb->offset_alignment < vect_align_c
@@ -1107,14 +1156,6 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
poly_int64 misalignment
= base_misalignment + wi::to_poly_offset (drb->init).force_shwi ();
- /* If this is a backward running DR then first access in the larger
- vectype actually is N-1 elements before the address in the DR.
- Adjust misalign accordingly. */
- if (tree_int_cst_sgn (drb->step) < 0)
- /* PLUS because STEP is negative. */
- misalignment += ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
- * -TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
-
unsigned int const_misalignment;
if (!known_misalignment (misalignment, vect_align_c, &const_misalignment))
{
@@ -1129,7 +1170,7 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"misalign = %d bytes of ref %T\n",
- DR_MISALIGNMENT (dr_info), ref);
+ const_misalignment, ref);
return;
}
@@ -1173,6 +1214,29 @@ vect_dr_aligned_if_peeled_dr_is (dr_vec_info *dr_info,
return vect_dr_aligned_if_related_peeled_dr_is (dr_info, dr_peel_info);
}
+/* Compute the value for dr_info->misalign so that the access appears
+ aligned. This is used by peeling to compensate for dr_misalignment
+ applying the offset for negative step. */
+
+int
+vect_dr_misalign_for_aligned_access (dr_vec_info *dr_info)
+{
+ if (tree_int_cst_sgn (DR_STEP (dr_info->dr)) >= 0)
+ return 0;
+
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
+ poly_int64 misalignment
+ = ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
+ * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype))));
+
+ unsigned HOST_WIDE_INT target_alignment_c;
+ int misalign;
+ if (!dr_info->target_alignment.is_constant (&target_alignment_c)
+ || !known_misalignment (misalignment, target_alignment_c, &misalign))
+ return DR_MISALIGNMENT_UNKNOWN;
+ return misalign;
+}
+
/* Function vect_update_misalignment_for_peel.
Sets DR_INFO's misalignment
- to 0 if it has the same alignment as DR_PEEL_INFO,
@@ -1192,19 +1256,22 @@ vect_update_misalignment_for_peel (dr_vec_info *dr_info,
/* 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))
{
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr_peel_info));
return;
}
unsigned HOST_WIDE_INT alignment;
if (DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)
- && known_alignment_for_access_p (dr_info)
- && known_alignment_for_access_p (dr_peel_info))
+ && known_alignment_for_access_p (dr_info,
+ STMT_VINFO_VECTYPE (dr_info->stmt))
+ && known_alignment_for_access_p (dr_peel_info,
+ STMT_VINFO_VECTYPE (dr_peel_info->stmt)))
{
- int misal = DR_MISALIGNMENT (dr_info);
+ int misal = dr_info->misalignment;
misal += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr));
misal &= alignment - 1;
- SET_DR_MISALIGNMENT (dr_info, misal);
+ set_dr_misalignment (dr_info, misal);
return;
}
@@ -1276,13 +1343,13 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
int elem_size, mis_in_elements;
/* FORNOW: handle only known alignment. */
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
return false;
poly_uint64 nelements = TYPE_VECTOR_SUBPARTS (vectype);
poly_uint64 vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
elem_size = vector_element_size (vector_size, nelements);
- mis_in_elements = DR_MISALIGNMENT (dr_info) / elem_size;
+ mis_in_elements = dr_misalignment (dr_info, vectype) / elem_size;
if (!multiple_p (nelements - mis_in_elements, DR_GROUP_SIZE (stmt_info)))
return false;
@@ -1290,7 +1357,8 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
/* If misalignment is known at the compile time then allow peeling
only if natural alignment is reachable through peeling. */
- if (known_alignment_for_access_p (dr_info) && !aligned_access_p (dr_info))
+ if (known_alignment_for_access_p (dr_info, vectype)
+ && !aligned_access_p (dr_info, vectype))
{
HOST_WIDE_INT elmsize =
int_cst_value (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
@@ -1298,9 +1366,9 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
{
dump_printf_loc (MSG_NOTE, vect_location,
"data size = %wd. misalignment = %d.\n", elmsize,
- DR_MISALIGNMENT (dr_info));
+ dr_misalignment (dr_info, vectype));
}
- if (DR_MISALIGNMENT (dr_info) % elmsize)
+ if (dr_misalignment (dr_info, vectype) % elmsize)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1309,7 +1377,7 @@ vector_alignment_reachable_p (dr_vec_info *dr_info)
}
}
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
{
tree type = TREE_TYPE (DR_REF (dr_info->dr));
bool is_packed = not_size_aligned (DR_REF (dr_info->dr));
@@ -1401,8 +1469,9 @@ vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab,
{
struct _vect_peel_info elem, *slot;
_vect_peel_info **new_slot;
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
bool supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, true);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true);
elem.npeel = npeel;
slot = peeling_htab->find (&elem);
@@ -1447,7 +1516,8 @@ vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
/* Get the costs of peeling NPEEL iterations for LOOP_VINFO, checking
data access costs for all data refs. If UNKNOWN_MISALIGNMENT is true,
- we assume DR0_INFO's misalignment will be zero after peeling. */
+ npeel is computed at runtime but DR0_INFO's misalignment will be zero
+ after peeling. */
static void
vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
@@ -1468,11 +1538,12 @@ vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
continue;
int save_misalignment;
- save_misalignment = DR_MISALIGNMENT (dr_info);
+ save_misalignment = dr_info->misalignment;
if (npeel == 0)
;
else if (unknown_misalignment && dr_info == dr0_info)
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr0_info));
else
vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
vect_get_data_access_cost (loop_vinfo, dr_info, inside_cost, outside_cost,
@@ -1585,10 +1656,11 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info,
if (!vect_relevant_for_alignment_p (dr_info))
continue;
- save_misalignment = DR_MISALIGNMENT (dr_info);
+ save_misalignment = dr_info->misalignment;
vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, false);
SET_DR_MISALIGNMENT (dr_info, save_misalignment);
if (!supportable_dr_alignment)
@@ -1742,7 +1814,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
bool one_misalignment_unknown = false;
bool one_dr_unsupportable = false;
dr_vec_info *unsupportable_dr_info = NULL;
- unsigned int mis, dr0_same_align_drs = 0, first_store_same_align_drs = 0;
+ unsigned int dr0_same_align_drs = 0, first_store_same_align_drs = 0;
hash_table<peel_info_hasher> peeling_htab (1);
DUMP_VECT_SCOPE ("vect_enhance_data_refs_alignment");
@@ -1838,12 +1910,13 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
continue;
stmt_vec_info stmt_info = dr_info->stmt;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, true);
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true);
do_peeling = vector_alignment_reachable_p (dr_info);
if (do_peeling)
{
- if (known_alignment_for_access_p (dr_info))
+ if (known_alignment_for_access_p (dr_info, vectype))
{
unsigned int npeel_tmp = 0;
bool negative = tree_int_cst_compare (DR_STEP (dr),
@@ -1856,10 +1929,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unsigned int target_align =
DR_TARGET_ALIGNMENT (dr_info).to_constant ();
unsigned int dr_size = vect_get_scalar_dr_size (dr_info);
- mis = (negative
- ? DR_MISALIGNMENT (dr_info)
- : -DR_MISALIGNMENT (dr_info));
- if (DR_MISALIGNMENT (dr_info) != 0)
+ unsigned int mis = dr_misalignment (dr_info, vectype);
+ mis = negative ? mis : -mis;
+ if (mis != 0)
npeel_tmp = (mis & (target_align - 1)) / dr_size;
/* For multiple types, it is possible that the bigger type access
@@ -1942,7 +2014,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
else
{
- if (!aligned_access_p (dr_info))
+ if (!aligned_access_p (dr_info, vectype))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2112,7 +2184,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_peeling)
{
stmt_vec_info stmt_info = dr0_info->stmt;
- if (known_alignment_for_access_p (dr0_info))
+ if (known_alignment_for_access_p (dr0_info,
+ STMT_VINFO_VECTYPE (stmt_info)))
{
bool negative = tree_int_cst_compare (DR_STEP (dr0_info->dr),
size_zero_node) < 0;
@@ -2123,9 +2196,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
updating DR_MISALIGNMENT values. The peeling factor is the
vectorization factor minus the misalignment as an element
count. */
- mis = (negative
- ? DR_MISALIGNMENT (dr0_info)
- : -DR_MISALIGNMENT (dr0_info));
+ unsigned int mis
+ = dr_misalignment (dr0_info, STMT_VINFO_VECTYPE (stmt_info));
+ mis = negative ? mis : -mis;
/* If known_alignment_for_access_p then we have set
DR_MISALIGNMENT which is only done if we know it at compiler
time, so it is safe to assume target alignment is constant.
@@ -2152,7 +2225,10 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
do_peeling = false;
/* Check if all datarefs are supportable and log. */
- if (do_peeling && known_alignment_for_access_p (dr0_info) && npeel == 0)
+ if (do_peeling
+ && npeel == 0
+ && known_alignment_for_access_p (dr0_info,
+ STMT_VINFO_VECTYPE (stmt_info)))
return opt_result::success ();
/* Cost model #1 - honor --param vect-max-peeling-for-alignment. */
@@ -2160,7 +2236,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 (loop_cost_model (loop) <= VECT_COST_MODEL_CHEAP)
max_allowed_peel = 0;
if (max_allowed_peel != (unsigned)-1)
{
@@ -2228,9 +2304,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (npeel)
LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = npeel;
else
- LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
- = DR_MISALIGNMENT (dr0_info);
- SET_DR_MISALIGNMENT (dr0_info, 0);
+ LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = -1;
+ SET_DR_MISALIGNMENT (dr0_info,
+ vect_dr_misalign_for_aligned_access (dr0_info));
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
@@ -2258,18 +2334,19 @@ 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);
+ && loop_cost_model (loop) > VECT_COST_MODEL_CHEAP);
if (do_versioning)
{
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
- if (aligned_access_p (dr_info)
+ stmt_vec_info stmt_info = dr_info->stmt;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (aligned_access_p (dr_info, vectype)
|| !vect_relevant_for_alignment_p (dr_info))
continue;
- stmt_vec_info stmt_info = dr_info->stmt;
if (STMT_VINFO_STRIDED_P (stmt_info))
{
do_versioning = false;
@@ -2277,14 +2354,11 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
supportable_dr_alignment
- = vect_supportable_dr_alignment (loop_vinfo, dr_info, false);
-
+ = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype,
+ false);
if (!supportable_dr_alignment)
{
- int mask;
- tree vectype;
-
- if (known_alignment_for_access_p (dr_info)
+ if (known_alignment_for_access_p (dr_info, vectype)
|| LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length ()
>= (unsigned) param_vect_max_version_for_alignment_checks)
{
@@ -2292,9 +2366,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
break;
}
- vectype = STMT_VINFO_VECTYPE (stmt_info);
- gcc_assert (vectype);
-
/* At present we don't support versioning for alignment
with variable VF, since there's no guarantee that the
VF is a power of two. We could relax this if we added
@@ -2324,7 +2395,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
Construct the mask needed for this test. For example,
GET_MODE_SIZE for the vector mode V4SI is 16 bytes so the
mask must be 15 = 0xf. */
- mask = size - 1;
+ int mask = size - 1;
/* FORNOW: use the same mask to test all potentially unaligned
references in the loop. */
@@ -2359,7 +2430,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt_info)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
- SET_DR_MISALIGNMENT (dr_info, 0);
+ SET_DR_MISALIGNMENT (dr_info,
+ vect_dr_misalign_for_aligned_access (dr_info));
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"Alignment of access forced using versioning.\n");
@@ -2401,7 +2473,13 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
{
dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
if (STMT_VINFO_VECTORIZABLE (dr_info->stmt))
- vect_compute_data_ref_alignment (loop_vinfo, dr_info);
+ {
+ if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt)
+ && DR_GROUP_FIRST_ELEMENT (dr_info->stmt) != dr_info->stmt)
+ continue;
+ vect_compute_data_ref_alignment (loop_vinfo, dr_info,
+ STMT_VINFO_VECTYPE (dr_info->stmt));
+ }
}
return opt_result::success ();
@@ -2413,42 +2491,33 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
static bool
vect_slp_analyze_node_alignment (vec_info *vinfo, slp_tree node)
{
- /* We vectorize from the first scalar stmt in the node unless
- the node is permuted in which case we start from the first
- element in the group. */
+ /* Alignment is maintained in the first element of the group. */
stmt_vec_info first_stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
- dr_vec_info *first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
- if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
- first_stmt_info = DR_GROUP_FIRST_ELEMENT (first_stmt_info);
-
- /* 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)))
- {
- 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;
- }
-
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (first_stmt_info);
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
- vect_compute_data_ref_alignment (vinfo, dr_info);
- /* In several places we need alignment of the first element anyway. */
- if (dr_info != first_dr_info)
- vect_compute_data_ref_alignment (vinfo, first_dr_info);
-
- /* For creating the data-ref pointer we need alignment of the
- first element as well. */
- 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])
+ tree vectype = SLP_TREE_VECTYPE (node);
+ poly_uint64 vector_alignment
+ = exact_div (targetm.vectorize.preferred_vector_alignment (vectype),
+ BITS_PER_UNIT);
+ if (dr_info->misalignment == DR_MISALIGNMENT_UNINITIALIZED)
+ vect_compute_data_ref_alignment (vinfo, dr_info, SLP_TREE_VECTYPE (node));
+ /* Re-analyze alignment when we're facing a vectorization with a bigger
+ alignment requirement. */
+ else if (known_lt (dr_info->target_alignment, vector_alignment))
{
- first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
- if (dr_info != first_dr_info)
- vect_compute_data_ref_alignment (vinfo, first_dr_info);
+ poly_uint64 old_target_alignment = dr_info->target_alignment;
+ int old_misalignment = dr_info->misalignment;
+ vect_compute_data_ref_alignment (vinfo, dr_info, SLP_TREE_VECTYPE (node));
+ /* But keep knowledge about a smaller alignment. */
+ if (old_misalignment != DR_MISALIGNMENT_UNKNOWN
+ && dr_info->misalignment == DR_MISALIGNMENT_UNKNOWN)
+ {
+ dr_info->target_alignment = old_target_alignment;
+ dr_info->misalignment = old_misalignment;
+ }
}
-
+ /* When we ever face unordered target alignments the first one wins in terms
+ of analyzing and the other will become unknown in dr_misalignment. */
return true;
}
@@ -2813,18 +2882,16 @@ vect_analyze_data_ref_access (vec_info *vinfo, dr_vec_info *dr_info)
return vect_analyze_group_access (vinfo, dr_info);
}
-typedef std::pair<data_reference_p, int> data_ref_pair;
-
/* Compare two data-references DRA and DRB to group them into chunks
suitable for grouping. */
static int
dr_group_sort_cmp (const void *dra_, const void *drb_)
{
- data_ref_pair dra_pair = *(data_ref_pair *)const_cast<void *>(dra_);
- data_ref_pair drb_pair = *(data_ref_pair *)const_cast<void *>(drb_);
- data_reference_p dra = dra_pair.first;
- data_reference_p drb = drb_pair.first;
+ dr_vec_info *dra_info = *(dr_vec_info **)const_cast<void *>(dra_);
+ dr_vec_info *drb_info = *(dr_vec_info **)const_cast<void *>(drb_);
+ data_reference_p dra = dra_info->dr;
+ data_reference_p drb = drb_info->dr;
int cmp;
/* Stabilize sort. */
@@ -2832,8 +2899,8 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
return 0;
/* Different group IDs lead never belong to the same group. */
- if (dra_pair.second != drb_pair.second)
- return dra_pair.second < drb_pair.second ? -1 : 1;
+ if (dra_info->group != drb_info->group)
+ return dra_info->group < drb_info->group ? -1 : 1;
/* Ordering of DRs according to base. */
cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2953,18 +3020,18 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Sort the array of datarefs to make building the interleaving chains
linear. Don't modify the original vector's order, it is needed for
determining what dependencies are reversed. */
- vec<data_ref_pair> datarefs_copy;
+ vec<dr_vec_info *> datarefs_copy;
datarefs_copy.create (datarefs.length ());
for (unsigned i = 0; i < datarefs.length (); i++)
{
- int group_id;
+ dr_vec_info *dr_info = vinfo->lookup_dr (datarefs[i]);
/* If the caller computed DR grouping use that, otherwise group by
basic blocks. */
if (dataref_groups)
- group_id = (*dataref_groups)[i];
+ dr_info->group = (*dataref_groups)[i];
else
- group_id = gimple_bb (DR_STMT (datarefs[i]))->index;
- datarefs_copy.quick_push (data_ref_pair (datarefs[i], group_id));
+ dr_info->group = gimple_bb (DR_STMT (datarefs[i]))->index;
+ datarefs_copy.quick_push (dr_info);
}
datarefs_copy.qsort (dr_group_sort_cmp);
hash_set<stmt_vec_info> to_fixup;
@@ -2972,9 +3039,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Build the interleaving chains. */
for (i = 0; i < datarefs_copy.length () - 1;)
{
- data_reference_p dra = datarefs_copy[i].first;
- int dra_group_id = datarefs_copy[i].second;
- dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
+ dr_vec_info *dr_info_a = datarefs_copy[i];
+ data_reference_p dra = dr_info_a->dr;
+ int dra_group_id = dr_info_a->group;
stmt_vec_info stmtinfo_a = dr_info_a->stmt;
stmt_vec_info lastinfo = NULL;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
@@ -2985,9 +3052,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
}
for (i = i + 1; i < datarefs_copy.length (); ++i)
{
- data_reference_p drb = datarefs_copy[i].first;
- int drb_group_id = datarefs_copy[i].second;
- dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
+ dr_vec_info *dr_info_b = datarefs_copy[i];
+ data_reference_p drb = dr_info_b->dr;
+ int drb_group_id = dr_info_b->group;
stmt_vec_info stmtinfo_b = dr_info_b->stmt;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
@@ -3048,7 +3115,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
HOST_WIDE_INT init_a = TREE_INT_CST_LOW (DR_INIT (dra));
HOST_WIDE_INT init_b = TREE_INT_CST_LOW (DR_INIT (drb));
HOST_WIDE_INT init_prev
- = TREE_INT_CST_LOW (DR_INIT (datarefs_copy[i-1].first));
+ = TREE_INT_CST_LOW (DR_INIT (datarefs_copy[i-1]->dr));
gcc_assert (init_a <= init_b
&& init_a <= init_prev
&& init_prev <= init_b);
@@ -3056,7 +3123,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Do not place the same access in the interleaving chain twice. */
if (init_b == init_prev)
{
- gcc_assert (gimple_uid (DR_STMT (datarefs_copy[i-1].first))
+ gcc_assert (gimple_uid (DR_STMT (datarefs_copy[i-1]->dr))
< gimple_uid (DR_STMT (drb)));
/* Simply link in duplicates and fix up the chain below. */
}
@@ -3169,10 +3236,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
to_fixup.add (newgroup);
}
- data_ref_pair *dr_pair;
- FOR_EACH_VEC_ELT (datarefs_copy, i, dr_pair)
+ dr_vec_info *dr_info;
+ FOR_EACH_VEC_ELT (datarefs_copy, i, dr_info)
{
- dr_vec_info *dr_info = vinfo->lookup_dr (dr_pair->first);
if (STMT_VINFO_VECTORIZABLE (dr_info->stmt)
&& !vect_analyze_data_ref_access (vinfo, dr_info))
{
@@ -3236,12 +3302,12 @@ vect_vfa_access_size (vec_info *vinfo, dr_vec_info *dr_info)
gcc_assert (DR_GROUP_FIRST_ELEMENT (stmt_vinfo) == stmt_vinfo);
access_size *= DR_GROUP_SIZE (stmt_vinfo) - DR_GROUP_GAP (stmt_vinfo);
}
+ tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
if (STMT_VINFO_VEC_STMTS (stmt_vinfo).exists ()
- && (vect_supportable_dr_alignment (vinfo, dr_info, false)
+ && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, false)
== dr_explicit_realign_optimized))
{
/* We might access a full vector's worth. */
- tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
access_size += tree_to_uhwi (TYPE_SIZE_UNIT (vectype)) - ref_size;
}
return access_size;
@@ -3685,7 +3751,9 @@ 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)
+ if (count
+ && (loop_cost_model (LOOP_VINFO_LOOP (loop_vinfo))
+ == VECT_COST_MODEL_VERY_CHEAP))
return opt_result::failure_at
(vect_location, "would need a runtime alias check\n");
@@ -3694,7 +3762,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
"improved number of alias checks from %d to %d\n",
may_alias_ddrs.length (), count);
unsigned limit = param_vect_max_version_for_alias_checks;
- if (flag_simd_cost_model == VECT_COST_MODEL_CHEAP)
+ if (loop_cost_model (LOOP_VINFO_LOOP (loop_vinfo)) == VECT_COST_MODEL_CHEAP)
limit = param_vect_max_version_for_alias_checks * 6 / 10;
if (count > limit)
return opt_result::failure_at
@@ -4606,19 +4674,15 @@ vect_get_new_ssa_name (tree type, enum vect_var_kind var_kind, const char *name)
return new_vect_var;
}
-/* Duplicate ptr info and set alignment/misaligment on NAME from DR_INFO. */
+/* Duplicate points-to info on NAME from DR_INFO. */
static void
vect_duplicate_ssa_name_ptr_info (tree name, dr_vec_info *dr_info)
{
duplicate_ssa_name_ptr_info (name, DR_PTR_INFO (dr_info->dr));
- int misalign = DR_MISALIGNMENT (dr_info);
- if (misalign == DR_MISALIGNMENT_UNKNOWN)
- mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
- else
- set_ptr_info_alignment (SSA_NAME_PTR_INFO (name),
- known_alignment (DR_TARGET_ALIGNMENT (dr_info)),
- misalign);
+ /* DR_PTR_INFO is for a base SSA name, not including constant or
+ variable offsets in the ref so its alignment info does not apply. */
+ mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
}
/* Function vect_create_addr_base_for_vector_ref.
@@ -4714,18 +4778,18 @@ vect_create_addr_base_for_vector_ref (vec_info *vinfo, stmt_vec_info stmt_info,
unshare_expr (DR_REF (dr)));
}
- vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
+ vect_ptr_type = build_pointer_type (TREE_TYPE (DR_REF (dr)));
dest = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, base_name);
addr_base = force_gimple_operand (addr_base, &seq, true, dest);
gimple_seq_add_seq (new_stmt_list, seq);
if (DR_PTR_INFO (dr)
&& TREE_CODE (addr_base) == SSA_NAME
- && !SSA_NAME_PTR_INFO (addr_base))
+ /* We should only duplicate pointer info to newly created SSA names. */
+ && SSA_NAME_VAR (addr_base) == dest)
{
+ gcc_assert (!SSA_NAME_PTR_INFO (addr_base));
vect_duplicate_ssa_name_ptr_info (addr_base, dr_info);
- if (offset || byte_offset)
- mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (addr_base));
}
if (dump_enabled_p ())
@@ -6565,17 +6629,16 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment)
enum dr_alignment_support
vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
- bool check_aligned_accesses)
+ tree vectype, bool check_aligned_accesses)
{
data_reference *dr = dr_info->dr;
stmt_vec_info stmt_info = dr_info->stmt;
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
machine_mode mode = TYPE_MODE (vectype);
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
class loop *vect_loop = NULL;
bool nested_in_vect_loop = false;
- if (aligned_access_p (dr_info) && !check_aligned_accesses)
+ if (aligned_access_p (dr_info, vectype) && !check_aligned_accesses)
return dr_aligned;
/* For now assume all conditional loads/stores support unaligned
@@ -6664,8 +6727,6 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
&& (!targetm.vectorize.builtin_mask_for_load
|| targetm.vectorize.builtin_mask_for_load ()))
{
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
-
/* If we are doing SLP then the accesses need not have the
same alignment, instead it depends on the SLP group size. */
if (loop_vinfo
@@ -6683,11 +6744,11 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
else
return dr_explicit_realign_optimized;
}
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
+ (mode, type, dr_misalignment (dr_info, vectype), is_packed))
/* Can't software pipeline the loads, but can at least do them. */
return dr_unaligned_supported;
}
@@ -6696,11 +6757,11 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
bool is_packed = false;
tree type = (TREE_TYPE (DR_REF (dr)));
- if (!known_alignment_for_access_p (dr_info))
+ if (!known_alignment_for_access_p (dr_info, vectype))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
+ (mode, type, dr_misalignment (dr_info, vectype), is_packed))
return dr_unaligned_supported;
}
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 0c8d992..961c162 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1850,7 +1850,7 @@ 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
+ if (loop_cost_model (loop) == 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)))
@@ -1922,7 +1922,7 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
/* 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
+ if (loop_cost_model (loop) == VECT_COST_MODEL_VERY_CHEAP
&& min_profitable_estimate > (int) vect_vf_for_cost (loop_vinfo))
{
if (dump_enabled_p ())
@@ -2047,6 +2047,7 @@ vect_dissolve_slp_only_groups (loop_vec_info loop_vinfo)
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
stmt_vec_info first_element = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_element);
unsigned int group_size = DR_GROUP_SIZE (first_element);
/* Check if SLP-only groups. */
@@ -2067,6 +2068,24 @@ vect_dissolve_slp_only_groups (loop_vec_info loop_vinfo)
DR_GROUP_GAP (vinfo) = 0;
else
DR_GROUP_GAP (vinfo) = group_size - 1;
+ /* Duplicate and adjust alignment info, it needs to
+ be present on each group leader, see dr_misalignment. */
+ if (vinfo != first_element)
+ {
+ dr_vec_info *dr_info2 = STMT_VINFO_DR_INFO (vinfo);
+ dr_info2->target_alignment = dr_info->target_alignment;
+ int misalignment = dr_info->misalignment;
+ if (misalignment != DR_MISALIGNMENT_UNKNOWN)
+ {
+ HOST_WIDE_INT diff
+ = (TREE_INT_CST_LOW (DR_INIT (dr_info2->dr))
+ - TREE_INT_CST_LOW (DR_INIT (dr_info->dr)));
+ unsigned HOST_WIDE_INT align_c
+ = dr_info->target_alignment.to_constant ();
+ misalignment = (misalignment + diff) % align_c;
+ }
+ dr_info2->misalignment = misalignment;
+ }
vinfo = next;
}
}
@@ -7755,9 +7774,18 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo,
(reduc_info),
&stmts);
}
+ /* The epilogue loop might use a different vector mode, like
+ VNx2DI vs. V2DI. */
+ if (TYPE_MODE (vectype_out) != TYPE_MODE (TREE_TYPE (def)))
+ {
+ tree reduc_type = build_vector_type_for_mode
+ (TREE_TYPE (TREE_TYPE (def)), TYPE_MODE (vectype_out));
+ def = gimple_convert (&stmts, reduc_type, def);
+ }
/* Adjust the input so we pick up the partially reduced value
for the skip edge in vect_create_epilog_for_reduction. */
accumulator->reduc_input = def;
+ /* And the reduction could be carried out using a different sign. */
if (!useless_type_conversion_p (vectype_out, TREE_TYPE (def)))
def = gimple_convert (&stmts, vectype_out, def);
if (loop_vinfo->main_loop_edge)
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 8997340..854cbcf 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -119,8 +119,9 @@ vect_init_pattern_stmt (vec_info *vinfo, gimple *pattern_stmt,
= STMT_VINFO_DEF_TYPE (orig_stmt_info);
if (!STMT_VINFO_VECTYPE (pattern_stmt_info))
{
- gcc_assert (VECTOR_BOOLEAN_TYPE_P (vectype)
- == vect_use_mask_type_p (orig_stmt_info));
+ gcc_assert (!vectype
+ || (VECTOR_BOOLEAN_TYPE_P (vectype)
+ == vect_use_mask_type_p (orig_stmt_info)));
STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype;
pattern_stmt_info->mask_precision = orig_stmt_info->mask_precision;
}
@@ -1268,11 +1269,31 @@ vect_recog_widen_op_pattern (vec_info *vinfo,
/* Check target support */
tree vectype = get_vectype_for_scalar_type (vinfo, half_type);
tree vecitype = get_vectype_for_scalar_type (vinfo, itype);
+ tree ctype = itype;
+ tree vecctype = vecitype;
+ if (orig_code == MINUS_EXPR
+ && TYPE_UNSIGNED (itype)
+ && TYPE_PRECISION (type) > TYPE_PRECISION (itype))
+ {
+ /* Subtraction is special, even if half_type is unsigned and no matter
+ whether type is signed or unsigned, if type is wider than itype,
+ we need to sign-extend from the widening operation result to the
+ result type.
+ Consider half_type unsigned char, operand 1 0xfe, operand 2 0xff,
+ itype unsigned short and type either int or unsigned int.
+ Widened (unsigned short) 0xfe - (unsigned short) 0xff is
+ (unsigned short) 0xffff, but for type int we want the result -1
+ and for type unsigned int 0xffffffff rather than 0xffff. */
+ ctype = build_nonstandard_integer_type (TYPE_PRECISION (itype), 0);
+ vecctype = get_vectype_for_scalar_type (vinfo, ctype);
+ }
+
enum tree_code dummy_code;
int dummy_int;
auto_vec<tree> dummy_vec;
if (!vectype
|| !vecitype
+ || !vecctype
|| !supportable_widening_operation (vinfo, wide_code, last_stmt_info,
vecitype, vectype,
&dummy_code, &dummy_code,
@@ -1291,8 +1312,12 @@ vect_recog_widen_op_pattern (vec_info *vinfo,
gimple *pattern_stmt = gimple_build_assign (var, wide_code,
oprnd[0], oprnd[1]);
+ if (vecctype != vecitype)
+ pattern_stmt = vect_convert_output (vinfo, last_stmt_info, ctype,
+ pattern_stmt, vecitype);
+
return vect_convert_output (vinfo, last_stmt_info,
- type, pattern_stmt, vecitype);
+ type, pattern_stmt, vecctype);
}
/* Try to detect multiplication on widened inputs, converting MULT_EXPR
@@ -4259,8 +4284,6 @@ vect_recog_bool_pattern (vec_info *vinfo,
|| VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
return NULL;
vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
- if (vectype == NULL_TREE)
- return NULL;
if (check_bool_pattern (var, vinfo, bool_stmts))
{
@@ -5672,7 +5695,6 @@ vect_pattern_recog_1 (vec_info *vinfo,
}
loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
- gcc_assert (pattern_vectype);
/* Found a vectorizable pattern. */
if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 4d688c7..709bcb6 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -779,56 +779,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
return 0;
}
-/* Try to assign vector type VECTYPE to STMT_INFO for BB vectorization.
- Return true if we can, meaning that this choice doesn't conflict with
- existing SLP nodes that use STMT_INFO. */
-
-bool
-vect_update_shared_vectype (stmt_vec_info stmt_info, tree vectype)
-{
- tree old_vectype = STMT_VINFO_VECTYPE (stmt_info);
- if (old_vectype)
- return useless_type_conversion_p (vectype, old_vectype);
-
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- {
- /* We maintain the invariant that if any statement in the group is
- used, all other members of the group have the same vector type. */
- stmt_vec_info first_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
- stmt_vec_info member_info = first_info;
- for (; member_info; member_info = DR_GROUP_NEXT_ELEMENT (member_info))
- if (is_pattern_stmt_p (member_info)
- && !useless_type_conversion_p (vectype,
- STMT_VINFO_VECTYPE (member_info)))
- break;
-
- if (!member_info)
- {
- for (member_info = first_info; member_info;
- member_info = DR_GROUP_NEXT_ELEMENT (member_info))
- STMT_VINFO_VECTYPE (member_info) = vectype;
- return true;
- }
- }
- else if (!is_pattern_stmt_p (stmt_info))
- {
- STMT_VINFO_VECTYPE (stmt_info) = vectype;
- return true;
- }
-
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: incompatible vector"
- " types for: %G", stmt_info->stmt);
- dump_printf_loc (MSG_NOTE, vect_location,
- " old vector type: %T\n", old_vectype);
- dump_printf_loc (MSG_NOTE, vect_location,
- " new vector type: %T\n", vectype);
- }
- return false;
-}
-
/* Return true if call statements CALL1 and CALL2 are similar enough
to be combined into the same SLP group. */
@@ -1811,6 +1761,7 @@ vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node,
bit_field_size (bfref), &lane))
{
lperm.release ();
+ matches[0] = false;
return NULL;
}
lperm.safe_push (std::make_pair (0, (unsigned)lane));
@@ -4508,15 +4459,6 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
return vectorizable_slp_permutation (vinfo, NULL, node, cost_vec);
gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
- if (is_a <bb_vec_info> (vinfo)
- && !vect_update_shared_vectype (stmt_info, SLP_TREE_VECTYPE (node)))
- {
- 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,
@@ -5104,6 +5046,42 @@ vect_bb_partition_graph (bb_vec_info bb_vinfo)
}
}
+/* Compute the set of scalar stmts participating in internal and external
+ nodes. */
+
+static void
+vect_slp_gather_vectorized_scalar_stmts (vec_info *vinfo, slp_tree node,
+ hash_set<slp_tree> &visited,
+ hash_set<stmt_vec_info> &vstmts,
+ hash_set<stmt_vec_info> &estmts)
+{
+ int i;
+ stmt_vec_info stmt_info;
+ slp_tree child;
+
+ if (visited.add (node))
+ return;
+
+ if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
+ {
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ vstmts.add (stmt_info);
+
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ if (child)
+ vect_slp_gather_vectorized_scalar_stmts (vinfo, child, visited,
+ vstmts, estmts);
+ }
+ else
+ for (tree def : SLP_TREE_SCALAR_OPS (node))
+ {
+ stmt_vec_info def_stmt = vinfo->lookup_def (def);
+ if (def_stmt)
+ estmts.add (def_stmt);
+ }
+}
+
+
/* Compute the scalar cost of the SLP node NODE and its children
and return it. Do not account defs that are marked in LIFE and
update LIFE according to uses of NODE. */
@@ -5112,6 +5090,7 @@ static void
vect_bb_slp_scalar_cost (vec_info *vinfo,
slp_tree node, vec<bool, va_heap> *life,
stmt_vector_for_cost *cost_vec,
+ hash_set<stmt_vec_info> &vectorized_scalar_stmts,
hash_set<slp_tree> &visited)
{
unsigned i;
@@ -5148,8 +5127,7 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
{
stmt_vec_info use_stmt_info = vinfo->lookup_stmt (use_stmt);
if (!use_stmt_info
- || !PURE_SLP_STMT
- (vect_stmt_to_vectorize (use_stmt_info)))
+ || !vectorized_scalar_stmts.contains (use_stmt_info))
{
(*life)[i] = true;
break;
@@ -5212,7 +5190,7 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
subtree_life.safe_splice (*life);
}
vect_bb_slp_scalar_cost (vinfo, child, &subtree_life, cost_vec,
- visited);
+ vectorized_scalar_stmts, visited);
subtree_life.truncate (0);
}
}
@@ -5254,11 +5232,33 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
SLP_INSTANCE_TREE (instance), visited);
}
+ /* Compute the set of scalar stmts we know will go away 'locally' when
+ vectorizing. This used to be tracked with just PURE_SLP_STMT but that's
+ not accurate for nodes promoted extern late or for scalar stmts that
+ are used both in extern defs and in vectorized defs. */
+ hash_set<stmt_vec_info> vectorized_scalar_stmts;
+ hash_set<stmt_vec_info> scalar_stmts_in_externs;
+ hash_set<slp_tree> visited;
+ FOR_EACH_VEC_ELT (slp_instances, i, instance)
+ {
+ vect_slp_gather_vectorized_scalar_stmts (bb_vinfo,
+ SLP_INSTANCE_TREE (instance),
+ visited,
+ vectorized_scalar_stmts,
+ scalar_stmts_in_externs);
+ for (stmt_vec_info rstmt : SLP_INSTANCE_ROOT_STMTS (instance))
+ vectorized_scalar_stmts.add (rstmt);
+ }
+ /* Scalar stmts used as defs in external nodes need to be preseved, so
+ remove them from vectorized_scalar_stmts. */
+ for (stmt_vec_info stmt : scalar_stmts_in_externs)
+ vectorized_scalar_stmts.remove (stmt);
+
/* Calculate scalar cost and sum the cost for the vector stmts
previously collected. */
stmt_vector_for_cost scalar_costs = vNULL;
stmt_vector_for_cost vector_costs = vNULL;
- hash_set<slp_tree> visited;
+ visited.empty ();
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
auto_vec<bool, 20> life;
@@ -5271,38 +5271,11 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
SLP_INSTANCE_ROOT_STMTS (instance)[0], 0, vect_body);
vect_bb_slp_scalar_cost (bb_vinfo,
SLP_INSTANCE_TREE (instance),
- &life, &scalar_costs, visited);
+ &life, &scalar_costs, vectorized_scalar_stmts,
+ visited);
vector_costs.safe_splice (instance->cost_vec);
instance->cost_vec.release ();
}
- /* When we're vectorizing an if-converted loop body with the
- very-cheap cost model make sure we vectorized all if-converted
- code. */
- bool force_not_profitable = false;
- if (orig_loop && flag_vect_cost_model == VECT_COST_MODEL_VERY_CHEAP)
- {
- gcc_assert (bb_vinfo->bbs.length () == 1);
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb_vinfo->bbs[0]);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- /* The costing above left us with DCEable vectorized scalar
- stmts having the visited flag set. */
- if (gimple_visited_p (gsi_stmt (gsi)))
- continue;
-
- if (gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi)))
- if (gimple_assign_rhs_code (ass) == COND_EXPR)
- {
- force_not_profitable = true;
- break;
- }
- }
- }
-
- /* Unset visited flag. */
- stmt_info_for_cost *cost;
- FOR_EACH_VEC_ELT (scalar_costs, i, cost)
- gimple_set_visited (cost->stmt_info->stmt, false);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "Cost model analysis: \n");
@@ -5319,6 +5292,7 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
li_scalar_costs (scalar_costs.length ());
auto_vec<std::pair<unsigned, stmt_info_for_cost *> >
li_vector_costs (vector_costs.length ());
+ stmt_info_for_cost *cost;
FOR_EACH_VEC_ELT (scalar_costs, i, cost)
{
unsigned l = gimple_bb (cost->stmt_info->stmt)->loop_father->num;
@@ -5341,6 +5315,7 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
/* Now cost the portions individually. */
unsigned vi = 0;
unsigned si = 0;
+ bool profitable = true;
while (si < li_scalar_costs.length ()
&& vi < li_vector_costs.length ())
{
@@ -5407,30 +5382,29 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
example). */
if (vec_outside_cost + vec_inside_cost > scalar_cost)
{
- scalar_costs.release ();
- vector_costs.release ();
- return false;
+ profitable = false;
+ break;
}
}
- if (vi < li_vector_costs.length ())
+ if (profitable && vi < li_vector_costs.length ())
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"Excess vector cost for part in loop %d:\n",
li_vector_costs[vi].first);
- scalar_costs.release ();
- vector_costs.release ();
- return false;
+ profitable = false;
}
- if (dump_enabled_p () && force_not_profitable)
- dump_printf_loc (MSG_NOTE, vect_location,
- "not profitable because of unprofitable if-converted "
- "scalar code\n");
+ /* Unset visited flag. This is delayed when the subgraph is profitable
+ and we process the loop for remaining unvectorized if-converted code. */
+ if (!orig_loop || !profitable)
+ FOR_EACH_VEC_ELT (scalar_costs, i, cost)
+ gimple_set_visited (cost->stmt_info->stmt, false);
scalar_costs.release ();
vector_costs.release ();
- return !force_not_profitable;
+
+ return profitable;
}
/* qsort comparator for lane defs. */
@@ -5884,9 +5858,8 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
bb_vinfo->shared->check_datarefs ();
- unsigned i;
- slp_instance instance;
- FOR_EACH_VEC_ELT (BB_VINFO_SLP_INSTANCES (bb_vinfo), i, instance)
+ auto_vec<slp_instance> profitable_subgraphs;
+ for (slp_instance instance : BB_VINFO_SLP_INSTANCES (bb_vinfo))
{
if (instance->subgraph_entries.is_empty ())
continue;
@@ -5894,9 +5867,7 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
vect_location = instance->location ();
if (!unlimited_cost_model (NULL)
&& !vect_bb_vectorization_profitable_p
- (bb_vinfo,
- orig_loop ? BB_VINFO_SLP_INSTANCES (bb_vinfo)
- : instance->subgraph_entries, orig_loop))
+ (bb_vinfo, instance->subgraph_entries, orig_loop))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -5908,15 +5879,54 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
if (!dbg_cnt (vect_slp))
continue;
+ profitable_subgraphs.safe_push (instance);
+ }
+
+ /* When we're vectorizing an if-converted loop body with the
+ very-cheap cost model make sure we vectorized all if-converted
+ code. */
+ if (!profitable_subgraphs.is_empty ()
+ && orig_loop)
+ {
+ gcc_assert (bb_vinfo->bbs.length () == 1);
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb_vinfo->bbs[0]);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ /* The costing above left us with DCEable vectorized scalar
+ stmts having the visited flag set on profitable
+ subgraphs. Do the delayed clearing of the flag here. */
+ if (gimple_visited_p (gsi_stmt (gsi)))
+ {
+ gimple_set_visited (gsi_stmt (gsi), false);
+ continue;
+ }
+ if (flag_vect_cost_model != VECT_COST_MODEL_VERY_CHEAP)
+ continue;
+
+ if (gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi)))
+ if (gimple_assign_rhs_code (ass) == COND_EXPR)
+ {
+ if (!profitable_subgraphs.is_empty ()
+ && dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "not profitable because of "
+ "unprofitable if-converted scalar "
+ "code\n");
+ profitable_subgraphs.truncate (0);
+ }
+ }
+ }
+
+ /* Finally schedule the profitable subgraphs. */
+ for (slp_instance instance : profitable_subgraphs)
+ {
if (!vectorized && dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"Basic block will be vectorized "
"using SLP\n");
vectorized = true;
- vect_schedule_slp (bb_vinfo,
- orig_loop ? BB_VINFO_SLP_INSTANCES (bb_vinfo)
- : instance->subgraph_entries);
+ vect_schedule_slp (bb_vinfo, instance->subgraph_entries);
unsigned HOST_WIDE_INT bytes;
if (dump_enabled_p ())
@@ -5931,11 +5941,6 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
"basic block part vectorized using "
"variable length vectors\n");
}
-
- /* When we're called from loop vectorization we're considering
- all subgraphs at once. */
- if (orig_loop)
- break;
}
}
else
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 4e0b2ad..f5e1941 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1026,8 +1026,9 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
stmt_vector_for_cost *body_cost_vec)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
int alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false);
switch (alignment_support_scheme)
{
@@ -1048,7 +1049,7 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned store. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_store, stmt_info,
- DR_MISALIGNMENT (dr_info),
+ dr_misalignment (dr_info, vectype),
vect_body);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1216,8 +1217,9 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
bool record_prologue_costs)
{
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
int alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false);
switch (alignment_support_scheme)
{
@@ -1237,7 +1239,7 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned load. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_load, stmt_info,
- DR_MISALIGNMENT (dr_info),
+ dr_misalignment (dr_info, vectype),
vect_body);
if (dump_enabled_p ())
@@ -1984,8 +1986,8 @@ get_negative_load_store_type (vec_info *vinfo,
return VMAT_ELEMENTWISE;
}
- alignment_support_scheme = vect_supportable_dr_alignment (vinfo,
- dr_info, false);
+ alignment_support_scheme = vect_supportable_dr_alignment (vinfo, dr_info,
+ vectype, false);
if (alignment_support_scheme != dr_aligned
&& alignment_support_scheme != dr_unaligned_supported)
{
@@ -2169,7 +2171,8 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
be a multiple of B and so we are guaranteed to access a
non-gap element in the same B-sized block. */
if (overrun_p
- && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ && gap < (vect_known_alignment_in_bytes (first_dr_info,
+ vectype)
/ vect_get_scalar_dr_size (first_dr_info)))
overrun_p = false;
@@ -2182,8 +2185,8 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
if (overrun_p
&& !masked_p
&& (((alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo,
- first_dr_info, false)))
+ = vect_supportable_dr_alignment (vinfo, first_dr_info,
+ vectype, false)))
== dr_aligned
|| alignment_support_scheme == dr_unaligned_supported)
&& known_eq (nunits, (group_size - gap) * 2)
@@ -2240,7 +2243,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
same B-sized block. */
if (would_overrun_p
&& !masked_p
- && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ && gap < (vect_known_alignment_in_bytes (first_dr_info, vectype)
/ vect_get_scalar_dr_size (first_dr_info)))
would_overrun_p = false;
@@ -2294,7 +2297,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
*alignment_support_scheme = dr_unaligned_supported;
else
*alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, first_dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false);
if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
{
@@ -2435,7 +2438,7 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
*alignment_support_scheme
= vect_supportable_dr_alignment (vinfo,
STMT_VINFO_DR_INFO (stmt_info),
- false);
+ vectype, false);
}
}
@@ -2788,7 +2791,7 @@ vect_build_gather_load_calls (vec_info *vinfo, stmt_vec_info stmt_info,
if (mask)
vect_get_vec_defs_for_operand (vinfo, stmt_info,
modifier == NARROW ? ncopies / 2 : ncopies,
- mask, &vec_masks);
+ mask, &vec_masks, masktype);
for (int j = 0; j < ncopies; ++j)
{
tree op, var;
@@ -7907,7 +7910,7 @@ vectorizable_store (vec_info *vinfo,
alignment_support_scheme = dr_unaligned_supported;
else
alignment_support_scheme
- = vect_supportable_dr_alignment (vinfo, first_dr_info, false);
+ = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false);
gcc_assert (alignment_support_scheme);
vec_loop_masks *loop_masks
@@ -8218,15 +8221,16 @@ vectorizable_store (vec_info *vinfo,
vec_oprnd = result_chain[i];
align = known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
- if (aligned_access_p (first_dr_info))
+ if (aligned_access_p (first_dr_info, vectype))
misalign = 0;
- else if (DR_MISALIGNMENT (first_dr_info) == -1)
+ else if (dr_misalignment (first_dr_info, vectype)
+ == DR_MISALIGNMENT_UNKNOWN)
{
align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr_info);
+ misalign = dr_misalignment (first_dr_info, vectype);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
@@ -8303,7 +8307,7 @@ vectorizable_store (vec_info *vinfo,
dataref_offset
? dataref_offset
: build_int_cst (ref_type, 0));
- if (aligned_access_p (first_dr_info))
+ if (aligned_access_p (first_dr_info, vectype))
;
else
TREE_TYPE (data_ref)
@@ -8515,17 +8519,6 @@ vectorizable_load (vec_info *vinfo,
if (!STMT_VINFO_DATA_REF (stmt_info))
return false;
- /* ??? Alignment analysis for SLP looks at SLP_TREE_SCALAR_STMTS[0]
- for unpermuted loads but we get passed SLP_TREE_REPRESENTATIVE
- which can be different when reduction chains were re-ordered.
- Now that we figured we're a dataref reset stmt_info back to
- SLP_TREE_SCALAR_STMTS[0]. When we're SLP only things should be
- refactored in a way to maintain the dr_vec_info pointer for the
- relevant access explicitely. */
- stmt_vec_info orig_stmt_info = stmt_info;
- if (slp_node)
- stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
-
tree mask = NULL_TREE, mask_vectype = NULL_TREE;
if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
{
@@ -8661,7 +8654,7 @@ vectorizable_load (vec_info *vinfo,
FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (slp_node), j, k)
if (k > maxk)
maxk = k;
- tree vectype = STMT_VINFO_VECTYPE (group_info);
+ tree vectype = SLP_TREE_VECTYPE (slp_node);
if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits)
|| maxk >= (DR_GROUP_SIZE (group_info) & ~(nunits - 1)))
{
@@ -8768,7 +8761,7 @@ vectorizable_load (vec_info *vinfo,
dump_printf_loc (MSG_NOTE, vect_location,
"Vectorizing an unaligned access.\n");
- STMT_VINFO_TYPE (orig_stmt_info) = load_vec_info_type;
+ STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
vect_model_load_cost (vinfo, stmt_info, ncopies, vf, memory_access_type,
&gs_info, slp_node, cost_vec);
return true;
@@ -9562,17 +9555,17 @@ vectorizable_load (vec_info *vinfo,
known_alignment (DR_TARGET_ALIGNMENT (first_dr_info));
if (alignment_support_scheme == dr_aligned)
{
- gcc_assert (aligned_access_p (first_dr_info));
+ gcc_assert (aligned_access_p (first_dr_info, vectype));
misalign = 0;
}
- else if (DR_MISALIGNMENT (first_dr_info) == -1)
+ else if (dr_misalignment (first_dr_info, vectype) == -1)
{
align = dr_alignment
(vect_dr_behavior (vinfo, first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr_info);
+ misalign = dr_misalignment (first_dr_info, vectype);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr),
@@ -9635,7 +9628,8 @@ vectorizable_load (vec_info *vinfo,
unsigned HOST_WIDE_INT gap
= DR_GROUP_GAP (first_stmt_info);
unsigned int vect_align
- = vect_known_alignment_in_bytes (first_dr_info);
+ = vect_known_alignment_in_bytes (first_dr_info,
+ vectype);
unsigned int scalar_dr_size
= vect_get_scalar_dr_size (first_dr_info);
/* If there's no peeling for gaps but we have a gap
@@ -10908,6 +10902,10 @@ vect_analyze_stmt (vec_info *vinfo,
gcc_unreachable ();
}
+ tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (node)
+ STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node);
+
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
@@ -10978,6 +10976,9 @@ vect_analyze_stmt (vec_info *vinfo,
|| vectorizable_phi (vinfo, stmt_info, NULL, node, cost_vec));
}
+ if (node)
+ STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
+
if (!ok)
return opt_result::failure_at (stmt_info->stmt,
"not vectorized:"
@@ -11016,6 +11017,10 @@ vect_transform_stmt (vec_info *vinfo,
gcc_assert (slp_node || !PURE_SLP_STMT (stmt_info));
+ tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
+ if (slp_node)
+ STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
+
switch (STMT_VINFO_TYPE (stmt_info))
{
case type_demotion_vec_info_type:
@@ -11134,16 +11139,19 @@ vect_transform_stmt (vec_info *vinfo,
if (!slp_node && vec_stmt)
gcc_assert (STMT_VINFO_VEC_STMTS (stmt_info).exists ());
- if (STMT_VINFO_TYPE (stmt_info) == store_vec_info_type)
- return is_store;
+ if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type)
+ {
+ /* Handle stmts whose DEF is used outside the loop-nest that is
+ being vectorized. */
+ done = can_vectorize_live_stmts (vinfo, stmt_info, gsi, slp_node,
+ slp_node_instance, true, NULL);
+ gcc_assert (done);
+ }
- /* Handle stmts whose DEF is used outside the loop-nest that is
- being vectorized. */
- done = can_vectorize_live_stmts (vinfo, stmt_info, gsi, slp_node,
- slp_node_instance, true, NULL);
- gcc_assert (done);
+ if (slp_node)
+ STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
- return false;
+ return is_store;
}
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 3aa3e2a..4712dc6 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -507,7 +507,8 @@ vec_info_shared::check_datarefs ()
return;
gcc_assert (datarefs.length () == datarefs_copy.length ());
for (unsigned i = 0; i < datarefs.length (); ++i)
- if (memcmp (&datarefs_copy[i], datarefs[i], sizeof (data_reference)) != 0)
+ if (memcmp (&datarefs_copy[i], datarefs[i],
+ offsetof (data_reference, alt_indices)) != 0)
gcc_unreachable ();
}
@@ -851,7 +852,8 @@ vect_loop_vectorized_call (class loop *loop, gcond **cond)
do
{
g = last_stmt (bb);
- if (g)
+ if ((g && gimple_code (g) == GIMPLE_COND)
+ || !single_succ_p (bb))
break;
if (!single_pred_p (bb))
break;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 72e018e..4aa84ac 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -106,10 +106,11 @@ struct stmt_info_for_cost {
typedef vec<stmt_info_for_cost> stmt_vector_for_cost;
-/* Maps base addresses to an innermost_loop_behavior that gives the maximum
- known alignment for that base. */
+/* Maps base addresses to an innermost_loop_behavior and the stmt it was
+ derived from that gives the maximum known alignment for that base. */
typedef hash_map<tree_operand_hash,
- innermost_loop_behavior *> vec_base_alignments;
+ std::pair<stmt_vec_info, innermost_loop_behavior *> >
+ vec_base_alignments;
/************************************************************************
SLP
@@ -1059,6 +1060,9 @@ public:
data_reference *dr;
/* The statement that contains the data reference. */
stmt_vec_info stmt;
+ /* The analysis group this DR belongs to when doing BB vectorization.
+ DRs of the same group belong to the same conditional execution context. */
+ unsigned group;
/* The misalignment in bytes of the reference, or -1 if not known. */
int misalignment;
/* The byte alignment that we'd ideally like the reference to have,
@@ -1602,51 +1606,58 @@ set_dr_misalignment (dr_vec_info *dr_info, int val)
dr_info->misalignment = val;
}
-inline int
-dr_misalignment (dr_vec_info *dr_info)
-{
- int misalign = dr_info->misalignment;
- gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
- return misalign;
-}
+extern int dr_misalignment (dr_vec_info *dr_info, tree vectype);
-/* Reflects actual alignment of first access in the vectorized loop,
- taking into account peeling/versioning if applied. */
-#define DR_MISALIGNMENT(DR) dr_misalignment (DR)
#define SET_DR_MISALIGNMENT(DR, VAL) set_dr_misalignment (DR, VAL)
/* Only defined once DR_MISALIGNMENT is defined. */
-#define DR_TARGET_ALIGNMENT(DR) ((DR)->target_alignment)
+static inline const poly_uint64
+dr_target_alignment (dr_vec_info *dr_info)
+{
+ if (STMT_VINFO_GROUPED_ACCESS (dr_info->stmt))
+ dr_info = STMT_VINFO_DR_INFO (DR_GROUP_FIRST_ELEMENT (dr_info->stmt));
+ return dr_info->target_alignment;
+}
+#define DR_TARGET_ALIGNMENT(DR) dr_target_alignment (DR)
+
+static inline void
+set_dr_target_alignment (dr_vec_info *dr_info, poly_uint64 val)
+{
+ dr_info->target_alignment = val;
+}
+#define SET_DR_TARGET_ALIGNMENT(DR, VAL) set_dr_target_alignment (DR, VAL)
-/* Return true if data access DR_INFO is aligned to its target alignment
- (which may be less than a full vector). */
+/* Return true if data access DR_INFO is aligned to the targets
+ preferred alignment for VECTYPE (which may be less than a full vector). */
static inline bool
-aligned_access_p (dr_vec_info *dr_info)
+aligned_access_p (dr_vec_info *dr_info, tree vectype)
{
- return (DR_MISALIGNMENT (dr_info) == 0);
+ return (dr_misalignment (dr_info, vectype) == 0);
}
-/* Return TRUE if the alignment of the data access is known, and FALSE
+/* Return TRUE if the (mis-)alignment of the data access is known with
+ respect to the targets preferred alignment for VECTYPE, and FALSE
otherwise. */
static inline bool
-known_alignment_for_access_p (dr_vec_info *dr_info)
+known_alignment_for_access_p (dr_vec_info *dr_info, tree vectype)
{
- return (DR_MISALIGNMENT (dr_info) != DR_MISALIGNMENT_UNKNOWN);
+ return (dr_misalignment (dr_info, vectype) != DR_MISALIGNMENT_UNKNOWN);
}
/* Return the minimum alignment in bytes that the vectorized version
of DR_INFO is guaranteed to have. */
static inline unsigned int
-vect_known_alignment_in_bytes (dr_vec_info *dr_info)
+vect_known_alignment_in_bytes (dr_vec_info *dr_info, tree vectype)
{
- if (DR_MISALIGNMENT (dr_info) == DR_MISALIGNMENT_UNKNOWN)
+ int misalignment = dr_misalignment (dr_info, vectype);
+ if (misalignment == DR_MISALIGNMENT_UNKNOWN)
return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_info->dr)));
- if (DR_MISALIGNMENT (dr_info) == 0)
+ else if (misalignment == 0)
return known_alignment (DR_TARGET_ALIGNMENT (dr_info));
- return DR_MISALIGNMENT (dr_info) & -DR_MISALIGNMENT (dr_info);
+ return misalignment & -misalignment;
}
/* Return the behavior of DR_INFO with respect to the vectorization context
@@ -1690,14 +1701,22 @@ get_dr_vinfo_offset (vec_info *vinfo,
}
+/* Return the vect cost model for LOOP. */
+static inline enum vect_cost_model
+loop_cost_model (loop_p loop)
+{
+ if (loop != NULL
+ && loop->force_vectorize
+ && flag_simd_cost_model != VECT_COST_MODEL_DEFAULT)
+ return flag_simd_cost_model;
+ return flag_vect_cost_model;
+}
+
/* Return true if the vect cost model is unlimited. */
static inline bool
unlimited_cost_model (loop_p loop)
{
- if (loop != NULL && loop->force_vectorize
- && flag_simd_cost_model != VECT_COST_MODEL_DEFAULT)
- return flag_simd_cost_model == VECT_COST_MODEL_UNLIMITED;
- return (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED);
+ return loop_cost_model (loop) == VECT_COST_MODEL_UNLIMITED;
}
/* Return true if the loop described by LOOP_VINFO is fully-masked and
@@ -1959,7 +1978,7 @@ extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, unsigned int = 0);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64);
extern enum dr_alignment_support vect_supportable_dr_alignment
- (vec_info *, dr_vec_info *, bool);
+ (vec_info *, dr_vec_info *, tree, bool);
extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree);
extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance);
@@ -2098,7 +2117,6 @@ extern bool can_duplicate_and_interleave_p (vec_info *, unsigned int, tree,
extern void duplicate_and_interleave (vec_info *, gimple_seq *, tree,
const 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);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 26e71e7..c24c67f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -21,51 +21,34 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "backend.h"
-#include "insn-codes.h"
-#include "rtl.h"
+#include "basic-block.h"
+#include "bitmap.h"
+#include "sbitmap.h"
+#include "options.h"
+#include "dominance.h"
+#include "function.h"
+#include "cfg.h"
#include "tree.h"
#include "gimple.h"
-#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
-#include "optabs-tree.h"
#include "gimple-pretty-print.h"
-#include "flags.h"
#include "fold-const.h"
-#include "stor-layout.h"
-#include "calls.h"
#include "cfganal.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
#include "gimple-iterator.h"
-#include "gimple-walk.h"
#include "tree-cfg.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
-#include "tree-ssa-loop.h"
#include "tree-into-ssa.h"
-#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "tree-ssa-propagate.h"
-#include "tree-chrec.h"
-#include "tree-ssa-threadupdate.h"
-#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
-#include "omp-general.h"
-#include "target.h"
-#include "case-cfn-macros.h"
-#include "alloc-pool.h"
#include "domwalk.h"
-#include "tree-cfgcleanup.h"
-#include "stringpool.h"
-#include "attribs.h"
#include "vr-values.h"
-#include "builtins.h"
-#include "range-op.h"
-#include "value-range-equiv.h"
#include "gimple-array-bounds.h"
+#include "gimple-range.h"
+#include "gimple-range-path.h"
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
@@ -2346,34 +2329,6 @@ stmt_interesting_for_vrp (gimple *stmt)
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;
-}
-
/* 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.
@@ -4160,200 +4115,6 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si)
return simplifier.simplify (si);
}
-class vrp_jump_threader_simplifier : public jump_threader_simplifier
-{
-public:
- vrp_jump_threader_simplifier (vr_values *v, avail_exprs_stack *avails)
- : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
-
-private:
- tree simplify (gimple *, gimple *, basic_block, jt_state *) OVERRIDE;
- avail_exprs_stack *m_avail_exprs_stack;
-};
-
-tree
-vrp_jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block bb,
- jt_state *state)
-{
- /* First see if the conditional is in the hash table. */
- tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, false, true);
- if (cached_lhs && is_gimple_min_invariant (cached_lhs))
- return cached_lhs;
-
- if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
- {
- tree op0 = gimple_cond_lhs (cond_stmt);
- op0 = lhs_of_dominating_assert (op0, bb, stmt);
-
- tree op1 = gimple_cond_rhs (cond_stmt);
- op1 = lhs_of_dominating_assert (op1, bb, stmt);
-
- simplify_using_ranges simplifier (m_vr_values);
- return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- op0, op1, within_stmt);
- }
-
- if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
- {
- tree op = gimple_switch_index (switch_stmt);
- if (TREE_CODE (op) != SSA_NAME)
- return NULL_TREE;
-
- op = lhs_of_dominating_assert (op, bb, stmt);
-
- const value_range_equiv *vr = m_vr_values->get_value_range (op);
- return find_case_label_range (switch_stmt, vr);
- }
-
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
-}
-
-/* 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 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
-{
-public:
- vrp_jump_threader (function *, vr_values *);
- ~vrp_jump_threader ();
-
- void thread_jumps ()
- {
- walk (m_fun->cfg->x_entry_block_ptr);
- }
-
- void thread_through_all_blocks ()
- {
- // FIXME: Put this in the destructor?
- m_threader->thread_through_all_blocks (false);
- }
-
-private:
- 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;
- vrp_jump_threader_simplifier *m_simplifier;
- jump_threader *m_threader;
- jt_state *m_state;
-};
-
-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_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);
- m_state = new jt_state (m_const_and_copies, m_avail_exprs_stack, NULL);
-
- m_simplifier = new vrp_jump_threader_simplifier (m_vr_values,
- m_avail_exprs_stack);
- m_threader = new jump_threader (m_simplifier, m_state);
-}
-
-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;
- delete m_simplifier;
- delete m_threader;
- delete m_state;
-}
-
-/* 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))
- {
- 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_jump_threader::after_dom_children (basic_block bb)
-{
- m_threader->thread_outgoing_edges (bb);
- m_avail_exprs_stack->pop_to_marker ();
- m_const_and_copies->pop_to_marker ();
-}
-
/* 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
@@ -4538,11 +4299,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
array_checker.check ();
}
- /* We must identify jump threading opportunities before we release
- the datastructures built by VRP. */
- vrp_jump_threader threader (fun, &vrp_vr_values);
- threader.thread_jumps ();
-
simplify_casted_conds (fun, &vrp_vr_values);
free_numbers_of_iterations_estimates (fun);
@@ -4552,21 +4308,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
does not properly handle ASSERT_EXPRs. */
assert_engine.remove_range_assertions ();
- /* If we exposed any new variables, go ahead and put them into
- SSA form now, before we handle jump threading. This simplifies
- interactions between rewriting of _DECL nodes into SSA form
- and rewriting SSA_NAME nodes into SSA form after block
- duplication and CFG manipulation. */
- update_ssa (TODO_update_ssa);
-
- /* We identified all the jump threading opportunities earlier, but could
- not transform the CFG at that time. This routine transforms the
- CFG and arranges for the dominator tree to be rebuilt if necessary.
-
- Note the SSA graph update will occur during the normal TODO
- processing by the pass manager. */
- threader.thread_through_all_blocks ();
-
scev_finalize ();
loop_optimizer_finalize ();
return 0;
@@ -4616,3 +4357,126 @@ make_pass_vrp (gcc::context *ctxt)
{
return new pass_vrp (ctxt);
}
+
+// This is the dom walker for the hybrid threader. The reason this is
+// here, as opposed to the generic threading files, is because the
+// other client would be DOM, and they have their own custom walker.
+
+class hybrid_threader : public dom_walker
+{
+public:
+ hybrid_threader ();
+ ~hybrid_threader ();
+
+ void thread_jumps (function *fun)
+ {
+ walk (fun->cfg->x_entry_block_ptr);
+ }
+ bool thread_through_all_blocks ()
+ {
+ return m_threader->thread_through_all_blocks (false);
+ }
+
+private:
+ edge before_dom_children (basic_block) override;
+ void after_dom_children (basic_block bb) override;
+
+ hybrid_jt_simplifier *m_simplifier;
+ jump_threader *m_threader;
+ jt_state *m_state;
+ gimple_ranger *m_ranger;
+ path_range_query *m_query;
+};
+
+hybrid_threader::hybrid_threader () : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS)
+{
+ loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
+ scev_initialize ();
+ calculate_dominance_info (CDI_DOMINATORS);
+ mark_dfs_back_edges ();
+
+ m_ranger = new gimple_ranger;
+ m_query = new path_range_query (*m_ranger, /*resolve=*/true);
+ m_simplifier = new hybrid_jt_simplifier (m_ranger, m_query);
+ m_state = new hybrid_jt_state;
+ m_threader = new jump_threader (m_simplifier, m_state);
+}
+
+hybrid_threader::~hybrid_threader ()
+{
+ delete m_simplifier;
+ delete m_threader;
+ delete m_state;
+ delete m_ranger;
+ delete m_query;
+
+ scev_finalize ();
+ loop_optimizer_finalize ();
+}
+
+edge
+hybrid_threader::before_dom_children (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ int_range<2> r;
+
+ for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ m_ranger->range_of_stmt (r, stmt);
+ }
+ return NULL;
+}
+
+void
+hybrid_threader::after_dom_children (basic_block bb)
+{
+ m_threader->thread_outgoing_edges (bb);
+}
+
+static unsigned int
+execute_vrp_threader (function *fun)
+{
+ hybrid_threader threader;
+ threader.thread_jumps (fun);
+ if (threader.thread_through_all_blocks ())
+ return (TODO_cleanup_cfg | TODO_update_ssa);
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_vrp_threader =
+{
+ GIMPLE_PASS, /* type */
+ "vrp-thread", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_TREE_VRP_THREADER, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+};
+
+class pass_vrp_threader : public gimple_opt_pass
+{
+public:
+ pass_vrp_threader (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_vrp_threader, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_vrp_threader (m_ctxt); }
+ virtual bool gate (function *) { return flag_tree_vrp != 0; }
+ virtual unsigned int execute (function *fun)
+ { return execute_vrp_threader (fun); }
+};
+
+} // namespace {
+
+gimple_opt_pass *
+make_pass_vrp_threader (gcc::context *ctxt)
+{
+ return new pass_vrp_threader (ctxt);
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index cba3bca..7bfd641 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -275,7 +275,7 @@ struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
bool tree_contains_struct[MAX_TREE_CODES][64];
-/* Number of operands for each OpenMP clause. */
+/* Number of operands for each OMP clause. */
unsigned const char omp_clause_num_ops[] =
{
0, /* OMP_CLAUSE_ERROR */
@@ -291,7 +291,7 @@ unsigned const char omp_clause_num_ops[] =
3, /* OMP_CLAUSE_LINEAR */
1, /* OMP_CLAUSE_AFFINITY */
2, /* OMP_CLAUSE_ALIGNED */
- 2, /* OMP_CLAUSE_ALLOCATE */
+ 3, /* OMP_CLAUSE_ALLOCATE */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_NONTEMPORAL */
1, /* OMP_CLAUSE_UNIFORM */
@@ -7637,7 +7637,8 @@ excess_precision_type (tree type)
enum excess_precision_type requested_type
= (flag_excess_precision == EXCESS_PRECISION_FAST
? EXCESS_PRECISION_TYPE_FAST
- : EXCESS_PRECISION_TYPE_STANDARD);
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16 :EXCESS_PRECISION_TYPE_STANDARD));
enum flt_eval_method target_flt_eval_method
= targetm.c.excess_precision (requested_type);
@@ -9510,6 +9511,19 @@ build_common_builtin_nodes (void)
tree tmp, ftype;
int ecf_flags;
+ if (!builtin_decl_explicit_p (BUILT_IN_CLEAR_PADDING))
+ {
+ ftype = build_function_type_list (void_type_node,
+ ptr_type_node,
+ ptr_type_node,
+ integer_type_node,
+ NULL_TREE);
+ local_define_builtin ("__builtin_clear_padding", ftype,
+ BUILT_IN_CLEAR_PADDING,
+ "__builtin_clear_padding",
+ ECF_LEAF | ECF_NOTHROW);
+ }
+
if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
|| !builtin_decl_explicit_p (BUILT_IN_ABORT))
{
@@ -10289,7 +10303,7 @@ build_empty_stmt (location_t loc)
}
-/* Build an OpenMP clause with code CODE. LOC is the location of the
+/* Build an OMP clause with code CODE. LOC is the location of the
clause. */
tree
@@ -10723,6 +10737,35 @@ signed_type_for (tree type)
return signed_or_unsigned_type_for (0, type);
}
+/* - For VECTOR_TYPEs:
+ - The truth type must be a VECTOR_BOOLEAN_TYPE.
+ - The number of elements must match (known_eq).
+ - targetm.vectorize.get_mask_mode exists, and exactly
+ the same mode as the truth type.
+ - Otherwise, the truth type must be a BOOLEAN_TYPE
+ or useless_type_conversion_p to BOOLEAN_TYPE. */
+bool
+is_truth_type_for (tree type, tree truth_type)
+{
+ machine_mode mask_mode = TYPE_MODE (truth_type);
+ machine_mode vmode = TYPE_MODE (type);
+ machine_mode tmask_mode;
+
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ if (VECTOR_BOOLEAN_TYPE_P (truth_type)
+ && known_eq (TYPE_VECTOR_SUBPARTS (type),
+ TYPE_VECTOR_SUBPARTS (truth_type))
+ && targetm.vectorize.get_mask_mode (vmode).exists (&tmask_mode)
+ && tmask_mode == mask_mode)
+ return true;
+
+ return false;
+ }
+
+ return useless_type_conversion_p (boolean_type_node, truth_type);
+}
+
/* If TYPE is a vector type, return a signed integer vector type with the
same width and number of subparts. Otherwise return boolean_type_node. */
@@ -11091,130 +11134,12 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
break;
case OMP_CLAUSE:
- switch (OMP_CLAUSE_CODE (*tp))
- {
- case OMP_CLAUSE_GANG:
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
- /* FALLTHRU */
-
- case OMP_CLAUSE_AFFINITY:
- case OMP_CLAUSE_ASYNC:
- case OMP_CLAUSE_WAIT:
- case OMP_CLAUSE_WORKER:
- case OMP_CLAUSE_VECTOR:
- case OMP_CLAUSE_NUM_GANGS:
- case OMP_CLAUSE_NUM_WORKERS:
- case OMP_CLAUSE_VECTOR_LENGTH:
- case OMP_CLAUSE_PRIVATE:
- case OMP_CLAUSE_SHARED:
- case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_COPYIN:
- case OMP_CLAUSE_COPYPRIVATE:
- case OMP_CLAUSE_FINAL:
- case OMP_CLAUSE_IF:
- case OMP_CLAUSE_NUM_THREADS:
- case OMP_CLAUSE_SCHEDULE:
- case OMP_CLAUSE_UNIFORM:
- case OMP_CLAUSE_DEPEND:
- case OMP_CLAUSE_NONTEMPORAL:
- case OMP_CLAUSE_NUM_TEAMS:
- case OMP_CLAUSE_THREAD_LIMIT:
- case OMP_CLAUSE_DEVICE:
- case OMP_CLAUSE_DIST_SCHEDULE:
- case OMP_CLAUSE_SAFELEN:
- case OMP_CLAUSE_SIMDLEN:
- case OMP_CLAUSE_ORDERED:
- case OMP_CLAUSE_PRIORITY:
- case OMP_CLAUSE_GRAINSIZE:
- case OMP_CLAUSE_NUM_TASKS:
- case OMP_CLAUSE_HINT:
- case OMP_CLAUSE_FILTER:
- case OMP_CLAUSE_TO_DECLARE:
- case OMP_CLAUSE_LINK:
- case OMP_CLAUSE_DETACH:
- case OMP_CLAUSE_USE_DEVICE_PTR:
- case OMP_CLAUSE_USE_DEVICE_ADDR:
- case OMP_CLAUSE_IS_DEVICE_PTR:
- case OMP_CLAUSE_INCLUSIVE:
- case OMP_CLAUSE_EXCLUSIVE:
- case OMP_CLAUSE__LOOPTEMP_:
- case OMP_CLAUSE__REDUCTEMP_:
- case OMP_CLAUSE__CONDTEMP_:
- case OMP_CLAUSE__SCANTEMP_:
- case OMP_CLAUSE__SIMDUID_:
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
- /* FALLTHRU */
-
- case OMP_CLAUSE_INDEPENDENT:
- case OMP_CLAUSE_NOWAIT:
- case OMP_CLAUSE_DEFAULT:
- case OMP_CLAUSE_UNTIED:
- case OMP_CLAUSE_MERGEABLE:
- case OMP_CLAUSE_PROC_BIND:
- case OMP_CLAUSE_DEVICE_TYPE:
- case OMP_CLAUSE_INBRANCH:
- case OMP_CLAUSE_NOTINBRANCH:
- case OMP_CLAUSE_FOR:
- case OMP_CLAUSE_PARALLEL:
- case OMP_CLAUSE_SECTIONS:
- case OMP_CLAUSE_TASKGROUP:
- case OMP_CLAUSE_NOGROUP:
- case OMP_CLAUSE_THREADS:
- case OMP_CLAUSE_SIMD:
- case OMP_CLAUSE_DEFAULTMAP:
- case OMP_CLAUSE_ORDER:
- case OMP_CLAUSE_BIND:
- case OMP_CLAUSE_AUTO:
- case OMP_CLAUSE_SEQ:
- case OMP_CLAUSE_TILE:
- case OMP_CLAUSE__SIMT_:
- case OMP_CLAUSE_IF_PRESENT:
- case OMP_CLAUSE_FINALIZE:
- case OMP_CLAUSE_NOHOST:
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_LASTPRIVATE:
- WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_COLLAPSE:
- {
- int i;
- for (i = 0; i < 3; i++)
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
- }
-
- case OMP_CLAUSE_LINEAR:
- WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LINEAR_STEP (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LINEAR_STMT (*tp));
- 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:
- case OMP_CLAUSE__CACHE_:
- WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_REDUCTION:
- case OMP_CLAUSE_TASK_REDUCTION:
- case OMP_CLAUSE_IN_REDUCTION:
- {
- int i;
- for (i = 0; i < 5; i++)
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
- }
-
- default:
- gcc_unreachable ();
- }
+ {
+ int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)];
+ for (int i = 0; i < len; i++)
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+ }
break;
case TARGET_EXPR:
@@ -11548,30 +11473,13 @@ hashval_t
cl_option_hasher::hash (tree x)
{
const_tree const t = x;
- const char *p;
- size_t i;
- size_t len = 0;
- hashval_t hash = 0;
if (TREE_CODE (t) == OPTIMIZATION_NODE)
- {
- p = (const char *)TREE_OPTIMIZATION (t);
- len = sizeof (struct cl_optimization);
- }
-
+ return cl_optimization_hash (TREE_OPTIMIZATION (t));
else if (TREE_CODE (t) == TARGET_OPTION_NODE)
return cl_target_option_hash (TREE_TARGET_OPTION (t));
-
else
gcc_unreachable ();
-
- /* assume most opt flags are just 0/1, some are 2-3, and a few might be
- something else. */
- for (i = 0; i < len; i++)
- if (p[i])
- hash = (hash << 4) ^ ((i << 2) | p[i]);
-
- return hash;
}
/* Return nonzero if the value represented by *X (an OPTIMIZATION or
@@ -12154,6 +12062,78 @@ warn_deprecated_use (tree node, tree attr)
return w;
}
+/* Error out with an identifier which was marked 'unavailable'. */
+void
+error_unavailable_use (tree node, tree attr)
+{
+ escaped_string msg;
+
+ if (node == 0)
+ return;
+
+ if (!attr)
+ {
+ if (DECL_P (node))
+ attr = DECL_ATTRIBUTES (node);
+ else if (TYPE_P (node))
+ {
+ tree decl = TYPE_STUB_DECL (node);
+ if (decl)
+ attr = lookup_attribute ("unavailable",
+ TYPE_ATTRIBUTES (TREE_TYPE (decl)));
+ }
+ }
+
+ if (attr)
+ attr = lookup_attribute ("unavailable", attr);
+
+ if (attr)
+ msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+
+ if (DECL_P (node))
+ {
+ auto_diagnostic_group d;
+ if (msg)
+ error ("%qD is unavailable: %s", node, (const char *) msg);
+ else
+ error ("%qD is unavailable", node);
+ inform (DECL_SOURCE_LOCATION (node), "declared here");
+ }
+ else if (TYPE_P (node))
+ {
+ tree what = NULL_TREE;
+ tree decl = TYPE_STUB_DECL (node);
+
+ if (TYPE_NAME (node))
+ {
+ if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+ what = TYPE_NAME (node);
+ else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (node)))
+ what = DECL_NAME (TYPE_NAME (node));
+ }
+
+ auto_diagnostic_group d;
+ if (what)
+ {
+ if (msg)
+ error ("%qE is unavailable: %s", what, (const char *) msg);
+ else
+ error ("%qE is unavailable", what);
+ }
+ else
+ {
+ if (msg)
+ error ("type is unavailable: %s", (const char *) msg);
+ else
+ error ("type is unavailable");
+ }
+
+ if (decl)
+ inform (DECL_SOURCE_LOCATION (decl), "declared here");
+ }
+}
+
/* Return true if REF has a COMPONENT_REF with a bit-field field declaration
somewhere in it. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 060a41f..7542d97 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -956,6 +956,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define TREE_DEPRECATED(NODE) \
((NODE)->base.deprecated_flag)
+/* Nonzero in a _DECL if the use of the name is defined as an
+ unavailable feature by __attribute__((unavailable)). */
+#define TREE_UNAVAILABLE(NODE) \
+ ((NODE)->base.u.bits.unavailable_flag)
+
/* Nonzero indicates an IDENTIFIER_NODE that names an anonymous
aggregate, (as created by anon_aggr_name_format). */
#define IDENTIFIER_ANON_P(NODE) \
@@ -1524,6 +1529,11 @@ class auto_suppress_location_wrappers
(TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
OMP_ATOMIC_CAPTURE_NEW)->base.u.omp_atomic_memory_order)
+/* Weak clause on OMP_ATOMIC*. */
+#define OMP_ATOMIC_WEAK(NODE) \
+ (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
+ OMP_ATOMIC_CAPTURE_NEW)->base.public_flag)
+
/* True on a PRIVATE clause if its decl is kept around for debugging
information only and its DECL_VALUE_EXPR is supposed to point
to what it has been remapped to. */
@@ -1691,6 +1701,10 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_DEVICE_TYPE_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE_TYPE)->omp_clause.subcode.device_type_kind)
+/* True if there is a device clause with a device-modifier 'ancestor'. */
+#define OMP_CLAUSE_DEVICE_ANCESTOR(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE)->base.public_flag)
+
#define OMP_CLAUSE_COLLAPSE_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_COLLAPSE), 0)
#define OMP_CLAUSE_COLLAPSE_ITERVAR(NODE) \
@@ -1701,6 +1715,13 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ORDERED_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0)
+/* True for unconstrained modifier on order(concurrent) clause. */
+#define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag)
+/* True for reproducible modifier on order(concurrent) clause. */
+#define OMP_CLAUSE_ORDER_REPRODUCIBLE(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER))
+
#define OMP_CLAUSE_REDUCTION_CODE(NODE) \
(OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
OMP_CLAUSE_IN_REDUCTION)->omp_clause.subcode.reduction_code)
@@ -1772,6 +1793,9 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ALLOCATE_ALLOCATOR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 1)
+#define OMP_CLAUSE_ALLOCATE_ALIGN(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 2)
+
/* 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
@@ -2843,16 +2867,34 @@ extern void decl_value_expr_insert (tree, tree);
/* In a FIELD_DECL, indicates this field should be bit-packed. */
#define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->base.u.bits.packed_flag)
+/* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed
+ specially. */
+#define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1)
+
/* In a FIELD_DECL, indicates this field should be ignored for ABI decisions
like passing/returning containing struct by value.
Set for C++17 empty base artificial FIELD_DECLs as well as
empty [[no_unique_address]] non-static data members. */
#define DECL_FIELD_ABI_IGNORED(NODE) \
- (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0)
+ (!DECL_BIT_FIELD (NODE) && (NODE)->decl_common.decl_flag_0)
+#define SET_DECL_FIELD_ABI_IGNORED(NODE, VAL) \
+ do { \
+ gcc_checking_assert (!DECL_BIT_FIELD (NODE)); \
+ FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0 = (VAL); \
+ } while (0)
-/* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed
- specially. */
-#define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1)
+/* In a FIELD_DECL, indicates C++ zero-width bitfield that used to be
+ removed from the IL since PR42217 until PR101539 and by that changed
+ the ABI on several targets. This flag is provided so that the backends
+ can decide on the ABI with zero-width bitfields and emit -Wpsabi
+ warnings. */
+#define DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD(NODE) \
+ (DECL_BIT_FIELD (NODE) && (NODE)->decl_common.decl_flag_0)
+#define SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD(NODE, VAL) \
+ do { \
+ gcc_checking_assert (DECL_BIT_FIELD (NODE)); \
+ FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0 = (VAL); \
+ } while (0)
/* Used in a FIELD_DECL to indicate that we cannot form the address of
this component. This makes it possible for Type-Based Alias Analysis
@@ -4338,11 +4380,14 @@ tree_strip_any_location_wrapper (tree exp)
#define long_long_integer_type_node integer_types[itk_long_long]
#define long_long_unsigned_type_node integer_types[itk_unsigned_long_long]
-/* True if NODE is an erroneous expression. */
+/* True if T is an erroneous expression. */
-#define error_operand_p(NODE) \
- ((NODE) == error_mark_node \
- || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
+inline bool
+error_operand_p (const_tree t)
+{
+ return (t == error_mark_node
+ || (t && TREE_TYPE (t) == error_mark_node));
+}
/* Return the number of elements encoded directly in a VECTOR_CST. */
@@ -4556,6 +4601,7 @@ extern tree build_string_literal (unsigned, const char * = NULL,
extern tree signed_or_unsigned_type_for (int, tree);
extern tree signed_type_for (tree);
extern tree unsigned_type_for (tree);
+extern bool is_truth_type_for (tree, tree);
extern tree truth_type_for (tree);
extern tree build_pointer_type_for_mode (tree, machine_mode, bool);
extern tree build_pointer_type (tree);
@@ -5203,6 +5249,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 error_unavailable_use (tree, tree);
extern tree cache_integer_cst (tree, bool might_duplicate = false);
extern const char *combined_fn_name (combined_fn);
diff --git a/gcc/tsystem.h b/gcc/tsystem.h
index e1e6a96..5c72c69 100644
--- a/gcc/tsystem.h
+++ b/gcc/tsystem.h
@@ -59,7 +59,7 @@ extern int atexit (void (*)(void));
#endif
#ifndef abort
-extern void abort (void) __attribute__ ((__noreturn__));
+#define abort() __builtin_trap ()
#endif
#ifndef strlen
diff --git a/gcc/value-pointer-equiv.cc b/gcc/value-pointer-equiv.cc
new file mode 100644
index 0000000..7d2658b
--- /dev/null
+++ b/gcc/value-pointer-equiv.cc
@@ -0,0 +1,302 @@
+/* Context-aware pointer equivalence tracker.
+ Copyright (C) 2020-2021 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@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 "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "gimple-pretty-print.h"
+#include "cfganal.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-iterator.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop.h"
+#include "cfgloop.h"
+#include "tree-scalar-evolution.h"
+#include "tree-ssa-propagate.h"
+#include "alloc-pool.h"
+#include "domwalk.h"
+#include "tree-cfgcleanup.h"
+#include "vr-values.h"
+#include "gimple-ssa-evrp-analyze.h"
+#include "gimple-range.h"
+#include "fold-const.h"
+#include "value-pointer-equiv.h"
+
+// Unwindable SSA equivalence table for pointers.
+//
+// The main query point is get_replacement() which returns what a
+// given SSA can be replaced with in the current scope.
+
+class ssa_equiv_stack
+{
+public:
+ ssa_equiv_stack ();
+ void enter (basic_block);
+ void leave (basic_block);
+ void push_replacement (tree name, tree replacement);
+ tree get_replacement (tree name) const;
+
+private:
+ auto_vec<std::pair <tree, tree>> m_stack;
+ auto_vec<tree> m_replacements;
+ const std::pair <tree, tree> m_marker = std::make_pair (NULL, NULL);
+};
+
+ssa_equiv_stack::ssa_equiv_stack ()
+{
+ m_replacements.safe_grow_cleared (num_ssa_names);
+}
+
+// Pushes a marker at the given point.
+
+void
+ssa_equiv_stack::enter (basic_block)
+{
+ m_stack.safe_push (m_marker);
+}
+
+// Pops the stack to the last marker, while performing replacements
+// along the way.
+
+void
+ssa_equiv_stack::leave (basic_block)
+{
+ gcc_checking_assert (!m_stack.is_empty ());
+ while (m_stack.last () != m_marker)
+ {
+ std::pair<tree, tree> e = m_stack.pop ();
+ m_replacements[SSA_NAME_VERSION (e.first)] = e.second;
+ }
+ m_stack.pop ();
+}
+
+// Set the equivalence of NAME to REPLACEMENT.
+
+void
+ssa_equiv_stack::push_replacement (tree name, tree replacement)
+{
+ tree old = m_replacements[SSA_NAME_VERSION (name)];
+ m_replacements[SSA_NAME_VERSION (name)] = replacement;
+ m_stack.safe_push (std::make_pair (name, old));
+}
+
+// Return the equivalence of NAME.
+
+tree
+ssa_equiv_stack::get_replacement (tree name) const
+{
+ return m_replacements[SSA_NAME_VERSION (name)];
+}
+
+pointer_equiv_analyzer::pointer_equiv_analyzer (gimple_ranger *r)
+{
+ m_ranger = r;
+ m_global_points = new tree[num_ssa_names] ();
+ m_cond_points = new ssa_equiv_stack;
+}
+
+pointer_equiv_analyzer::~pointer_equiv_analyzer ()
+{
+ delete[] m_global_points;
+ delete m_cond_points;
+}
+
+// Set the global pointer equivalency for SSA to POINTEE.
+
+void
+pointer_equiv_analyzer::set_global_equiv (tree ssa, tree pointee)
+{
+ m_global_points[SSA_NAME_VERSION (ssa)] = pointee;
+}
+
+// Set the conditional pointer equivalency for SSA to POINTEE.
+
+void
+pointer_equiv_analyzer::set_cond_equiv (tree ssa, tree pointee)
+{
+ m_cond_points->push_replacement (ssa, pointee);
+}
+
+// Return the current pointer equivalency info for SSA, or NULL if
+// none is available. Note that global info takes priority over
+// conditional info.
+
+tree
+pointer_equiv_analyzer::get_equiv (tree ssa) const
+{
+ tree ret = m_global_points[SSA_NAME_VERSION (ssa)];
+ if (ret)
+ return ret;
+ return m_cond_points->get_replacement (ssa);
+}
+
+// Method to be called on entry to a BB.
+
+void
+pointer_equiv_analyzer::enter (basic_block bb)
+{
+ m_cond_points->enter (bb);
+
+ for (gphi_iterator iter = gsi_start_phis (bb);
+ !gsi_end_p (iter);
+ gsi_next (&iter))
+ {
+ gphi *phi = iter.phi ();
+ tree lhs = gimple_phi_result (phi);
+ if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
+ continue;
+ tree arg0 = gimple_phi_arg_def (phi, 0);
+ if (TREE_CODE (arg0) == SSA_NAME && !is_gimple_min_invariant (arg0))
+ arg0 = get_equiv (arg0);
+ if (arg0 && is_gimple_min_invariant (arg0))
+ {
+ // If all the PHI args point to the same place, set the
+ // pointer equivalency info for the PHI result. This can
+ // happen for passes that create redundant PHIs like
+ // PHI<&foo, &foo> or PHI<&foo>.
+ for (size_t i = 1; i < gimple_phi_num_args (phi); ++i)
+ {
+ tree argi = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (argi) == SSA_NAME
+ && !is_gimple_min_invariant (argi))
+ argi = get_equiv (argi);
+ if (!argi || !operand_equal_p (arg0, argi))
+ return;
+ }
+ set_global_equiv (lhs, arg0);
+ }
+ }
+
+ edge pred = single_pred_edge_ignoring_loop_edges (bb, false);
+ if (pred)
+ visit_edge (pred);
+}
+
+// Method to be called on exit from a BB.
+
+void
+pointer_equiv_analyzer::leave (basic_block bb)
+{
+ m_cond_points->leave (bb);
+}
+
+// Helper function to return the pointer equivalency information for
+// EXPR from a gimple statement with CODE. This returns either the
+// cached pointer equivalency info for an SSA, or an invariant in case
+// EXPR is one (i.e. &foo). Returns NULL if EXPR is neither an SSA
+// nor an invariant.
+
+tree
+pointer_equiv_analyzer::get_equiv_expr (tree_code code, tree expr) const
+{
+ if (code == SSA_NAME)
+ return get_equiv (expr);
+
+ if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
+ && is_gimple_min_invariant (expr))
+ return expr;
+
+ return NULL;
+}
+
+// Hack to provide context to the gimple fold callback.
+static struct
+{
+ gimple *m_stmt;
+ gimple_ranger *m_ranger;
+ pointer_equiv_analyzer *m_pta;
+} x_fold_context;
+
+// Gimple fold callback.
+static tree
+pta_valueize (tree name)
+{
+ tree ret
+ = x_fold_context.m_ranger->value_of_expr (name, x_fold_context.m_stmt);
+
+ if (!ret && supported_pointer_equiv_p (name))
+ ret = x_fold_context.m_pta->get_equiv (name);
+
+ return ret ? ret : name;
+}
+
+// Method to be called on gimple statements during traversal of the IL.
+
+void
+pointer_equiv_analyzer::visit_stmt (gimple *stmt)
+{
+ if (gimple_code (stmt) != GIMPLE_ASSIGN)
+ return;
+
+ tree lhs = gimple_assign_lhs (stmt);
+ if (!supported_pointer_equiv_p (lhs))
+ return;
+
+ tree rhs = gimple_assign_rhs1 (stmt);
+ rhs = get_equiv_expr (gimple_assign_rhs_code (stmt), rhs);
+ if (rhs)
+ {
+ set_global_equiv (lhs, rhs);
+ return;
+ }
+
+ // If we couldn't find anything, try fold.
+ x_fold_context = { stmt, m_ranger, this};
+ rhs = gimple_fold_stmt_to_constant_1 (stmt, pta_valueize, pta_valueize);
+ if (rhs)
+ {
+ rhs = get_equiv_expr (TREE_CODE (rhs), rhs);
+ if (rhs)
+ {
+ set_global_equiv (lhs, rhs);
+ return;
+ }
+ }
+}
+
+// If the edge in E is a conditional that sets a pointer equality, set the
+// conditional pointer equivalency information.
+
+void
+pointer_equiv_analyzer::visit_edge (edge e)
+{
+ gimple *stmt = last_stmt (e->src);
+ tree lhs;
+ // Recognize: x_13 [==,!=] &foo.
+ if (stmt
+ && gimple_code (stmt) == GIMPLE_COND
+ && (lhs = gimple_cond_lhs (stmt))
+ && TREE_CODE (lhs) == SSA_NAME
+ && POINTER_TYPE_P (TREE_TYPE (lhs))
+ && TREE_CODE (gimple_cond_rhs (stmt)) == ADDR_EXPR)
+ {
+ tree_code code = gimple_cond_code (stmt);
+ if ((code == EQ_EXPR && e->flags & EDGE_TRUE_VALUE)
+ || ((code == NE_EXPR && e->flags & EDGE_FALSE_VALUE)))
+ set_cond_equiv (lhs, gimple_cond_rhs (stmt));
+ }
+}
diff --git a/gcc/value-pointer-equiv.h b/gcc/value-pointer-equiv.h
new file mode 100644
index 0000000..0921579
--- /dev/null
+++ b/gcc/value-pointer-equiv.h
@@ -0,0 +1,62 @@
+/* Header file for the context-aware pointer equivalence tracker.
+ Copyright (C) 2020-2021 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@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_VALUE_POINTER_EQUIV_H
+#define GCC_VALUE_POINTER_EQUIV_H
+
+// Simple context-aware pointer equivalency analyzer that returns what
+// a pointer SSA name is equivalent to at a given point during a walk
+// of the IL.
+//
+// Note that global equivalency take priority over conditional
+// equivalency. That is, p = &q takes priority over a later p == &t.
+//
+// This class is meant to be called during a DOM walk.
+
+class pointer_equiv_analyzer
+{
+public:
+ pointer_equiv_analyzer (gimple_ranger *r);
+ ~pointer_equiv_analyzer ();
+ void enter (basic_block);
+ void leave (basic_block);
+ void visit_stmt (gimple *stmt);
+ tree get_equiv (tree ssa) const;
+
+private:
+ void visit_edge (edge e);
+ tree get_equiv_expr (tree_code code, tree expr) const;
+ void set_global_equiv (tree ssa, tree pointee);
+ void set_cond_equiv (tree ssa, tree pointee);
+
+ gimple_ranger *m_ranger;
+ // Global pointer equivalency indexed by SSA_NAME_VERSION.
+ tree *m_global_points;
+ // Conditional pointer equivalency.
+ class ssa_equiv_stack *m_cond_points;
+};
+
+inline bool
+supported_pointer_equiv_p (tree expr)
+{
+ return TREE_CODE (expr) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (expr));
+}
+
+#endif // GCC_VALUE_POINTER_EQUIV_H
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 730a214..17ebd86 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -296,7 +296,7 @@ get_ssa_name_ptr_info_nonnull (const_tree name)
return false;
/* TODO Now pt->null is conservatively set to true in PTA
analysis. vrp is the only pass (including ipa-vrp)
- that clears pt.null via set_ptr_nonull when it knows
+ that clears pt.null via set_ptr_nonnull when it knows
for sure. PTA will preserves the pt.null value set by VRP.
When PTA analysis is improved, pt.anything, pt.nonlocal
@@ -416,8 +416,9 @@ get_range_global (irange &r, tree name)
value_range
gimple_range_global (tree name)
{
- gcc_checking_assert (gimple_range_ssa_p (name));
tree type = TREE_TYPE (name);
+ gcc_checking_assert (TREE_CODE (name) == SSA_NAME
+ && irange::supports_type_p (type));
if (SSA_NAME_IS_DEFAULT_DEF (name) || (cfun && cfun->after_inlining)
|| is_a<gphi *> (SSA_NAME_DEF_STMT (name)))
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index f113fd7..caef249 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1648,6 +1648,8 @@ void
irange::irange_intersect (const irange &r)
{
gcc_checking_assert (!legacy_mode_p () && !r.legacy_mode_p ());
+ gcc_checking_assert (undefined_p () || r.undefined_p ()
+ || range_compatible_p (type (), r.type ()));
if (undefined_p () || r.varying_p ())
return;
@@ -1662,6 +1664,13 @@ irange::irange_intersect (const irange &r)
return;
}
+ if (r.num_pairs () == 1)
+ {
+ // R cannot be undefined, use more efficent pair routine.
+ intersect (r.lower_bound(), r.upper_bound ());
+ return;
+ }
+
signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]));
unsigned bld_pair = 0;
unsigned bld_lim = m_max_ranges;
@@ -1737,6 +1746,66 @@ irange::irange_intersect (const irange &r)
verify_range ();
}
+// Multirange intersect for a specified wide_int [lb, ub] range.
+
+void
+irange::intersect (const wide_int& lb, const wide_int& ub)
+{
+ // Undefined remains undefined.
+ if (undefined_p ())
+ return;
+
+ if (legacy_mode_p ())
+ {
+ intersect (int_range<1> (type (), lb, ub));
+ return;
+ }
+
+ tree range_type = type();
+ signop sign = TYPE_SIGN (range_type);
+
+ gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (lb));
+ gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (ub));
+
+ unsigned bld_index = 0;
+ unsigned pair_lim = num_pairs ();
+ for (unsigned i = 0; i < pair_lim; i++)
+ {
+ tree pairl = m_base[i * 2];
+ tree pairu = m_base[i * 2 + 1];
+ // Once UB is less than a pairs lower bound, we're done.
+ if (wi::lt_p (ub, wi::to_wide (pairl), sign))
+ break;
+ // if LB is greater than this pairs upper, this pair is excluded.
+ if (wi::lt_p (wi::to_wide (pairu), lb, sign))
+ continue;
+
+ // Must be some overlap. Find the highest of the lower bounds,
+ // and set it
+ if (wi::gt_p (lb, wi::to_wide (pairl), sign))
+ m_base[bld_index * 2] = wide_int_to_tree (range_type, lb);
+ else
+ m_base[bld_index * 2] = pairl;
+
+ // ...and choose the lower of the upper bounds and if the base pair
+ // has the lower upper bound, need to check next pair too.
+ if (wi::lt_p (ub, wi::to_wide (pairu), sign))
+ {
+ m_base[bld_index++ * 2 + 1] = wide_int_to_tree (range_type, ub);
+ break;
+ }
+ else
+ m_base[bld_index++ * 2 + 1] = pairu;
+ }
+
+ m_num_ranges = bld_index;
+
+ m_kind = VR_RANGE;
+ normalize_kind ();
+
+ if (flag_checking)
+ 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.
@@ -1931,6 +2000,13 @@ irange::dump (FILE *file) const
}
void
+irange::debug () const
+{
+ dump (stderr);
+ fprintf (stderr, "\n");
+}
+
+void
dump_value_range (FILE *file, const irange *vr)
{
vr->dump (file);
diff --git a/gcc/value-range.h b/gcc/value-range.h
index a8adc50..32200ff 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -73,6 +73,7 @@ public:
// In-place operators.
void union_ (const irange &);
void intersect (const irange &);
+ void intersect (const wide_int& lb, const wide_int& ub);
void invert ();
// Operator overloads.
@@ -83,6 +84,7 @@ public:
// Misc methods.
bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); }
void dump (FILE * = stderr) const;
+ void debug () const;
// Deprecated legacy public methods.
enum value_range_kind kind () const; // DEPRECATED
@@ -476,10 +478,21 @@ irange::set_varying (tree type)
if (INTEGRAL_TYPE_P (type))
{
+ // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
+ // min_value and max_value.
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);
+ if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
+ && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
+ {
+ m_base[0] = TYPE_MIN_VALUE (type);
+ m_base[1] = TYPE_MAX_VALUE (type);
+ }
+ else
+ {
+ m_base[0] = wide_int_to_tree (type, min);
+ m_base[1] = wide_int_to_tree (type, max);
+ }
}
else if (POINTER_TYPE_P (type))
{
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 8edd98b..ac5f3f9 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -190,26 +190,31 @@ relation_transitive (relation_kind r1, relation_kind r2)
// -------------------------------------------------------------------------
-// This class represents an equivalency set, and contains a link to the next
-// one in the list to be searched.
-
// The very first element in the m_equiv chain is actually just a summary
// element in which the m_names bitmap is used to indicate that an ssa_name
// has an equivalence set in this block.
// This allows for much faster traversal of the DOM chain, as a search for
// SSA_NAME simply requires walking the DOM chain until a block is found
// which has the bit for SSA_NAME set. Then scan for the equivalency set in
-// that block. No previous blcoks need be searched.
+// that block. No previous lists need be searched.
-class equiv_chain
-{
-public:
- bitmap m_names; // ssa-names in equiv set.
- basic_block m_bb; // Block this belongs to
- equiv_chain *m_next; // Next in block list.
- void dump (FILE *f) const; // Show names in this list.
-};
+// If SSA has an equivalence in this list, find and return it.
+// Otherwise return NULL.
+equiv_chain *
+equiv_chain::find (unsigned ssa)
+{
+ equiv_chain *ptr = NULL;
+ // If there are equiv sets and SSA is in one in this list, find it.
+ // Otherwise return NULL.
+ if (bitmap_bit_p (m_names, ssa))
+ {
+ for (ptr = m_next; ptr; ptr = ptr->m_next)
+ if (bitmap_bit_p (ptr->m_names, ssa))
+ break;
+ }
+ return ptr;
+}
// Dump the names in this equivalence set.
@@ -244,12 +249,15 @@ equiv_oracle::equiv_oracle ()
m_equiv.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
m_equiv_set = BITMAP_ALLOC (&m_bitmaps);
obstack_init (&m_chain_obstack);
+ m_self_equiv.create (0);
+ m_self_equiv.safe_grow_cleared (num_ssa_names + 1);
}
// Destruct an equivalency oracle.
equiv_oracle::~equiv_oracle ()
{
+ m_self_equiv.release ();
obstack_free (&m_chain_obstack, NULL);
m_equiv.release ();
bitmap_obstack_release (&m_bitmaps);
@@ -259,16 +267,48 @@ equiv_oracle::~equiv_oracle ()
// This is the external API.
const_bitmap
-equiv_oracle::equiv_set (tree ssa, basic_block bb) const
+equiv_oracle::equiv_set (tree ssa, basic_block bb)
{
// Search the dominator tree for an equivalency.
equiv_chain *equiv = find_equiv_dom (ssa, bb);
if (equiv)
return equiv->m_names;
- return NULL;
+ // Otherwise return a cached equiv set containing just this SSA.
+ unsigned v = SSA_NAME_VERSION (ssa);
+ if (v >= m_self_equiv.length ())
+ m_self_equiv.safe_grow_cleared (num_ssa_names + 1);
+
+ if (!m_self_equiv[v])
+ {
+ m_self_equiv[v] = BITMAP_ALLOC (&m_bitmaps);
+ bitmap_set_bit (m_self_equiv[v], v);
+ }
+ return m_self_equiv[v];
+}
+
+// Query if thre is a relation (equivalence) between 2 SSA_NAMEs.
+
+relation_kind
+equiv_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
+{
+ // If the 2 ssa names share the same equiv set, they are equal.
+ if (equiv_set (ssa1, bb) == equiv_set (ssa2, bb))
+ return EQ_EXPR;
+ return VREL_NONE;
}
+// Query if thre is a relation (equivalence) between 2 SSA_NAMEs.
+
+relation_kind
+equiv_oracle::query_relation (basic_block bb ATTRIBUTE_UNUSED, const_bitmap e1,
+ const_bitmap e2)
+{
+ // If the 2 ssa names share the same equiv set, they are equal.
+ if (bitmap_equal_p (e1, e2))
+ return EQ_EXPR;
+ return VREL_NONE;
+}
// If SSA has an equivalence in block BB, find and return it.
// Otherwise return NULL.
@@ -276,19 +316,10 @@ equiv_oracle::equiv_set (tree ssa, basic_block bb) const
equiv_chain *
equiv_oracle::find_equiv_block (unsigned ssa, int bb) const
{
- equiv_chain *ptr = NULL;
- if (bb >= (int)m_equiv.length ())
+ if (bb >= (int)m_equiv.length () || !m_equiv[bb])
return NULL;
- // If there are equiv sets and SSA is in one in this block, find it.
- // Otherwise return NULL.
- if (m_equiv[bb] && bitmap_bit_p (m_equiv[bb]->m_names, ssa))
- {
- for (ptr = m_equiv[bb]->m_next; ptr; ptr = ptr->m_next)
- if (bitmap_bit_p (ptr->m_names, ssa))
- break;
- }
- return ptr;
+ return m_equiv[bb]->find (ssa);
}
// Starting at block BB, walk the dominator chain looking for the nearest
@@ -376,6 +407,24 @@ equiv_oracle::register_equiv (basic_block bb, equiv_chain *equiv_1,
return b;
}
+// Create an equivalency set containing only SSA in its definition block.
+// This is done the first time SSA is registered in an equivalency and blocks
+// any DOM searches past the definition.
+
+void
+equiv_oracle::register_initial_def (tree ssa)
+{
+ if (SSA_NAME_IS_DEFAULT_DEF (ssa))
+ return;
+ basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (ssa));
+ gcc_checking_assert (bb && !find_equiv_dom (ssa, bb));
+
+ unsigned v = SSA_NAME_VERSION (ssa);
+ bitmap_set_bit (m_equiv_set, v);
+ bitmap equiv_set = BITMAP_ALLOC (&m_bitmaps);
+ bitmap_set_bit (equiv_set, v);
+ add_equiv_to_block (bb, equiv_set);
+}
// Register an equivalence between SSA1 and SSA2 in block BB.
// The equivalence oracle maintains a vector of equivalencies indexed by basic
@@ -385,10 +434,23 @@ equiv_oracle::register_equiv (basic_block bb, equiv_chain *equiv_1,
// containing all the ssa_names in this basic block.
void
-equiv_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
+equiv_oracle::register_relation (basic_block bb, relation_kind k, tree ssa1,
+ tree ssa2)
{
+ // Only handle equality relations.
+ if (k != EQ_EXPR)
+ return;
+
unsigned v1 = SSA_NAME_VERSION (ssa1);
unsigned v2 = SSA_NAME_VERSION (ssa2);
+
+ // If this is the first time an ssa_name has an equivalency registered
+ // create a self-equivalency record in the def block.
+ if (!bitmap_bit_p (m_equiv_set, v1))
+ register_initial_def (ssa1);
+ if (!bitmap_bit_p (m_equiv_set, v2))
+ register_initial_def (ssa2);
+
equiv_chain *equiv_1 = find_equiv_dom (ssa1, bb);
equiv_chain *equiv_2 = find_equiv_dom (ssa2, bb);
@@ -420,6 +482,15 @@ equiv_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
if (!equiv_set)
return;
+ add_equiv_to_block (bb, equiv_set);
+}
+
+// Add an equivalency record in block BB containing bitmap EQUIV_SET.
+// Note the internal caller is responible for allocating EQUIV_SET properly.
+
+void
+equiv_oracle::add_equiv_to_block (basic_block bb, bitmap equiv_set)
+{
equiv_chain *ptr;
// Check if this is the first time a block has an equivalence added.
@@ -681,9 +752,37 @@ public:
// ------------------------------------------------------------------------
+// Find the relation between any ssa_name in B1 and any name in B2 in LIST.
+// This will allow equivalencies to be applied to any SSA_NAME in a relation.
+
+relation_kind
+relation_chain_head::find_relation (const_bitmap b1, const_bitmap b2) const
+{
+ if (!m_names)
+ return VREL_NONE;
+
+ // If both b1 and b2 aren't referenced in thie block, cant be a relation
+ if (!bitmap_intersect_p (m_names, b1) || !bitmap_intersect_p (m_names, b2))
+ return VREL_NONE;
+
+ // Search for the fiorst relation that contains BOTH an element from B1
+ // and B2, and return that relation.
+ for (relation_chain *ptr = m_head; ptr ; ptr = ptr->m_next)
+ {
+ unsigned op1 = SSA_NAME_VERSION (ptr->op1 ());
+ unsigned op2 = SSA_NAME_VERSION (ptr->op2 ());
+ if (bitmap_bit_p (b1, op1) && bitmap_bit_p (b2, op2))
+ return ptr->kind ();
+ if (bitmap_bit_p (b1, op2) && bitmap_bit_p (b2, op1))
+ return relation_swap (ptr->kind ());
+ }
+
+ return VREL_NONE;
+}
+
// Instantiate a relation oracle.
-relation_oracle::relation_oracle ()
+dom_oracle::dom_oracle ()
{
m_relations.create (0);
m_relations.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
@@ -694,7 +793,7 @@ relation_oracle::relation_oracle ()
// Destruct a relation oracle.
-relation_oracle::~relation_oracle ()
+dom_oracle::~dom_oracle ()
{
m_relations.release ();
}
@@ -702,8 +801,8 @@ relation_oracle::~relation_oracle ()
// Register relation K between ssa_name OP1 and OP2 on STMT.
void
-relation_oracle::register_relation (gimple *stmt, relation_kind k, tree op1,
- tree op2)
+relation_oracle::register_stmt (gimple *stmt, relation_kind k, tree op1,
+ tree op2)
{
gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
@@ -722,19 +821,35 @@ relation_oracle::register_relation (gimple *stmt, relation_kind k, tree op1,
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
- // This relation applies to the entire block, use STMT's block.
- // Equivalencies are handled by the equivalence oracle.
- if (k == EQ_EXPR)
- register_equiv (gimple_bb (stmt), op1, op2);
- else
- register_relation (gimple_bb (stmt), k, op1, op2);
+ // If an equivalence is being added between a PHI and one of its arguments
+ // make sure that that argument is not defined in the same block.
+ // This can happen along back edges and the equivalence will not be
+ // applicable as it would require a use before def.
+ if (k == EQ_EXPR && is_a<gphi *> (stmt))
+ {
+ tree phi_def = gimple_phi_result (stmt);
+ gcc_checking_assert (phi_def == op1 || phi_def == op2);
+ tree arg = op2;
+ if (phi_def == op2)
+ arg = op1;
+ if (gimple_bb (stmt) == gimple_bb (SSA_NAME_DEF_STMT (arg)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, " Not registered due to ");
+ print_generic_expr (dump_file, arg, TDF_SLIM);
+ fprintf (dump_file, " being defined in the same block.\n");
+ }
+ return;
+ }
+ }
+ register_relation (gimple_bb (stmt), k, op1, op2);
}
// Register relation K between ssa_name OP1 and OP2 on edge E.
void
-relation_oracle::register_relation (edge e, relation_kind k, tree op1,
- tree op2)
+relation_oracle::register_edge (edge e, relation_kind k, tree op1, tree op2)
{
gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
@@ -752,24 +867,35 @@ relation_oracle::register_relation (edge e, relation_kind k, tree op1,
fprintf (dump_file, " on (%d->%d)\n", e->src->index, e->dest->index);
}
- // Equivalencies are handled by the equivalence oracle.
+ register_relation (e->dest, k, op1, op2);
+}
+
+// Register relation K between OP! and OP2 in block BB.
+// This creates the record and searches for existing records in the dominator
+// tree to merge with.
+
+void
+dom_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
+ tree op2)
+{ // Equivalencies are handled by the equivalence oracle.
if (k == EQ_EXPR)
- register_equiv (e->dest, op1, op2);
+ equiv_oracle::register_relation (bb, k, op1, op2);
else
- register_relation (e->dest, k, op1, op2);
+ {
+ relation_chain *ptr = set_one_relation (bb, k, op1, op2);
+ register_transitives (bb, *ptr);
+ }
}
// Register relation K between OP! and OP2 in block BB.
// This creates the record and searches for existing records in the dominator
// tree to merge with.
-// TRANSITIVE_P is true if this is being registered as a transitive operation,
-// and should not try to register further transitives.
-void
-relation_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
- tree op2, bool transitive_p)
+relation_chain *
+dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1,
+ tree op2)
{
- gcc_checking_assert (k != VREL_NONE);
+ gcc_checking_assert (k != VREL_NONE && k != EQ_EXPR);
value_relation vr(k, op1, op2);
int bbi = bb->index;
@@ -824,11 +950,9 @@ relation_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
sizeof (relation_chain));
ptr->set_relation (k, op1, op2);
ptr->m_next = m_relations[bbi].m_head;
- m_relations[bbi].m_head = ptr;;
+ m_relations[bbi].m_head = ptr;
}
-
- if (!transitive_p)
- register_transitives (bb, *ptr);
+ return ptr;
}
// Starting at ROOT_BB search the DOM tree looking for relations which
@@ -837,12 +961,25 @@ relation_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
// considered.
void
-relation_oracle::register_transitives (basic_block root_bb,
- const value_relation &relation,
- const_bitmap equiv1,
- const_bitmap equiv2)
+dom_oracle::register_transitives (basic_block root_bb,
+ const value_relation &relation)
{
basic_block bb;
+ // Only apply transitives to certain kinds of operations.
+ switch (relation.kind ())
+ {
+ case LE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ break;
+ default:
+ return;
+ }
+
+ const_bitmap equiv1 = equiv_set (relation.op1 (), root_bb);
+ const_bitmap equiv2 = equiv_set (relation.op2 (), root_bb);
+
for (bb = root_bb; bb; bb = get_immediate_dominator (CDI_DOMINATORS, bb))
{
int bbi = bb->index;
@@ -897,8 +1034,7 @@ relation_oracle::register_transitives (basic_block root_bb,
value_relation nr (relation.kind (), r1, r2);
if (nr.apply_transitive (*ptr))
{
- register_relation (root_bb, nr.kind (), nr.op1 (), nr.op2 (),
- true);
+ set_one_relation (root_bb, nr.kind (), nr.op1 (), nr.op2 ());
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " Registering transitive relation ");
@@ -911,98 +1047,30 @@ relation_oracle::register_transitives (basic_block root_bb,
}
}
-// Find adn register any transitive relations implied by RELATION occuring
-// in block BB.
-
-void
-relation_oracle::register_transitives (basic_block bb,
- const value_relation &relation)
-{
- // Only apply transitives to certain kinds of operations.
- switch (relation.kind ())
- {
- case LE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- break;
- default:
- return;
- }
-
- // Set up the bitmaps for op1 and op2, and if there are no equivalencies,
- // set just op1 or op2 in their own bitmap.
- const_bitmap equiv1 = equiv_set (relation.op1 (), bb);
- const_bitmap equiv2 = equiv_set (relation.op2 (), bb);
- if (equiv1)
- {
- if (equiv2)
- register_transitives (bb, relation, equiv1, equiv2);
- else
- {
- bitmap_clear (m_tmp);
- bitmap_set_bit (m_tmp, SSA_NAME_VERSION (relation.op2 ()));
- register_transitives (bb, relation, equiv1, m_tmp);
- }
- }
- else if (equiv2)
- {
- bitmap_clear (m_tmp);
- bitmap_set_bit (m_tmp, SSA_NAME_VERSION (relation.op1 ()));
- register_transitives (bb, relation, m_tmp, equiv2);
- }
- else
- {
- bitmap_clear (m_tmp);
- bitmap_clear (m_tmp2);
- bitmap_set_bit (m_tmp, SSA_NAME_VERSION (relation.op1 ()));
- bitmap_set_bit (m_tmp2, SSA_NAME_VERSION (relation.op2 ()));
- register_transitives (bb, relation, m_tmp, m_tmp2);
- }
-}
-
// Find the relation between any ssa_name in B1 and any name in B2 in block BB.
// This will allow equivalencies to be applied to any SSA_NAME in a relation.
relation_kind
-relation_oracle::find_relation_block (unsigned bb, const_bitmap b1,
- const_bitmap b2)
+dom_oracle::find_relation_block (unsigned bb, const_bitmap b1,
+ const_bitmap b2) const
{
- const_bitmap bm;
if (bb >= m_relations.length())
return VREL_NONE;
- bm = m_relations[bb].m_names;
- if (!bm)
- return VREL_NONE;
-
- // If both b1 and b2 aren't referenced in thie block, cant be a relation
- if (!bitmap_intersect_p (bm, b1) || !bitmap_intersect_p (bm, b2))
- return VREL_NONE;
-
- // Search for the fiorst relation that contains BOTH an element from B1
- // and B2, and return that relation.
- for (relation_chain *ptr = m_relations[bb].m_head; ptr ; ptr = ptr->m_next)
- {
- unsigned op1 = SSA_NAME_VERSION (ptr->op1 ());
- unsigned op2 = SSA_NAME_VERSION (ptr->op2 ());
- if (bitmap_bit_p (b1, op1) && bitmap_bit_p (b2, op2))
- return ptr->kind ();
- if (bitmap_bit_p (b1, op2) && bitmap_bit_p (b2, op1))
- return relation_swap (ptr->kind ());
- }
-
- return VREL_NONE;
+ return m_relations[bb].find_relation (b1, b2);
}
-// Search the DOM tree for a relation between an element of B1 and B2, starting
-// with block BB.
+// Search the DOM tree for a relation between an element of equivalency set B1
+// and B2, starting with block BB.
relation_kind
-relation_oracle::find_relation_dom (basic_block bb, const_bitmap b1,
- const_bitmap b2)
+dom_oracle::query_relation (basic_block bb, const_bitmap b1,
+ const_bitmap b2)
{
relation_kind r;
+ if (bitmap_equal_p (b1, b2))
+ return EQ_EXPR;
+
// If either name does not occur in a relation anywhere, there isnt one.
if (!bitmap_intersect_p (m_relation_set, b1)
|| !bitmap_intersect_p (m_relation_set, b2))
@@ -1023,8 +1091,8 @@ relation_oracle::find_relation_dom (basic_block bb, const_bitmap b1,
// is found, return a pointer to the chain object in OBJ.
relation_kind
-relation_oracle::find_relation_block (int bb, unsigned v1, unsigned v2,
- relation_chain **obj)
+dom_oracle::find_relation_block (int bb, unsigned v1, unsigned v2,
+ relation_chain **obj) const
{
if (bb >= (int)m_relations.length())
return VREL_NONE;
@@ -1063,7 +1131,7 @@ relation_oracle::find_relation_block (int bb, unsigned v1, unsigned v2,
// starting with block BB
relation_kind
-relation_oracle::find_relation_dom (basic_block bb, unsigned v1, unsigned v2)
+dom_oracle::find_relation_dom (basic_block bb, unsigned v1, unsigned v2) const
{
relation_kind r;
// IF either name does not occur in a relation anywhere, there isnt one.
@@ -1084,7 +1152,7 @@ relation_oracle::find_relation_dom (basic_block bb, unsigned v1, unsigned v2)
// dominator of BB
relation_kind
-relation_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
+dom_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
{
relation_kind kind;
unsigned v1 = SSA_NAME_VERSION (ssa1);
@@ -1092,9 +1160,10 @@ relation_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
if (v1 == v2)
return EQ_EXPR;
- // Check for equivalence first.
+ // Check for equivalence first. They must be in each equivalency set.
const_bitmap equiv1 = equiv_set (ssa1, bb);
- if (equiv1 && bitmap_bit_p (equiv1, v2))
+ const_bitmap equiv2 = equiv_set (ssa2, bb);
+ if (bitmap_bit_p (equiv1, v2) && bitmap_bit_p (equiv2, v1))
return EQ_EXPR;
// Initially look for a direct relationship and just return that.
@@ -1102,38 +1171,15 @@ relation_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
if (kind != VREL_NONE)
return kind;
- // If v2 isn't in v1s equiv set, then v1 shouldn't be in v2's set either.
- // It is possible for out-of-order dominator processing to have an out of
- // sync set of equivalences.. Down the road, when we do full updates,
- // change this to an assert to ensure everything is in sync.
- const_bitmap equiv2 = equiv_set (ssa2, bb);
- if (equiv2 && bitmap_bit_p (equiv2, v1))
- return EQ_EXPR;
-
- // If not equal, see if there is a relationship between equivalences.
- if (!equiv1 && !equiv2)
- kind = VREL_NONE;
- else if (!equiv1)
- {
- bitmap_clear (m_tmp);
- bitmap_set_bit (m_tmp, v1);
- kind = find_relation_dom (bb, m_tmp, equiv2);
- }
- else if (!equiv2)
- {
- bitmap_clear (m_tmp);
- bitmap_set_bit (m_tmp, v2);
- kind = find_relation_dom (bb, equiv1, m_tmp);
- }
- else
- kind = find_relation_dom (bb, equiv1, equiv2);
+ // Query using the equiovalence sets.
+ kind = query_relation (bb, equiv1, equiv2);
return kind;
}
// Dump all the relations in block BB to file F.
void
-relation_oracle::dump (FILE *f, basic_block bb) const
+dom_oracle::dump (FILE *f, basic_block bb) const
{
equiv_oracle::dump (f,bb);
@@ -1154,7 +1200,7 @@ relation_oracle::dump (FILE *f, basic_block bb) const
// Dump all the relations known to file F.
void
-relation_oracle::dump (FILE *f) const
+dom_oracle::dump (FILE *f) const
{
fprintf (f, "Relation dump\n");
for (unsigned i = 0; i < m_relations.length (); i++)
@@ -1164,3 +1210,184 @@ relation_oracle::dump (FILE *f) const
dump (f, BASIC_BLOCK_FOR_FN (cfun, i));
}
}
+
+void
+relation_oracle::debug () const
+{
+ dump (stderr);
+}
+
+path_oracle::path_oracle (relation_oracle *oracle)
+{
+ m_root = oracle;
+ bitmap_obstack_initialize (&m_bitmaps);
+ obstack_init (&m_chain_obstack);
+
+ // Initialize header records.
+ m_equiv.m_names = BITMAP_ALLOC (&m_bitmaps);
+ m_equiv.m_bb = NULL;
+ m_equiv.m_next = NULL;
+ m_relations.m_names = BITMAP_ALLOC (&m_bitmaps);
+ m_relations.m_head = NULL;
+}
+
+path_oracle::~path_oracle ()
+{
+ obstack_free (&m_chain_obstack, NULL);
+ bitmap_obstack_release (&m_bitmaps);
+}
+
+// Return the equiv set for SSA, and if there isn't one, check for equivs
+// starting in block BB.
+
+const_bitmap
+path_oracle::equiv_set (tree ssa, basic_block bb)
+{
+ // Check the list first.
+ equiv_chain *ptr = m_equiv.find (SSA_NAME_VERSION (ssa));
+ if (ptr)
+ return ptr->m_names;
+
+ // Otherwise defer to the root oracle.
+ if (m_root)
+ return m_root->equiv_set (ssa, bb);
+
+ // Allocate a throw away bitmap if there isn't a root oracle.
+ bitmap tmp = BITMAP_ALLOC (&m_bitmaps);
+ bitmap_set_bit (tmp, SSA_NAME_VERSION (ssa));
+ return tmp;
+}
+
+// Register an equivalence between SSA1 and SSA2 resolving unkowns from
+// block BB.
+
+void
+path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
+{
+ const_bitmap equiv_1 = equiv_set (ssa1, bb);
+ const_bitmap equiv_2 = equiv_set (ssa2, bb);
+
+ // Check if they are the same set, if so, we're done.
+ if (bitmap_equal_p (equiv_1, equiv_2))
+ return;
+
+ // Don't mess around, simply create a new record and insert it first.
+ bitmap b = BITMAP_ALLOC (&m_bitmaps);
+ bitmap_copy (b, equiv_1);
+ bitmap_ior_into (b, equiv_2);
+
+ equiv_chain *ptr = (equiv_chain *) obstack_alloc (&m_chain_obstack,
+ sizeof (equiv_chain));
+ ptr->m_names = b;
+ ptr->m_bb = NULL;
+ ptr->m_next = m_equiv.m_next;
+ m_equiv.m_next = ptr;
+ bitmap_ior_into (m_equiv.m_names, b);
+}
+
+// Register relation K between SSA1 and SSA2, resolving unknowns by
+// querying from BB.
+
+void
+path_oracle::register_relation (basic_block bb, relation_kind k, tree ssa1,
+ tree ssa2)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ value_relation vr (k, ssa1, ssa2);
+ fprintf (dump_file, " Registering value_relation (path_oracle) ");
+ vr.dump (dump_file);
+ fprintf (dump_file, " (bb%d)\n", bb->index);
+ }
+
+ if (k == EQ_EXPR)
+ {
+ register_equiv (bb, ssa1, ssa2);
+ return;
+ }
+
+ relation_kind curr = query_relation (bb, ssa1, ssa2);
+ if (curr != VREL_NONE)
+ k = relation_intersect (curr, k);
+
+ bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1));
+ bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa2));
+ relation_chain *ptr = (relation_chain *) obstack_alloc (&m_chain_obstack,
+ sizeof (relation_chain));
+ ptr->set_relation (k, ssa1, ssa2);
+ ptr->m_next = m_relations.m_head;
+ m_relations.m_head = ptr;
+}
+
+// Query for a relationship between equiv set B1 and B2, resolving unknowns
+// starting at block BB.
+
+relation_kind
+path_oracle::query_relation (basic_block bb, const_bitmap b1, const_bitmap b2)
+{
+ if (bitmap_equal_p (b1, b2))
+ return EQ_EXPR;
+
+ relation_kind k = m_relations.find_relation (b1, b2);
+
+ if (k == VREL_NONE && m_root)
+ k = m_root->query_relation (bb, b1, b2);
+
+ return k;
+}
+
+// Query for a relationship between SSA1 and SSA2, resolving unknowns
+// starting at block BB.
+
+relation_kind
+path_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
+{
+ unsigned v1 = SSA_NAME_VERSION (ssa1);
+ unsigned v2 = SSA_NAME_VERSION (ssa2);
+
+ if (v1 == v2)
+ return EQ_EXPR;
+
+ const_bitmap equiv_1 = equiv_set (ssa1, bb);
+ const_bitmap equiv_2 = equiv_set (ssa2, bb);
+ if (bitmap_bit_p (equiv_1, v2) && bitmap_bit_p (equiv_2, v1))
+ return EQ_EXPR;
+
+ return query_relation (bb, equiv_1, equiv_2);
+}
+
+// Reset any relations registered on this path.
+
+void
+path_oracle::reset_path ()
+{
+ m_equiv.m_next = NULL;
+ bitmap_clear (m_equiv.m_names);
+ m_relations.m_head = NULL;
+ bitmap_clear (m_relations.m_names);
+}
+
+// Dump relation in basic block... Do nothing here.
+
+void
+path_oracle::dump (FILE *, basic_block) const
+{
+}
+
+// Dump the relations and equivalencies found in the path.
+
+void
+path_oracle::dump (FILE *f) const
+{
+ equiv_chain *ptr = m_equiv.m_next;
+ for (; ptr; ptr = ptr->m_next)
+ ptr->dump (f);
+
+ relation_chain *ptr2 = m_relations.m_head;
+ for (; ptr2; ptr2 = ptr2->m_next)
+ {
+ fprintf (f, "Relational : ");
+ ptr2->dump (f);
+ fprintf (f, "\n");
+ }
+}
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index e0e2f82..53cefbf 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -73,23 +73,61 @@ relation_kind relation_negate (relation_kind r);
relation_kind relation_swap (relation_kind r);
void print_relation (FILE *f, relation_kind rel);
-// Declared internally in value-relation.cc
-class equiv_chain;
+
+class relation_oracle
+{
+public:
+ virtual ~relation_oracle () { }
+ // register a relation between 2 ssa names at a stmt.
+ void register_stmt (gimple *, relation_kind, tree, tree);
+ // register a relation between 2 ssa names on an edge.
+ void register_edge (edge, relation_kind, tree, tree);
+
+ // Return equivalency set for an SSA name in a basic block.
+ virtual const_bitmap equiv_set (tree, basic_block) = 0;
+ // register a relation between 2 ssa names in a basic block.
+ virtual void register_relation (basic_block, relation_kind, tree, tree) = 0;
+ // Query for a relation between two ssa names in a basic block.
+ virtual relation_kind query_relation (basic_block, tree, tree) = 0;
+ // Query for a relation between two equivalency stes in a basic block.
+ virtual relation_kind query_relation (basic_block, const_bitmap,
+ const_bitmap) = 0;
+
+ virtual void dump (FILE *, basic_block) const = 0;
+ virtual void dump (FILE *) const = 0;
+ void debug () const;
+};
+
+// This class represents an equivalency set, and contains a link to the next
+// one in the list to be searched.
+
+class equiv_chain
+{
+public:
+ bitmap m_names; // ssa-names in equiv set.
+ basic_block m_bb; // Block this belongs to
+ equiv_chain *m_next; // Next in block list.
+ void dump (FILE *f) const; // Show names in this list.
+ equiv_chain *find (unsigned ssa);
+};
// The equivalency oracle maintains equivalencies using the dominator tree.
// Equivalencies apply to an entire basic block. Equivalencies on edges
// can be represented only on edges whose destination is a single-pred block,
// and the equivalence is simply applied to that succesor block.
-class equiv_oracle
+class equiv_oracle : public relation_oracle
{
public:
equiv_oracle ();
~equiv_oracle ();
- const_bitmap equiv_set (tree ssa, basic_block bb) const;
- void register_equiv (basic_block bb, tree ssa1, tree ssa2);
+ const_bitmap equiv_set (tree ssa, basic_block bb);
+ void register_relation (basic_block bb, relation_kind k, tree ssa1,
+ tree ssa2);
+ relation_kind query_relation (basic_block, tree, tree);
+ relation_kind query_relation (basic_block, const_bitmap, const_bitmap);
void dump (FILE *f, basic_block bb) const;
void dump (FILE *f) const;
@@ -99,6 +137,7 @@ protected:
private:
bitmap m_equiv_set; // Index by ssa-name. true if an equivalence exists.
vec <equiv_chain *> m_equiv; // Index by BB. list of equivalences.
+ vec <bitmap> m_self_equiv; // Index by ssa-name, self equivalency set.
void limit_check (basic_block bb = NULL);
equiv_chain *find_equiv_block (unsigned ssa, int bb) const;
@@ -107,7 +146,8 @@ private:
bitmap register_equiv (basic_block bb, unsigned v, equiv_chain *equiv_1);
bitmap register_equiv (basic_block bb, equiv_chain *equiv_1,
equiv_chain *equiv_2);
-
+ void register_initial_def (tree ssa);
+ void add_equiv_to_block (basic_block bb, bitmap equiv);
};
// Summary block header for relations.
@@ -117,6 +157,7 @@ class relation_chain_head
public:
bitmap m_names; // ssa_names with relations in this block.
class relation_chain *m_head; // List of relations in block.
+ relation_kind find_relation (const_bitmap b1, const_bitmap b2) const;
};
// A relation oracle maintains a set of relations between ssa_names using the
@@ -129,16 +170,17 @@ public:
// relation to the destination block of the edge, but ONLY if that block
// has a single successor. For now.
-class relation_oracle : public equiv_oracle
+class dom_oracle : public equiv_oracle
{
public:
- relation_oracle ();
- ~relation_oracle ();
+ dom_oracle ();
+ ~dom_oracle ();
- void register_relation (gimple *stmt, relation_kind k, tree op1, tree op2);
- void register_relation (edge e, relation_kind k, tree op1, tree op2);
+ void register_relation (basic_block bb, relation_kind k, tree op1, tree op2);
relation_kind query_relation (basic_block bb, tree ssa1, tree ssa2);
+ relation_kind query_relation (basic_block bb, const_bitmap b1,
+ const_bitmap b2);
void dump (FILE *f, basic_block bb) const;
void dump (FILE *f) const;
@@ -147,18 +189,51 @@ private:
bitmap m_relation_set; // Index by ssa-name. True if a relation exists
vec <relation_chain_head> m_relations; // Index by BB, list of relations.
relation_kind find_relation_block (unsigned bb, const_bitmap b1,
- const_bitmap b2);
- relation_kind find_relation_dom (basic_block bb, const_bitmap b1,
- const_bitmap b2);
+ const_bitmap b2) const;
relation_kind find_relation_block (int bb, unsigned v1, unsigned v2,
- relation_chain **obj = NULL);
- relation_kind find_relation_dom (basic_block bb, unsigned v1, unsigned v2);
- void register_relation (basic_block bb, relation_kind k, tree op1, tree op2,
- bool transitive_p = false);
+ relation_chain **obj = NULL) const;
+ relation_kind find_relation_dom (basic_block bb, unsigned v1, unsigned v2) const;
+ relation_chain *set_one_relation (basic_block bb, relation_kind k, tree op1,
+ tree op2);
void register_transitives (basic_block, const class value_relation &);
- void register_transitives (basic_block, const value_relation &, const_bitmap,
- const_bitmap);
};
+// A path_oracle implements relations in a list. The only sense of ordering
+// is the latest registered relation is the first found during a search.
+// It can be constructed with an optional "root" oracle which will be used
+// to look up any relations not found in the list.
+// This allows the client to walk paths starting at some block and register
+// and query relations along that path, ignoring other edges.
+//
+// For registering a relation, a query if made of the root oracle if there is
+// any known relationship at block BB, and it is combined with this new
+// relation and entered in the list.
+//
+// Queries are resolved by looking first in the list, and only if nothing is
+// found is the root oracle queried at block BB.
+//
+// reset_path is used to clear all locally registered paths to initial state.
+
+class path_oracle : public relation_oracle
+{
+public:
+ path_oracle (relation_oracle *oracle = NULL);
+ ~path_oracle ();
+ const_bitmap equiv_set (tree, basic_block);
+ void register_relation (basic_block, relation_kind, tree, tree);
+ relation_kind query_relation (basic_block, tree, tree);
+ relation_kind query_relation (basic_block, const_bitmap, const_bitmap);
+ void reset_path ();
+ void dump (FILE *, basic_block) const;
+ void dump (FILE *) const;
+private:
+ void register_equiv (basic_block bb, tree ssa1, tree ssa2);
+ equiv_chain m_equiv;
+ relation_chain_head m_relations;
+ relation_oracle *m_root;
+
+ bitmap_obstack m_bitmaps;
+ struct obstack m_chain_obstack;
+};
#endif /* GCC_VALUE_RELATION_H */
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 26365a7..638a96c 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -6129,7 +6129,8 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
on which register holds that VALUE in some instruction. */
if (!frame_pointer_needed
&& cfa_base_rtx
- && cselib_sp_derived_value_p (v))
+ && cselib_sp_derived_value_p (v)
+ && loc == stack_pointer_rtx)
{
if (preserve)
preserve_value (v);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 53cf6de..09316c6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5531,14 +5531,20 @@ output_constructor_regular_field (oc_local_state *local)
&& (!TYPE_DOMAIN (TREE_TYPE (local->field))
|| !TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field)))))
{
- fieldsize = array_size_for_constructor (local->val);
+ unsigned HOST_WIDE_INT fldsize
+ = array_size_for_constructor (local->val);
+ fieldsize = int_size_in_bytes (TREE_TYPE (local->val));
+ /* In most cases fieldsize == fldsize as the size of the initializer
+ determines how many elements the flexible array member has. For
+ C++ fldsize can be smaller though, if the last or several last or
+ all initializers of the flexible array member have side-effects
+ and the FE splits them into dynamic initialization. */
+ gcc_checking_assert (fieldsize >= fldsize);
/* Given a non-empty initialization, this field had better
be last. Given a flexible array member, the next field
on the chain is a TYPE_DECL of the enclosing struct. */
const_tree next = DECL_CHAIN (local->field);
gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
- tree size = TYPE_SIZE_UNIT (TREE_TYPE (local->val));
- gcc_checking_assert (compare_tree_int (size, fieldsize) == 0);
}
else
fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
@@ -7821,10 +7827,7 @@ switch_to_section (section *new_section, tree decl)
else if (in_section == new_section)
return;
- if (new_section->common.flags & SECTION_FORGET)
- in_section = NULL;
- else
- in_section = new_section;
+ in_section = new_section;
switch (SECTION_STYLE (new_section))
{
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index c999ca8..d0f7cb4 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -3454,6 +3454,34 @@ range_fits_type_p (const value_range *vr,
return true;
}
+// Clear edge E of EDGE_EXECUTABLE (it is unexecutable). If it wasn't
+// previously clear, propagate to successor blocks if appropriate.
+
+void
+simplify_using_ranges::set_and_propagate_unexecutable (edge e)
+{
+ // If not_executable is already set, we're done.
+ // This works in the absence of a flag as well.
+ if ((e->flags & m_not_executable_flag) == m_not_executable_flag)
+ return;
+
+ e->flags |= m_not_executable_flag;
+ m_flag_set_edges.safe_push (e);
+
+ // Check if the destination block needs to propagate the property.
+ basic_block bb = e->dest;
+
+ // If any incoming edge is executable, we are done.
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if ((e->flags & m_not_executable_flag) == 0)
+ return;
+
+ // This block is also unexecutable, propagate to all exit edges as well.
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ set_and_propagate_unexecutable (e);
+}
+
/* If COND can be folded entirely as TRUE or FALSE, rewrite the
conditional as such, and return TRUE. */
@@ -3467,18 +3495,27 @@ simplify_using_ranges::fold_cond (gcond *cond)
if (TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
&& TREE_CODE (gimple_cond_rhs (cond)) != SSA_NAME)
return false;
-
+ edge e0 = EDGE_SUCC (gimple_bb (cond), 0);
+ edge e1 = EDGE_SUCC (gimple_bb (cond), 1);
if (r.zero_p ())
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nPredicate evaluates to: 0\n");
gimple_cond_make_false (cond);
+ if (e0->flags & EDGE_TRUE_VALUE)
+ set_and_propagate_unexecutable (e0);
+ else
+ set_and_propagate_unexecutable (e1);
}
else
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nPredicate evaluates to: 1\n");
gimple_cond_make_true (cond);
+ if (e0->flags & EDGE_FALSE_VALUE)
+ set_and_propagate_unexecutable (e0);
+ else
+ set_and_propagate_unexecutable (e1);
}
update_stmt (cond);
return true;
@@ -3769,6 +3806,7 @@ simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
fprintf (dump_file, "removing unreachable case label\n");
}
to_remove_edges.safe_push (e);
+ set_and_propagate_unexecutable (e);
e->flags &= ~EDGE_EXECUTABLE;
e->flags |= EDGE_IGNORE;
}
@@ -3787,6 +3825,12 @@ simplify_using_ranges::cleanup_edges_and_switches (void)
edge e;
switch_update *su;
+ /* Clear any edges marked as not executable. */
+ if (m_not_executable_flag)
+ {
+ FOR_EACH_VEC_ELT (m_flag_set_edges, i, e)
+ e->flags &= ~m_not_executable_flag;
+ }
/* Remove dead edges from SWITCH_EXPR optimization. This leaves the
CFG in a broken state and requires a cfg_cleanup run. */
FOR_EACH_VEC_ELT (to_remove_edges, i, e)
@@ -4089,11 +4133,14 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b,
return false;
}
-simplify_using_ranges::simplify_using_ranges (range_query *query)
+simplify_using_ranges::simplify_using_ranges (range_query *query,
+ int not_executable_flag)
: query (query)
{
to_remove_edges = vNULL;
to_update_switch_stmts = vNULL;
+ m_not_executable_flag = not_executable_flag;
+ m_flag_set_edges = vNULL;
}
simplify_using_ranges::~simplify_using_ranges ()
@@ -4234,6 +4281,28 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
case MAX_EXPR:
return simplify_min_or_max_using_ranges (gsi, stmt);
+ case RSHIFT_EXPR:
+ {
+ tree op0 = gimple_assign_rhs1 (stmt);
+ tree type = TREE_TYPE (op0);
+ int_range_max range;
+ if (TYPE_SIGN (type) == SIGNED
+ && query->range_of_expr (range, op0, stmt))
+ {
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (op0));
+ int_range<2> nzm1 (type, wi::minus_one (prec), wi::zero (prec),
+ VR_ANTI_RANGE);
+ range.intersect (nzm1);
+ // If there are no ranges other than [-1, 0] remove the shift.
+ if (range.undefined_p ())
+ {
+ gimple_assign_set_rhs_from_tree (gsi, op0);
+ return true;
+ }
+ return false;
+ }
+ break;
+ }
default:
break;
}
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 7fdefef..821bcb9 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -30,9 +30,11 @@ along with GCC; see the file COPYING3. If not see
class simplify_using_ranges
{
public:
- simplify_using_ranges (class range_query *query = NULL);
+ simplify_using_ranges (range_query *query = NULL,
+ int not_executable_flag = 0);
~simplify_using_ranges ();
- void set_range_query (class range_query *q) { query = q; }
+ void set_range_query (class range_query *q, int not_executable_flag = 0)
+ { query = q; m_not_executable_flag = not_executable_flag; }
bool simplify (gimple_stmt_iterator *);
@@ -66,6 +68,7 @@ private:
tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
tree, tree,
bool *, gimple *s);
+ void set_and_propagate_unexecutable (edge e);
void cleanup_edges_and_switches (void);
/* Vectors of edges that need removing and switch statements that
@@ -81,6 +84,8 @@ private:
vec<edge> to_remove_edges;
vec<switch_update> to_update_switch_stmts;
class range_query *query;
+ int m_not_executable_flag; // Non zero if not_executable flag exists.
+ vec<edge> m_flag_set_edges; // List of edges with flag to be cleared.
};
/* The VR_VALUES class holds the current view of range information
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index ec8ed232..36a47ab 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -62,22 +62,22 @@ set_no_warning_bit (gimple *stmt, bool value)
stmt->no_warning = value;
}
-/* Return EXPR location or zero. */
+/* Return EXPR location or 'UNKNOWN_LOCATION'. */
-static inline key_type_t
-convert_to_key (const_tree expr)
+static inline location_t
+get_location (const_tree expr)
{
if (DECL_P (expr))
return DECL_SOURCE_LOCATION (expr);
if (EXPR_P (expr))
return EXPR_LOCATION (expr);
- return 0;
+ return UNKNOWN_LOCATION;
}
-/* Return STMT location (may be zero). */
+/* Return STMT location (may be 'UNKNOWN_LOCATION'). */
-static inline key_type_t
-convert_to_key (const gimple *stmt)
+static inline location_t
+get_location (const gimple *stmt)
{
return gimple_location (stmt);
}
@@ -87,12 +87,15 @@ convert_to_key (const gimple *stmt)
static nowarn_spec_t *
get_nowarn_spec (const_tree expr)
{
- const key_type_t key = convert_to_key (expr);
+ const location_t loc = get_location (expr);
- if (!get_no_warning_bit (expr) || !key)
+ if (RESERVED_LOCATION_P (loc))
return NULL;
- return nowarn_map ? nowarn_map->get (key) : NULL;
+ if (!get_no_warning_bit (expr))
+ return NULL;
+
+ return nowarn_map ? nowarn_map->get (loc) : NULL;
}
/* Return the no-warning bitmap for stateemt STMT. */
@@ -100,12 +103,15 @@ get_nowarn_spec (const_tree expr)
static nowarn_spec_t *
get_nowarn_spec (const gimple *stmt)
{
- const key_type_t key = convert_to_key (stmt);
+ const location_t loc = get_location (stmt);
+
+ if (RESERVED_LOCATION_P (loc))
+ return NULL;
if (!get_no_warning_bit (stmt))
return NULL;
- return nowarn_map ? nowarn_map->get (key) : NULL;
+ return nowarn_map ? nowarn_map->get (loc) : NULL;
}
/* Return true if warning OPT is suppressed for decl/expression EXPR.
@@ -153,9 +159,10 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
if (opt == no_warning)
return;
- const key_type_t key = convert_to_key (expr);
+ const location_t loc = get_location (expr);
- supp = suppress_warning_at (key, opt, supp) || supp;
+ if (!RESERVED_LOCATION_P (loc))
+ supp = suppress_warning_at (loc, opt, supp) || supp;
set_no_warning_bit (expr, supp);
}
@@ -169,9 +176,10 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
if (opt == no_warning)
return;
- const key_type_t key = convert_to_key (stmt);
+ const location_t loc = get_location (stmt);
- supp = suppress_warning_at (key, opt, supp) || supp;
+ if (!RESERVED_LOCATION_P (loc))
+ supp = suppress_warning_at (loc, opt, supp) || supp;
set_no_warning_bit (stmt, supp);
}
@@ -181,28 +189,35 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
template <class ToType, class FromType>
void copy_warning (ToType to, FromType from)
{
- const key_type_t to_key = convert_to_key (to);
+ const location_t to_loc = get_location (to);
- if (nowarn_spec_t *from_map = get_nowarn_spec (from))
- {
- /* If there's an entry in the map the no-warning bit must be set. */
- gcc_assert (get_no_warning_bit (from));
+ bool supp = get_no_warning_bit (from);
- if (!nowarn_map)
- nowarn_map = xint_hash_map_t::create_ggc (32);
-
- nowarn_map->put (to_key, *from_map);
- set_no_warning_bit (to, true);
- }
+ nowarn_spec_t *from_spec = get_nowarn_spec (from);
+ if (RESERVED_LOCATION_P (to_loc))
+ /* We cannot set no-warning dispositions for 'to', so we have no chance but
+ lose those potentially set for 'from'. */
+ ;
else
{
- if (nowarn_map)
- nowarn_map->remove (to_key);
-
- /* The no-warning bit might be set even if there's no entry
- in the map. */
- set_no_warning_bit (to, get_no_warning_bit (from));
+ if (from_spec)
+ {
+ /* If there's an entry in the map the no-warning bit must be set. */
+ gcc_assert (supp);
+
+ gcc_checking_assert (nowarn_map);
+ nowarn_map->put (to_loc, *from_spec);
+ }
+ else
+ {
+ if (nowarn_map)
+ nowarn_map->remove (to_loc);
+ }
}
+
+ /* The no-warning bit might be set even if the map has not been consulted, or
+ otherwise if there's no entry in the map. */
+ set_no_warning_bit (to, supp);
}
/* Copy the warning disposition mapping from one expression to another. */
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index 906f4ea..a142151 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -2050,6 +2050,10 @@ wi::arshift_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
int
wi::clz (const wide_int_ref &x)
{
+ if (x.sign_mask () < 0)
+ /* The upper bit is set, so there are no leading zeros. */
+ return 0;
+
/* Calculate how many bits there above the highest represented block. */
int count = x.precision - x.len * HOST_BITS_PER_WIDE_INT;
@@ -2058,9 +2062,6 @@ wi::clz (const wide_int_ref &x)
/* The upper -COUNT bits of HIGH are not part of the value.
Clear them out. */
high = (high << -count) >> -count;
- else if (x.sign_mask () < 0)
- /* The upper bit is set, so there are no leading zeros. */
- return 0;
/* We don't need to look below HIGH. Either HIGH is nonzero,
or the top bit of the block below is nonzero; clz_hwi is